target/mips: Extract FPU specific definitions to translate.h
[qemu/ar7.git] / target / mips / translate.c
blob4c400ec0b3cae6175e611c7d9b0f4e5bcf505451
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_CP2 = (0x12 << 26),
47 OPC_CP3 = (0x13 << 26),
48 OPC_SPECIAL2 = (0x1C << 26),
49 OPC_SPECIAL3 = (0x1F << 26),
50 /* arithmetic with immediate */
51 OPC_ADDI = (0x08 << 26),
52 OPC_ADDIU = (0x09 << 26),
53 OPC_SLTI = (0x0A << 26),
54 OPC_SLTIU = (0x0B << 26),
55 /* logic with immediate */
56 OPC_ANDI = (0x0C << 26),
57 OPC_ORI = (0x0D << 26),
58 OPC_XORI = (0x0E << 26),
59 OPC_LUI = (0x0F << 26),
60 /* arithmetic with immediate */
61 OPC_DADDI = (0x18 << 26),
62 OPC_DADDIU = (0x19 << 26),
63 /* Jump and branches */
64 OPC_J = (0x02 << 26),
65 OPC_JAL = (0x03 << 26),
66 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
67 OPC_BEQL = (0x14 << 26),
68 OPC_BNE = (0x05 << 26),
69 OPC_BNEL = (0x15 << 26),
70 OPC_BLEZ = (0x06 << 26),
71 OPC_BLEZL = (0x16 << 26),
72 OPC_BGTZ = (0x07 << 26),
73 OPC_BGTZL = (0x17 << 26),
74 OPC_JALX = (0x1D << 26),
75 OPC_DAUI = (0x1D << 26),
76 /* Load and stores */
77 OPC_LDL = (0x1A << 26),
78 OPC_LDR = (0x1B << 26),
79 OPC_LB = (0x20 << 26),
80 OPC_LH = (0x21 << 26),
81 OPC_LWL = (0x22 << 26),
82 OPC_LW = (0x23 << 26),
83 OPC_LWPC = OPC_LW | 0x5,
84 OPC_LBU = (0x24 << 26),
85 OPC_LHU = (0x25 << 26),
86 OPC_LWR = (0x26 << 26),
87 OPC_LWU = (0x27 << 26),
88 OPC_SB = (0x28 << 26),
89 OPC_SH = (0x29 << 26),
90 OPC_SWL = (0x2A << 26),
91 OPC_SW = (0x2B << 26),
92 OPC_SDL = (0x2C << 26),
93 OPC_SDR = (0x2D << 26),
94 OPC_SWR = (0x2E << 26),
95 OPC_LL = (0x30 << 26),
96 OPC_LLD = (0x34 << 26),
97 OPC_LD = (0x37 << 26),
98 OPC_LDPC = OPC_LD | 0x5,
99 OPC_SC = (0x38 << 26),
100 OPC_SCD = (0x3C << 26),
101 OPC_SD = (0x3F << 26),
102 /* Floating point load/store */
103 OPC_LWC1 = (0x31 << 26),
104 OPC_LWC2 = (0x32 << 26),
105 OPC_LDC1 = (0x35 << 26),
106 OPC_LDC2 = (0x36 << 26),
107 OPC_SWC1 = (0x39 << 26),
108 OPC_SWC2 = (0x3A << 26),
109 OPC_SDC1 = (0x3D << 26),
110 OPC_SDC2 = (0x3E << 26),
111 /* Compact Branches */
112 OPC_BLEZALC = (0x06 << 26),
113 OPC_BGEZALC = (0x06 << 26),
114 OPC_BGEUC = (0x06 << 26),
115 OPC_BGTZALC = (0x07 << 26),
116 OPC_BLTZALC = (0x07 << 26),
117 OPC_BLTUC = (0x07 << 26),
118 OPC_BOVC = (0x08 << 26),
119 OPC_BEQZALC = (0x08 << 26),
120 OPC_BEQC = (0x08 << 26),
121 OPC_BLEZC = (0x16 << 26),
122 OPC_BGEZC = (0x16 << 26),
123 OPC_BGEC = (0x16 << 26),
124 OPC_BGTZC = (0x17 << 26),
125 OPC_BLTZC = (0x17 << 26),
126 OPC_BLTC = (0x17 << 26),
127 OPC_BNVC = (0x18 << 26),
128 OPC_BNEZALC = (0x18 << 26),
129 OPC_BNEC = (0x18 << 26),
130 OPC_BC = (0x32 << 26),
131 OPC_BEQZC = (0x36 << 26),
132 OPC_JIC = (0x36 << 26),
133 OPC_BALC = (0x3A << 26),
134 OPC_BNEZC = (0x3E << 26),
135 OPC_JIALC = (0x3E << 26),
136 /* MDMX ASE specific */
137 OPC_MDMX = (0x1E << 26),
138 /* MSA ASE, same as MDMX */
139 OPC_MSA = OPC_MDMX,
140 /* Cache and prefetch */
141 OPC_CACHE = (0x2F << 26),
142 OPC_PREF = (0x33 << 26),
143 /* PC-relative address computation / loads */
144 OPC_PCREL = (0x3B << 26),
147 /* PC-relative address computation / loads */
148 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
149 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
150 enum {
151 /* Instructions determined by bits 19 and 20 */
152 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
153 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
154 OPC_LWUPC = OPC_PCREL | (2 << 19),
156 /* Instructions determined by bits 16 ... 20 */
157 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
158 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
160 /* Other */
161 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
164 /* MIPS special opcodes */
165 #define MASK_SPECIAL(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
167 enum {
168 /* Shifts */
169 OPC_SLL = 0x00 | OPC_SPECIAL,
170 /* NOP is SLL r0, r0, 0 */
171 /* SSNOP is SLL r0, r0, 1 */
172 /* EHB is SLL r0, r0, 3 */
173 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
174 OPC_ROTR = OPC_SRL | (1 << 21),
175 OPC_SRA = 0x03 | OPC_SPECIAL,
176 OPC_SLLV = 0x04 | OPC_SPECIAL,
177 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
178 OPC_ROTRV = OPC_SRLV | (1 << 6),
179 OPC_SRAV = 0x07 | OPC_SPECIAL,
180 OPC_DSLLV = 0x14 | OPC_SPECIAL,
181 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
182 OPC_DROTRV = OPC_DSRLV | (1 << 6),
183 OPC_DSRAV = 0x17 | OPC_SPECIAL,
184 OPC_DSLL = 0x38 | OPC_SPECIAL,
185 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
186 OPC_DROTR = OPC_DSRL | (1 << 21),
187 OPC_DSRA = 0x3B | OPC_SPECIAL,
188 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
189 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
190 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
191 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
192 /* Multiplication / division */
193 OPC_MULT = 0x18 | OPC_SPECIAL,
194 OPC_MULTU = 0x19 | OPC_SPECIAL,
195 OPC_DIV = 0x1A | OPC_SPECIAL,
196 OPC_DIVU = 0x1B | OPC_SPECIAL,
197 OPC_DMULT = 0x1C | OPC_SPECIAL,
198 OPC_DMULTU = 0x1D | OPC_SPECIAL,
199 OPC_DDIV = 0x1E | OPC_SPECIAL,
200 OPC_DDIVU = 0x1F | OPC_SPECIAL,
202 /* 2 registers arithmetic / logic */
203 OPC_ADD = 0x20 | OPC_SPECIAL,
204 OPC_ADDU = 0x21 | OPC_SPECIAL,
205 OPC_SUB = 0x22 | OPC_SPECIAL,
206 OPC_SUBU = 0x23 | OPC_SPECIAL,
207 OPC_AND = 0x24 | OPC_SPECIAL,
208 OPC_OR = 0x25 | OPC_SPECIAL,
209 OPC_XOR = 0x26 | OPC_SPECIAL,
210 OPC_NOR = 0x27 | OPC_SPECIAL,
211 OPC_SLT = 0x2A | OPC_SPECIAL,
212 OPC_SLTU = 0x2B | OPC_SPECIAL,
213 OPC_DADD = 0x2C | OPC_SPECIAL,
214 OPC_DADDU = 0x2D | OPC_SPECIAL,
215 OPC_DSUB = 0x2E | OPC_SPECIAL,
216 OPC_DSUBU = 0x2F | OPC_SPECIAL,
217 /* Jumps */
218 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
219 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
220 /* Traps */
221 OPC_TGE = 0x30 | OPC_SPECIAL,
222 OPC_TGEU = 0x31 | OPC_SPECIAL,
223 OPC_TLT = 0x32 | OPC_SPECIAL,
224 OPC_TLTU = 0x33 | OPC_SPECIAL,
225 OPC_TEQ = 0x34 | OPC_SPECIAL,
226 OPC_TNE = 0x36 | OPC_SPECIAL,
227 /* HI / LO registers load & stores */
228 OPC_MFHI = 0x10 | OPC_SPECIAL,
229 OPC_MTHI = 0x11 | OPC_SPECIAL,
230 OPC_MFLO = 0x12 | OPC_SPECIAL,
231 OPC_MTLO = 0x13 | OPC_SPECIAL,
232 /* Conditional moves */
233 OPC_MOVZ = 0x0A | OPC_SPECIAL,
234 OPC_MOVN = 0x0B | OPC_SPECIAL,
236 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
237 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
239 OPC_MOVCI = 0x01 | OPC_SPECIAL,
241 /* Special */
242 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
243 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
244 OPC_BREAK = 0x0D | OPC_SPECIAL,
245 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
246 OPC_SYNC = 0x0F | OPC_SPECIAL,
248 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
249 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
250 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
251 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
255 * R6 Multiply and Divide instructions have the same opcode
256 * and function field as legacy OPC_MULT[U]/OPC_DIV[U]
258 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
260 enum {
261 R6_OPC_MUL = OPC_MULT | (2 << 6),
262 R6_OPC_MUH = OPC_MULT | (3 << 6),
263 R6_OPC_MULU = OPC_MULTU | (2 << 6),
264 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
265 R6_OPC_DIV = OPC_DIV | (2 << 6),
266 R6_OPC_MOD = OPC_DIV | (3 << 6),
267 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
268 R6_OPC_MODU = OPC_DIVU | (3 << 6),
270 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
271 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
272 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
273 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
274 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
275 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
276 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
277 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
279 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
280 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
281 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
282 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
283 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
285 OPC_LSA = 0x05 | OPC_SPECIAL,
286 OPC_DLSA = 0x15 | OPC_SPECIAL,
289 /* Multiplication variants of the vr54xx. */
290 #define MASK_MUL_VR54XX(op) (MASK_SPECIAL(op) | (op & (0x1F << 6)))
292 enum {
293 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
294 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
295 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
296 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
297 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
298 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
299 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
300 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
301 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
302 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
303 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
304 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
305 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
306 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
309 /* REGIMM (rt field) opcodes */
310 #define MASK_REGIMM(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 16)))
312 enum {
313 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
314 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
315 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
316 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
317 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
318 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
319 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
320 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
321 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
322 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
323 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
324 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
325 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
326 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
327 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
328 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
330 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
331 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
334 /* Special2 opcodes */
335 #define MASK_SPECIAL2(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
337 enum {
338 /* Multiply & xxx operations */
339 OPC_MADD = 0x00 | OPC_SPECIAL2,
340 OPC_MADDU = 0x01 | OPC_SPECIAL2,
341 OPC_MUL = 0x02 | OPC_SPECIAL2,
342 OPC_MSUB = 0x04 | OPC_SPECIAL2,
343 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
344 /* Loongson 2F */
345 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
346 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
347 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
348 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
349 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
350 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
351 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
352 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
353 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
354 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
355 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
356 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
357 /* Misc */
358 OPC_CLZ = 0x20 | OPC_SPECIAL2,
359 OPC_CLO = 0x21 | OPC_SPECIAL2,
360 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
361 OPC_DCLO = 0x25 | OPC_SPECIAL2,
362 /* Special */
363 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
366 /* Special3 opcodes */
367 #define MASK_SPECIAL3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
369 enum {
370 OPC_EXT = 0x00 | OPC_SPECIAL3,
371 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
372 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
373 OPC_DEXT = 0x03 | OPC_SPECIAL3,
374 OPC_INS = 0x04 | OPC_SPECIAL3,
375 OPC_DINSM = 0x05 | OPC_SPECIAL3,
376 OPC_DINSU = 0x06 | OPC_SPECIAL3,
377 OPC_DINS = 0x07 | OPC_SPECIAL3,
378 OPC_FORK = 0x08 | OPC_SPECIAL3,
379 OPC_YIELD = 0x09 | OPC_SPECIAL3,
380 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
381 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
382 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
383 OPC_GINV = 0x3D | OPC_SPECIAL3,
385 /* Loongson 2E */
386 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
387 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
388 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
389 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
390 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
391 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
392 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
393 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
394 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
395 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
396 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
397 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
399 /* MIPS DSP Load */
400 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
401 /* MIPS DSP Arithmetic */
402 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
403 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
404 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
405 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
406 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
407 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
408 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
409 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
410 /* MIPS DSP GPR-Based Shift Sub-class */
411 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
412 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
413 /* MIPS DSP Multiply Sub-class insns */
414 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
415 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
416 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
417 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
418 /* DSP Bit/Manipulation Sub-class */
419 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
420 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
421 /* MIPS DSP Append Sub-class */
422 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
423 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
424 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
425 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
426 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
428 /* EVA */
429 OPC_LWLE = 0x19 | OPC_SPECIAL3,
430 OPC_LWRE = 0x1A | OPC_SPECIAL3,
431 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
432 OPC_SBE = 0x1C | OPC_SPECIAL3,
433 OPC_SHE = 0x1D | OPC_SPECIAL3,
434 OPC_SCE = 0x1E | OPC_SPECIAL3,
435 OPC_SWE = 0x1F | OPC_SPECIAL3,
436 OPC_SWLE = 0x21 | OPC_SPECIAL3,
437 OPC_SWRE = 0x22 | OPC_SPECIAL3,
438 OPC_PREFE = 0x23 | OPC_SPECIAL3,
439 OPC_LBUE = 0x28 | OPC_SPECIAL3,
440 OPC_LHUE = 0x29 | OPC_SPECIAL3,
441 OPC_LBE = 0x2C | OPC_SPECIAL3,
442 OPC_LHE = 0x2D | OPC_SPECIAL3,
443 OPC_LLE = 0x2E | OPC_SPECIAL3,
444 OPC_LWE = 0x2F | OPC_SPECIAL3,
446 /* R6 */
447 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
448 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
449 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
450 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
451 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
452 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
455 /* Loongson EXT load/store quad word opcodes */
456 #define MASK_LOONGSON_GSLSQ(op) (MASK_OP_MAJOR(op) | (op & 0x8020))
457 enum {
458 OPC_GSLQ = 0x0020 | OPC_LWC2,
459 OPC_GSLQC1 = 0x8020 | OPC_LWC2,
460 OPC_GSSHFL = OPC_LWC2,
461 OPC_GSSQ = 0x0020 | OPC_SWC2,
462 OPC_GSSQC1 = 0x8020 | OPC_SWC2,
463 OPC_GSSHFS = OPC_SWC2,
466 /* Loongson EXT shifted load/store opcodes */
467 #define MASK_LOONGSON_GSSHFLS(op) (MASK_OP_MAJOR(op) | (op & 0xc03f))
468 enum {
469 OPC_GSLWLC1 = 0x4 | OPC_GSSHFL,
470 OPC_GSLWRC1 = 0x5 | OPC_GSSHFL,
471 OPC_GSLDLC1 = 0x6 | OPC_GSSHFL,
472 OPC_GSLDRC1 = 0x7 | OPC_GSSHFL,
473 OPC_GSSWLC1 = 0x4 | OPC_GSSHFS,
474 OPC_GSSWRC1 = 0x5 | OPC_GSSHFS,
475 OPC_GSSDLC1 = 0x6 | OPC_GSSHFS,
476 OPC_GSSDRC1 = 0x7 | OPC_GSSHFS,
479 /* Loongson EXT LDC2/SDC2 opcodes */
480 #define MASK_LOONGSON_LSDC2(op) (MASK_OP_MAJOR(op) | (op & 0x7))
482 enum {
483 OPC_GSLBX = 0x0 | OPC_LDC2,
484 OPC_GSLHX = 0x1 | OPC_LDC2,
485 OPC_GSLWX = 0x2 | OPC_LDC2,
486 OPC_GSLDX = 0x3 | OPC_LDC2,
487 OPC_GSLWXC1 = 0x6 | OPC_LDC2,
488 OPC_GSLDXC1 = 0x7 | OPC_LDC2,
489 OPC_GSSBX = 0x0 | OPC_SDC2,
490 OPC_GSSHX = 0x1 | OPC_SDC2,
491 OPC_GSSWX = 0x2 | OPC_SDC2,
492 OPC_GSSDX = 0x3 | OPC_SDC2,
493 OPC_GSSWXC1 = 0x6 | OPC_SDC2,
494 OPC_GSSDXC1 = 0x7 | OPC_SDC2,
497 /* BSHFL opcodes */
498 #define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
500 enum {
501 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
502 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
503 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
504 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
505 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
506 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
507 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
508 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
511 /* DBSHFL opcodes */
512 #define MASK_DBSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
514 enum {
515 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
516 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
517 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
518 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
519 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
520 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
521 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
522 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
523 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
524 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
525 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
528 /* MIPS DSP REGIMM opcodes */
529 enum {
530 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
531 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
534 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
535 /* MIPS DSP Load */
536 enum {
537 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
538 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
539 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
540 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
543 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
544 enum {
545 /* MIPS DSP Arithmetic Sub-class */
546 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
547 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
548 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
549 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
550 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
551 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
552 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
553 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
554 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
555 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
556 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
557 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
558 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
559 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
560 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
561 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
562 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
563 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
564 /* MIPS DSP Multiply Sub-class insns */
565 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
566 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
567 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
568 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
569 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
570 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
573 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
574 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
575 enum {
576 /* MIPS DSP Arithmetic Sub-class */
577 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
578 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
579 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
580 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
581 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
582 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
583 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
584 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
585 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
586 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
587 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
588 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
589 /* MIPS DSP Multiply Sub-class insns */
590 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
591 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
592 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
593 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
596 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
597 enum {
598 /* MIPS DSP Arithmetic Sub-class */
599 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
600 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
601 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
602 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
603 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
604 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
605 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
606 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
607 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
608 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
609 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
610 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
611 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
612 /* DSP Bit/Manipulation Sub-class */
613 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
614 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
615 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
616 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
617 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
620 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
621 enum {
622 /* MIPS DSP Arithmetic Sub-class */
623 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
624 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
625 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
626 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
627 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
628 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
629 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
630 /* DSP Compare-Pick Sub-class */
631 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
632 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
633 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
634 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
635 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
636 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
637 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
638 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
639 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
640 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
641 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
642 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
643 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
644 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
645 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
648 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
649 enum {
650 /* MIPS DSP GPR-Based Shift Sub-class */
651 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
652 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
653 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
654 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
655 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
656 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
657 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
658 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
659 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
660 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
661 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
662 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
663 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
664 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
665 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
666 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
667 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
668 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
669 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
670 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
671 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
672 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
675 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
676 enum {
677 /* MIPS DSP Multiply Sub-class insns */
678 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
679 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
680 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
681 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
682 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
683 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
684 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
685 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
686 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
687 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
688 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
689 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
690 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
691 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
692 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
693 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
694 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
695 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
696 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
697 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
698 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
699 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
702 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
703 enum {
704 /* DSP Bit/Manipulation Sub-class */
705 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
708 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
709 enum {
710 /* MIPS DSP Append Sub-class */
711 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
712 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
713 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
716 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
717 enum {
718 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
719 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
720 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
721 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
722 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
723 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
724 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
725 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
726 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
727 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
728 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
729 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
730 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
731 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
732 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
733 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
734 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
735 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
738 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
739 enum {
740 /* MIPS DSP Arithmetic Sub-class */
741 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
742 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
743 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
744 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
745 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
746 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
747 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
748 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
749 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
750 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
751 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
752 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
753 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
754 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
755 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
756 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
757 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
758 /* DSP Bit/Manipulation Sub-class */
759 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
760 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
761 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
762 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
763 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
764 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
767 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
768 enum {
769 /* MIPS DSP Multiply Sub-class insns */
770 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
771 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
772 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
773 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
774 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
775 /* MIPS DSP Arithmetic Sub-class */
776 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
777 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
778 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
779 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
780 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
781 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
782 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
783 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
784 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
785 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
786 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
787 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
788 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
789 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
790 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
791 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
792 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
793 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
794 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
795 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
796 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
799 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
800 enum {
801 /* DSP Compare-Pick Sub-class */
802 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
803 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
804 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
805 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
806 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
807 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
808 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
809 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
810 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
811 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
812 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
813 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
814 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
815 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
816 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
817 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
818 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
819 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
820 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
821 /* MIPS DSP Arithmetic Sub-class */
822 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
823 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
824 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
825 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
826 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
827 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
828 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
829 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
832 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
833 enum {
834 /* DSP Append Sub-class */
835 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
836 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
837 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
838 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
841 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
842 enum {
843 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
844 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
845 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
846 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
847 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
848 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
849 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
850 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
851 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
852 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
853 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
854 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
855 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
856 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
857 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
858 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
859 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
860 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
861 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
862 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
863 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
864 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
867 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
868 enum {
869 /* DSP Bit/Manipulation Sub-class */
870 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
873 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
874 enum {
875 /* MIPS DSP Multiply Sub-class insns */
876 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
877 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
878 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
879 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
880 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
881 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
882 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
883 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
884 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
885 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
886 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
887 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
888 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
889 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
890 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
891 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
892 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
893 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
894 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
895 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
896 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
897 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
898 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
899 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
900 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
901 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
904 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
905 enum {
906 /* MIPS DSP GPR-Based Shift Sub-class */
907 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
908 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
909 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
910 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
911 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
912 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
913 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
914 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
915 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
916 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
917 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
918 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
919 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
920 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
921 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
922 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
923 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
924 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
925 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
926 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
927 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
928 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
929 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
930 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
931 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
932 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
935 /* Coprocessor 0 (rs field) */
936 #define MASK_CP0(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
938 enum {
939 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
940 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
941 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
942 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
943 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
944 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
945 OPC_MFTR = (0x08 << 21) | OPC_CP0,
946 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
947 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
948 OPC_MTTR = (0x0C << 21) | OPC_CP0,
949 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
950 OPC_C0 = (0x10 << 21) | OPC_CP0,
951 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
952 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
953 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
954 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
955 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
956 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
957 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
958 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
959 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
960 OPC_C0_A = (0x1A << 21) | OPC_CP0,
961 OPC_C0_B = (0x1B << 21) | OPC_CP0,
962 OPC_C0_C = (0x1C << 21) | OPC_CP0,
963 OPC_C0_D = (0x1D << 21) | OPC_CP0,
964 OPC_C0_E = (0x1E << 21) | OPC_CP0,
965 OPC_C0_F = (0x1F << 21) | OPC_CP0,
968 /* MFMC0 opcodes */
969 #define MASK_MFMC0(op) (MASK_CP0(op) | (op & 0xFFFF))
971 enum {
972 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
973 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
974 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
975 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
976 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
977 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
978 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
979 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
982 /* Coprocessor 0 (with rs == C0) */
983 #define MASK_C0(op) (MASK_CP0(op) | (op & 0x3F))
985 enum {
986 OPC_TLBR = 0x01 | OPC_C0,
987 OPC_TLBWI = 0x02 | OPC_C0,
988 OPC_TLBINV = 0x03 | OPC_C0,
989 OPC_TLBINVF = 0x04 | OPC_C0,
990 OPC_TLBWR = 0x06 | OPC_C0,
991 OPC_TLBP = 0x08 | OPC_C0,
992 OPC_RFE = 0x10 | OPC_C0,
993 OPC_ERET = 0x18 | OPC_C0,
994 OPC_DERET = 0x1F | OPC_C0,
995 OPC_WAIT = 0x20 | OPC_C0,
998 #define MASK_CP2(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
1000 enum {
1001 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1002 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1003 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1004 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1005 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1006 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1007 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1008 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1009 OPC_BC2 = (0x08 << 21) | OPC_CP2,
1010 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1011 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1014 #define MASK_LMMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1016 enum {
1017 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1018 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1019 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1020 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1021 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1022 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1023 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1024 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1026 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1027 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1028 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1029 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1030 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1031 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1032 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1033 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1035 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1036 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1037 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1038 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1039 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1040 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1041 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1042 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1044 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1045 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1046 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1047 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1048 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1049 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1050 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1051 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1053 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1054 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1055 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1056 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1057 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1058 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1060 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1061 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1062 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1063 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1064 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1065 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1067 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1068 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1069 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1070 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1071 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1072 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1074 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1075 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1076 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1077 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1078 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1079 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1081 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1082 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1083 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1084 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1085 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1086 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1088 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1089 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1090 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1091 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1092 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1093 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1095 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1096 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1097 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1098 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1099 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1100 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1102 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1103 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1104 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1105 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1106 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1107 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1111 #define MASK_CP3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1113 enum {
1114 OPC_LWXC1 = 0x00 | OPC_CP3,
1115 OPC_LDXC1 = 0x01 | OPC_CP3,
1116 OPC_LUXC1 = 0x05 | OPC_CP3,
1117 OPC_SWXC1 = 0x08 | OPC_CP3,
1118 OPC_SDXC1 = 0x09 | OPC_CP3,
1119 OPC_SUXC1 = 0x0D | OPC_CP3,
1120 OPC_PREFX = 0x0F | OPC_CP3,
1121 OPC_ALNV_PS = 0x1E | OPC_CP3,
1122 OPC_MADD_S = 0x20 | OPC_CP3,
1123 OPC_MADD_D = 0x21 | OPC_CP3,
1124 OPC_MADD_PS = 0x26 | OPC_CP3,
1125 OPC_MSUB_S = 0x28 | OPC_CP3,
1126 OPC_MSUB_D = 0x29 | OPC_CP3,
1127 OPC_MSUB_PS = 0x2E | OPC_CP3,
1128 OPC_NMADD_S = 0x30 | OPC_CP3,
1129 OPC_NMADD_D = 0x31 | OPC_CP3,
1130 OPC_NMADD_PS = 0x36 | OPC_CP3,
1131 OPC_NMSUB_S = 0x38 | OPC_CP3,
1132 OPC_NMSUB_D = 0x39 | OPC_CP3,
1133 OPC_NMSUB_PS = 0x3E | OPC_CP3,
1136 /* MSA Opcodes */
1137 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1138 enum {
1139 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1140 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1141 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1142 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1143 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1144 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1145 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1146 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1147 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1148 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1149 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1150 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1151 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1152 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1153 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1154 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1155 OPC_MSA_ELM = 0x19 | OPC_MSA,
1156 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1157 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1158 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1159 OPC_MSA_VEC = 0x1E | OPC_MSA,
1161 /* MI10 instruction */
1162 OPC_LD_B = (0x20) | OPC_MSA,
1163 OPC_LD_H = (0x21) | OPC_MSA,
1164 OPC_LD_W = (0x22) | OPC_MSA,
1165 OPC_LD_D = (0x23) | OPC_MSA,
1166 OPC_ST_B = (0x24) | OPC_MSA,
1167 OPC_ST_H = (0x25) | OPC_MSA,
1168 OPC_ST_W = (0x26) | OPC_MSA,
1169 OPC_ST_D = (0x27) | OPC_MSA,
1172 enum {
1173 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1174 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1175 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1176 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1177 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1178 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1179 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1180 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1181 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1182 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1183 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1184 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1185 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1187 /* I8 instruction */
1188 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1189 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1190 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1191 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1192 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1193 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1194 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1195 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1196 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1197 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1199 /* VEC/2R/2RF instruction */
1200 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1201 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1202 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1203 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1204 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1205 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1206 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1208 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1209 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1211 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1212 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1213 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1214 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1215 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1217 /* 2RF instruction df(bit 16) = _w, _d */
1218 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1219 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1220 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1221 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1222 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1223 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1224 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1225 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1226 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1227 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1228 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1229 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1230 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1231 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1232 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1233 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1235 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1236 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1237 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1238 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1239 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1240 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1241 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1242 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1243 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1244 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1245 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1246 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1247 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1248 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1249 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1250 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1251 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1252 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1253 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1254 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1255 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1256 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1257 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1258 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1259 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1260 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1261 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1262 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1263 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1264 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1265 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1266 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1267 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1268 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1269 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1270 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1271 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1272 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1273 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1274 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1275 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1276 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1277 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1278 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1279 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1280 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1281 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1282 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1283 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1284 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1285 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1286 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1287 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1288 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1289 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1290 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1291 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1292 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1293 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1294 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1295 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1296 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1297 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1298 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1300 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1301 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1302 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1303 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1304 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1305 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1306 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1307 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1308 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1309 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1311 /* 3RF instruction _df(bit 21) = _w, _d */
1312 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1313 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1314 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1315 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1316 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1317 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1318 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1319 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1320 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1321 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1322 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1323 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1324 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1325 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1326 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1327 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1328 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1329 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1330 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1331 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1332 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1333 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1334 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1335 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1336 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1337 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1338 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1339 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1340 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1341 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1342 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1343 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1344 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1345 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1346 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1347 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1348 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1349 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1350 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1351 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1352 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1354 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1355 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1356 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1357 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1358 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1359 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1360 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1361 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1362 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1363 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1364 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1365 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1366 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1372 * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
1373 * ============================================
1376 * MXU (full name: MIPS eXtension/enhanced Unit) is a SIMD extension of MIPS32
1377 * instructions set. It is designed to fit the needs of signal, graphical and
1378 * video processing applications. MXU instruction set is used in Xburst family
1379 * of microprocessors by Ingenic.
1381 * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
1382 * the control register.
1385 * The notation used in MXU assembler mnemonics
1386 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1388 * Register operands:
1390 * XRa, XRb, XRc, XRd - MXU registers
1391 * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
1393 * Non-register operands:
1395 * aptn1 - 1-bit accumulate add/subtract pattern
1396 * aptn2 - 2-bit accumulate add/subtract pattern
1397 * eptn2 - 2-bit execute add/subtract pattern
1398 * optn2 - 2-bit operand pattern
1399 * optn3 - 3-bit operand pattern
1400 * sft4 - 4-bit shift amount
1401 * strd2 - 2-bit stride amount
1403 * Prefixes:
1405 * Level of parallelism: Operand size:
1406 * S - single operation at a time 32 - word
1407 * D - two operations in parallel 16 - half word
1408 * Q - four operations in parallel 8 - byte
1410 * Operations:
1412 * ADD - Add or subtract
1413 * ADDC - Add with carry-in
1414 * ACC - Accumulate
1415 * ASUM - Sum together then accumulate (add or subtract)
1416 * ASUMC - Sum together then accumulate (add or subtract) with carry-in
1417 * AVG - Average between 2 operands
1418 * ABD - Absolute difference
1419 * ALN - Align data
1420 * AND - Logical bitwise 'and' operation
1421 * CPS - Copy sign
1422 * EXTR - Extract bits
1423 * I2M - Move from GPR register to MXU register
1424 * LDD - Load data from memory to XRF
1425 * LDI - Load data from memory to XRF (and increase the address base)
1426 * LUI - Load unsigned immediate
1427 * MUL - Multiply
1428 * MULU - Unsigned multiply
1429 * MADD - 64-bit operand add 32x32 product
1430 * MSUB - 64-bit operand subtract 32x32 product
1431 * MAC - Multiply and accumulate (add or subtract)
1432 * MAD - Multiply and add or subtract
1433 * MAX - Maximum between 2 operands
1434 * MIN - Minimum between 2 operands
1435 * M2I - Move from MXU register to GPR register
1436 * MOVZ - Move if zero
1437 * MOVN - Move if non-zero
1438 * NOR - Logical bitwise 'nor' operation
1439 * OR - Logical bitwise 'or' operation
1440 * STD - Store data from XRF to memory
1441 * SDI - Store data from XRF to memory (and increase the address base)
1442 * SLT - Set of less than comparison
1443 * SAD - Sum of absolute differences
1444 * SLL - Logical shift left
1445 * SLR - Logical shift right
1446 * SAR - Arithmetic shift right
1447 * SAT - Saturation
1448 * SFL - Shuffle
1449 * SCOP - Calculate x’s scope (-1, means x<0; 0, means x==0; 1, means x>0)
1450 * XOR - Logical bitwise 'exclusive or' operation
1452 * Suffixes:
1454 * E - Expand results
1455 * F - Fixed point multiplication
1456 * L - Low part result
1457 * R - Doing rounding
1458 * V - Variable instead of immediate
1459 * W - Combine above L and V
1462 * The list of MXU instructions grouped by functionality
1463 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1465 * Load/Store instructions Multiplication instructions
1466 * ----------------------- ---------------------------
1468 * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
1469 * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
1470 * S32LDDV XRa, Rb, rc, strd2 S32MSUB XRa, XRd, Rs, Rt
1471 * S32STDV XRa, Rb, rc, strd2 S32MSUBU XRa, XRd, Rs, Rt
1472 * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
1473 * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
1474 * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
1475 * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
1476 * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
1477 * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
1478 * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
1479 * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
1480 * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
1481 * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
1482 * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
1483 * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
1484 * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
1485 * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
1486 * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
1487 * S16SDI XRa, Rb, s10, eptn2
1488 * S8LDD XRa, Rb, s8, eptn3
1489 * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
1490 * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
1491 * S8SDI XRa, Rb, s8, eptn3
1492 * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
1493 * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
1494 * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
1495 * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
1496 * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
1497 * S32CPS XRa, XRb, XRc
1498 * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
1499 * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
1500 * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
1501 * D16ASUM XRa, XRb, XRc, XRd, eptn2
1502 * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
1503 * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
1504 * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
1505 * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
1506 * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
1507 * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
1508 * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
1509 * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
1510 * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
1511 * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
1512 * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
1513 * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
1514 * Q8SLT XRa, XRb, XRc
1515 * Q8SLTU XRa, XRb, XRc
1516 * Q8MOVZ XRa, XRb, XRc Shift instructions
1517 * Q8MOVN XRa, XRb, XRc ------------------
1519 * D32SLL XRa, XRb, XRc, XRd, sft4
1520 * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
1521 * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
1522 * D32SARL XRa, XRb, XRc, sft4
1523 * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
1524 * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
1525 * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
1526 * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
1527 * Q16SLL XRa, XRb, XRc, XRd, sft4
1528 * Q16SLR XRa, XRb, XRc, XRd, sft4
1529 * Miscellaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
1530 * ------------------------- Q16SLLV XRa, XRb, Rb
1531 * Q16SLRV XRa, XRb, Rb
1532 * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
1533 * S32ALN XRa, XRb, XRc, Rb
1534 * S32ALNI XRa, XRb, XRc, s3
1535 * S32LUI XRa, s8, optn3 Move instructions
1536 * S32EXTR XRa, XRb, Rb, bits5 -----------------
1537 * S32EXTRV XRa, XRb, Rs, Rt
1538 * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
1539 * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
1542 * The opcode organization of MXU instructions
1543 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1545 * The bits 31..26 of all MXU instructions are equal to 0x1C (also referred
1546 * as opcode SPECIAL2 in the base MIPS ISA). The organization and meaning of
1547 * other bits up to the instruction level is as follows:
1549 * bits
1550 * 05..00
1552 * ┌─ 000000 ─ OPC_MXU_S32MADD
1553 * ├─ 000001 ─ OPC_MXU_S32MADDU
1554 * ├─ 000010 ─ <not assigned> (non-MXU OPC_MUL)
1555 * │
1556 * │ 20..18
1557 * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
1558 * │ ├─ 001 ─ OPC_MXU_S32MIN
1559 * │ ├─ 010 ─ OPC_MXU_D16MAX
1560 * │ ├─ 011 ─ OPC_MXU_D16MIN
1561 * │ ├─ 100 ─ OPC_MXU_Q8MAX
1562 * │ ├─ 101 ─ OPC_MXU_Q8MIN
1563 * │ ├─ 110 ─ OPC_MXU_Q8SLT
1564 * │ └─ 111 ─ OPC_MXU_Q8SLTU
1565 * ├─ 000100 ─ OPC_MXU_S32MSUB
1566 * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
1567 * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
1568 * │ ├─ 001 ─ OPC_MXU_D16SLT
1569 * │ ├─ 010 ─ OPC_MXU_D16AVG
1570 * │ ├─ 011 ─ OPC_MXU_D16AVGR
1571 * │ ├─ 100 ─ OPC_MXU_Q8AVG
1572 * │ ├─ 101 ─ OPC_MXU_Q8AVGR
1573 * │ └─ 111 ─ OPC_MXU_Q8ADD
1574 * │
1575 * │ 20..18
1576 * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
1577 * │ ├─ 010 ─ OPC_MXU_D16CPS
1578 * │ ├─ 100 ─ OPC_MXU_Q8ABD
1579 * │ └─ 110 ─ OPC_MXU_Q16SAT
1580 * ├─ 001000 ─ OPC_MXU_D16MUL
1581 * │ 25..24
1582 * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
1583 * │ └─ 01 ─ OPC_MXU_D16MULE
1584 * ├─ 001010 ─ OPC_MXU_D16MAC
1585 * ├─ 001011 ─ OPC_MXU_D16MACF
1586 * ├─ 001100 ─ OPC_MXU_D16MADL
1587 * ├─ 001101 ─ OPC_MXU_S16MAD
1588 * ├─ 001110 ─ OPC_MXU_Q16ADD
1589 * ├─ 001111 ─ OPC_MXU_D16MACE 23
1590 * │ ┌─ 0 ─ OPC_MXU_S32LDD
1591 * ├─ 010000 ─ OPC_MXU__POOL04 ─┴─ 1 ─ OPC_MXU_S32LDDR
1592 * │
1593 * │ 23
1594 * ├─ 010001 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32STD
1595 * │ └─ 1 ─ OPC_MXU_S32STDR
1596 * │
1597 * │ 13..10
1598 * ├─ 010010 ─ OPC_MXU__POOL06 ─┬─ 0000 ─ OPC_MXU_S32LDDV
1599 * │ └─ 0001 ─ OPC_MXU_S32LDDVR
1600 * │
1601 * │ 13..10
1602 * ├─ 010011 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32STDV
1603 * │ └─ 0001 ─ OPC_MXU_S32STDVR
1604 * │
1605 * │ 23
1606 * ├─ 010100 ─ OPC_MXU__POOL08 ─┬─ 0 ─ OPC_MXU_S32LDI
1607 * │ └─ 1 ─ OPC_MXU_S32LDIR
1608 * │
1609 * │ 23
1610 * ├─ 010101 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32SDI
1611 * │ └─ 1 ─ OPC_MXU_S32SDIR
1612 * │
1613 * │ 13..10
1614 * ├─ 010110 ─ OPC_MXU__POOL10 ─┬─ 0000 ─ OPC_MXU_S32LDIV
1615 * │ └─ 0001 ─ OPC_MXU_S32LDIVR
1616 * │
1617 * │ 13..10
1618 * ├─ 010111 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32SDIV
1619 * │ └─ 0001 ─ OPC_MXU_S32SDIVR
1620 * ├─ 011000 ─ OPC_MXU_D32ADD
1621 * │ 23..22
1622 * MXU ├─ 011001 ─ OPC_MXU__POOL12 ─┬─ 00 ─ OPC_MXU_D32ACC
1623 * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
1624 * │ └─ 10 ─ OPC_MXU_D32ASUM
1625 * ├─ 011010 ─ <not assigned>
1626 * │ 23..22
1627 * ├─ 011011 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_Q16ACC
1628 * │ ├─ 01 ─ OPC_MXU_Q16ACCM
1629 * │ └─ 10 ─ OPC_MXU_Q16ASUM
1630 * │
1631 * │ 23..22
1632 * ├─ 011100 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q8ADDE
1633 * │ ├─ 01 ─ OPC_MXU_D8SUM
1634 * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
1635 * ├─ 011110 ─ <not assigned>
1636 * ├─ 011111 ─ <not assigned>
1637 * ├─ 100000 ─ <not assigned> (overlaps with CLZ)
1638 * ├─ 100001 ─ <not assigned> (overlaps with CLO)
1639 * ├─ 100010 ─ OPC_MXU_S8LDD
1640 * ├─ 100011 ─ OPC_MXU_S8STD 15..14
1641 * ├─ 100100 ─ OPC_MXU_S8LDI ┌─ 00 ─ OPC_MXU_S32MUL
1642 * ├─ 100101 ─ OPC_MXU_S8SDI ├─ 00 ─ OPC_MXU_S32MULU
1643 * │ ├─ 00 ─ OPC_MXU_S32EXTR
1644 * ├─ 100110 ─ OPC_MXU__POOL15 ─┴─ 00 ─ OPC_MXU_S32EXTRV
1645 * │
1646 * │ 20..18
1647 * ├─ 100111 ─ OPC_MXU__POOL16 ─┬─ 000 ─ OPC_MXU_D32SARW
1648 * │ ├─ 001 ─ OPC_MXU_S32ALN
1649 * │ ├─ 010 ─ OPC_MXU_S32ALNI
1650 * │ ├─ 011 ─ OPC_MXU_S32LUI
1651 * │ ├─ 100 ─ OPC_MXU_S32NOR
1652 * │ ├─ 101 ─ OPC_MXU_S32AND
1653 * │ ├─ 110 ─ OPC_MXU_S32OR
1654 * │ └─ 111 ─ OPC_MXU_S32XOR
1655 * │
1656 * │ 7..5
1657 * ├─ 101000 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_LXB
1658 * │ ├─ 001 ─ OPC_MXU_LXH
1659 * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_LXW
1660 * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_LXBU
1661 * ├─ 101011 ─ OPC_MXU_S16STD └─ 101 ─ OPC_MXU_LXHU
1662 * ├─ 101100 ─ OPC_MXU_S16LDI
1663 * ├─ 101101 ─ OPC_MXU_S16SDI
1664 * ├─ 101110 ─ OPC_MXU_S32M2I
1665 * ├─ 101111 ─ OPC_MXU_S32I2M
1666 * ├─ 110000 ─ OPC_MXU_D32SLL
1667 * ├─ 110001 ─ OPC_MXU_D32SLR 20..18
1668 * ├─ 110010 ─ OPC_MXU_D32SARL ┌─ 000 ─ OPC_MXU_D32SLLV
1669 * ├─ 110011 ─ OPC_MXU_D32SAR ├─ 001 ─ OPC_MXU_D32SLRV
1670 * ├─ 110100 ─ OPC_MXU_Q16SLL ├─ 010 ─ OPC_MXU_D32SARV
1671 * ├─ 110101 ─ OPC_MXU_Q16SLR ├─ 011 ─ OPC_MXU_Q16SLLV
1672 * │ ├─ 100 ─ OPC_MXU_Q16SLRV
1673 * ├─ 110110 ─ OPC_MXU__POOL18 ─┴─ 101 ─ OPC_MXU_Q16SARV
1674 * │
1675 * ├─ 110111 ─ OPC_MXU_Q16SAR
1676 * │ 23..22
1677 * ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL
1678 * │ └─ 01 ─ OPC_MXU_Q8MULSU
1679 * │
1680 * │ 20..18
1681 * ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
1682 * │ ├─ 001 ─ OPC_MXU_Q8MOVN
1683 * │ ├─ 010 ─ OPC_MXU_D16MOVZ
1684 * │ ├─ 011 ─ OPC_MXU_D16MOVN
1685 * │ ├─ 100 ─ OPC_MXU_S32MOVZ
1686 * │ └─ 101 ─ OPC_MXU_S32MOVN
1687 * │
1688 * │ 23..22
1689 * ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC
1690 * │ └─ 10 ─ OPC_MXU_Q8MACSU
1691 * ├─ 111011 ─ OPC_MXU_Q16SCOP
1692 * ├─ 111100 ─ OPC_MXU_Q8MADL
1693 * ├─ 111101 ─ OPC_MXU_S32SFL
1694 * ├─ 111110 ─ OPC_MXU_Q8SAD
1695 * └─ 111111 ─ <not assigned> (overlaps with SDBBP)
1698 * Compiled after:
1700 * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
1701 * Programming Manual", Ingenic Semiconductor Co, Ltd., revision June 2, 2017
1704 enum {
1705 OPC_MXU_S32MADD = 0x00,
1706 OPC_MXU_S32MADDU = 0x01,
1707 OPC__MXU_MUL = 0x02,
1708 OPC_MXU__POOL00 = 0x03,
1709 OPC_MXU_S32MSUB = 0x04,
1710 OPC_MXU_S32MSUBU = 0x05,
1711 OPC_MXU__POOL01 = 0x06,
1712 OPC_MXU__POOL02 = 0x07,
1713 OPC_MXU_D16MUL = 0x08,
1714 OPC_MXU__POOL03 = 0x09,
1715 OPC_MXU_D16MAC = 0x0A,
1716 OPC_MXU_D16MACF = 0x0B,
1717 OPC_MXU_D16MADL = 0x0C,
1718 OPC_MXU_S16MAD = 0x0D,
1719 OPC_MXU_Q16ADD = 0x0E,
1720 OPC_MXU_D16MACE = 0x0F,
1721 OPC_MXU__POOL04 = 0x10,
1722 OPC_MXU__POOL05 = 0x11,
1723 OPC_MXU__POOL06 = 0x12,
1724 OPC_MXU__POOL07 = 0x13,
1725 OPC_MXU__POOL08 = 0x14,
1726 OPC_MXU__POOL09 = 0x15,
1727 OPC_MXU__POOL10 = 0x16,
1728 OPC_MXU__POOL11 = 0x17,
1729 OPC_MXU_D32ADD = 0x18,
1730 OPC_MXU__POOL12 = 0x19,
1731 /* not assigned 0x1A */
1732 OPC_MXU__POOL13 = 0x1B,
1733 OPC_MXU__POOL14 = 0x1C,
1734 OPC_MXU_Q8ACCE = 0x1D,
1735 /* not assigned 0x1E */
1736 /* not assigned 0x1F */
1737 /* not assigned 0x20 */
1738 /* not assigned 0x21 */
1739 OPC_MXU_S8LDD = 0x22,
1740 OPC_MXU_S8STD = 0x23,
1741 OPC_MXU_S8LDI = 0x24,
1742 OPC_MXU_S8SDI = 0x25,
1743 OPC_MXU__POOL15 = 0x26,
1744 OPC_MXU__POOL16 = 0x27,
1745 OPC_MXU__POOL17 = 0x28,
1746 /* not assigned 0x29 */
1747 OPC_MXU_S16LDD = 0x2A,
1748 OPC_MXU_S16STD = 0x2B,
1749 OPC_MXU_S16LDI = 0x2C,
1750 OPC_MXU_S16SDI = 0x2D,
1751 OPC_MXU_S32M2I = 0x2E,
1752 OPC_MXU_S32I2M = 0x2F,
1753 OPC_MXU_D32SLL = 0x30,
1754 OPC_MXU_D32SLR = 0x31,
1755 OPC_MXU_D32SARL = 0x32,
1756 OPC_MXU_D32SAR = 0x33,
1757 OPC_MXU_Q16SLL = 0x34,
1758 OPC_MXU_Q16SLR = 0x35,
1759 OPC_MXU__POOL18 = 0x36,
1760 OPC_MXU_Q16SAR = 0x37,
1761 OPC_MXU__POOL19 = 0x38,
1762 OPC_MXU__POOL20 = 0x39,
1763 OPC_MXU__POOL21 = 0x3A,
1764 OPC_MXU_Q16SCOP = 0x3B,
1765 OPC_MXU_Q8MADL = 0x3C,
1766 OPC_MXU_S32SFL = 0x3D,
1767 OPC_MXU_Q8SAD = 0x3E,
1768 /* not assigned 0x3F */
1773 * MXU pool 00
1775 enum {
1776 OPC_MXU_S32MAX = 0x00,
1777 OPC_MXU_S32MIN = 0x01,
1778 OPC_MXU_D16MAX = 0x02,
1779 OPC_MXU_D16MIN = 0x03,
1780 OPC_MXU_Q8MAX = 0x04,
1781 OPC_MXU_Q8MIN = 0x05,
1782 OPC_MXU_Q8SLT = 0x06,
1783 OPC_MXU_Q8SLTU = 0x07,
1787 * MXU pool 01
1789 enum {
1790 OPC_MXU_S32SLT = 0x00,
1791 OPC_MXU_D16SLT = 0x01,
1792 OPC_MXU_D16AVG = 0x02,
1793 OPC_MXU_D16AVGR = 0x03,
1794 OPC_MXU_Q8AVG = 0x04,
1795 OPC_MXU_Q8AVGR = 0x05,
1796 OPC_MXU_Q8ADD = 0x07,
1800 * MXU pool 02
1802 enum {
1803 OPC_MXU_S32CPS = 0x00,
1804 OPC_MXU_D16CPS = 0x02,
1805 OPC_MXU_Q8ABD = 0x04,
1806 OPC_MXU_Q16SAT = 0x06,
1810 * MXU pool 03
1812 enum {
1813 OPC_MXU_D16MULF = 0x00,
1814 OPC_MXU_D16MULE = 0x01,
1818 * MXU pool 04
1820 enum {
1821 OPC_MXU_S32LDD = 0x00,
1822 OPC_MXU_S32LDDR = 0x01,
1826 * MXU pool 05
1828 enum {
1829 OPC_MXU_S32STD = 0x00,
1830 OPC_MXU_S32STDR = 0x01,
1834 * MXU pool 06
1836 enum {
1837 OPC_MXU_S32LDDV = 0x00,
1838 OPC_MXU_S32LDDVR = 0x01,
1842 * MXU pool 07
1844 enum {
1845 OPC_MXU_S32STDV = 0x00,
1846 OPC_MXU_S32STDVR = 0x01,
1850 * MXU pool 08
1852 enum {
1853 OPC_MXU_S32LDI = 0x00,
1854 OPC_MXU_S32LDIR = 0x01,
1858 * MXU pool 09
1860 enum {
1861 OPC_MXU_S32SDI = 0x00,
1862 OPC_MXU_S32SDIR = 0x01,
1866 * MXU pool 10
1868 enum {
1869 OPC_MXU_S32LDIV = 0x00,
1870 OPC_MXU_S32LDIVR = 0x01,
1874 * MXU pool 11
1876 enum {
1877 OPC_MXU_S32SDIV = 0x00,
1878 OPC_MXU_S32SDIVR = 0x01,
1882 * MXU pool 12
1884 enum {
1885 OPC_MXU_D32ACC = 0x00,
1886 OPC_MXU_D32ACCM = 0x01,
1887 OPC_MXU_D32ASUM = 0x02,
1891 * MXU pool 13
1893 enum {
1894 OPC_MXU_Q16ACC = 0x00,
1895 OPC_MXU_Q16ACCM = 0x01,
1896 OPC_MXU_Q16ASUM = 0x02,
1900 * MXU pool 14
1902 enum {
1903 OPC_MXU_Q8ADDE = 0x00,
1904 OPC_MXU_D8SUM = 0x01,
1905 OPC_MXU_D8SUMC = 0x02,
1909 * MXU pool 15
1911 enum {
1912 OPC_MXU_S32MUL = 0x00,
1913 OPC_MXU_S32MULU = 0x01,
1914 OPC_MXU_S32EXTR = 0x02,
1915 OPC_MXU_S32EXTRV = 0x03,
1919 * MXU pool 16
1921 enum {
1922 OPC_MXU_D32SARW = 0x00,
1923 OPC_MXU_S32ALN = 0x01,
1924 OPC_MXU_S32ALNI = 0x02,
1925 OPC_MXU_S32LUI = 0x03,
1926 OPC_MXU_S32NOR = 0x04,
1927 OPC_MXU_S32AND = 0x05,
1928 OPC_MXU_S32OR = 0x06,
1929 OPC_MXU_S32XOR = 0x07,
1933 * MXU pool 17
1935 enum {
1936 OPC_MXU_LXB = 0x00,
1937 OPC_MXU_LXH = 0x01,
1938 OPC_MXU_LXW = 0x03,
1939 OPC_MXU_LXBU = 0x04,
1940 OPC_MXU_LXHU = 0x05,
1944 * MXU pool 18
1946 enum {
1947 OPC_MXU_D32SLLV = 0x00,
1948 OPC_MXU_D32SLRV = 0x01,
1949 OPC_MXU_D32SARV = 0x03,
1950 OPC_MXU_Q16SLLV = 0x04,
1951 OPC_MXU_Q16SLRV = 0x05,
1952 OPC_MXU_Q16SARV = 0x07,
1956 * MXU pool 19
1958 enum {
1959 OPC_MXU_Q8MUL = 0x00,
1960 OPC_MXU_Q8MULSU = 0x01,
1964 * MXU pool 20
1966 enum {
1967 OPC_MXU_Q8MOVZ = 0x00,
1968 OPC_MXU_Q8MOVN = 0x01,
1969 OPC_MXU_D16MOVZ = 0x02,
1970 OPC_MXU_D16MOVN = 0x03,
1971 OPC_MXU_S32MOVZ = 0x04,
1972 OPC_MXU_S32MOVN = 0x05,
1976 * MXU pool 21
1978 enum {
1979 OPC_MXU_Q8MAC = 0x00,
1980 OPC_MXU_Q8MACSU = 0x01,
1984 * Overview of the TX79-specific instruction set
1985 * =============================================
1987 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
1988 * are only used by the specific quadword (128-bit) LQ/SQ load/store
1989 * instructions and certain multimedia instructions (MMIs). These MMIs
1990 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
1991 * or sixteen 8-bit paths.
1993 * Reference:
1995 * The Toshiba TX System RISC TX79 Core Architecture manual,
1996 * https://wiki.qemu.org/File:C790.pdf
1998 * Three-Operand Multiply and Multiply-Add (4 instructions)
1999 * --------------------------------------------------------
2000 * MADD [rd,] rs, rt Multiply/Add
2001 * MADDU [rd,] rs, rt Multiply/Add Unsigned
2002 * MULT [rd,] rs, rt Multiply (3-operand)
2003 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
2005 * Multiply Instructions for Pipeline 1 (10 instructions)
2006 * ------------------------------------------------------
2007 * MULT1 [rd,] rs, rt Multiply Pipeline 1
2008 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
2009 * DIV1 rs, rt Divide Pipeline 1
2010 * DIVU1 rs, rt Divide Unsigned Pipeline 1
2011 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
2012 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
2013 * MFHI1 rd Move From HI1 Register
2014 * MFLO1 rd Move From LO1 Register
2015 * MTHI1 rs Move To HI1 Register
2016 * MTLO1 rs Move To LO1 Register
2018 * Arithmetic (19 instructions)
2019 * ----------------------------
2020 * PADDB rd, rs, rt Parallel Add Byte
2021 * PSUBB rd, rs, rt Parallel Subtract Byte
2022 * PADDH rd, rs, rt Parallel Add Halfword
2023 * PSUBH rd, rs, rt Parallel Subtract Halfword
2024 * PADDW rd, rs, rt Parallel Add Word
2025 * PSUBW rd, rs, rt Parallel Subtract Word
2026 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
2027 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
2028 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
2029 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
2030 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
2031 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
2032 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
2033 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
2034 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
2035 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
2036 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
2037 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
2038 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
2040 * Min/Max (4 instructions)
2041 * ------------------------
2042 * PMAXH rd, rs, rt Parallel Maximum Halfword
2043 * PMINH rd, rs, rt Parallel Minimum Halfword
2044 * PMAXW rd, rs, rt Parallel Maximum Word
2045 * PMINW rd, rs, rt Parallel Minimum Word
2047 * Absolute (2 instructions)
2048 * -------------------------
2049 * PABSH rd, rt Parallel Absolute Halfword
2050 * PABSW rd, rt Parallel Absolute Word
2052 * Logical (4 instructions)
2053 * ------------------------
2054 * PAND rd, rs, rt Parallel AND
2055 * POR rd, rs, rt Parallel OR
2056 * PXOR rd, rs, rt Parallel XOR
2057 * PNOR rd, rs, rt Parallel NOR
2059 * Shift (9 instructions)
2060 * ----------------------
2061 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
2062 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
2063 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
2064 * PSLLW rd, rt, sa Parallel Shift Left Logical Word
2065 * PSRLW rd, rt, sa Parallel Shift Right Logical Word
2066 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
2067 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
2068 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
2069 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
2071 * Compare (6 instructions)
2072 * ------------------------
2073 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
2074 * PCEQB rd, rs, rt Parallel Compare for Equal Byte
2075 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
2076 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
2077 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
2078 * PCEQW rd, rs, rt Parallel Compare for Equal Word
2080 * LZC (1 instruction)
2081 * -------------------
2082 * PLZCW rd, rs Parallel Leading Zero or One Count Word
2084 * Quadword Load and Store (2 instructions)
2085 * ----------------------------------------
2086 * LQ rt, offset(base) Load Quadword
2087 * SQ rt, offset(base) Store Quadword
2089 * Multiply and Divide (19 instructions)
2090 * -------------------------------------
2091 * PMULTW rd, rs, rt Parallel Multiply Word
2092 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
2093 * PDIVW rs, rt Parallel Divide Word
2094 * PDIVUW rs, rt Parallel Divide Unsigned Word
2095 * PMADDW rd, rs, rt Parallel Multiply-Add Word
2096 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
2097 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
2098 * PMULTH rd, rs, rt Parallel Multiply Halfword
2099 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
2100 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
2101 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
2102 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
2103 * PDIVBW rs, rt Parallel Divide Broadcast Word
2104 * PMFHI rd Parallel Move From HI Register
2105 * PMFLO rd Parallel Move From LO Register
2106 * PMTHI rs Parallel Move To HI Register
2107 * PMTLO rs Parallel Move To LO Register
2108 * PMFHL rd Parallel Move From HI/LO Register
2109 * PMTHL rs Parallel Move To HI/LO Register
2111 * Pack/Extend (11 instructions)
2112 * -----------------------------
2113 * PPAC5 rd, rt Parallel Pack to 5 bits
2114 * PPACB rd, rs, rt Parallel Pack to Byte
2115 * PPACH rd, rs, rt Parallel Pack to Halfword
2116 * PPACW rd, rs, rt Parallel Pack to Word
2117 * PEXT5 rd, rt Parallel Extend Upper from 5 bits
2118 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
2119 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
2120 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
2121 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
2122 * PEXTUW rd, rs, rt Parallel Extend Upper from Word
2123 * PEXTLW rd, rs, rt Parallel Extend Lower from Word
2125 * Others (16 instructions)
2126 * ------------------------
2127 * PCPYH rd, rt Parallel Copy Halfword
2128 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
2129 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
2130 * PREVH rd, rt Parallel Reverse Halfword
2131 * PINTH rd, rs, rt Parallel Interleave Halfword
2132 * PINTEH rd, rs, rt Parallel Interleave Even Halfword
2133 * PEXEH rd, rt Parallel Exchange Even Halfword
2134 * PEXCH rd, rt Parallel Exchange Center Halfword
2135 * PEXEW rd, rt Parallel Exchange Even Word
2136 * PEXCW rd, rt Parallel Exchange Center Word
2137 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
2138 * MFSA rd Move from Shift Amount Register
2139 * MTSA rs Move to Shift Amount Register
2140 * MTSAB rs, immediate Move Byte Count to Shift Amount Register
2141 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
2142 * PROT3W rd, rt Parallel Rotate 3 Words
2144 * MMI (MultiMedia Instruction) encodings
2145 * ======================================
2147 * MMI instructions encoding table keys:
2149 * * This code is reserved for future use. An attempt to execute it
2150 * causes a Reserved Instruction exception.
2151 * % This code indicates an instruction class. The instruction word
2152 * must be further decoded by examining additional tables that show
2153 * the values for other instruction fields.
2154 * # This code is reserved for the unsupported instructions DMULT,
2155 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
2156 * to execute it causes a Reserved Instruction exception.
2158 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
2160 * 31 26 0
2161 * +--------+----------------------------------------+
2162 * | opcode | |
2163 * +--------+----------------------------------------+
2165 * opcode bits 28..26
2166 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2167 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2168 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2169 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
2170 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
2171 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
2172 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
2173 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
2174 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
2175 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
2176 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
2179 enum {
2180 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
2181 MMI_OPC_LQ = 0x1E << 26, /* Same as OPC_MSA */
2182 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
2186 * MMI instructions with opcode field = MMI:
2188 * 31 26 5 0
2189 * +--------+-------------------------------+--------+
2190 * | MMI | |function|
2191 * +--------+-------------------------------+--------+
2193 * function bits 2..0
2194 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2195 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2196 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2197 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
2198 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
2199 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
2200 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
2201 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
2202 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
2203 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
2204 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
2207 #define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
2208 enum {
2209 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
2210 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
2211 MMI_OPC_PLZCW = 0x04 | MMI_OPC_CLASS_MMI,
2212 MMI_OPC_CLASS_MMI0 = 0x08 | MMI_OPC_CLASS_MMI,
2213 MMI_OPC_CLASS_MMI2 = 0x09 | MMI_OPC_CLASS_MMI,
2214 MMI_OPC_MFHI1 = 0x10 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFHI */
2215 MMI_OPC_MTHI1 = 0x11 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTHI */
2216 MMI_OPC_MFLO1 = 0x12 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFLO */
2217 MMI_OPC_MTLO1 = 0x13 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTLO */
2218 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
2219 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
2220 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
2221 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
2222 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
2223 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
2224 MMI_OPC_CLASS_MMI1 = 0x28 | MMI_OPC_CLASS_MMI,
2225 MMI_OPC_CLASS_MMI3 = 0x29 | MMI_OPC_CLASS_MMI,
2226 MMI_OPC_PMFHL = 0x30 | MMI_OPC_CLASS_MMI,
2227 MMI_OPC_PMTHL = 0x31 | MMI_OPC_CLASS_MMI,
2228 MMI_OPC_PSLLH = 0x34 | MMI_OPC_CLASS_MMI,
2229 MMI_OPC_PSRLH = 0x36 | MMI_OPC_CLASS_MMI,
2230 MMI_OPC_PSRAH = 0x37 | MMI_OPC_CLASS_MMI,
2231 MMI_OPC_PSLLW = 0x3C | MMI_OPC_CLASS_MMI,
2232 MMI_OPC_PSRLW = 0x3E | MMI_OPC_CLASS_MMI,
2233 MMI_OPC_PSRAW = 0x3F | MMI_OPC_CLASS_MMI,
2237 * MMI instructions with opcode field = MMI and bits 5..0 = MMI0:
2239 * 31 26 10 6 5 0
2240 * +--------+----------------------+--------+--------+
2241 * | MMI | |function| MMI0 |
2242 * +--------+----------------------+--------+--------+
2244 * function bits 7..6
2245 * bits | 0 | 1 | 2 | 3
2246 * 10..8 | 00 | 01 | 10 | 11
2247 * -------+-------+-------+-------+-------
2248 * 0 000 | PADDW | PSUBW | PCGTW | PMAXW
2249 * 1 001 | PADDH | PSUBH | PCGTH | PMAXH
2250 * 2 010 | PADDB | PSUBB | PCGTB | *
2251 * 3 011 | * | * | * | *
2252 * 4 100 | PADDSW| PSUBSW| PEXTLW| PPACW
2253 * 5 101 | PADDSH| PSUBSH| PEXTLH| PPACH
2254 * 6 110 | PADDSB| PSUBSB| PEXTLB| PPACB
2255 * 7 111 | * | * | PEXT5 | PPAC5
2258 #define MASK_MMI0(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2259 enum {
2260 MMI_OPC_0_PADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI0,
2261 MMI_OPC_0_PSUBW = (0x01 << 6) | MMI_OPC_CLASS_MMI0,
2262 MMI_OPC_0_PCGTW = (0x02 << 6) | MMI_OPC_CLASS_MMI0,
2263 MMI_OPC_0_PMAXW = (0x03 << 6) | MMI_OPC_CLASS_MMI0,
2264 MMI_OPC_0_PADDH = (0x04 << 6) | MMI_OPC_CLASS_MMI0,
2265 MMI_OPC_0_PSUBH = (0x05 << 6) | MMI_OPC_CLASS_MMI0,
2266 MMI_OPC_0_PCGTH = (0x06 << 6) | MMI_OPC_CLASS_MMI0,
2267 MMI_OPC_0_PMAXH = (0x07 << 6) | MMI_OPC_CLASS_MMI0,
2268 MMI_OPC_0_PADDB = (0x08 << 6) | MMI_OPC_CLASS_MMI0,
2269 MMI_OPC_0_PSUBB = (0x09 << 6) | MMI_OPC_CLASS_MMI0,
2270 MMI_OPC_0_PCGTB = (0x0A << 6) | MMI_OPC_CLASS_MMI0,
2271 MMI_OPC_0_PADDSW = (0x10 << 6) | MMI_OPC_CLASS_MMI0,
2272 MMI_OPC_0_PSUBSW = (0x11 << 6) | MMI_OPC_CLASS_MMI0,
2273 MMI_OPC_0_PEXTLW = (0x12 << 6) | MMI_OPC_CLASS_MMI0,
2274 MMI_OPC_0_PPACW = (0x13 << 6) | MMI_OPC_CLASS_MMI0,
2275 MMI_OPC_0_PADDSH = (0x14 << 6) | MMI_OPC_CLASS_MMI0,
2276 MMI_OPC_0_PSUBSH = (0x15 << 6) | MMI_OPC_CLASS_MMI0,
2277 MMI_OPC_0_PEXTLH = (0x16 << 6) | MMI_OPC_CLASS_MMI0,
2278 MMI_OPC_0_PPACH = (0x17 << 6) | MMI_OPC_CLASS_MMI0,
2279 MMI_OPC_0_PADDSB = (0x18 << 6) | MMI_OPC_CLASS_MMI0,
2280 MMI_OPC_0_PSUBSB = (0x19 << 6) | MMI_OPC_CLASS_MMI0,
2281 MMI_OPC_0_PEXTLB = (0x1A << 6) | MMI_OPC_CLASS_MMI0,
2282 MMI_OPC_0_PPACB = (0x1B << 6) | MMI_OPC_CLASS_MMI0,
2283 MMI_OPC_0_PEXT5 = (0x1E << 6) | MMI_OPC_CLASS_MMI0,
2284 MMI_OPC_0_PPAC5 = (0x1F << 6) | MMI_OPC_CLASS_MMI0,
2288 * MMI instructions with opcode field = MMI and bits 5..0 = MMI1:
2290 * 31 26 10 6 5 0
2291 * +--------+----------------------+--------+--------+
2292 * | MMI | |function| MMI1 |
2293 * +--------+----------------------+--------+--------+
2295 * function bits 7..6
2296 * bits | 0 | 1 | 2 | 3
2297 * 10..8 | 00 | 01 | 10 | 11
2298 * -------+-------+-------+-------+-------
2299 * 0 000 | * | PABSW | PCEQW | PMINW
2300 * 1 001 | PADSBH| PABSH | PCEQH | PMINH
2301 * 2 010 | * | * | PCEQB | *
2302 * 3 011 | * | * | * | *
2303 * 4 100 | PADDUW| PSUBUW| PEXTUW| *
2304 * 5 101 | PADDUH| PSUBUH| PEXTUH| *
2305 * 6 110 | PADDUB| PSUBUB| PEXTUB| QFSRV
2306 * 7 111 | * | * | * | *
2309 #define MASK_MMI1(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2310 enum {
2311 MMI_OPC_1_PABSW = (0x01 << 6) | MMI_OPC_CLASS_MMI1,
2312 MMI_OPC_1_PCEQW = (0x02 << 6) | MMI_OPC_CLASS_MMI1,
2313 MMI_OPC_1_PMINW = (0x03 << 6) | MMI_OPC_CLASS_MMI1,
2314 MMI_OPC_1_PADSBH = (0x04 << 6) | MMI_OPC_CLASS_MMI1,
2315 MMI_OPC_1_PABSH = (0x05 << 6) | MMI_OPC_CLASS_MMI1,
2316 MMI_OPC_1_PCEQH = (0x06 << 6) | MMI_OPC_CLASS_MMI1,
2317 MMI_OPC_1_PMINH = (0x07 << 6) | MMI_OPC_CLASS_MMI1,
2318 MMI_OPC_1_PCEQB = (0x0A << 6) | MMI_OPC_CLASS_MMI1,
2319 MMI_OPC_1_PADDUW = (0x10 << 6) | MMI_OPC_CLASS_MMI1,
2320 MMI_OPC_1_PSUBUW = (0x11 << 6) | MMI_OPC_CLASS_MMI1,
2321 MMI_OPC_1_PEXTUW = (0x12 << 6) | MMI_OPC_CLASS_MMI1,
2322 MMI_OPC_1_PADDUH = (0x14 << 6) | MMI_OPC_CLASS_MMI1,
2323 MMI_OPC_1_PSUBUH = (0x15 << 6) | MMI_OPC_CLASS_MMI1,
2324 MMI_OPC_1_PEXTUH = (0x16 << 6) | MMI_OPC_CLASS_MMI1,
2325 MMI_OPC_1_PADDUB = (0x18 << 6) | MMI_OPC_CLASS_MMI1,
2326 MMI_OPC_1_PSUBUB = (0x19 << 6) | MMI_OPC_CLASS_MMI1,
2327 MMI_OPC_1_PEXTUB = (0x1A << 6) | MMI_OPC_CLASS_MMI1,
2328 MMI_OPC_1_QFSRV = (0x1B << 6) | MMI_OPC_CLASS_MMI1,
2332 * MMI instructions with opcode field = MMI and bits 5..0 = MMI2:
2334 * 31 26 10 6 5 0
2335 * +--------+----------------------+--------+--------+
2336 * | MMI | |function| MMI2 |
2337 * +--------+----------------------+--------+--------+
2339 * function bits 7..6
2340 * bits | 0 | 1 | 2 | 3
2341 * 10..8 | 00 | 01 | 10 | 11
2342 * -------+-------+-------+-------+-------
2343 * 0 000 | PMADDW| * | PSLLVW| PSRLVW
2344 * 1 001 | PMSUBW| * | * | *
2345 * 2 010 | PMFHI | PMFLO | PINTH | *
2346 * 3 011 | PMULTW| PDIVW | PCPYLD| *
2347 * 4 100 | PMADDH| PHMADH| PAND | PXOR
2348 * 5 101 | PMSUBH| PHMSBH| * | *
2349 * 6 110 | * | * | PEXEH | PREVH
2350 * 7 111 | PMULTH| PDIVBW| PEXEW | PROT3W
2353 #define MASK_MMI2(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2354 enum {
2355 MMI_OPC_2_PMADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI2,
2356 MMI_OPC_2_PSLLVW = (0x02 << 6) | MMI_OPC_CLASS_MMI2,
2357 MMI_OPC_2_PSRLVW = (0x03 << 6) | MMI_OPC_CLASS_MMI2,
2358 MMI_OPC_2_PMSUBW = (0x04 << 6) | MMI_OPC_CLASS_MMI2,
2359 MMI_OPC_2_PMFHI = (0x08 << 6) | MMI_OPC_CLASS_MMI2,
2360 MMI_OPC_2_PMFLO = (0x09 << 6) | MMI_OPC_CLASS_MMI2,
2361 MMI_OPC_2_PINTH = (0x0A << 6) | MMI_OPC_CLASS_MMI2,
2362 MMI_OPC_2_PMULTW = (0x0C << 6) | MMI_OPC_CLASS_MMI2,
2363 MMI_OPC_2_PDIVW = (0x0D << 6) | MMI_OPC_CLASS_MMI2,
2364 MMI_OPC_2_PCPYLD = (0x0E << 6) | MMI_OPC_CLASS_MMI2,
2365 MMI_OPC_2_PMADDH = (0x10 << 6) | MMI_OPC_CLASS_MMI2,
2366 MMI_OPC_2_PHMADH = (0x11 << 6) | MMI_OPC_CLASS_MMI2,
2367 MMI_OPC_2_PAND = (0x12 << 6) | MMI_OPC_CLASS_MMI2,
2368 MMI_OPC_2_PXOR = (0x13 << 6) | MMI_OPC_CLASS_MMI2,
2369 MMI_OPC_2_PMSUBH = (0x14 << 6) | MMI_OPC_CLASS_MMI2,
2370 MMI_OPC_2_PHMSBH = (0x15 << 6) | MMI_OPC_CLASS_MMI2,
2371 MMI_OPC_2_PEXEH = (0x1A << 6) | MMI_OPC_CLASS_MMI2,
2372 MMI_OPC_2_PREVH = (0x1B << 6) | MMI_OPC_CLASS_MMI2,
2373 MMI_OPC_2_PMULTH = (0x1C << 6) | MMI_OPC_CLASS_MMI2,
2374 MMI_OPC_2_PDIVBW = (0x1D << 6) | MMI_OPC_CLASS_MMI2,
2375 MMI_OPC_2_PEXEW = (0x1E << 6) | MMI_OPC_CLASS_MMI2,
2376 MMI_OPC_2_PROT3W = (0x1F << 6) | MMI_OPC_CLASS_MMI2,
2380 * MMI instructions with opcode field = MMI and bits 5..0 = MMI3:
2382 * 31 26 10 6 5 0
2383 * +--------+----------------------+--------+--------+
2384 * | MMI | |function| MMI3 |
2385 * +--------+----------------------+--------+--------+
2387 * function bits 7..6
2388 * bits | 0 | 1 | 2 | 3
2389 * 10..8 | 00 | 01 | 10 | 11
2390 * -------+-------+-------+-------+-------
2391 * 0 000 |PMADDUW| * | * | PSRAVW
2392 * 1 001 | * | * | * | *
2393 * 2 010 | PMTHI | PMTLO | PINTEH| *
2394 * 3 011 |PMULTUW| PDIVUW| PCPYUD| *
2395 * 4 100 | * | * | POR | PNOR
2396 * 5 101 | * | * | * | *
2397 * 6 110 | * | * | PEXCH | PCPYH
2398 * 7 111 | * | * | PEXCW | *
2401 #define MASK_MMI3(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2402 enum {
2403 MMI_OPC_3_PMADDUW = (0x00 << 6) | MMI_OPC_CLASS_MMI3,
2404 MMI_OPC_3_PSRAVW = (0x03 << 6) | MMI_OPC_CLASS_MMI3,
2405 MMI_OPC_3_PMTHI = (0x08 << 6) | MMI_OPC_CLASS_MMI3,
2406 MMI_OPC_3_PMTLO = (0x09 << 6) | MMI_OPC_CLASS_MMI3,
2407 MMI_OPC_3_PINTEH = (0x0A << 6) | MMI_OPC_CLASS_MMI3,
2408 MMI_OPC_3_PMULTUW = (0x0C << 6) | MMI_OPC_CLASS_MMI3,
2409 MMI_OPC_3_PDIVUW = (0x0D << 6) | MMI_OPC_CLASS_MMI3,
2410 MMI_OPC_3_PCPYUD = (0x0E << 6) | MMI_OPC_CLASS_MMI3,
2411 MMI_OPC_3_POR = (0x12 << 6) | MMI_OPC_CLASS_MMI3,
2412 MMI_OPC_3_PNOR = (0x13 << 6) | MMI_OPC_CLASS_MMI3,
2413 MMI_OPC_3_PEXCH = (0x1A << 6) | MMI_OPC_CLASS_MMI3,
2414 MMI_OPC_3_PCPYH = (0x1B << 6) | MMI_OPC_CLASS_MMI3,
2415 MMI_OPC_3_PEXCW = (0x1E << 6) | MMI_OPC_CLASS_MMI3,
2418 /* global register indices */
2419 TCGv cpu_gpr[32], cpu_PC;
2420 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
2421 static TCGv cpu_dspctrl, btarget;
2422 TCGv bcond;
2423 static TCGv cpu_lladdr, cpu_llval;
2424 static TCGv_i32 hflags;
2425 TCGv_i32 fpu_fcr0, fpu_fcr31;
2426 TCGv_i64 fpu_f64[32];
2427 static TCGv_i64 msa_wr_d[64];
2429 #if defined(TARGET_MIPS64)
2430 /* Upper halves of R5900's 128-bit registers: MMRs (multimedia registers) */
2431 static TCGv_i64 cpu_mmr[32];
2432 #endif
2434 #if !defined(TARGET_MIPS64)
2435 /* MXU registers */
2436 static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1];
2437 static TCGv mxu_CR;
2438 #endif
2440 #include "exec/gen-icount.h"
2442 #define gen_helper_0e0i(name, arg) do { \
2443 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
2444 gen_helper_##name(cpu_env, helper_tmp); \
2445 tcg_temp_free_i32(helper_tmp); \
2446 } while (0)
2448 #define gen_helper_0e1i(name, arg1, arg2) do { \
2449 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2450 gen_helper_##name(cpu_env, arg1, helper_tmp); \
2451 tcg_temp_free_i32(helper_tmp); \
2452 } while (0)
2454 #define gen_helper_1e0i(name, ret, arg1) do { \
2455 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
2456 gen_helper_##name(ret, cpu_env, helper_tmp); \
2457 tcg_temp_free_i32(helper_tmp); \
2458 } while (0)
2460 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
2461 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2462 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
2463 tcg_temp_free_i32(helper_tmp); \
2464 } while (0)
2466 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
2467 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2468 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
2469 tcg_temp_free_i32(helper_tmp); \
2470 } while (0)
2472 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
2473 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2474 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
2475 tcg_temp_free_i32(helper_tmp); \
2476 } while (0)
2478 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
2479 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
2480 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
2481 tcg_temp_free_i32(helper_tmp); \
2482 } while (0)
2484 #define DISAS_STOP DISAS_TARGET_0
2485 #define DISAS_EXIT DISAS_TARGET_1
2487 static const char * const regnames[] = {
2488 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2489 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2490 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2491 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2494 static const char * const regnames_HI[] = {
2495 "HI0", "HI1", "HI2", "HI3",
2498 static const char * const regnames_LO[] = {
2499 "LO0", "LO1", "LO2", "LO3",
2502 static const char * const fregnames[] = {
2503 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2504 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2505 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2506 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2509 static const char * const msaregnames[] = {
2510 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
2511 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
2512 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
2513 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
2514 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
2515 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
2516 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
2517 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
2518 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
2519 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
2520 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
2521 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
2522 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
2523 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
2524 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
2525 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
2528 #if !defined(TARGET_MIPS64)
2529 static const char * const mxuregnames[] = {
2530 "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8",
2531 "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR",
2533 #endif
2535 /* General purpose registers moves. */
2536 void gen_load_gpr(TCGv t, int reg)
2538 if (reg == 0) {
2539 tcg_gen_movi_tl(t, 0);
2540 } else {
2541 tcg_gen_mov_tl(t, cpu_gpr[reg]);
2545 void gen_store_gpr(TCGv t, int reg)
2547 if (reg != 0) {
2548 tcg_gen_mov_tl(cpu_gpr[reg], t);
2552 /* Moves to/from shadow registers. */
2553 static inline void gen_load_srsgpr(int from, int to)
2555 TCGv t0 = tcg_temp_new();
2557 if (from == 0) {
2558 tcg_gen_movi_tl(t0, 0);
2559 } else {
2560 TCGv_i32 t2 = tcg_temp_new_i32();
2561 TCGv_ptr addr = tcg_temp_new_ptr();
2563 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2564 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2565 tcg_gen_andi_i32(t2, t2, 0xf);
2566 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2567 tcg_gen_ext_i32_ptr(addr, t2);
2568 tcg_gen_add_ptr(addr, cpu_env, addr);
2570 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
2571 tcg_temp_free_ptr(addr);
2572 tcg_temp_free_i32(t2);
2574 gen_store_gpr(t0, to);
2575 tcg_temp_free(t0);
2578 static inline void gen_store_srsgpr(int from, int to)
2580 if (to != 0) {
2581 TCGv t0 = tcg_temp_new();
2582 TCGv_i32 t2 = tcg_temp_new_i32();
2583 TCGv_ptr addr = tcg_temp_new_ptr();
2585 gen_load_gpr(t0, from);
2586 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2587 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2588 tcg_gen_andi_i32(t2, t2, 0xf);
2589 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2590 tcg_gen_ext_i32_ptr(addr, t2);
2591 tcg_gen_add_ptr(addr, cpu_env, addr);
2593 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
2594 tcg_temp_free_ptr(addr);
2595 tcg_temp_free_i32(t2);
2596 tcg_temp_free(t0);
2600 #if !defined(TARGET_MIPS64)
2601 /* MXU General purpose registers moves. */
2602 static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg)
2604 if (reg == 0) {
2605 tcg_gen_movi_tl(t, 0);
2606 } else if (reg <= 15) {
2607 tcg_gen_mov_tl(t, mxu_gpr[reg - 1]);
2611 static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg)
2613 if (reg > 0 && reg <= 15) {
2614 tcg_gen_mov_tl(mxu_gpr[reg - 1], t);
2618 /* MXU control register moves. */
2619 static inline void gen_load_mxu_cr(TCGv t)
2621 tcg_gen_mov_tl(t, mxu_CR);
2624 static inline void gen_store_mxu_cr(TCGv t)
2626 /* TODO: Add handling of RW rules for MXU_CR. */
2627 tcg_gen_mov_tl(mxu_CR, t);
2629 #endif
2632 /* Tests */
2633 static inline void gen_save_pc(target_ulong pc)
2635 tcg_gen_movi_tl(cpu_PC, pc);
2638 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2640 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
2641 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2642 gen_save_pc(ctx->base.pc_next);
2643 ctx->saved_pc = ctx->base.pc_next;
2645 if (ctx->hflags != ctx->saved_hflags) {
2646 tcg_gen_movi_i32(hflags, ctx->hflags);
2647 ctx->saved_hflags = ctx->hflags;
2648 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2649 case MIPS_HFLAG_BR:
2650 break;
2651 case MIPS_HFLAG_BC:
2652 case MIPS_HFLAG_BL:
2653 case MIPS_HFLAG_B:
2654 tcg_gen_movi_tl(btarget, ctx->btarget);
2655 break;
2660 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2662 ctx->saved_hflags = ctx->hflags;
2663 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2664 case MIPS_HFLAG_BR:
2665 break;
2666 case MIPS_HFLAG_BC:
2667 case MIPS_HFLAG_BL:
2668 case MIPS_HFLAG_B:
2669 ctx->btarget = env->btarget;
2670 break;
2674 void generate_exception_err(DisasContext *ctx, int excp, int err)
2676 TCGv_i32 texcp = tcg_const_i32(excp);
2677 TCGv_i32 terr = tcg_const_i32(err);
2678 save_cpu_state(ctx, 1);
2679 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2680 tcg_temp_free_i32(terr);
2681 tcg_temp_free_i32(texcp);
2682 ctx->base.is_jmp = DISAS_NORETURN;
2685 void generate_exception(DisasContext *ctx, int excp)
2687 gen_helper_0e0i(raise_exception, excp);
2690 void generate_exception_end(DisasContext *ctx, int excp)
2692 generate_exception_err(ctx, excp, 0);
2695 void gen_reserved_instruction(DisasContext *ctx)
2697 generate_exception_end(ctx, EXCP_RI);
2700 /* Floating point register moves. */
2701 void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2703 if (ctx->hflags & MIPS_HFLAG_FRE) {
2704 generate_exception(ctx, EXCP_RI);
2706 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
2709 void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2711 TCGv_i64 t64;
2712 if (ctx->hflags & MIPS_HFLAG_FRE) {
2713 generate_exception(ctx, EXCP_RI);
2715 t64 = tcg_temp_new_i64();
2716 tcg_gen_extu_i32_i64(t64, t);
2717 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2718 tcg_temp_free_i64(t64);
2721 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2723 if (ctx->hflags & MIPS_HFLAG_F64) {
2724 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
2725 } else {
2726 gen_load_fpr32(ctx, t, reg | 1);
2730 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2732 if (ctx->hflags & MIPS_HFLAG_F64) {
2733 TCGv_i64 t64 = tcg_temp_new_i64();
2734 tcg_gen_extu_i32_i64(t64, t);
2735 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2736 tcg_temp_free_i64(t64);
2737 } else {
2738 gen_store_fpr32(ctx, t, reg | 1);
2742 void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2744 if (ctx->hflags & MIPS_HFLAG_F64) {
2745 tcg_gen_mov_i64(t, fpu_f64[reg]);
2746 } else {
2747 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
2751 void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2753 if (ctx->hflags & MIPS_HFLAG_F64) {
2754 tcg_gen_mov_i64(fpu_f64[reg], t);
2755 } else {
2756 TCGv_i64 t0;
2757 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2758 t0 = tcg_temp_new_i64();
2759 tcg_gen_shri_i64(t0, t, 32);
2760 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
2761 tcg_temp_free_i64(t0);
2765 int get_fp_bit(int cc)
2767 if (cc) {
2768 return 24 + cc;
2769 } else {
2770 return 23;
2774 /* Addresses computation */
2775 void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
2777 tcg_gen_add_tl(ret, arg0, arg1);
2779 #if defined(TARGET_MIPS64)
2780 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2781 tcg_gen_ext32s_i64(ret, ret);
2783 #endif
2786 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2787 target_long ofs)
2789 tcg_gen_addi_tl(ret, base, ofs);
2791 #if defined(TARGET_MIPS64)
2792 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2793 tcg_gen_ext32s_i64(ret, ret);
2795 #endif
2798 /* Addresses computation (translation time) */
2799 static target_long addr_add(DisasContext *ctx, target_long base,
2800 target_long offset)
2802 target_long sum = base + offset;
2804 #if defined(TARGET_MIPS64)
2805 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2806 sum = (int32_t)sum;
2808 #endif
2809 return sum;
2812 /* Sign-extract the low 32-bits to a target_long. */
2813 void gen_move_low32(TCGv ret, TCGv_i64 arg)
2815 #if defined(TARGET_MIPS64)
2816 tcg_gen_ext32s_i64(ret, arg);
2817 #else
2818 tcg_gen_extrl_i64_i32(ret, arg);
2819 #endif
2822 /* Sign-extract the high 32-bits to a target_long. */
2823 void gen_move_high32(TCGv ret, TCGv_i64 arg)
2825 #if defined(TARGET_MIPS64)
2826 tcg_gen_sari_i64(ret, arg, 32);
2827 #else
2828 tcg_gen_extrh_i64_i32(ret, arg);
2829 #endif
2832 void check_cp0_enabled(DisasContext *ctx)
2834 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
2835 generate_exception_end(ctx, EXCP_CpU);
2839 void check_cp1_enabled(DisasContext *ctx)
2841 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) {
2842 generate_exception_err(ctx, EXCP_CpU, 1);
2847 * Verify that the processor is running with COP1X instructions enabled.
2848 * This is associated with the nabla symbol in the MIPS32 and MIPS64
2849 * opcode tables.
2851 void check_cop1x(DisasContext *ctx)
2853 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) {
2854 gen_reserved_instruction(ctx);
2859 * Verify that the processor is running with 64-bit floating-point
2860 * operations enabled.
2862 void check_cp1_64bitmode(DisasContext *ctx)
2864 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) {
2865 gen_reserved_instruction(ctx);
2870 * Verify if floating point register is valid; an operation is not defined
2871 * if bit 0 of any register specification is set and the FR bit in the
2872 * Status register equals zero, since the register numbers specify an
2873 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2874 * in the Status register equals one, both even and odd register numbers
2875 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2877 * Multiple 64 bit wide registers can be checked by calling
2878 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2880 void check_cp1_registers(DisasContext *ctx, int regs)
2882 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) {
2883 gen_reserved_instruction(ctx);
2888 * Verify that the processor is running with DSP instructions enabled.
2889 * This is enabled by CP0 Status register MX(24) bit.
2891 static inline void check_dsp(DisasContext *ctx)
2893 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
2894 if (ctx->insn_flags & ASE_DSP) {
2895 generate_exception_end(ctx, EXCP_DSPDIS);
2896 } else {
2897 gen_reserved_instruction(ctx);
2902 static inline void check_dsp_r2(DisasContext *ctx)
2904 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
2905 if (ctx->insn_flags & ASE_DSP) {
2906 generate_exception_end(ctx, EXCP_DSPDIS);
2907 } else {
2908 gen_reserved_instruction(ctx);
2913 static inline void check_dsp_r3(DisasContext *ctx)
2915 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
2916 if (ctx->insn_flags & ASE_DSP) {
2917 generate_exception_end(ctx, EXCP_DSPDIS);
2918 } else {
2919 gen_reserved_instruction(ctx);
2925 * This code generates a "reserved instruction" exception if the
2926 * CPU does not support the instruction set corresponding to flags.
2928 void check_insn(DisasContext *ctx, uint64_t flags)
2930 if (unlikely(!(ctx->insn_flags & flags))) {
2931 gen_reserved_instruction(ctx);
2936 * This code generates a "reserved instruction" exception if the
2937 * CPU has corresponding flag set which indicates that the instruction
2938 * has been removed.
2940 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
2942 if (unlikely(ctx->insn_flags & flags)) {
2943 gen_reserved_instruction(ctx);
2948 * The Linux kernel traps certain reserved instruction exceptions to
2949 * emulate the corresponding instructions. QEMU is the kernel in user
2950 * mode, so those traps are emulated by accepting the instructions.
2952 * A reserved instruction exception is generated for flagged CPUs if
2953 * QEMU runs in system mode.
2955 static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
2957 #ifndef CONFIG_USER_ONLY
2958 check_insn_opc_removed(ctx, flags);
2959 #endif
2963 * This code generates a "reserved instruction" exception if the
2964 * CPU does not support 64-bit paired-single (PS) floating point data type.
2966 static inline void check_ps(DisasContext *ctx)
2968 if (unlikely(!ctx->ps)) {
2969 generate_exception(ctx, EXCP_RI);
2971 check_cp1_64bitmode(ctx);
2974 #ifdef TARGET_MIPS64
2976 * This code generates a "reserved instruction" exception if 64-bit
2977 * instructions are not enabled.
2979 void check_mips_64(DisasContext *ctx)
2981 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64))) {
2982 gen_reserved_instruction(ctx);
2985 #endif
2987 #ifndef CONFIG_USER_ONLY
2988 static inline void check_mvh(DisasContext *ctx)
2990 if (unlikely(!ctx->mvh)) {
2991 generate_exception(ctx, EXCP_RI);
2994 #endif
2997 * This code generates a "reserved instruction" exception if the
2998 * Config5 XNP bit is set.
3000 static inline void check_xnp(DisasContext *ctx)
3002 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
3003 gen_reserved_instruction(ctx);
3007 #ifndef CONFIG_USER_ONLY
3009 * This code generates a "reserved instruction" exception if the
3010 * Config3 PW bit is NOT set.
3012 static inline void check_pw(DisasContext *ctx)
3014 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
3015 gen_reserved_instruction(ctx);
3018 #endif
3021 * This code generates a "reserved instruction" exception if the
3022 * Config3 MT bit is NOT set.
3024 static inline void check_mt(DisasContext *ctx)
3026 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3027 gen_reserved_instruction(ctx);
3031 #ifndef CONFIG_USER_ONLY
3033 * This code generates a "coprocessor unusable" exception if CP0 is not
3034 * available, and, if that is not the case, generates a "reserved instruction"
3035 * exception if the Config5 MT bit is NOT set. This is needed for availability
3036 * control of some of MT ASE instructions.
3038 static inline void check_cp0_mt(DisasContext *ctx)
3040 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
3041 generate_exception_end(ctx, EXCP_CpU);
3042 } else {
3043 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3044 gen_reserved_instruction(ctx);
3048 #endif
3051 * This code generates a "reserved instruction" exception if the
3052 * Config5 NMS bit is set.
3054 static inline void check_nms(DisasContext *ctx)
3056 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
3057 gen_reserved_instruction(ctx);
3062 * This code generates a "reserved instruction" exception if the
3063 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
3064 * Config2 TL, and Config5 L2C are unset.
3066 static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
3068 if (unlikely((ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
3069 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
3070 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
3071 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
3072 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
3073 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))) {
3074 gen_reserved_instruction(ctx);
3079 * This code generates a "reserved instruction" exception if the
3080 * Config5 EVA bit is NOT set.
3082 static inline void check_eva(DisasContext *ctx)
3084 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
3085 gen_reserved_instruction(ctx);
3091 * Define small wrappers for gen_load_fpr* so that we have a uniform
3092 * calling interface for 32 and 64-bit FPRs. No sense in changing
3093 * all callers for gen_load_fpr32 when we need the CTX parameter for
3094 * this one use.
3096 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
3097 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
3098 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
3099 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
3100 int ft, int fs, int cc) \
3102 TCGv_i##bits fp0 = tcg_temp_new_i##bits(); \
3103 TCGv_i##bits fp1 = tcg_temp_new_i##bits(); \
3104 switch (ifmt) { \
3105 case FMT_PS: \
3106 check_ps(ctx); \
3107 break; \
3108 case FMT_D: \
3109 if (abs) { \
3110 check_cop1x(ctx); \
3112 check_cp1_registers(ctx, fs | ft); \
3113 break; \
3114 case FMT_S: \
3115 if (abs) { \
3116 check_cop1x(ctx); \
3118 break; \
3120 gen_ldcmp_fpr##bits(ctx, fp0, fs); \
3121 gen_ldcmp_fpr##bits(ctx, fp1, ft); \
3122 switch (n) { \
3123 case 0: \
3124 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); \
3125 break; \
3126 case 1: \
3127 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); \
3128 break; \
3129 case 2: \
3130 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); \
3131 break; \
3132 case 3: \
3133 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); \
3134 break; \
3135 case 4: \
3136 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); \
3137 break; \
3138 case 5: \
3139 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); \
3140 break; \
3141 case 6: \
3142 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); \
3143 break; \
3144 case 7: \
3145 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); \
3146 break; \
3147 case 8: \
3148 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); \
3149 break; \
3150 case 9: \
3151 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); \
3152 break; \
3153 case 10: \
3154 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); \
3155 break; \
3156 case 11: \
3157 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); \
3158 break; \
3159 case 12: \
3160 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); \
3161 break; \
3162 case 13: \
3163 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); \
3164 break; \
3165 case 14: \
3166 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); \
3167 break; \
3168 case 15: \
3169 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); \
3170 break; \
3171 default: \
3172 abort(); \
3174 tcg_temp_free_i##bits(fp0); \
3175 tcg_temp_free_i##bits(fp1); \
3178 FOP_CONDS(, 0, d, FMT_D, 64)
3179 FOP_CONDS(abs, 1, d, FMT_D, 64)
3180 FOP_CONDS(, 0, s, FMT_S, 32)
3181 FOP_CONDS(abs, 1, s, FMT_S, 32)
3182 FOP_CONDS(, 0, ps, FMT_PS, 64)
3183 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
3184 #undef FOP_CONDS
3186 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
3187 static inline void gen_r6_cmp_ ## fmt(DisasContext *ctx, int n, \
3188 int ft, int fs, int fd) \
3190 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
3191 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
3192 if (ifmt == FMT_D) { \
3193 check_cp1_registers(ctx, fs | ft | fd); \
3195 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
3196 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
3197 switch (n) { \
3198 case 0: \
3199 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
3200 break; \
3201 case 1: \
3202 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
3203 break; \
3204 case 2: \
3205 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
3206 break; \
3207 case 3: \
3208 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
3209 break; \
3210 case 4: \
3211 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
3212 break; \
3213 case 5: \
3214 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
3215 break; \
3216 case 6: \
3217 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
3218 break; \
3219 case 7: \
3220 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
3221 break; \
3222 case 8: \
3223 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
3224 break; \
3225 case 9: \
3226 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
3227 break; \
3228 case 10: \
3229 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
3230 break; \
3231 case 11: \
3232 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
3233 break; \
3234 case 12: \
3235 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
3236 break; \
3237 case 13: \
3238 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
3239 break; \
3240 case 14: \
3241 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
3242 break; \
3243 case 15: \
3244 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
3245 break; \
3246 case 17: \
3247 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
3248 break; \
3249 case 18: \
3250 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
3251 break; \
3252 case 19: \
3253 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
3254 break; \
3255 case 25: \
3256 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
3257 break; \
3258 case 26: \
3259 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
3260 break; \
3261 case 27: \
3262 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
3263 break; \
3264 default: \
3265 abort(); \
3267 STORE; \
3268 tcg_temp_free_i ## bits(fp0); \
3269 tcg_temp_free_i ## bits(fp1); \
3272 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
3273 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3274 #undef FOP_CONDNS
3275 #undef gen_ldcmp_fpr32
3276 #undef gen_ldcmp_fpr64
3278 /* load/store instructions. */
3279 #ifdef CONFIG_USER_ONLY
3280 #define OP_LD_ATOMIC(insn, fname) \
3281 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3282 DisasContext *ctx) \
3284 TCGv t0 = tcg_temp_new(); \
3285 tcg_gen_mov_tl(t0, arg1); \
3286 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
3287 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3288 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
3289 tcg_temp_free(t0); \
3291 #else
3292 #define OP_LD_ATOMIC(insn, fname) \
3293 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3294 DisasContext *ctx) \
3296 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
3298 #endif
3299 OP_LD_ATOMIC(ll, ld32s);
3300 #if defined(TARGET_MIPS64)
3301 OP_LD_ATOMIC(lld, ld64);
3302 #endif
3303 #undef OP_LD_ATOMIC
3305 void gen_base_offset_addr(DisasContext *ctx, TCGv addr, int base, int offset)
3307 if (base == 0) {
3308 tcg_gen_movi_tl(addr, offset);
3309 } else if (offset == 0) {
3310 gen_load_gpr(addr, base);
3311 } else {
3312 tcg_gen_movi_tl(addr, offset);
3313 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
3317 static target_ulong pc_relative_pc(DisasContext *ctx)
3319 target_ulong pc = ctx->base.pc_next;
3321 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3322 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
3324 pc -= branch_bytes;
3327 pc &= ~(target_ulong)3;
3328 return pc;
3331 /* Load */
3332 static void gen_ld(DisasContext *ctx, uint32_t opc,
3333 int rt, int base, int offset)
3335 TCGv t0, t1, t2;
3336 int mem_idx = ctx->mem_idx;
3338 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F |
3339 INSN_LOONGSON3A)) {
3341 * Loongson CPU uses a load to zero register for prefetch.
3342 * We emulate it as a NOP. On other CPU we must perform the
3343 * actual memory access.
3345 return;
3348 t0 = tcg_temp_new();
3349 gen_base_offset_addr(ctx, t0, base, offset);
3351 switch (opc) {
3352 #if defined(TARGET_MIPS64)
3353 case OPC_LWU:
3354 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
3355 ctx->default_tcg_memop_mask);
3356 gen_store_gpr(t0, rt);
3357 break;
3358 case OPC_LD:
3359 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
3360 ctx->default_tcg_memop_mask);
3361 gen_store_gpr(t0, rt);
3362 break;
3363 case OPC_LLD:
3364 case R6_OPC_LLD:
3365 op_ld_lld(t0, t0, mem_idx, ctx);
3366 gen_store_gpr(t0, rt);
3367 break;
3368 case OPC_LDL:
3369 t1 = tcg_temp_new();
3371 * Do a byte access to possibly trigger a page
3372 * fault with the unaligned address.
3374 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3375 tcg_gen_andi_tl(t1, t0, 7);
3376 #ifndef TARGET_WORDS_BIGENDIAN
3377 tcg_gen_xori_tl(t1, t1, 7);
3378 #endif
3379 tcg_gen_shli_tl(t1, t1, 3);
3380 tcg_gen_andi_tl(t0, t0, ~7);
3381 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3382 tcg_gen_shl_tl(t0, t0, t1);
3383 t2 = tcg_const_tl(-1);
3384 tcg_gen_shl_tl(t2, t2, t1);
3385 gen_load_gpr(t1, rt);
3386 tcg_gen_andc_tl(t1, t1, t2);
3387 tcg_temp_free(t2);
3388 tcg_gen_or_tl(t0, t0, t1);
3389 tcg_temp_free(t1);
3390 gen_store_gpr(t0, rt);
3391 break;
3392 case OPC_LDR:
3393 t1 = tcg_temp_new();
3395 * Do a byte access to possibly trigger a page
3396 * fault with the unaligned address.
3398 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3399 tcg_gen_andi_tl(t1, t0, 7);
3400 #ifdef TARGET_WORDS_BIGENDIAN
3401 tcg_gen_xori_tl(t1, t1, 7);
3402 #endif
3403 tcg_gen_shli_tl(t1, t1, 3);
3404 tcg_gen_andi_tl(t0, t0, ~7);
3405 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3406 tcg_gen_shr_tl(t0, t0, t1);
3407 tcg_gen_xori_tl(t1, t1, 63);
3408 t2 = tcg_const_tl(0xfffffffffffffffeull);
3409 tcg_gen_shl_tl(t2, t2, t1);
3410 gen_load_gpr(t1, rt);
3411 tcg_gen_and_tl(t1, t1, t2);
3412 tcg_temp_free(t2);
3413 tcg_gen_or_tl(t0, t0, t1);
3414 tcg_temp_free(t1);
3415 gen_store_gpr(t0, rt);
3416 break;
3417 case OPC_LDPC:
3418 t1 = tcg_const_tl(pc_relative_pc(ctx));
3419 gen_op_addr_add(ctx, t0, t0, t1);
3420 tcg_temp_free(t1);
3421 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3422 gen_store_gpr(t0, rt);
3423 break;
3424 #endif
3425 case OPC_LWPC:
3426 t1 = tcg_const_tl(pc_relative_pc(ctx));
3427 gen_op_addr_add(ctx, t0, t0, t1);
3428 tcg_temp_free(t1);
3429 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
3430 gen_store_gpr(t0, rt);
3431 break;
3432 case OPC_LWE:
3433 mem_idx = MIPS_HFLAG_UM;
3434 /* fall through */
3435 case OPC_LW:
3436 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
3437 ctx->default_tcg_memop_mask);
3438 gen_store_gpr(t0, rt);
3439 break;
3440 case OPC_LHE:
3441 mem_idx = MIPS_HFLAG_UM;
3442 /* fall through */
3443 case OPC_LH:
3444 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
3445 ctx->default_tcg_memop_mask);
3446 gen_store_gpr(t0, rt);
3447 break;
3448 case OPC_LHUE:
3449 mem_idx = MIPS_HFLAG_UM;
3450 /* fall through */
3451 case OPC_LHU:
3452 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
3453 ctx->default_tcg_memop_mask);
3454 gen_store_gpr(t0, rt);
3455 break;
3456 case OPC_LBE:
3457 mem_idx = MIPS_HFLAG_UM;
3458 /* fall through */
3459 case OPC_LB:
3460 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
3461 gen_store_gpr(t0, rt);
3462 break;
3463 case OPC_LBUE:
3464 mem_idx = MIPS_HFLAG_UM;
3465 /* fall through */
3466 case OPC_LBU:
3467 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
3468 gen_store_gpr(t0, rt);
3469 break;
3470 case OPC_LWLE:
3471 mem_idx = MIPS_HFLAG_UM;
3472 /* fall through */
3473 case OPC_LWL:
3474 t1 = tcg_temp_new();
3476 * Do a byte access to possibly trigger a page
3477 * fault with the unaligned address.
3479 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3480 tcg_gen_andi_tl(t1, t0, 3);
3481 #ifndef TARGET_WORDS_BIGENDIAN
3482 tcg_gen_xori_tl(t1, t1, 3);
3483 #endif
3484 tcg_gen_shli_tl(t1, t1, 3);
3485 tcg_gen_andi_tl(t0, t0, ~3);
3486 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3487 tcg_gen_shl_tl(t0, t0, t1);
3488 t2 = tcg_const_tl(-1);
3489 tcg_gen_shl_tl(t2, t2, t1);
3490 gen_load_gpr(t1, rt);
3491 tcg_gen_andc_tl(t1, t1, t2);
3492 tcg_temp_free(t2);
3493 tcg_gen_or_tl(t0, t0, t1);
3494 tcg_temp_free(t1);
3495 tcg_gen_ext32s_tl(t0, t0);
3496 gen_store_gpr(t0, rt);
3497 break;
3498 case OPC_LWRE:
3499 mem_idx = MIPS_HFLAG_UM;
3500 /* fall through */
3501 case OPC_LWR:
3502 t1 = tcg_temp_new();
3504 * Do a byte access to possibly trigger a page
3505 * fault with the unaligned address.
3507 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3508 tcg_gen_andi_tl(t1, t0, 3);
3509 #ifdef TARGET_WORDS_BIGENDIAN
3510 tcg_gen_xori_tl(t1, t1, 3);
3511 #endif
3512 tcg_gen_shli_tl(t1, t1, 3);
3513 tcg_gen_andi_tl(t0, t0, ~3);
3514 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3515 tcg_gen_shr_tl(t0, t0, t1);
3516 tcg_gen_xori_tl(t1, t1, 31);
3517 t2 = tcg_const_tl(0xfffffffeull);
3518 tcg_gen_shl_tl(t2, t2, t1);
3519 gen_load_gpr(t1, rt);
3520 tcg_gen_and_tl(t1, t1, t2);
3521 tcg_temp_free(t2);
3522 tcg_gen_or_tl(t0, t0, t1);
3523 tcg_temp_free(t1);
3524 tcg_gen_ext32s_tl(t0, t0);
3525 gen_store_gpr(t0, rt);
3526 break;
3527 case OPC_LLE:
3528 mem_idx = MIPS_HFLAG_UM;
3529 /* fall through */
3530 case OPC_LL:
3531 case R6_OPC_LL:
3532 op_ld_ll(t0, t0, mem_idx, ctx);
3533 gen_store_gpr(t0, rt);
3534 break;
3536 tcg_temp_free(t0);
3539 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3540 uint32_t reg1, uint32_t reg2)
3542 TCGv taddr = tcg_temp_new();
3543 TCGv_i64 tval = tcg_temp_new_i64();
3544 TCGv tmp1 = tcg_temp_new();
3545 TCGv tmp2 = tcg_temp_new();
3547 gen_base_offset_addr(ctx, taddr, base, offset);
3548 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3549 #ifdef TARGET_WORDS_BIGENDIAN
3550 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3551 #else
3552 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3553 #endif
3554 gen_store_gpr(tmp1, reg1);
3555 tcg_temp_free(tmp1);
3556 gen_store_gpr(tmp2, reg2);
3557 tcg_temp_free(tmp2);
3558 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3559 tcg_temp_free_i64(tval);
3560 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3561 tcg_temp_free(taddr);
3564 /* Store */
3565 static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
3566 int base, int offset)
3568 TCGv t0 = tcg_temp_new();
3569 TCGv t1 = tcg_temp_new();
3570 int mem_idx = ctx->mem_idx;
3572 gen_base_offset_addr(ctx, t0, base, offset);
3573 gen_load_gpr(t1, rt);
3574 switch (opc) {
3575 #if defined(TARGET_MIPS64)
3576 case OPC_SD:
3577 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
3578 ctx->default_tcg_memop_mask);
3579 break;
3580 case OPC_SDL:
3581 gen_helper_0e2i(sdl, t1, t0, mem_idx);
3582 break;
3583 case OPC_SDR:
3584 gen_helper_0e2i(sdr, t1, t0, mem_idx);
3585 break;
3586 #endif
3587 case OPC_SWE:
3588 mem_idx = MIPS_HFLAG_UM;
3589 /* fall through */
3590 case OPC_SW:
3591 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
3592 ctx->default_tcg_memop_mask);
3593 break;
3594 case OPC_SHE:
3595 mem_idx = MIPS_HFLAG_UM;
3596 /* fall through */
3597 case OPC_SH:
3598 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
3599 ctx->default_tcg_memop_mask);
3600 break;
3601 case OPC_SBE:
3602 mem_idx = MIPS_HFLAG_UM;
3603 /* fall through */
3604 case OPC_SB:
3605 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
3606 break;
3607 case OPC_SWLE:
3608 mem_idx = MIPS_HFLAG_UM;
3609 /* fall through */
3610 case OPC_SWL:
3611 gen_helper_0e2i(swl, t1, t0, mem_idx);
3612 break;
3613 case OPC_SWRE:
3614 mem_idx = MIPS_HFLAG_UM;
3615 /* fall through */
3616 case OPC_SWR:
3617 gen_helper_0e2i(swr, t1, t0, mem_idx);
3618 break;
3620 tcg_temp_free(t0);
3621 tcg_temp_free(t1);
3625 /* Store conditional */
3626 static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
3627 MemOp tcg_mo, bool eva)
3629 TCGv addr, t0, val;
3630 TCGLabel *l1 = gen_new_label();
3631 TCGLabel *done = gen_new_label();
3633 t0 = tcg_temp_new();
3634 addr = tcg_temp_new();
3635 /* compare the address against that of the preceding LL */
3636 gen_base_offset_addr(ctx, addr, base, offset);
3637 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
3638 tcg_temp_free(addr);
3639 tcg_gen_movi_tl(t0, 0);
3640 gen_store_gpr(t0, rt);
3641 tcg_gen_br(done);
3643 gen_set_label(l1);
3644 /* generate cmpxchg */
3645 val = tcg_temp_new();
3646 gen_load_gpr(val, rt);
3647 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
3648 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
3649 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
3650 gen_store_gpr(t0, rt);
3651 tcg_temp_free(val);
3653 gen_set_label(done);
3654 tcg_temp_free(t0);
3658 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
3659 uint32_t reg1, uint32_t reg2, bool eva)
3661 TCGv taddr = tcg_temp_local_new();
3662 TCGv lladdr = tcg_temp_local_new();
3663 TCGv_i64 tval = tcg_temp_new_i64();
3664 TCGv_i64 llval = tcg_temp_new_i64();
3665 TCGv_i64 val = tcg_temp_new_i64();
3666 TCGv tmp1 = tcg_temp_new();
3667 TCGv tmp2 = tcg_temp_new();
3668 TCGLabel *lab_fail = gen_new_label();
3669 TCGLabel *lab_done = gen_new_label();
3671 gen_base_offset_addr(ctx, taddr, base, offset);
3673 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3674 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3676 gen_load_gpr(tmp1, reg1);
3677 gen_load_gpr(tmp2, reg2);
3679 #ifdef TARGET_WORDS_BIGENDIAN
3680 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3681 #else
3682 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3683 #endif
3685 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3686 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
3687 eva ? MIPS_HFLAG_UM : ctx->mem_idx, MO_64);
3688 if (reg1 != 0) {
3689 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3691 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3693 gen_set_label(lab_fail);
3695 if (reg1 != 0) {
3696 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3698 gen_set_label(lab_done);
3699 tcg_gen_movi_tl(lladdr, -1);
3700 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3703 /* Load and store */
3704 static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
3705 TCGv t0)
3708 * Don't do NOP if destination is zero: we must perform the actual
3709 * memory access.
3711 switch (opc) {
3712 case OPC_LWC1:
3714 TCGv_i32 fp0 = tcg_temp_new_i32();
3715 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3716 ctx->default_tcg_memop_mask);
3717 gen_store_fpr32(ctx, fp0, ft);
3718 tcg_temp_free_i32(fp0);
3720 break;
3721 case OPC_SWC1:
3723 TCGv_i32 fp0 = tcg_temp_new_i32();
3724 gen_load_fpr32(ctx, fp0, ft);
3725 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3726 ctx->default_tcg_memop_mask);
3727 tcg_temp_free_i32(fp0);
3729 break;
3730 case OPC_LDC1:
3732 TCGv_i64 fp0 = tcg_temp_new_i64();
3733 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3734 ctx->default_tcg_memop_mask);
3735 gen_store_fpr64(ctx, fp0, ft);
3736 tcg_temp_free_i64(fp0);
3738 break;
3739 case OPC_SDC1:
3741 TCGv_i64 fp0 = tcg_temp_new_i64();
3742 gen_load_fpr64(ctx, fp0, ft);
3743 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3744 ctx->default_tcg_memop_mask);
3745 tcg_temp_free_i64(fp0);
3747 break;
3748 default:
3749 MIPS_INVAL("flt_ldst");
3750 gen_reserved_instruction(ctx);
3751 break;
3755 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3756 int rs, int16_t imm)
3758 TCGv t0 = tcg_temp_new();
3760 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3761 check_cp1_enabled(ctx);
3762 switch (op) {
3763 case OPC_LDC1:
3764 case OPC_SDC1:
3765 check_insn(ctx, ISA_MIPS2);
3766 /* Fallthrough */
3767 default:
3768 gen_base_offset_addr(ctx, t0, rs, imm);
3769 gen_flt_ldst(ctx, op, rt, t0);
3771 } else {
3772 generate_exception_err(ctx, EXCP_CpU, 1);
3774 tcg_temp_free(t0);
3777 /* Arithmetic with immediate operand */
3778 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
3779 int rt, int rs, int imm)
3781 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3783 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
3785 * If no destination, treat it as a NOP.
3786 * For addi, we must generate the overflow exception when needed.
3788 return;
3790 switch (opc) {
3791 case OPC_ADDI:
3793 TCGv t0 = tcg_temp_local_new();
3794 TCGv t1 = tcg_temp_new();
3795 TCGv t2 = tcg_temp_new();
3796 TCGLabel *l1 = gen_new_label();
3798 gen_load_gpr(t1, rs);
3799 tcg_gen_addi_tl(t0, t1, uimm);
3800 tcg_gen_ext32s_tl(t0, t0);
3802 tcg_gen_xori_tl(t1, t1, ~uimm);
3803 tcg_gen_xori_tl(t2, t0, uimm);
3804 tcg_gen_and_tl(t1, t1, t2);
3805 tcg_temp_free(t2);
3806 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3807 tcg_temp_free(t1);
3808 /* operands of same sign, result different sign */
3809 generate_exception(ctx, EXCP_OVERFLOW);
3810 gen_set_label(l1);
3811 tcg_gen_ext32s_tl(t0, t0);
3812 gen_store_gpr(t0, rt);
3813 tcg_temp_free(t0);
3815 break;
3816 case OPC_ADDIU:
3817 if (rs != 0) {
3818 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3819 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3820 } else {
3821 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3823 break;
3824 #if defined(TARGET_MIPS64)
3825 case OPC_DADDI:
3827 TCGv t0 = tcg_temp_local_new();
3828 TCGv t1 = tcg_temp_new();
3829 TCGv t2 = tcg_temp_new();
3830 TCGLabel *l1 = gen_new_label();
3832 gen_load_gpr(t1, rs);
3833 tcg_gen_addi_tl(t0, t1, uimm);
3835 tcg_gen_xori_tl(t1, t1, ~uimm);
3836 tcg_gen_xori_tl(t2, t0, uimm);
3837 tcg_gen_and_tl(t1, t1, t2);
3838 tcg_temp_free(t2);
3839 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3840 tcg_temp_free(t1);
3841 /* operands of same sign, result different sign */
3842 generate_exception(ctx, EXCP_OVERFLOW);
3843 gen_set_label(l1);
3844 gen_store_gpr(t0, rt);
3845 tcg_temp_free(t0);
3847 break;
3848 case OPC_DADDIU:
3849 if (rs != 0) {
3850 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3851 } else {
3852 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3854 break;
3855 #endif
3859 /* Logic with immediate operand */
3860 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
3861 int rt, int rs, int16_t imm)
3863 target_ulong uimm;
3865 if (rt == 0) {
3866 /* If no destination, treat it as a NOP. */
3867 return;
3869 uimm = (uint16_t)imm;
3870 switch (opc) {
3871 case OPC_ANDI:
3872 if (likely(rs != 0)) {
3873 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3874 } else {
3875 tcg_gen_movi_tl(cpu_gpr[rt], 0);
3877 break;
3878 case OPC_ORI:
3879 if (rs != 0) {
3880 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3881 } else {
3882 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3884 break;
3885 case OPC_XORI:
3886 if (likely(rs != 0)) {
3887 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3888 } else {
3889 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3891 break;
3892 case OPC_LUI:
3893 if (rs != 0 && (ctx->insn_flags & ISA_MIPS_R6)) {
3894 /* OPC_AUI */
3895 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3896 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3897 } else {
3898 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
3900 break;
3902 default:
3903 break;
3907 /* Set on less than with immediate operand */
3908 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
3909 int rt, int rs, int16_t imm)
3911 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3912 TCGv t0;
3914 if (rt == 0) {
3915 /* If no destination, treat it as a NOP. */
3916 return;
3918 t0 = tcg_temp_new();
3919 gen_load_gpr(t0, rs);
3920 switch (opc) {
3921 case OPC_SLTI:
3922 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
3923 break;
3924 case OPC_SLTIU:
3925 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
3926 break;
3928 tcg_temp_free(t0);
3931 /* Shifts with immediate operand */
3932 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
3933 int rt, int rs, int16_t imm)
3935 target_ulong uimm = ((uint16_t)imm) & 0x1f;
3936 TCGv t0;
3938 if (rt == 0) {
3939 /* If no destination, treat it as a NOP. */
3940 return;
3943 t0 = tcg_temp_new();
3944 gen_load_gpr(t0, rs);
3945 switch (opc) {
3946 case OPC_SLL:
3947 tcg_gen_shli_tl(t0, t0, uimm);
3948 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3949 break;
3950 case OPC_SRA:
3951 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3952 break;
3953 case OPC_SRL:
3954 if (uimm != 0) {
3955 tcg_gen_ext32u_tl(t0, t0);
3956 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3957 } else {
3958 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3960 break;
3961 case OPC_ROTR:
3962 if (uimm != 0) {
3963 TCGv_i32 t1 = tcg_temp_new_i32();
3965 tcg_gen_trunc_tl_i32(t1, t0);
3966 tcg_gen_rotri_i32(t1, t1, uimm);
3967 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
3968 tcg_temp_free_i32(t1);
3969 } else {
3970 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3972 break;
3973 #if defined(TARGET_MIPS64)
3974 case OPC_DSLL:
3975 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
3976 break;
3977 case OPC_DSRA:
3978 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3979 break;
3980 case OPC_DSRL:
3981 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3982 break;
3983 case OPC_DROTR:
3984 if (uimm != 0) {
3985 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3986 } else {
3987 tcg_gen_mov_tl(cpu_gpr[rt], t0);
3989 break;
3990 case OPC_DSLL32:
3991 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
3992 break;
3993 case OPC_DSRA32:
3994 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
3995 break;
3996 case OPC_DSRL32:
3997 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
3998 break;
3999 case OPC_DROTR32:
4000 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
4001 break;
4002 #endif
4004 tcg_temp_free(t0);
4007 /* Arithmetic */
4008 static void gen_arith(DisasContext *ctx, uint32_t opc,
4009 int rd, int rs, int rt)
4011 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
4012 && opc != OPC_DADD && opc != OPC_DSUB) {
4014 * If no destination, treat it as a NOP.
4015 * For add & sub, we must generate the overflow exception when needed.
4017 return;
4020 switch (opc) {
4021 case OPC_ADD:
4023 TCGv t0 = tcg_temp_local_new();
4024 TCGv t1 = tcg_temp_new();
4025 TCGv t2 = tcg_temp_new();
4026 TCGLabel *l1 = gen_new_label();
4028 gen_load_gpr(t1, rs);
4029 gen_load_gpr(t2, rt);
4030 tcg_gen_add_tl(t0, t1, t2);
4031 tcg_gen_ext32s_tl(t0, t0);
4032 tcg_gen_xor_tl(t1, t1, t2);
4033 tcg_gen_xor_tl(t2, t0, t2);
4034 tcg_gen_andc_tl(t1, t2, t1);
4035 tcg_temp_free(t2);
4036 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4037 tcg_temp_free(t1);
4038 /* operands of same sign, result different sign */
4039 generate_exception(ctx, EXCP_OVERFLOW);
4040 gen_set_label(l1);
4041 gen_store_gpr(t0, rd);
4042 tcg_temp_free(t0);
4044 break;
4045 case OPC_ADDU:
4046 if (rs != 0 && rt != 0) {
4047 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4048 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4049 } else if (rs == 0 && rt != 0) {
4050 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4051 } else if (rs != 0 && rt == 0) {
4052 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4053 } else {
4054 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4056 break;
4057 case OPC_SUB:
4059 TCGv t0 = tcg_temp_local_new();
4060 TCGv t1 = tcg_temp_new();
4061 TCGv t2 = tcg_temp_new();
4062 TCGLabel *l1 = gen_new_label();
4064 gen_load_gpr(t1, rs);
4065 gen_load_gpr(t2, rt);
4066 tcg_gen_sub_tl(t0, t1, t2);
4067 tcg_gen_ext32s_tl(t0, t0);
4068 tcg_gen_xor_tl(t2, t1, t2);
4069 tcg_gen_xor_tl(t1, t0, t1);
4070 tcg_gen_and_tl(t1, t1, t2);
4071 tcg_temp_free(t2);
4072 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4073 tcg_temp_free(t1);
4075 * operands of different sign, first operand and the result
4076 * of different sign
4078 generate_exception(ctx, EXCP_OVERFLOW);
4079 gen_set_label(l1);
4080 gen_store_gpr(t0, rd);
4081 tcg_temp_free(t0);
4083 break;
4084 case OPC_SUBU:
4085 if (rs != 0 && rt != 0) {
4086 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4087 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4088 } else if (rs == 0 && rt != 0) {
4089 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4090 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4091 } else if (rs != 0 && rt == 0) {
4092 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4093 } else {
4094 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4096 break;
4097 #if defined(TARGET_MIPS64)
4098 case OPC_DADD:
4100 TCGv t0 = tcg_temp_local_new();
4101 TCGv t1 = tcg_temp_new();
4102 TCGv t2 = tcg_temp_new();
4103 TCGLabel *l1 = gen_new_label();
4105 gen_load_gpr(t1, rs);
4106 gen_load_gpr(t2, rt);
4107 tcg_gen_add_tl(t0, t1, t2);
4108 tcg_gen_xor_tl(t1, t1, t2);
4109 tcg_gen_xor_tl(t2, t0, t2);
4110 tcg_gen_andc_tl(t1, t2, t1);
4111 tcg_temp_free(t2);
4112 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4113 tcg_temp_free(t1);
4114 /* operands of same sign, result different sign */
4115 generate_exception(ctx, EXCP_OVERFLOW);
4116 gen_set_label(l1);
4117 gen_store_gpr(t0, rd);
4118 tcg_temp_free(t0);
4120 break;
4121 case OPC_DADDU:
4122 if (rs != 0 && rt != 0) {
4123 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4124 } else if (rs == 0 && rt != 0) {
4125 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4126 } else if (rs != 0 && rt == 0) {
4127 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4128 } else {
4129 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4131 break;
4132 case OPC_DSUB:
4134 TCGv t0 = tcg_temp_local_new();
4135 TCGv t1 = tcg_temp_new();
4136 TCGv t2 = tcg_temp_new();
4137 TCGLabel *l1 = gen_new_label();
4139 gen_load_gpr(t1, rs);
4140 gen_load_gpr(t2, rt);
4141 tcg_gen_sub_tl(t0, t1, t2);
4142 tcg_gen_xor_tl(t2, t1, t2);
4143 tcg_gen_xor_tl(t1, t0, t1);
4144 tcg_gen_and_tl(t1, t1, t2);
4145 tcg_temp_free(t2);
4146 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4147 tcg_temp_free(t1);
4149 * Operands of different sign, first operand and result different
4150 * sign.
4152 generate_exception(ctx, EXCP_OVERFLOW);
4153 gen_set_label(l1);
4154 gen_store_gpr(t0, rd);
4155 tcg_temp_free(t0);
4157 break;
4158 case OPC_DSUBU:
4159 if (rs != 0 && rt != 0) {
4160 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4161 } else if (rs == 0 && rt != 0) {
4162 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4163 } else if (rs != 0 && rt == 0) {
4164 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4165 } else {
4166 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4168 break;
4169 #endif
4170 case OPC_MUL:
4171 if (likely(rs != 0 && rt != 0)) {
4172 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4173 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4174 } else {
4175 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4177 break;
4181 /* Conditional move */
4182 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
4183 int rd, int rs, int rt)
4185 TCGv t0, t1, t2;
4187 if (rd == 0) {
4188 /* If no destination, treat it as a NOP. */
4189 return;
4192 t0 = tcg_temp_new();
4193 gen_load_gpr(t0, rt);
4194 t1 = tcg_const_tl(0);
4195 t2 = tcg_temp_new();
4196 gen_load_gpr(t2, rs);
4197 switch (opc) {
4198 case OPC_MOVN:
4199 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4200 break;
4201 case OPC_MOVZ:
4202 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4203 break;
4204 case OPC_SELNEZ:
4205 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
4206 break;
4207 case OPC_SELEQZ:
4208 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
4209 break;
4211 tcg_temp_free(t2);
4212 tcg_temp_free(t1);
4213 tcg_temp_free(t0);
4216 /* Logic */
4217 static void gen_logic(DisasContext *ctx, uint32_t opc,
4218 int rd, int rs, int rt)
4220 if (rd == 0) {
4221 /* If no destination, treat it as a NOP. */
4222 return;
4225 switch (opc) {
4226 case OPC_AND:
4227 if (likely(rs != 0 && rt != 0)) {
4228 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4229 } else {
4230 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4232 break;
4233 case OPC_NOR:
4234 if (rs != 0 && rt != 0) {
4235 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4236 } else if (rs == 0 && rt != 0) {
4237 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
4238 } else if (rs != 0 && rt == 0) {
4239 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
4240 } else {
4241 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
4243 break;
4244 case OPC_OR:
4245 if (likely(rs != 0 && rt != 0)) {
4246 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4247 } else if (rs == 0 && rt != 0) {
4248 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4249 } else if (rs != 0 && rt == 0) {
4250 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4251 } else {
4252 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4254 break;
4255 case OPC_XOR:
4256 if (likely(rs != 0 && rt != 0)) {
4257 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4258 } else if (rs == 0 && rt != 0) {
4259 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4260 } else if (rs != 0 && rt == 0) {
4261 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4262 } else {
4263 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4265 break;
4269 /* Set on lower than */
4270 static void gen_slt(DisasContext *ctx, uint32_t opc,
4271 int rd, int rs, int rt)
4273 TCGv t0, t1;
4275 if (rd == 0) {
4276 /* If no destination, treat it as a NOP. */
4277 return;
4280 t0 = tcg_temp_new();
4281 t1 = tcg_temp_new();
4282 gen_load_gpr(t0, rs);
4283 gen_load_gpr(t1, rt);
4284 switch (opc) {
4285 case OPC_SLT:
4286 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
4287 break;
4288 case OPC_SLTU:
4289 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
4290 break;
4292 tcg_temp_free(t0);
4293 tcg_temp_free(t1);
4296 /* Shifts */
4297 static void gen_shift(DisasContext *ctx, uint32_t opc,
4298 int rd, int rs, int rt)
4300 TCGv t0, t1;
4302 if (rd == 0) {
4304 * If no destination, treat it as a NOP.
4305 * For add & sub, we must generate the overflow exception when needed.
4307 return;
4310 t0 = tcg_temp_new();
4311 t1 = tcg_temp_new();
4312 gen_load_gpr(t0, rs);
4313 gen_load_gpr(t1, rt);
4314 switch (opc) {
4315 case OPC_SLLV:
4316 tcg_gen_andi_tl(t0, t0, 0x1f);
4317 tcg_gen_shl_tl(t0, t1, t0);
4318 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4319 break;
4320 case OPC_SRAV:
4321 tcg_gen_andi_tl(t0, t0, 0x1f);
4322 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4323 break;
4324 case OPC_SRLV:
4325 tcg_gen_ext32u_tl(t1, t1);
4326 tcg_gen_andi_tl(t0, t0, 0x1f);
4327 tcg_gen_shr_tl(t0, t1, t0);
4328 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4329 break;
4330 case OPC_ROTRV:
4332 TCGv_i32 t2 = tcg_temp_new_i32();
4333 TCGv_i32 t3 = tcg_temp_new_i32();
4335 tcg_gen_trunc_tl_i32(t2, t0);
4336 tcg_gen_trunc_tl_i32(t3, t1);
4337 tcg_gen_andi_i32(t2, t2, 0x1f);
4338 tcg_gen_rotr_i32(t2, t3, t2);
4339 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4340 tcg_temp_free_i32(t2);
4341 tcg_temp_free_i32(t3);
4343 break;
4344 #if defined(TARGET_MIPS64)
4345 case OPC_DSLLV:
4346 tcg_gen_andi_tl(t0, t0, 0x3f);
4347 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
4348 break;
4349 case OPC_DSRAV:
4350 tcg_gen_andi_tl(t0, t0, 0x3f);
4351 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4352 break;
4353 case OPC_DSRLV:
4354 tcg_gen_andi_tl(t0, t0, 0x3f);
4355 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
4356 break;
4357 case OPC_DROTRV:
4358 tcg_gen_andi_tl(t0, t0, 0x3f);
4359 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
4360 break;
4361 #endif
4363 tcg_temp_free(t0);
4364 tcg_temp_free(t1);
4367 #if defined(TARGET_MIPS64)
4368 /* Copy GPR to and from TX79 HI1/LO1 register. */
4369 static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg)
4371 if (reg == 0 && (opc == MMI_OPC_MFHI1 || opc == MMI_OPC_MFLO1)) {
4372 /* Treat as NOP. */
4373 return;
4376 switch (opc) {
4377 case MMI_OPC_MFHI1:
4378 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[1]);
4379 break;
4380 case MMI_OPC_MFLO1:
4381 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[1]);
4382 break;
4383 case MMI_OPC_MTHI1:
4384 if (reg != 0) {
4385 tcg_gen_mov_tl(cpu_HI[1], cpu_gpr[reg]);
4386 } else {
4387 tcg_gen_movi_tl(cpu_HI[1], 0);
4389 break;
4390 case MMI_OPC_MTLO1:
4391 if (reg != 0) {
4392 tcg_gen_mov_tl(cpu_LO[1], cpu_gpr[reg]);
4393 } else {
4394 tcg_gen_movi_tl(cpu_LO[1], 0);
4396 break;
4397 default:
4398 MIPS_INVAL("mfthilo1 TX79");
4399 gen_reserved_instruction(ctx);
4400 break;
4403 #endif
4405 /* Arithmetic on HI/LO registers */
4406 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
4408 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
4409 /* Treat as NOP. */
4410 return;
4413 if (acc != 0) {
4414 check_dsp(ctx);
4417 switch (opc) {
4418 case OPC_MFHI:
4419 #if defined(TARGET_MIPS64)
4420 if (acc != 0) {
4421 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
4422 } else
4423 #endif
4425 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
4427 break;
4428 case OPC_MFLO:
4429 #if defined(TARGET_MIPS64)
4430 if (acc != 0) {
4431 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
4432 } else
4433 #endif
4435 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
4437 break;
4438 case OPC_MTHI:
4439 if (reg != 0) {
4440 #if defined(TARGET_MIPS64)
4441 if (acc != 0) {
4442 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
4443 } else
4444 #endif
4446 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
4448 } else {
4449 tcg_gen_movi_tl(cpu_HI[acc], 0);
4451 break;
4452 case OPC_MTLO:
4453 if (reg != 0) {
4454 #if defined(TARGET_MIPS64)
4455 if (acc != 0) {
4456 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
4457 } else
4458 #endif
4460 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
4462 } else {
4463 tcg_gen_movi_tl(cpu_LO[acc], 0);
4465 break;
4469 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
4470 MemOp memop)
4472 TCGv t0 = tcg_const_tl(addr);
4473 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
4474 gen_store_gpr(t0, reg);
4475 tcg_temp_free(t0);
4478 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
4479 int rs)
4481 target_long offset;
4482 target_long addr;
4484 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
4485 case OPC_ADDIUPC:
4486 if (rs != 0) {
4487 offset = sextract32(ctx->opcode << 2, 0, 21);
4488 addr = addr_add(ctx, pc, offset);
4489 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4491 break;
4492 case R6_OPC_LWPC:
4493 offset = sextract32(ctx->opcode << 2, 0, 21);
4494 addr = addr_add(ctx, pc, offset);
4495 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4496 break;
4497 #if defined(TARGET_MIPS64)
4498 case OPC_LWUPC:
4499 check_mips_64(ctx);
4500 offset = sextract32(ctx->opcode << 2, 0, 21);
4501 addr = addr_add(ctx, pc, offset);
4502 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4503 break;
4504 #endif
4505 default:
4506 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
4507 case OPC_AUIPC:
4508 if (rs != 0) {
4509 offset = sextract32(ctx->opcode, 0, 16) << 16;
4510 addr = addr_add(ctx, pc, offset);
4511 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4513 break;
4514 case OPC_ALUIPC:
4515 if (rs != 0) {
4516 offset = sextract32(ctx->opcode, 0, 16) << 16;
4517 addr = ~0xFFFF & addr_add(ctx, pc, offset);
4518 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4520 break;
4521 #if defined(TARGET_MIPS64)
4522 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4523 case R6_OPC_LDPC + (1 << 16):
4524 case R6_OPC_LDPC + (2 << 16):
4525 case R6_OPC_LDPC + (3 << 16):
4526 check_mips_64(ctx);
4527 offset = sextract32(ctx->opcode << 3, 0, 21);
4528 addr = addr_add(ctx, (pc & ~0x7), offset);
4529 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4530 break;
4531 #endif
4532 default:
4533 MIPS_INVAL("OPC_PCREL");
4534 gen_reserved_instruction(ctx);
4535 break;
4537 break;
4541 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4543 TCGv t0, t1;
4545 if (rd == 0) {
4546 /* Treat as NOP. */
4547 return;
4550 t0 = tcg_temp_new();
4551 t1 = tcg_temp_new();
4553 gen_load_gpr(t0, rs);
4554 gen_load_gpr(t1, rt);
4556 switch (opc) {
4557 case R6_OPC_DIV:
4559 TCGv t2 = tcg_temp_new();
4560 TCGv t3 = tcg_temp_new();
4561 tcg_gen_ext32s_tl(t0, t0);
4562 tcg_gen_ext32s_tl(t1, t1);
4563 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4564 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4565 tcg_gen_and_tl(t2, t2, t3);
4566 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4567 tcg_gen_or_tl(t2, t2, t3);
4568 tcg_gen_movi_tl(t3, 0);
4569 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4570 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4571 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4572 tcg_temp_free(t3);
4573 tcg_temp_free(t2);
4575 break;
4576 case R6_OPC_MOD:
4578 TCGv t2 = tcg_temp_new();
4579 TCGv t3 = tcg_temp_new();
4580 tcg_gen_ext32s_tl(t0, t0);
4581 tcg_gen_ext32s_tl(t1, t1);
4582 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4583 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4584 tcg_gen_and_tl(t2, t2, t3);
4585 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4586 tcg_gen_or_tl(t2, t2, t3);
4587 tcg_gen_movi_tl(t3, 0);
4588 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4589 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4590 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4591 tcg_temp_free(t3);
4592 tcg_temp_free(t2);
4594 break;
4595 case R6_OPC_DIVU:
4597 TCGv t2 = tcg_const_tl(0);
4598 TCGv t3 = tcg_const_tl(1);
4599 tcg_gen_ext32u_tl(t0, t0);
4600 tcg_gen_ext32u_tl(t1, t1);
4601 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4602 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4603 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4604 tcg_temp_free(t3);
4605 tcg_temp_free(t2);
4607 break;
4608 case R6_OPC_MODU:
4610 TCGv t2 = tcg_const_tl(0);
4611 TCGv t3 = tcg_const_tl(1);
4612 tcg_gen_ext32u_tl(t0, t0);
4613 tcg_gen_ext32u_tl(t1, t1);
4614 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4615 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4616 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4617 tcg_temp_free(t3);
4618 tcg_temp_free(t2);
4620 break;
4621 case R6_OPC_MUL:
4623 TCGv_i32 t2 = tcg_temp_new_i32();
4624 TCGv_i32 t3 = tcg_temp_new_i32();
4625 tcg_gen_trunc_tl_i32(t2, t0);
4626 tcg_gen_trunc_tl_i32(t3, t1);
4627 tcg_gen_mul_i32(t2, t2, t3);
4628 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4629 tcg_temp_free_i32(t2);
4630 tcg_temp_free_i32(t3);
4632 break;
4633 case R6_OPC_MUH:
4635 TCGv_i32 t2 = tcg_temp_new_i32();
4636 TCGv_i32 t3 = tcg_temp_new_i32();
4637 tcg_gen_trunc_tl_i32(t2, t0);
4638 tcg_gen_trunc_tl_i32(t3, t1);
4639 tcg_gen_muls2_i32(t2, t3, t2, t3);
4640 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4641 tcg_temp_free_i32(t2);
4642 tcg_temp_free_i32(t3);
4644 break;
4645 case R6_OPC_MULU:
4647 TCGv_i32 t2 = tcg_temp_new_i32();
4648 TCGv_i32 t3 = tcg_temp_new_i32();
4649 tcg_gen_trunc_tl_i32(t2, t0);
4650 tcg_gen_trunc_tl_i32(t3, t1);
4651 tcg_gen_mul_i32(t2, t2, t3);
4652 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4653 tcg_temp_free_i32(t2);
4654 tcg_temp_free_i32(t3);
4656 break;
4657 case R6_OPC_MUHU:
4659 TCGv_i32 t2 = tcg_temp_new_i32();
4660 TCGv_i32 t3 = tcg_temp_new_i32();
4661 tcg_gen_trunc_tl_i32(t2, t0);
4662 tcg_gen_trunc_tl_i32(t3, t1);
4663 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4664 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4665 tcg_temp_free_i32(t2);
4666 tcg_temp_free_i32(t3);
4668 break;
4669 #if defined(TARGET_MIPS64)
4670 case R6_OPC_DDIV:
4672 TCGv t2 = tcg_temp_new();
4673 TCGv t3 = tcg_temp_new();
4674 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4675 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4676 tcg_gen_and_tl(t2, t2, t3);
4677 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4678 tcg_gen_or_tl(t2, t2, t3);
4679 tcg_gen_movi_tl(t3, 0);
4680 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4681 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4682 tcg_temp_free(t3);
4683 tcg_temp_free(t2);
4685 break;
4686 case R6_OPC_DMOD:
4688 TCGv t2 = tcg_temp_new();
4689 TCGv t3 = tcg_temp_new();
4690 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4691 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4692 tcg_gen_and_tl(t2, t2, t3);
4693 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4694 tcg_gen_or_tl(t2, t2, t3);
4695 tcg_gen_movi_tl(t3, 0);
4696 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4697 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4698 tcg_temp_free(t3);
4699 tcg_temp_free(t2);
4701 break;
4702 case R6_OPC_DDIVU:
4704 TCGv t2 = tcg_const_tl(0);
4705 TCGv t3 = tcg_const_tl(1);
4706 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4707 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4708 tcg_temp_free(t3);
4709 tcg_temp_free(t2);
4711 break;
4712 case R6_OPC_DMODU:
4714 TCGv t2 = tcg_const_tl(0);
4715 TCGv t3 = tcg_const_tl(1);
4716 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4717 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4718 tcg_temp_free(t3);
4719 tcg_temp_free(t2);
4721 break;
4722 case R6_OPC_DMUL:
4723 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4724 break;
4725 case R6_OPC_DMUH:
4727 TCGv t2 = tcg_temp_new();
4728 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4729 tcg_temp_free(t2);
4731 break;
4732 case R6_OPC_DMULU:
4733 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4734 break;
4735 case R6_OPC_DMUHU:
4737 TCGv t2 = tcg_temp_new();
4738 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4739 tcg_temp_free(t2);
4741 break;
4742 #endif
4743 default:
4744 MIPS_INVAL("r6 mul/div");
4745 gen_reserved_instruction(ctx);
4746 goto out;
4748 out:
4749 tcg_temp_free(t0);
4750 tcg_temp_free(t1);
4753 #if defined(TARGET_MIPS64)
4754 static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
4756 TCGv t0, t1;
4758 t0 = tcg_temp_new();
4759 t1 = tcg_temp_new();
4761 gen_load_gpr(t0, rs);
4762 gen_load_gpr(t1, rt);
4764 switch (opc) {
4765 case MMI_OPC_DIV1:
4767 TCGv t2 = tcg_temp_new();
4768 TCGv t3 = tcg_temp_new();
4769 tcg_gen_ext32s_tl(t0, t0);
4770 tcg_gen_ext32s_tl(t1, t1);
4771 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4772 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4773 tcg_gen_and_tl(t2, t2, t3);
4774 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4775 tcg_gen_or_tl(t2, t2, t3);
4776 tcg_gen_movi_tl(t3, 0);
4777 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4778 tcg_gen_div_tl(cpu_LO[1], t0, t1);
4779 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
4780 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4781 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4782 tcg_temp_free(t3);
4783 tcg_temp_free(t2);
4785 break;
4786 case MMI_OPC_DIVU1:
4788 TCGv t2 = tcg_const_tl(0);
4789 TCGv t3 = tcg_const_tl(1);
4790 tcg_gen_ext32u_tl(t0, t0);
4791 tcg_gen_ext32u_tl(t1, t1);
4792 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4793 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
4794 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
4795 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4796 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4797 tcg_temp_free(t3);
4798 tcg_temp_free(t2);
4800 break;
4801 default:
4802 MIPS_INVAL("div1 TX79");
4803 gen_reserved_instruction(ctx);
4804 goto out;
4806 out:
4807 tcg_temp_free(t0);
4808 tcg_temp_free(t1);
4810 #endif
4812 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4813 int acc, int rs, int rt)
4815 TCGv t0, t1;
4817 t0 = tcg_temp_new();
4818 t1 = tcg_temp_new();
4820 gen_load_gpr(t0, rs);
4821 gen_load_gpr(t1, rt);
4823 if (acc != 0) {
4824 check_dsp(ctx);
4827 switch (opc) {
4828 case OPC_DIV:
4830 TCGv t2 = tcg_temp_new();
4831 TCGv t3 = tcg_temp_new();
4832 tcg_gen_ext32s_tl(t0, t0);
4833 tcg_gen_ext32s_tl(t1, t1);
4834 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4835 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4836 tcg_gen_and_tl(t2, t2, t3);
4837 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4838 tcg_gen_or_tl(t2, t2, t3);
4839 tcg_gen_movi_tl(t3, 0);
4840 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4841 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4842 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4843 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4844 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4845 tcg_temp_free(t3);
4846 tcg_temp_free(t2);
4848 break;
4849 case OPC_DIVU:
4851 TCGv t2 = tcg_const_tl(0);
4852 TCGv t3 = tcg_const_tl(1);
4853 tcg_gen_ext32u_tl(t0, t0);
4854 tcg_gen_ext32u_tl(t1, t1);
4855 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4856 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4857 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4858 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4859 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4860 tcg_temp_free(t3);
4861 tcg_temp_free(t2);
4863 break;
4864 case OPC_MULT:
4866 TCGv_i32 t2 = tcg_temp_new_i32();
4867 TCGv_i32 t3 = tcg_temp_new_i32();
4868 tcg_gen_trunc_tl_i32(t2, t0);
4869 tcg_gen_trunc_tl_i32(t3, t1);
4870 tcg_gen_muls2_i32(t2, t3, t2, t3);
4871 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4872 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4873 tcg_temp_free_i32(t2);
4874 tcg_temp_free_i32(t3);
4876 break;
4877 case OPC_MULTU:
4879 TCGv_i32 t2 = tcg_temp_new_i32();
4880 TCGv_i32 t3 = tcg_temp_new_i32();
4881 tcg_gen_trunc_tl_i32(t2, t0);
4882 tcg_gen_trunc_tl_i32(t3, t1);
4883 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4884 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4885 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4886 tcg_temp_free_i32(t2);
4887 tcg_temp_free_i32(t3);
4889 break;
4890 #if defined(TARGET_MIPS64)
4891 case OPC_DDIV:
4893 TCGv t2 = tcg_temp_new();
4894 TCGv t3 = tcg_temp_new();
4895 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4896 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4897 tcg_gen_and_tl(t2, t2, t3);
4898 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4899 tcg_gen_or_tl(t2, t2, t3);
4900 tcg_gen_movi_tl(t3, 0);
4901 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4902 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4903 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4904 tcg_temp_free(t3);
4905 tcg_temp_free(t2);
4907 break;
4908 case OPC_DDIVU:
4910 TCGv t2 = tcg_const_tl(0);
4911 TCGv t3 = tcg_const_tl(1);
4912 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4913 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
4914 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
4915 tcg_temp_free(t3);
4916 tcg_temp_free(t2);
4918 break;
4919 case OPC_DMULT:
4920 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4921 break;
4922 case OPC_DMULTU:
4923 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4924 break;
4925 #endif
4926 case OPC_MADD:
4928 TCGv_i64 t2 = tcg_temp_new_i64();
4929 TCGv_i64 t3 = tcg_temp_new_i64();
4931 tcg_gen_ext_tl_i64(t2, t0);
4932 tcg_gen_ext_tl_i64(t3, t1);
4933 tcg_gen_mul_i64(t2, t2, t3);
4934 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4935 tcg_gen_add_i64(t2, t2, t3);
4936 tcg_temp_free_i64(t3);
4937 gen_move_low32(cpu_LO[acc], t2);
4938 gen_move_high32(cpu_HI[acc], t2);
4939 tcg_temp_free_i64(t2);
4941 break;
4942 case OPC_MADDU:
4944 TCGv_i64 t2 = tcg_temp_new_i64();
4945 TCGv_i64 t3 = tcg_temp_new_i64();
4947 tcg_gen_ext32u_tl(t0, t0);
4948 tcg_gen_ext32u_tl(t1, t1);
4949 tcg_gen_extu_tl_i64(t2, t0);
4950 tcg_gen_extu_tl_i64(t3, t1);
4951 tcg_gen_mul_i64(t2, t2, t3);
4952 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4953 tcg_gen_add_i64(t2, t2, t3);
4954 tcg_temp_free_i64(t3);
4955 gen_move_low32(cpu_LO[acc], t2);
4956 gen_move_high32(cpu_HI[acc], t2);
4957 tcg_temp_free_i64(t2);
4959 break;
4960 case OPC_MSUB:
4962 TCGv_i64 t2 = tcg_temp_new_i64();
4963 TCGv_i64 t3 = tcg_temp_new_i64();
4965 tcg_gen_ext_tl_i64(t2, t0);
4966 tcg_gen_ext_tl_i64(t3, t1);
4967 tcg_gen_mul_i64(t2, t2, t3);
4968 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4969 tcg_gen_sub_i64(t2, t3, t2);
4970 tcg_temp_free_i64(t3);
4971 gen_move_low32(cpu_LO[acc], t2);
4972 gen_move_high32(cpu_HI[acc], t2);
4973 tcg_temp_free_i64(t2);
4975 break;
4976 case OPC_MSUBU:
4978 TCGv_i64 t2 = tcg_temp_new_i64();
4979 TCGv_i64 t3 = tcg_temp_new_i64();
4981 tcg_gen_ext32u_tl(t0, t0);
4982 tcg_gen_ext32u_tl(t1, t1);
4983 tcg_gen_extu_tl_i64(t2, t0);
4984 tcg_gen_extu_tl_i64(t3, t1);
4985 tcg_gen_mul_i64(t2, t2, t3);
4986 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4987 tcg_gen_sub_i64(t2, t3, t2);
4988 tcg_temp_free_i64(t3);
4989 gen_move_low32(cpu_LO[acc], t2);
4990 gen_move_high32(cpu_HI[acc], t2);
4991 tcg_temp_free_i64(t2);
4993 break;
4994 default:
4995 MIPS_INVAL("mul/div");
4996 gen_reserved_instruction(ctx);
4997 goto out;
4999 out:
5000 tcg_temp_free(t0);
5001 tcg_temp_free(t1);
5005 * These MULT[U] and MADD[U] instructions implemented in for example
5006 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
5007 * architectures are special three-operand variants with the syntax
5009 * MULT[U][1] rd, rs, rt
5011 * such that
5013 * (rd, LO, HI) <- rs * rt
5015 * and
5017 * MADD[U][1] rd, rs, rt
5019 * such that
5021 * (rd, LO, HI) <- (LO, HI) + rs * rt
5023 * where the low-order 32-bits of the result is placed into both the
5024 * GPR rd and the special register LO. The high-order 32-bits of the
5025 * result is placed into the special register HI.
5027 * If the GPR rd is omitted in assembly language, it is taken to be 0,
5028 * which is the zero register that always reads as 0.
5030 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
5031 int rd, int rs, int rt)
5033 TCGv t0 = tcg_temp_new();
5034 TCGv t1 = tcg_temp_new();
5035 int acc = 0;
5037 gen_load_gpr(t0, rs);
5038 gen_load_gpr(t1, rt);
5040 switch (opc) {
5041 case MMI_OPC_MULT1:
5042 acc = 1;
5043 /* Fall through */
5044 case OPC_MULT:
5046 TCGv_i32 t2 = tcg_temp_new_i32();
5047 TCGv_i32 t3 = tcg_temp_new_i32();
5048 tcg_gen_trunc_tl_i32(t2, t0);
5049 tcg_gen_trunc_tl_i32(t3, t1);
5050 tcg_gen_muls2_i32(t2, t3, t2, t3);
5051 if (rd) {
5052 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5054 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5055 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5056 tcg_temp_free_i32(t2);
5057 tcg_temp_free_i32(t3);
5059 break;
5060 case MMI_OPC_MULTU1:
5061 acc = 1;
5062 /* Fall through */
5063 case OPC_MULTU:
5065 TCGv_i32 t2 = tcg_temp_new_i32();
5066 TCGv_i32 t3 = tcg_temp_new_i32();
5067 tcg_gen_trunc_tl_i32(t2, t0);
5068 tcg_gen_trunc_tl_i32(t3, t1);
5069 tcg_gen_mulu2_i32(t2, t3, t2, t3);
5070 if (rd) {
5071 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5073 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5074 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5075 tcg_temp_free_i32(t2);
5076 tcg_temp_free_i32(t3);
5078 break;
5079 case MMI_OPC_MADD1:
5080 acc = 1;
5081 /* Fall through */
5082 case MMI_OPC_MADD:
5084 TCGv_i64 t2 = tcg_temp_new_i64();
5085 TCGv_i64 t3 = tcg_temp_new_i64();
5087 tcg_gen_ext_tl_i64(t2, t0);
5088 tcg_gen_ext_tl_i64(t3, t1);
5089 tcg_gen_mul_i64(t2, t2, t3);
5090 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5091 tcg_gen_add_i64(t2, t2, t3);
5092 tcg_temp_free_i64(t3);
5093 gen_move_low32(cpu_LO[acc], t2);
5094 gen_move_high32(cpu_HI[acc], t2);
5095 if (rd) {
5096 gen_move_low32(cpu_gpr[rd], t2);
5098 tcg_temp_free_i64(t2);
5100 break;
5101 case MMI_OPC_MADDU1:
5102 acc = 1;
5103 /* Fall through */
5104 case MMI_OPC_MADDU:
5106 TCGv_i64 t2 = tcg_temp_new_i64();
5107 TCGv_i64 t3 = tcg_temp_new_i64();
5109 tcg_gen_ext32u_tl(t0, t0);
5110 tcg_gen_ext32u_tl(t1, t1);
5111 tcg_gen_extu_tl_i64(t2, t0);
5112 tcg_gen_extu_tl_i64(t3, t1);
5113 tcg_gen_mul_i64(t2, t2, t3);
5114 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5115 tcg_gen_add_i64(t2, t2, t3);
5116 tcg_temp_free_i64(t3);
5117 gen_move_low32(cpu_LO[acc], t2);
5118 gen_move_high32(cpu_HI[acc], t2);
5119 if (rd) {
5120 gen_move_low32(cpu_gpr[rd], t2);
5122 tcg_temp_free_i64(t2);
5124 break;
5125 default:
5126 MIPS_INVAL("mul/madd TXx9");
5127 gen_reserved_instruction(ctx);
5128 goto out;
5131 out:
5132 tcg_temp_free(t0);
5133 tcg_temp_free(t1);
5136 static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc,
5137 int rd, int rs, int rt)
5139 TCGv t0 = tcg_temp_new();
5140 TCGv t1 = tcg_temp_new();
5142 gen_load_gpr(t0, rs);
5143 gen_load_gpr(t1, rt);
5145 switch (opc) {
5146 case OPC_VR54XX_MULS:
5147 gen_helper_muls(t0, cpu_env, t0, t1);
5148 break;
5149 case OPC_VR54XX_MULSU:
5150 gen_helper_mulsu(t0, cpu_env, t0, t1);
5151 break;
5152 case OPC_VR54XX_MACC:
5153 gen_helper_macc(t0, cpu_env, t0, t1);
5154 break;
5155 case OPC_VR54XX_MACCU:
5156 gen_helper_maccu(t0, cpu_env, t0, t1);
5157 break;
5158 case OPC_VR54XX_MSAC:
5159 gen_helper_msac(t0, cpu_env, t0, t1);
5160 break;
5161 case OPC_VR54XX_MSACU:
5162 gen_helper_msacu(t0, cpu_env, t0, t1);
5163 break;
5164 case OPC_VR54XX_MULHI:
5165 gen_helper_mulhi(t0, cpu_env, t0, t1);
5166 break;
5167 case OPC_VR54XX_MULHIU:
5168 gen_helper_mulhiu(t0, cpu_env, t0, t1);
5169 break;
5170 case OPC_VR54XX_MULSHI:
5171 gen_helper_mulshi(t0, cpu_env, t0, t1);
5172 break;
5173 case OPC_VR54XX_MULSHIU:
5174 gen_helper_mulshiu(t0, cpu_env, t0, t1);
5175 break;
5176 case OPC_VR54XX_MACCHI:
5177 gen_helper_macchi(t0, cpu_env, t0, t1);
5178 break;
5179 case OPC_VR54XX_MACCHIU:
5180 gen_helper_macchiu(t0, cpu_env, t0, t1);
5181 break;
5182 case OPC_VR54XX_MSACHI:
5183 gen_helper_msachi(t0, cpu_env, t0, t1);
5184 break;
5185 case OPC_VR54XX_MSACHIU:
5186 gen_helper_msachiu(t0, cpu_env, t0, t1);
5187 break;
5188 default:
5189 MIPS_INVAL("mul vr54xx");
5190 gen_reserved_instruction(ctx);
5191 goto out;
5193 gen_store_gpr(t0, rd);
5195 out:
5196 tcg_temp_free(t0);
5197 tcg_temp_free(t1);
5200 static void gen_cl(DisasContext *ctx, uint32_t opc,
5201 int rd, int rs)
5203 TCGv t0;
5205 if (rd == 0) {
5206 /* Treat as NOP. */
5207 return;
5209 t0 = cpu_gpr[rd];
5210 gen_load_gpr(t0, rs);
5212 switch (opc) {
5213 case OPC_CLO:
5214 case R6_OPC_CLO:
5215 #if defined(TARGET_MIPS64)
5216 case OPC_DCLO:
5217 case R6_OPC_DCLO:
5218 #endif
5219 tcg_gen_not_tl(t0, t0);
5220 break;
5223 switch (opc) {
5224 case OPC_CLO:
5225 case R6_OPC_CLO:
5226 case OPC_CLZ:
5227 case R6_OPC_CLZ:
5228 tcg_gen_ext32u_tl(t0, t0);
5229 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
5230 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
5231 break;
5232 #if defined(TARGET_MIPS64)
5233 case OPC_DCLO:
5234 case R6_OPC_DCLO:
5235 case OPC_DCLZ:
5236 case R6_OPC_DCLZ:
5237 tcg_gen_clzi_i64(t0, t0, 64);
5238 break;
5239 #endif
5243 /* Godson integer instructions */
5244 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
5245 int rd, int rs, int rt)
5247 TCGv t0, t1;
5249 if (rd == 0) {
5250 /* Treat as NOP. */
5251 return;
5254 switch (opc) {
5255 case OPC_MULT_G_2E:
5256 case OPC_MULT_G_2F:
5257 case OPC_MULTU_G_2E:
5258 case OPC_MULTU_G_2F:
5259 #if defined(TARGET_MIPS64)
5260 case OPC_DMULT_G_2E:
5261 case OPC_DMULT_G_2F:
5262 case OPC_DMULTU_G_2E:
5263 case OPC_DMULTU_G_2F:
5264 #endif
5265 t0 = tcg_temp_new();
5266 t1 = tcg_temp_new();
5267 break;
5268 default:
5269 t0 = tcg_temp_local_new();
5270 t1 = tcg_temp_local_new();
5271 break;
5274 gen_load_gpr(t0, rs);
5275 gen_load_gpr(t1, rt);
5277 switch (opc) {
5278 case OPC_MULT_G_2E:
5279 case OPC_MULT_G_2F:
5280 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5281 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5282 break;
5283 case OPC_MULTU_G_2E:
5284 case OPC_MULTU_G_2F:
5285 tcg_gen_ext32u_tl(t0, t0);
5286 tcg_gen_ext32u_tl(t1, t1);
5287 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5288 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5289 break;
5290 case OPC_DIV_G_2E:
5291 case OPC_DIV_G_2F:
5293 TCGLabel *l1 = gen_new_label();
5294 TCGLabel *l2 = gen_new_label();
5295 TCGLabel *l3 = gen_new_label();
5296 tcg_gen_ext32s_tl(t0, t0);
5297 tcg_gen_ext32s_tl(t1, t1);
5298 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5299 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5300 tcg_gen_br(l3);
5301 gen_set_label(l1);
5302 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5303 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5304 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5305 tcg_gen_br(l3);
5306 gen_set_label(l2);
5307 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5308 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5309 gen_set_label(l3);
5311 break;
5312 case OPC_DIVU_G_2E:
5313 case OPC_DIVU_G_2F:
5315 TCGLabel *l1 = gen_new_label();
5316 TCGLabel *l2 = gen_new_label();
5317 tcg_gen_ext32u_tl(t0, t0);
5318 tcg_gen_ext32u_tl(t1, t1);
5319 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5320 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5321 tcg_gen_br(l2);
5322 gen_set_label(l1);
5323 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5324 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5325 gen_set_label(l2);
5327 break;
5328 case OPC_MOD_G_2E:
5329 case OPC_MOD_G_2F:
5331 TCGLabel *l1 = gen_new_label();
5332 TCGLabel *l2 = gen_new_label();
5333 TCGLabel *l3 = gen_new_label();
5334 tcg_gen_ext32u_tl(t0, t0);
5335 tcg_gen_ext32u_tl(t1, t1);
5336 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5337 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5338 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5339 gen_set_label(l1);
5340 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5341 tcg_gen_br(l3);
5342 gen_set_label(l2);
5343 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5344 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5345 gen_set_label(l3);
5347 break;
5348 case OPC_MODU_G_2E:
5349 case OPC_MODU_G_2F:
5351 TCGLabel *l1 = gen_new_label();
5352 TCGLabel *l2 = gen_new_label();
5353 tcg_gen_ext32u_tl(t0, t0);
5354 tcg_gen_ext32u_tl(t1, t1);
5355 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5356 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5357 tcg_gen_br(l2);
5358 gen_set_label(l1);
5359 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5360 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5361 gen_set_label(l2);
5363 break;
5364 #if defined(TARGET_MIPS64)
5365 case OPC_DMULT_G_2E:
5366 case OPC_DMULT_G_2F:
5367 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5368 break;
5369 case OPC_DMULTU_G_2E:
5370 case OPC_DMULTU_G_2F:
5371 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5372 break;
5373 case OPC_DDIV_G_2E:
5374 case OPC_DDIV_G_2F:
5376 TCGLabel *l1 = gen_new_label();
5377 TCGLabel *l2 = gen_new_label();
5378 TCGLabel *l3 = gen_new_label();
5379 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5380 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5381 tcg_gen_br(l3);
5382 gen_set_label(l1);
5383 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5384 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5385 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5386 tcg_gen_br(l3);
5387 gen_set_label(l2);
5388 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5389 gen_set_label(l3);
5391 break;
5392 case OPC_DDIVU_G_2E:
5393 case OPC_DDIVU_G_2F:
5395 TCGLabel *l1 = gen_new_label();
5396 TCGLabel *l2 = gen_new_label();
5397 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5398 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5399 tcg_gen_br(l2);
5400 gen_set_label(l1);
5401 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5402 gen_set_label(l2);
5404 break;
5405 case OPC_DMOD_G_2E:
5406 case OPC_DMOD_G_2F:
5408 TCGLabel *l1 = gen_new_label();
5409 TCGLabel *l2 = gen_new_label();
5410 TCGLabel *l3 = gen_new_label();
5411 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5412 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5413 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5414 gen_set_label(l1);
5415 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5416 tcg_gen_br(l3);
5417 gen_set_label(l2);
5418 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5419 gen_set_label(l3);
5421 break;
5422 case OPC_DMODU_G_2E:
5423 case OPC_DMODU_G_2F:
5425 TCGLabel *l1 = gen_new_label();
5426 TCGLabel *l2 = gen_new_label();
5427 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5428 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5429 tcg_gen_br(l2);
5430 gen_set_label(l1);
5431 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5432 gen_set_label(l2);
5434 break;
5435 #endif
5438 tcg_temp_free(t0);
5439 tcg_temp_free(t1);
5442 /* Loongson multimedia instructions */
5443 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
5445 uint32_t opc, shift_max;
5446 TCGv_i64 t0, t1;
5447 TCGCond cond;
5449 opc = MASK_LMMI(ctx->opcode);
5450 switch (opc) {
5451 case OPC_ADD_CP2:
5452 case OPC_SUB_CP2:
5453 case OPC_DADD_CP2:
5454 case OPC_DSUB_CP2:
5455 t0 = tcg_temp_local_new_i64();
5456 t1 = tcg_temp_local_new_i64();
5457 break;
5458 default:
5459 t0 = tcg_temp_new_i64();
5460 t1 = tcg_temp_new_i64();
5461 break;
5464 check_cp1_enabled(ctx);
5465 gen_load_fpr64(ctx, t0, rs);
5466 gen_load_fpr64(ctx, t1, rt);
5468 switch (opc) {
5469 case OPC_PADDSH:
5470 gen_helper_paddsh(t0, t0, t1);
5471 break;
5472 case OPC_PADDUSH:
5473 gen_helper_paddush(t0, t0, t1);
5474 break;
5475 case OPC_PADDH:
5476 gen_helper_paddh(t0, t0, t1);
5477 break;
5478 case OPC_PADDW:
5479 gen_helper_paddw(t0, t0, t1);
5480 break;
5481 case OPC_PADDSB:
5482 gen_helper_paddsb(t0, t0, t1);
5483 break;
5484 case OPC_PADDUSB:
5485 gen_helper_paddusb(t0, t0, t1);
5486 break;
5487 case OPC_PADDB:
5488 gen_helper_paddb(t0, t0, t1);
5489 break;
5491 case OPC_PSUBSH:
5492 gen_helper_psubsh(t0, t0, t1);
5493 break;
5494 case OPC_PSUBUSH:
5495 gen_helper_psubush(t0, t0, t1);
5496 break;
5497 case OPC_PSUBH:
5498 gen_helper_psubh(t0, t0, t1);
5499 break;
5500 case OPC_PSUBW:
5501 gen_helper_psubw(t0, t0, t1);
5502 break;
5503 case OPC_PSUBSB:
5504 gen_helper_psubsb(t0, t0, t1);
5505 break;
5506 case OPC_PSUBUSB:
5507 gen_helper_psubusb(t0, t0, t1);
5508 break;
5509 case OPC_PSUBB:
5510 gen_helper_psubb(t0, t0, t1);
5511 break;
5513 case OPC_PSHUFH:
5514 gen_helper_pshufh(t0, t0, t1);
5515 break;
5516 case OPC_PACKSSWH:
5517 gen_helper_packsswh(t0, t0, t1);
5518 break;
5519 case OPC_PACKSSHB:
5520 gen_helper_packsshb(t0, t0, t1);
5521 break;
5522 case OPC_PACKUSHB:
5523 gen_helper_packushb(t0, t0, t1);
5524 break;
5526 case OPC_PUNPCKLHW:
5527 gen_helper_punpcklhw(t0, t0, t1);
5528 break;
5529 case OPC_PUNPCKHHW:
5530 gen_helper_punpckhhw(t0, t0, t1);
5531 break;
5532 case OPC_PUNPCKLBH:
5533 gen_helper_punpcklbh(t0, t0, t1);
5534 break;
5535 case OPC_PUNPCKHBH:
5536 gen_helper_punpckhbh(t0, t0, t1);
5537 break;
5538 case OPC_PUNPCKLWD:
5539 gen_helper_punpcklwd(t0, t0, t1);
5540 break;
5541 case OPC_PUNPCKHWD:
5542 gen_helper_punpckhwd(t0, t0, t1);
5543 break;
5545 case OPC_PAVGH:
5546 gen_helper_pavgh(t0, t0, t1);
5547 break;
5548 case OPC_PAVGB:
5549 gen_helper_pavgb(t0, t0, t1);
5550 break;
5551 case OPC_PMAXSH:
5552 gen_helper_pmaxsh(t0, t0, t1);
5553 break;
5554 case OPC_PMINSH:
5555 gen_helper_pminsh(t0, t0, t1);
5556 break;
5557 case OPC_PMAXUB:
5558 gen_helper_pmaxub(t0, t0, t1);
5559 break;
5560 case OPC_PMINUB:
5561 gen_helper_pminub(t0, t0, t1);
5562 break;
5564 case OPC_PCMPEQW:
5565 gen_helper_pcmpeqw(t0, t0, t1);
5566 break;
5567 case OPC_PCMPGTW:
5568 gen_helper_pcmpgtw(t0, t0, t1);
5569 break;
5570 case OPC_PCMPEQH:
5571 gen_helper_pcmpeqh(t0, t0, t1);
5572 break;
5573 case OPC_PCMPGTH:
5574 gen_helper_pcmpgth(t0, t0, t1);
5575 break;
5576 case OPC_PCMPEQB:
5577 gen_helper_pcmpeqb(t0, t0, t1);
5578 break;
5579 case OPC_PCMPGTB:
5580 gen_helper_pcmpgtb(t0, t0, t1);
5581 break;
5583 case OPC_PSLLW:
5584 gen_helper_psllw(t0, t0, t1);
5585 break;
5586 case OPC_PSLLH:
5587 gen_helper_psllh(t0, t0, t1);
5588 break;
5589 case OPC_PSRLW:
5590 gen_helper_psrlw(t0, t0, t1);
5591 break;
5592 case OPC_PSRLH:
5593 gen_helper_psrlh(t0, t0, t1);
5594 break;
5595 case OPC_PSRAW:
5596 gen_helper_psraw(t0, t0, t1);
5597 break;
5598 case OPC_PSRAH:
5599 gen_helper_psrah(t0, t0, t1);
5600 break;
5602 case OPC_PMULLH:
5603 gen_helper_pmullh(t0, t0, t1);
5604 break;
5605 case OPC_PMULHH:
5606 gen_helper_pmulhh(t0, t0, t1);
5607 break;
5608 case OPC_PMULHUH:
5609 gen_helper_pmulhuh(t0, t0, t1);
5610 break;
5611 case OPC_PMADDHW:
5612 gen_helper_pmaddhw(t0, t0, t1);
5613 break;
5615 case OPC_PASUBUB:
5616 gen_helper_pasubub(t0, t0, t1);
5617 break;
5618 case OPC_BIADD:
5619 gen_helper_biadd(t0, t0);
5620 break;
5621 case OPC_PMOVMSKB:
5622 gen_helper_pmovmskb(t0, t0);
5623 break;
5625 case OPC_PADDD:
5626 tcg_gen_add_i64(t0, t0, t1);
5627 break;
5628 case OPC_PSUBD:
5629 tcg_gen_sub_i64(t0, t0, t1);
5630 break;
5631 case OPC_XOR_CP2:
5632 tcg_gen_xor_i64(t0, t0, t1);
5633 break;
5634 case OPC_NOR_CP2:
5635 tcg_gen_nor_i64(t0, t0, t1);
5636 break;
5637 case OPC_AND_CP2:
5638 tcg_gen_and_i64(t0, t0, t1);
5639 break;
5640 case OPC_OR_CP2:
5641 tcg_gen_or_i64(t0, t0, t1);
5642 break;
5644 case OPC_PANDN:
5645 tcg_gen_andc_i64(t0, t1, t0);
5646 break;
5648 case OPC_PINSRH_0:
5649 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
5650 break;
5651 case OPC_PINSRH_1:
5652 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
5653 break;
5654 case OPC_PINSRH_2:
5655 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
5656 break;
5657 case OPC_PINSRH_3:
5658 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
5659 break;
5661 case OPC_PEXTRH:
5662 tcg_gen_andi_i64(t1, t1, 3);
5663 tcg_gen_shli_i64(t1, t1, 4);
5664 tcg_gen_shr_i64(t0, t0, t1);
5665 tcg_gen_ext16u_i64(t0, t0);
5666 break;
5668 case OPC_ADDU_CP2:
5669 tcg_gen_add_i64(t0, t0, t1);
5670 tcg_gen_ext32s_i64(t0, t0);
5671 break;
5672 case OPC_SUBU_CP2:
5673 tcg_gen_sub_i64(t0, t0, t1);
5674 tcg_gen_ext32s_i64(t0, t0);
5675 break;
5677 case OPC_SLL_CP2:
5678 shift_max = 32;
5679 goto do_shift;
5680 case OPC_SRL_CP2:
5681 shift_max = 32;
5682 goto do_shift;
5683 case OPC_SRA_CP2:
5684 shift_max = 32;
5685 goto do_shift;
5686 case OPC_DSLL_CP2:
5687 shift_max = 64;
5688 goto do_shift;
5689 case OPC_DSRL_CP2:
5690 shift_max = 64;
5691 goto do_shift;
5692 case OPC_DSRA_CP2:
5693 shift_max = 64;
5694 goto do_shift;
5695 do_shift:
5696 /* Make sure shift count isn't TCG undefined behaviour. */
5697 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5699 switch (opc) {
5700 case OPC_SLL_CP2:
5701 case OPC_DSLL_CP2:
5702 tcg_gen_shl_i64(t0, t0, t1);
5703 break;
5704 case OPC_SRA_CP2:
5705 case OPC_DSRA_CP2:
5707 * Since SRA is UndefinedResult without sign-extended inputs,
5708 * we can treat SRA and DSRA the same.
5710 tcg_gen_sar_i64(t0, t0, t1);
5711 break;
5712 case OPC_SRL_CP2:
5713 /* We want to shift in zeros for SRL; zero-extend first. */
5714 tcg_gen_ext32u_i64(t0, t0);
5715 /* FALLTHRU */
5716 case OPC_DSRL_CP2:
5717 tcg_gen_shr_i64(t0, t0, t1);
5718 break;
5721 if (shift_max == 32) {
5722 tcg_gen_ext32s_i64(t0, t0);
5725 /* Shifts larger than MAX produce zero. */
5726 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5727 tcg_gen_neg_i64(t1, t1);
5728 tcg_gen_and_i64(t0, t0, t1);
5729 break;
5731 case OPC_ADD_CP2:
5732 case OPC_DADD_CP2:
5734 TCGv_i64 t2 = tcg_temp_new_i64();
5735 TCGLabel *lab = gen_new_label();
5737 tcg_gen_mov_i64(t2, t0);
5738 tcg_gen_add_i64(t0, t1, t2);
5739 if (opc == OPC_ADD_CP2) {
5740 tcg_gen_ext32s_i64(t0, t0);
5742 tcg_gen_xor_i64(t1, t1, t2);
5743 tcg_gen_xor_i64(t2, t2, t0);
5744 tcg_gen_andc_i64(t1, t2, t1);
5745 tcg_temp_free_i64(t2);
5746 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5747 generate_exception(ctx, EXCP_OVERFLOW);
5748 gen_set_label(lab);
5749 break;
5752 case OPC_SUB_CP2:
5753 case OPC_DSUB_CP2:
5755 TCGv_i64 t2 = tcg_temp_new_i64();
5756 TCGLabel *lab = gen_new_label();
5758 tcg_gen_mov_i64(t2, t0);
5759 tcg_gen_sub_i64(t0, t1, t2);
5760 if (opc == OPC_SUB_CP2) {
5761 tcg_gen_ext32s_i64(t0, t0);
5763 tcg_gen_xor_i64(t1, t1, t2);
5764 tcg_gen_xor_i64(t2, t2, t0);
5765 tcg_gen_and_i64(t1, t1, t2);
5766 tcg_temp_free_i64(t2);
5767 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5768 generate_exception(ctx, EXCP_OVERFLOW);
5769 gen_set_label(lab);
5770 break;
5773 case OPC_PMULUW:
5774 tcg_gen_ext32u_i64(t0, t0);
5775 tcg_gen_ext32u_i64(t1, t1);
5776 tcg_gen_mul_i64(t0, t0, t1);
5777 break;
5779 case OPC_SEQU_CP2:
5780 case OPC_SEQ_CP2:
5781 cond = TCG_COND_EQ;
5782 goto do_cc_cond;
5783 break;
5784 case OPC_SLTU_CP2:
5785 cond = TCG_COND_LTU;
5786 goto do_cc_cond;
5787 break;
5788 case OPC_SLT_CP2:
5789 cond = TCG_COND_LT;
5790 goto do_cc_cond;
5791 break;
5792 case OPC_SLEU_CP2:
5793 cond = TCG_COND_LEU;
5794 goto do_cc_cond;
5795 break;
5796 case OPC_SLE_CP2:
5797 cond = TCG_COND_LE;
5798 do_cc_cond:
5800 int cc = (ctx->opcode >> 8) & 0x7;
5801 TCGv_i64 t64 = tcg_temp_new_i64();
5802 TCGv_i32 t32 = tcg_temp_new_i32();
5804 tcg_gen_setcond_i64(cond, t64, t0, t1);
5805 tcg_gen_extrl_i64_i32(t32, t64);
5806 tcg_gen_deposit_i32(fpu_fcr31, fpu_fcr31, t32,
5807 get_fp_bit(cc), 1);
5809 tcg_temp_free_i32(t32);
5810 tcg_temp_free_i64(t64);
5812 goto no_rd;
5813 break;
5814 default:
5815 MIPS_INVAL("loongson_cp2");
5816 gen_reserved_instruction(ctx);
5817 return;
5820 gen_store_fpr64(ctx, t0, rd);
5822 no_rd:
5823 tcg_temp_free_i64(t0);
5824 tcg_temp_free_i64(t1);
5827 static void gen_loongson_lswc2(DisasContext *ctx, int rt,
5828 int rs, int rd)
5830 TCGv t0, t1, t2;
5831 TCGv_i32 fp0;
5832 #if defined(TARGET_MIPS64)
5833 int lsq_rt1 = ctx->opcode & 0x1f;
5834 int lsq_offset = sextract32(ctx->opcode, 6, 9) << 4;
5835 #endif
5836 int shf_offset = sextract32(ctx->opcode, 6, 8);
5838 t0 = tcg_temp_new();
5840 switch (MASK_LOONGSON_GSLSQ(ctx->opcode)) {
5841 #if defined(TARGET_MIPS64)
5842 case OPC_GSLQ:
5843 t1 = tcg_temp_new();
5844 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5845 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5846 ctx->default_tcg_memop_mask);
5847 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5848 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
5849 ctx->default_tcg_memop_mask);
5850 gen_store_gpr(t1, rt);
5851 gen_store_gpr(t0, lsq_rt1);
5852 tcg_temp_free(t1);
5853 break;
5854 case OPC_GSLQC1:
5855 check_cp1_enabled(ctx);
5856 t1 = tcg_temp_new();
5857 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5858 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5859 ctx->default_tcg_memop_mask);
5860 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5861 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
5862 ctx->default_tcg_memop_mask);
5863 gen_store_fpr64(ctx, t1, rt);
5864 gen_store_fpr64(ctx, t0, lsq_rt1);
5865 tcg_temp_free(t1);
5866 break;
5867 case OPC_GSSQ:
5868 t1 = tcg_temp_new();
5869 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5870 gen_load_gpr(t1, rt);
5871 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5872 ctx->default_tcg_memop_mask);
5873 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5874 gen_load_gpr(t1, lsq_rt1);
5875 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5876 ctx->default_tcg_memop_mask);
5877 tcg_temp_free(t1);
5878 break;
5879 case OPC_GSSQC1:
5880 check_cp1_enabled(ctx);
5881 t1 = tcg_temp_new();
5882 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5883 gen_load_fpr64(ctx, t1, rt);
5884 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5885 ctx->default_tcg_memop_mask);
5886 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5887 gen_load_fpr64(ctx, t1, lsq_rt1);
5888 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5889 ctx->default_tcg_memop_mask);
5890 tcg_temp_free(t1);
5891 break;
5892 #endif
5893 case OPC_GSSHFL:
5894 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
5895 case OPC_GSLWLC1:
5896 check_cp1_enabled(ctx);
5897 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5898 t1 = tcg_temp_new();
5899 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
5900 tcg_gen_andi_tl(t1, t0, 3);
5901 #ifndef TARGET_WORDS_BIGENDIAN
5902 tcg_gen_xori_tl(t1, t1, 3);
5903 #endif
5904 tcg_gen_shli_tl(t1, t1, 3);
5905 tcg_gen_andi_tl(t0, t0, ~3);
5906 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
5907 tcg_gen_shl_tl(t0, t0, t1);
5908 t2 = tcg_const_tl(-1);
5909 tcg_gen_shl_tl(t2, t2, t1);
5910 fp0 = tcg_temp_new_i32();
5911 gen_load_fpr32(ctx, fp0, rt);
5912 tcg_gen_ext_i32_tl(t1, fp0);
5913 tcg_gen_andc_tl(t1, t1, t2);
5914 tcg_temp_free(t2);
5915 tcg_gen_or_tl(t0, t0, t1);
5916 tcg_temp_free(t1);
5917 #if defined(TARGET_MIPS64)
5918 tcg_gen_extrl_i64_i32(fp0, t0);
5919 #else
5920 tcg_gen_ext32s_tl(fp0, t0);
5921 #endif
5922 gen_store_fpr32(ctx, fp0, rt);
5923 tcg_temp_free_i32(fp0);
5924 break;
5925 case OPC_GSLWRC1:
5926 check_cp1_enabled(ctx);
5927 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5928 t1 = tcg_temp_new();
5929 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
5930 tcg_gen_andi_tl(t1, t0, 3);
5931 #ifdef TARGET_WORDS_BIGENDIAN
5932 tcg_gen_xori_tl(t1, t1, 3);
5933 #endif
5934 tcg_gen_shli_tl(t1, t1, 3);
5935 tcg_gen_andi_tl(t0, t0, ~3);
5936 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
5937 tcg_gen_shr_tl(t0, t0, t1);
5938 tcg_gen_xori_tl(t1, t1, 31);
5939 t2 = tcg_const_tl(0xfffffffeull);
5940 tcg_gen_shl_tl(t2, t2, t1);
5941 fp0 = tcg_temp_new_i32();
5942 gen_load_fpr32(ctx, fp0, rt);
5943 tcg_gen_ext_i32_tl(t1, fp0);
5944 tcg_gen_and_tl(t1, t1, t2);
5945 tcg_temp_free(t2);
5946 tcg_gen_or_tl(t0, t0, t1);
5947 tcg_temp_free(t1);
5948 #if defined(TARGET_MIPS64)
5949 tcg_gen_extrl_i64_i32(fp0, t0);
5950 #else
5951 tcg_gen_ext32s_tl(fp0, t0);
5952 #endif
5953 gen_store_fpr32(ctx, fp0, rt);
5954 tcg_temp_free_i32(fp0);
5955 break;
5956 #if defined(TARGET_MIPS64)
5957 case OPC_GSLDLC1:
5958 check_cp1_enabled(ctx);
5959 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5960 t1 = tcg_temp_new();
5961 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
5962 tcg_gen_andi_tl(t1, t0, 7);
5963 #ifndef TARGET_WORDS_BIGENDIAN
5964 tcg_gen_xori_tl(t1, t1, 7);
5965 #endif
5966 tcg_gen_shli_tl(t1, t1, 3);
5967 tcg_gen_andi_tl(t0, t0, ~7);
5968 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
5969 tcg_gen_shl_tl(t0, t0, t1);
5970 t2 = tcg_const_tl(-1);
5971 tcg_gen_shl_tl(t2, t2, t1);
5972 gen_load_fpr64(ctx, t1, rt);
5973 tcg_gen_andc_tl(t1, t1, t2);
5974 tcg_temp_free(t2);
5975 tcg_gen_or_tl(t0, t0, t1);
5976 tcg_temp_free(t1);
5977 gen_store_fpr64(ctx, t0, rt);
5978 break;
5979 case OPC_GSLDRC1:
5980 check_cp1_enabled(ctx);
5981 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5982 t1 = tcg_temp_new();
5983 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
5984 tcg_gen_andi_tl(t1, t0, 7);
5985 #ifdef TARGET_WORDS_BIGENDIAN
5986 tcg_gen_xori_tl(t1, t1, 7);
5987 #endif
5988 tcg_gen_shli_tl(t1, t1, 3);
5989 tcg_gen_andi_tl(t0, t0, ~7);
5990 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
5991 tcg_gen_shr_tl(t0, t0, t1);
5992 tcg_gen_xori_tl(t1, t1, 63);
5993 t2 = tcg_const_tl(0xfffffffffffffffeull);
5994 tcg_gen_shl_tl(t2, t2, t1);
5995 gen_load_fpr64(ctx, t1, rt);
5996 tcg_gen_and_tl(t1, t1, t2);
5997 tcg_temp_free(t2);
5998 tcg_gen_or_tl(t0, t0, t1);
5999 tcg_temp_free(t1);
6000 gen_store_fpr64(ctx, t0, rt);
6001 break;
6002 #endif
6003 default:
6004 MIPS_INVAL("loongson_gsshfl");
6005 gen_reserved_instruction(ctx);
6006 break;
6008 break;
6009 case OPC_GSSHFS:
6010 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
6011 case OPC_GSSWLC1:
6012 check_cp1_enabled(ctx);
6013 t1 = tcg_temp_new();
6014 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6015 fp0 = tcg_temp_new_i32();
6016 gen_load_fpr32(ctx, fp0, rt);
6017 tcg_gen_ext_i32_tl(t1, fp0);
6018 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
6019 tcg_temp_free_i32(fp0);
6020 tcg_temp_free(t1);
6021 break;
6022 case OPC_GSSWRC1:
6023 check_cp1_enabled(ctx);
6024 t1 = tcg_temp_new();
6025 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6026 fp0 = tcg_temp_new_i32();
6027 gen_load_fpr32(ctx, fp0, rt);
6028 tcg_gen_ext_i32_tl(t1, fp0);
6029 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
6030 tcg_temp_free_i32(fp0);
6031 tcg_temp_free(t1);
6032 break;
6033 #if defined(TARGET_MIPS64)
6034 case OPC_GSSDLC1:
6035 check_cp1_enabled(ctx);
6036 t1 = tcg_temp_new();
6037 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6038 gen_load_fpr64(ctx, t1, rt);
6039 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
6040 tcg_temp_free(t1);
6041 break;
6042 case OPC_GSSDRC1:
6043 check_cp1_enabled(ctx);
6044 t1 = tcg_temp_new();
6045 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6046 gen_load_fpr64(ctx, t1, rt);
6047 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
6048 tcg_temp_free(t1);
6049 break;
6050 #endif
6051 default:
6052 MIPS_INVAL("loongson_gsshfs");
6053 gen_reserved_instruction(ctx);
6054 break;
6056 break;
6057 default:
6058 MIPS_INVAL("loongson_gslsq");
6059 gen_reserved_instruction(ctx);
6060 break;
6062 tcg_temp_free(t0);
6065 /* Loongson EXT LDC2/SDC2 */
6066 static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
6067 int rs, int rd)
6069 int offset = sextract32(ctx->opcode, 3, 8);
6070 uint32_t opc = MASK_LOONGSON_LSDC2(ctx->opcode);
6071 TCGv t0, t1;
6072 TCGv_i32 fp0;
6074 /* Pre-conditions */
6075 switch (opc) {
6076 case OPC_GSLBX:
6077 case OPC_GSLHX:
6078 case OPC_GSLWX:
6079 case OPC_GSLDX:
6080 /* prefetch, implement as NOP */
6081 if (rt == 0) {
6082 return;
6084 break;
6085 case OPC_GSSBX:
6086 case OPC_GSSHX:
6087 case OPC_GSSWX:
6088 case OPC_GSSDX:
6089 break;
6090 case OPC_GSLWXC1:
6091 #if defined(TARGET_MIPS64)
6092 case OPC_GSLDXC1:
6093 #endif
6094 check_cp1_enabled(ctx);
6095 /* prefetch, implement as NOP */
6096 if (rt == 0) {
6097 return;
6099 break;
6100 case OPC_GSSWXC1:
6101 #if defined(TARGET_MIPS64)
6102 case OPC_GSSDXC1:
6103 #endif
6104 check_cp1_enabled(ctx);
6105 break;
6106 default:
6107 MIPS_INVAL("loongson_lsdc2");
6108 gen_reserved_instruction(ctx);
6109 return;
6110 break;
6113 t0 = tcg_temp_new();
6115 gen_base_offset_addr(ctx, t0, rs, offset);
6116 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
6118 switch (opc) {
6119 case OPC_GSLBX:
6120 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
6121 gen_store_gpr(t0, rt);
6122 break;
6123 case OPC_GSLHX:
6124 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
6125 ctx->default_tcg_memop_mask);
6126 gen_store_gpr(t0, rt);
6127 break;
6128 case OPC_GSLWX:
6129 gen_base_offset_addr(ctx, t0, rs, offset);
6130 if (rd) {
6131 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
6133 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
6134 ctx->default_tcg_memop_mask);
6135 gen_store_gpr(t0, rt);
6136 break;
6137 #if defined(TARGET_MIPS64)
6138 case OPC_GSLDX:
6139 gen_base_offset_addr(ctx, t0, rs, offset);
6140 if (rd) {
6141 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
6143 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
6144 ctx->default_tcg_memop_mask);
6145 gen_store_gpr(t0, rt);
6146 break;
6147 #endif
6148 case OPC_GSLWXC1:
6149 check_cp1_enabled(ctx);
6150 gen_base_offset_addr(ctx, t0, rs, offset);
6151 if (rd) {
6152 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
6154 fp0 = tcg_temp_new_i32();
6155 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
6156 ctx->default_tcg_memop_mask);
6157 gen_store_fpr32(ctx, fp0, rt);
6158 tcg_temp_free_i32(fp0);
6159 break;
6160 #if defined(TARGET_MIPS64)
6161 case OPC_GSLDXC1:
6162 check_cp1_enabled(ctx);
6163 gen_base_offset_addr(ctx, t0, rs, offset);
6164 if (rd) {
6165 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
6167 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
6168 ctx->default_tcg_memop_mask);
6169 gen_store_fpr64(ctx, t0, rt);
6170 break;
6171 #endif
6172 case OPC_GSSBX:
6173 t1 = tcg_temp_new();
6174 gen_load_gpr(t1, rt);
6175 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_SB);
6176 tcg_temp_free(t1);
6177 break;
6178 case OPC_GSSHX:
6179 t1 = tcg_temp_new();
6180 gen_load_gpr(t1, rt);
6181 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
6182 ctx->default_tcg_memop_mask);
6183 tcg_temp_free(t1);
6184 break;
6185 case OPC_GSSWX:
6186 t1 = tcg_temp_new();
6187 gen_load_gpr(t1, rt);
6188 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
6189 ctx->default_tcg_memop_mask);
6190 tcg_temp_free(t1);
6191 break;
6192 #if defined(TARGET_MIPS64)
6193 case OPC_GSSDX:
6194 t1 = tcg_temp_new();
6195 gen_load_gpr(t1, rt);
6196 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
6197 ctx->default_tcg_memop_mask);
6198 tcg_temp_free(t1);
6199 break;
6200 #endif
6201 case OPC_GSSWXC1:
6202 fp0 = tcg_temp_new_i32();
6203 gen_load_fpr32(ctx, fp0, rt);
6204 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
6205 ctx->default_tcg_memop_mask);
6206 tcg_temp_free_i32(fp0);
6207 break;
6208 #if defined(TARGET_MIPS64)
6209 case OPC_GSSDXC1:
6210 t1 = tcg_temp_new();
6211 gen_load_fpr64(ctx, t1, rt);
6212 tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, MO_TEQ |
6213 ctx->default_tcg_memop_mask);
6214 tcg_temp_free(t1);
6215 break;
6216 #endif
6217 default:
6218 break;
6221 tcg_temp_free(t0);
6224 /* Traps */
6225 static void gen_trap(DisasContext *ctx, uint32_t opc,
6226 int rs, int rt, int16_t imm)
6228 int cond;
6229 TCGv t0 = tcg_temp_new();
6230 TCGv t1 = tcg_temp_new();
6232 cond = 0;
6233 /* Load needed operands */
6234 switch (opc) {
6235 case OPC_TEQ:
6236 case OPC_TGE:
6237 case OPC_TGEU:
6238 case OPC_TLT:
6239 case OPC_TLTU:
6240 case OPC_TNE:
6241 /* Compare two registers */
6242 if (rs != rt) {
6243 gen_load_gpr(t0, rs);
6244 gen_load_gpr(t1, rt);
6245 cond = 1;
6247 break;
6248 case OPC_TEQI:
6249 case OPC_TGEI:
6250 case OPC_TGEIU:
6251 case OPC_TLTI:
6252 case OPC_TLTIU:
6253 case OPC_TNEI:
6254 /* Compare register to immediate */
6255 if (rs != 0 || imm != 0) {
6256 gen_load_gpr(t0, rs);
6257 tcg_gen_movi_tl(t1, (int32_t)imm);
6258 cond = 1;
6260 break;
6262 if (cond == 0) {
6263 switch (opc) {
6264 case OPC_TEQ: /* rs == rs */
6265 case OPC_TEQI: /* r0 == 0 */
6266 case OPC_TGE: /* rs >= rs */
6267 case OPC_TGEI: /* r0 >= 0 */
6268 case OPC_TGEU: /* rs >= rs unsigned */
6269 case OPC_TGEIU: /* r0 >= 0 unsigned */
6270 /* Always trap */
6271 generate_exception_end(ctx, EXCP_TRAP);
6272 break;
6273 case OPC_TLT: /* rs < rs */
6274 case OPC_TLTI: /* r0 < 0 */
6275 case OPC_TLTU: /* rs < rs unsigned */
6276 case OPC_TLTIU: /* r0 < 0 unsigned */
6277 case OPC_TNE: /* rs != rs */
6278 case OPC_TNEI: /* r0 != 0 */
6279 /* Never trap: treat as NOP. */
6280 break;
6282 } else {
6283 TCGLabel *l1 = gen_new_label();
6285 switch (opc) {
6286 case OPC_TEQ:
6287 case OPC_TEQI:
6288 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
6289 break;
6290 case OPC_TGE:
6291 case OPC_TGEI:
6292 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
6293 break;
6294 case OPC_TGEU:
6295 case OPC_TGEIU:
6296 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
6297 break;
6298 case OPC_TLT:
6299 case OPC_TLTI:
6300 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
6301 break;
6302 case OPC_TLTU:
6303 case OPC_TLTIU:
6304 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
6305 break;
6306 case OPC_TNE:
6307 case OPC_TNEI:
6308 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
6309 break;
6311 generate_exception(ctx, EXCP_TRAP);
6312 gen_set_label(l1);
6314 tcg_temp_free(t0);
6315 tcg_temp_free(t1);
6318 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
6320 if (unlikely(ctx->base.singlestep_enabled)) {
6321 return false;
6324 #ifndef CONFIG_USER_ONLY
6325 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
6326 #else
6327 return true;
6328 #endif
6331 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
6333 if (use_goto_tb(ctx, dest)) {
6334 tcg_gen_goto_tb(n);
6335 gen_save_pc(dest);
6336 tcg_gen_exit_tb(ctx->base.tb, n);
6337 } else {
6338 gen_save_pc(dest);
6339 if (ctx->base.singlestep_enabled) {
6340 save_cpu_state(ctx, 0);
6341 gen_helper_raise_exception_debug(cpu_env);
6343 tcg_gen_lookup_and_goto_ptr();
6347 /* Branches (before delay slot) */
6348 static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
6349 int insn_bytes,
6350 int rs, int rt, int32_t offset,
6351 int delayslot_size)
6353 target_ulong btgt = -1;
6354 int blink = 0;
6355 int bcond_compute = 0;
6356 TCGv t0 = tcg_temp_new();
6357 TCGv t1 = tcg_temp_new();
6359 if (ctx->hflags & MIPS_HFLAG_BMASK) {
6360 #ifdef MIPS_DEBUG_DISAS
6361 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
6362 TARGET_FMT_lx "\n", ctx->base.pc_next);
6363 #endif
6364 gen_reserved_instruction(ctx);
6365 goto out;
6368 /* Load needed operands */
6369 switch (opc) {
6370 case OPC_BEQ:
6371 case OPC_BEQL:
6372 case OPC_BNE:
6373 case OPC_BNEL:
6374 /* Compare two registers */
6375 if (rs != rt) {
6376 gen_load_gpr(t0, rs);
6377 gen_load_gpr(t1, rt);
6378 bcond_compute = 1;
6380 btgt = ctx->base.pc_next + insn_bytes + offset;
6381 break;
6382 case OPC_BGEZ:
6383 case OPC_BGEZAL:
6384 case OPC_BGEZALL:
6385 case OPC_BGEZL:
6386 case OPC_BGTZ:
6387 case OPC_BGTZL:
6388 case OPC_BLEZ:
6389 case OPC_BLEZL:
6390 case OPC_BLTZ:
6391 case OPC_BLTZAL:
6392 case OPC_BLTZALL:
6393 case OPC_BLTZL:
6394 /* Compare to zero */
6395 if (rs != 0) {
6396 gen_load_gpr(t0, rs);
6397 bcond_compute = 1;
6399 btgt = ctx->base.pc_next + insn_bytes + offset;
6400 break;
6401 case OPC_BPOSGE32:
6402 #if defined(TARGET_MIPS64)
6403 case OPC_BPOSGE64:
6404 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
6405 #else
6406 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6407 #endif
6408 bcond_compute = 1;
6409 btgt = ctx->base.pc_next + insn_bytes + offset;
6410 break;
6411 case OPC_J:
6412 case OPC_JAL:
6413 case OPC_JALX:
6414 /* Jump to immediate */
6415 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
6416 (uint32_t)offset;
6417 break;
6418 case OPC_JR:
6419 case OPC_JALR:
6420 /* Jump to register */
6421 if (offset != 0 && offset != 16) {
6423 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6424 * others are reserved.
6426 MIPS_INVAL("jump hint");
6427 gen_reserved_instruction(ctx);
6428 goto out;
6430 gen_load_gpr(btarget, rs);
6431 break;
6432 default:
6433 MIPS_INVAL("branch/jump");
6434 gen_reserved_instruction(ctx);
6435 goto out;
6437 if (bcond_compute == 0) {
6438 /* No condition to be computed */
6439 switch (opc) {
6440 case OPC_BEQ: /* rx == rx */
6441 case OPC_BEQL: /* rx == rx likely */
6442 case OPC_BGEZ: /* 0 >= 0 */
6443 case OPC_BGEZL: /* 0 >= 0 likely */
6444 case OPC_BLEZ: /* 0 <= 0 */
6445 case OPC_BLEZL: /* 0 <= 0 likely */
6446 /* Always take */
6447 ctx->hflags |= MIPS_HFLAG_B;
6448 break;
6449 case OPC_BGEZAL: /* 0 >= 0 */
6450 case OPC_BGEZALL: /* 0 >= 0 likely */
6451 /* Always take and link */
6452 blink = 31;
6453 ctx->hflags |= MIPS_HFLAG_B;
6454 break;
6455 case OPC_BNE: /* rx != rx */
6456 case OPC_BGTZ: /* 0 > 0 */
6457 case OPC_BLTZ: /* 0 < 0 */
6458 /* Treat as NOP. */
6459 goto out;
6460 case OPC_BLTZAL: /* 0 < 0 */
6462 * Handle as an unconditional branch to get correct delay
6463 * slot checking.
6465 blink = 31;
6466 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
6467 ctx->hflags |= MIPS_HFLAG_B;
6468 break;
6469 case OPC_BLTZALL: /* 0 < 0 likely */
6470 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6471 /* Skip the instruction in the delay slot */
6472 ctx->base.pc_next += 4;
6473 goto out;
6474 case OPC_BNEL: /* rx != rx likely */
6475 case OPC_BGTZL: /* 0 > 0 likely */
6476 case OPC_BLTZL: /* 0 < 0 likely */
6477 /* Skip the instruction in the delay slot */
6478 ctx->base.pc_next += 4;
6479 goto out;
6480 case OPC_J:
6481 ctx->hflags |= MIPS_HFLAG_B;
6482 break;
6483 case OPC_JALX:
6484 ctx->hflags |= MIPS_HFLAG_BX;
6485 /* Fallthrough */
6486 case OPC_JAL:
6487 blink = 31;
6488 ctx->hflags |= MIPS_HFLAG_B;
6489 break;
6490 case OPC_JR:
6491 ctx->hflags |= MIPS_HFLAG_BR;
6492 break;
6493 case OPC_JALR:
6494 blink = rt;
6495 ctx->hflags |= MIPS_HFLAG_BR;
6496 break;
6497 default:
6498 MIPS_INVAL("branch/jump");
6499 gen_reserved_instruction(ctx);
6500 goto out;
6502 } else {
6503 switch (opc) {
6504 case OPC_BEQ:
6505 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6506 goto not_likely;
6507 case OPC_BEQL:
6508 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6509 goto likely;
6510 case OPC_BNE:
6511 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6512 goto not_likely;
6513 case OPC_BNEL:
6514 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6515 goto likely;
6516 case OPC_BGEZ:
6517 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6518 goto not_likely;
6519 case OPC_BGEZL:
6520 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6521 goto likely;
6522 case OPC_BGEZAL:
6523 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6524 blink = 31;
6525 goto not_likely;
6526 case OPC_BGEZALL:
6527 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6528 blink = 31;
6529 goto likely;
6530 case OPC_BGTZ:
6531 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6532 goto not_likely;
6533 case OPC_BGTZL:
6534 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6535 goto likely;
6536 case OPC_BLEZ:
6537 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6538 goto not_likely;
6539 case OPC_BLEZL:
6540 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6541 goto likely;
6542 case OPC_BLTZ:
6543 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6544 goto not_likely;
6545 case OPC_BLTZL:
6546 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6547 goto likely;
6548 case OPC_BPOSGE32:
6549 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6550 goto not_likely;
6551 #if defined(TARGET_MIPS64)
6552 case OPC_BPOSGE64:
6553 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
6554 goto not_likely;
6555 #endif
6556 case OPC_BLTZAL:
6557 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6558 blink = 31;
6559 not_likely:
6560 ctx->hflags |= MIPS_HFLAG_BC;
6561 break;
6562 case OPC_BLTZALL:
6563 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6564 blink = 31;
6565 likely:
6566 ctx->hflags |= MIPS_HFLAG_BL;
6567 break;
6568 default:
6569 MIPS_INVAL("conditional branch/jump");
6570 gen_reserved_instruction(ctx);
6571 goto out;
6575 ctx->btarget = btgt;
6577 switch (delayslot_size) {
6578 case 2:
6579 ctx->hflags |= MIPS_HFLAG_BDS16;
6580 break;
6581 case 4:
6582 ctx->hflags |= MIPS_HFLAG_BDS32;
6583 break;
6586 if (blink > 0) {
6587 int post_delay = insn_bytes + delayslot_size;
6588 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
6590 tcg_gen_movi_tl(cpu_gpr[blink],
6591 ctx->base.pc_next + post_delay + lowbit);
6594 out:
6595 if (insn_bytes == 2) {
6596 ctx->hflags |= MIPS_HFLAG_B16;
6598 tcg_temp_free(t0);
6599 tcg_temp_free(t1);
6603 /* nanoMIPS Branches */
6604 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
6605 int insn_bytes,
6606 int rs, int rt, int32_t offset)
6608 target_ulong btgt = -1;
6609 int bcond_compute = 0;
6610 TCGv t0 = tcg_temp_new();
6611 TCGv t1 = tcg_temp_new();
6613 /* Load needed operands */
6614 switch (opc) {
6615 case OPC_BEQ:
6616 case OPC_BNE:
6617 /* Compare two registers */
6618 if (rs != rt) {
6619 gen_load_gpr(t0, rs);
6620 gen_load_gpr(t1, rt);
6621 bcond_compute = 1;
6623 btgt = ctx->base.pc_next + insn_bytes + offset;
6624 break;
6625 case OPC_BGEZAL:
6626 /* Compare to zero */
6627 if (rs != 0) {
6628 gen_load_gpr(t0, rs);
6629 bcond_compute = 1;
6631 btgt = ctx->base.pc_next + insn_bytes + offset;
6632 break;
6633 case OPC_BPOSGE32:
6634 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6635 bcond_compute = 1;
6636 btgt = ctx->base.pc_next + insn_bytes + offset;
6637 break;
6638 case OPC_JR:
6639 case OPC_JALR:
6640 /* Jump to register */
6641 if (offset != 0 && offset != 16) {
6643 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6644 * others are reserved.
6646 MIPS_INVAL("jump hint");
6647 gen_reserved_instruction(ctx);
6648 goto out;
6650 gen_load_gpr(btarget, rs);
6651 break;
6652 default:
6653 MIPS_INVAL("branch/jump");
6654 gen_reserved_instruction(ctx);
6655 goto out;
6657 if (bcond_compute == 0) {
6658 /* No condition to be computed */
6659 switch (opc) {
6660 case OPC_BEQ: /* rx == rx */
6661 /* Always take */
6662 ctx->hflags |= MIPS_HFLAG_B;
6663 break;
6664 case OPC_BGEZAL: /* 0 >= 0 */
6665 /* Always take and link */
6666 tcg_gen_movi_tl(cpu_gpr[31],
6667 ctx->base.pc_next + insn_bytes);
6668 ctx->hflags |= MIPS_HFLAG_B;
6669 break;
6670 case OPC_BNE: /* rx != rx */
6671 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6672 /* Skip the instruction in the delay slot */
6673 ctx->base.pc_next += 4;
6674 goto out;
6675 case OPC_JR:
6676 ctx->hflags |= MIPS_HFLAG_BR;
6677 break;
6678 case OPC_JALR:
6679 if (rt > 0) {
6680 tcg_gen_movi_tl(cpu_gpr[rt],
6681 ctx->base.pc_next + insn_bytes);
6683 ctx->hflags |= MIPS_HFLAG_BR;
6684 break;
6685 default:
6686 MIPS_INVAL("branch/jump");
6687 gen_reserved_instruction(ctx);
6688 goto out;
6690 } else {
6691 switch (opc) {
6692 case OPC_BEQ:
6693 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6694 goto not_likely;
6695 case OPC_BNE:
6696 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6697 goto not_likely;
6698 case OPC_BGEZAL:
6699 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6700 tcg_gen_movi_tl(cpu_gpr[31],
6701 ctx->base.pc_next + insn_bytes);
6702 goto not_likely;
6703 case OPC_BPOSGE32:
6704 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6705 not_likely:
6706 ctx->hflags |= MIPS_HFLAG_BC;
6707 break;
6708 default:
6709 MIPS_INVAL("conditional branch/jump");
6710 gen_reserved_instruction(ctx);
6711 goto out;
6715 ctx->btarget = btgt;
6717 out:
6718 if (insn_bytes == 2) {
6719 ctx->hflags |= MIPS_HFLAG_B16;
6721 tcg_temp_free(t0);
6722 tcg_temp_free(t1);
6726 /* special3 bitfield operations */
6727 static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
6728 int rs, int lsb, int msb)
6730 TCGv t0 = tcg_temp_new();
6731 TCGv t1 = tcg_temp_new();
6733 gen_load_gpr(t1, rs);
6734 switch (opc) {
6735 case OPC_EXT:
6736 if (lsb + msb > 31) {
6737 goto fail;
6739 if (msb != 31) {
6740 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6741 } else {
6743 * The two checks together imply that lsb == 0,
6744 * so this is a simple sign-extension.
6746 tcg_gen_ext32s_tl(t0, t1);
6748 break;
6749 #if defined(TARGET_MIPS64)
6750 case OPC_DEXTU:
6751 lsb += 32;
6752 goto do_dext;
6753 case OPC_DEXTM:
6754 msb += 32;
6755 goto do_dext;
6756 case OPC_DEXT:
6757 do_dext:
6758 if (lsb + msb > 63) {
6759 goto fail;
6761 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6762 break;
6763 #endif
6764 case OPC_INS:
6765 if (lsb > msb) {
6766 goto fail;
6768 gen_load_gpr(t0, rt);
6769 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6770 tcg_gen_ext32s_tl(t0, t0);
6771 break;
6772 #if defined(TARGET_MIPS64)
6773 case OPC_DINSU:
6774 lsb += 32;
6775 /* FALLTHRU */
6776 case OPC_DINSM:
6777 msb += 32;
6778 /* FALLTHRU */
6779 case OPC_DINS:
6780 if (lsb > msb) {
6781 goto fail;
6783 gen_load_gpr(t0, rt);
6784 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6785 break;
6786 #endif
6787 default:
6788 fail:
6789 MIPS_INVAL("bitops");
6790 gen_reserved_instruction(ctx);
6791 tcg_temp_free(t0);
6792 tcg_temp_free(t1);
6793 return;
6795 gen_store_gpr(t0, rt);
6796 tcg_temp_free(t0);
6797 tcg_temp_free(t1);
6800 static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
6802 TCGv t0;
6804 if (rd == 0) {
6805 /* If no destination, treat it as a NOP. */
6806 return;
6809 t0 = tcg_temp_new();
6810 gen_load_gpr(t0, rt);
6811 switch (op2) {
6812 case OPC_WSBH:
6814 TCGv t1 = tcg_temp_new();
6815 TCGv t2 = tcg_const_tl(0x00FF00FF);
6817 tcg_gen_shri_tl(t1, t0, 8);
6818 tcg_gen_and_tl(t1, t1, t2);
6819 tcg_gen_and_tl(t0, t0, t2);
6820 tcg_gen_shli_tl(t0, t0, 8);
6821 tcg_gen_or_tl(t0, t0, t1);
6822 tcg_temp_free(t2);
6823 tcg_temp_free(t1);
6824 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6826 break;
6827 case OPC_SEB:
6828 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
6829 break;
6830 case OPC_SEH:
6831 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
6832 break;
6833 #if defined(TARGET_MIPS64)
6834 case OPC_DSBH:
6836 TCGv t1 = tcg_temp_new();
6837 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
6839 tcg_gen_shri_tl(t1, t0, 8);
6840 tcg_gen_and_tl(t1, t1, t2);
6841 tcg_gen_and_tl(t0, t0, t2);
6842 tcg_gen_shli_tl(t0, t0, 8);
6843 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6844 tcg_temp_free(t2);
6845 tcg_temp_free(t1);
6847 break;
6848 case OPC_DSHD:
6850 TCGv t1 = tcg_temp_new();
6851 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
6853 tcg_gen_shri_tl(t1, t0, 16);
6854 tcg_gen_and_tl(t1, t1, t2);
6855 tcg_gen_and_tl(t0, t0, t2);
6856 tcg_gen_shli_tl(t0, t0, 16);
6857 tcg_gen_or_tl(t0, t0, t1);
6858 tcg_gen_shri_tl(t1, t0, 32);
6859 tcg_gen_shli_tl(t0, t0, 32);
6860 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6861 tcg_temp_free(t2);
6862 tcg_temp_free(t1);
6864 break;
6865 #endif
6866 default:
6867 MIPS_INVAL("bsfhl");
6868 gen_reserved_instruction(ctx);
6869 tcg_temp_free(t0);
6870 return;
6872 tcg_temp_free(t0);
6875 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
6876 int imm2)
6878 TCGv t0;
6879 TCGv t1;
6880 if (rd == 0) {
6881 /* Treat as NOP. */
6882 return;
6884 t0 = tcg_temp_new();
6885 t1 = tcg_temp_new();
6886 gen_load_gpr(t0, rs);
6887 gen_load_gpr(t1, rt);
6888 tcg_gen_shli_tl(t0, t0, imm2 + 1);
6889 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
6890 if (opc == OPC_LSA) {
6891 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
6894 tcg_temp_free(t1);
6895 tcg_temp_free(t0);
6897 return;
6900 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
6901 int rt, int bits)
6903 TCGv t0;
6904 if (rd == 0) {
6905 /* Treat as NOP. */
6906 return;
6908 t0 = tcg_temp_new();
6909 if (bits == 0 || bits == wordsz) {
6910 if (bits == 0) {
6911 gen_load_gpr(t0, rt);
6912 } else {
6913 gen_load_gpr(t0, rs);
6915 switch (wordsz) {
6916 case 32:
6917 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6918 break;
6919 #if defined(TARGET_MIPS64)
6920 case 64:
6921 tcg_gen_mov_tl(cpu_gpr[rd], t0);
6922 break;
6923 #endif
6925 } else {
6926 TCGv t1 = tcg_temp_new();
6927 gen_load_gpr(t0, rt);
6928 gen_load_gpr(t1, rs);
6929 switch (wordsz) {
6930 case 32:
6932 TCGv_i64 t2 = tcg_temp_new_i64();
6933 tcg_gen_concat_tl_i64(t2, t1, t0);
6934 tcg_gen_shri_i64(t2, t2, 32 - bits);
6935 gen_move_low32(cpu_gpr[rd], t2);
6936 tcg_temp_free_i64(t2);
6938 break;
6939 #if defined(TARGET_MIPS64)
6940 case 64:
6941 tcg_gen_shli_tl(t0, t0, bits);
6942 tcg_gen_shri_tl(t1, t1, 64 - bits);
6943 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
6944 break;
6945 #endif
6947 tcg_temp_free(t1);
6950 tcg_temp_free(t0);
6953 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6954 int bp)
6956 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
6959 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6960 int shift)
6962 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
6965 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
6967 TCGv t0;
6968 if (rd == 0) {
6969 /* Treat as NOP. */
6970 return;
6972 t0 = tcg_temp_new();
6973 gen_load_gpr(t0, rt);
6974 switch (opc) {
6975 case OPC_BITSWAP:
6976 gen_helper_bitswap(cpu_gpr[rd], t0);
6977 break;
6978 #if defined(TARGET_MIPS64)
6979 case OPC_DBITSWAP:
6980 gen_helper_dbitswap(cpu_gpr[rd], t0);
6981 break;
6982 #endif
6984 tcg_temp_free(t0);
6987 #ifndef CONFIG_USER_ONLY
6988 /* CP0 (MMU and control) */
6989 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
6991 TCGv_i64 t0 = tcg_temp_new_i64();
6992 TCGv_i64 t1 = tcg_temp_new_i64();
6994 tcg_gen_ext_tl_i64(t0, arg);
6995 tcg_gen_ld_i64(t1, cpu_env, off);
6996 #if defined(TARGET_MIPS64)
6997 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
6998 #else
6999 tcg_gen_concat32_i64(t1, t1, t0);
7000 #endif
7001 tcg_gen_st_i64(t1, cpu_env, off);
7002 tcg_temp_free_i64(t1);
7003 tcg_temp_free_i64(t0);
7006 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
7008 TCGv_i64 t0 = tcg_temp_new_i64();
7009 TCGv_i64 t1 = tcg_temp_new_i64();
7011 tcg_gen_ext_tl_i64(t0, arg);
7012 tcg_gen_ld_i64(t1, cpu_env, off);
7013 tcg_gen_concat32_i64(t1, t1, t0);
7014 tcg_gen_st_i64(t1, cpu_env, off);
7015 tcg_temp_free_i64(t1);
7016 tcg_temp_free_i64(t0);
7019 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
7021 TCGv_i64 t0 = tcg_temp_new_i64();
7023 tcg_gen_ld_i64(t0, cpu_env, off);
7024 #if defined(TARGET_MIPS64)
7025 tcg_gen_shri_i64(t0, t0, 30);
7026 #else
7027 tcg_gen_shri_i64(t0, t0, 32);
7028 #endif
7029 gen_move_low32(arg, t0);
7030 tcg_temp_free_i64(t0);
7033 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
7035 TCGv_i64 t0 = tcg_temp_new_i64();
7037 tcg_gen_ld_i64(t0, cpu_env, off);
7038 tcg_gen_shri_i64(t0, t0, 32 + shift);
7039 gen_move_low32(arg, t0);
7040 tcg_temp_free_i64(t0);
7043 static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
7045 TCGv_i32 t0 = tcg_temp_new_i32();
7047 tcg_gen_ld_i32(t0, cpu_env, off);
7048 tcg_gen_ext_i32_tl(arg, t0);
7049 tcg_temp_free_i32(t0);
7052 static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
7054 tcg_gen_ld_tl(arg, cpu_env, off);
7055 tcg_gen_ext32s_tl(arg, arg);
7058 static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
7060 TCGv_i32 t0 = tcg_temp_new_i32();
7062 tcg_gen_trunc_tl_i32(t0, arg);
7063 tcg_gen_st_i32(t0, cpu_env, off);
7064 tcg_temp_free_i32(t0);
7067 #define CP0_CHECK(c) \
7068 do { \
7069 if (!(c)) { \
7070 goto cp0_unimplemented; \
7072 } while (0)
7074 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7076 const char *register_name = "invalid";
7078 switch (reg) {
7079 case CP0_REGISTER_02:
7080 switch (sel) {
7081 case 0:
7082 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
7083 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
7084 register_name = "EntryLo0";
7085 break;
7086 default:
7087 goto cp0_unimplemented;
7089 break;
7090 case CP0_REGISTER_03:
7091 switch (sel) {
7092 case CP0_REG03__ENTRYLO1:
7093 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
7094 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
7095 register_name = "EntryLo1";
7096 break;
7097 default:
7098 goto cp0_unimplemented;
7100 break;
7101 case CP0_REGISTER_09:
7102 switch (sel) {
7103 case CP0_REG09__SAAR:
7104 CP0_CHECK(ctx->saar);
7105 gen_helper_mfhc0_saar(arg, cpu_env);
7106 register_name = "SAAR";
7107 break;
7108 default:
7109 goto cp0_unimplemented;
7111 break;
7112 case CP0_REGISTER_17:
7113 switch (sel) {
7114 case CP0_REG17__LLADDR:
7115 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
7116 ctx->CP0_LLAddr_shift);
7117 register_name = "LLAddr";
7118 break;
7119 case CP0_REG17__MAAR:
7120 CP0_CHECK(ctx->mrp);
7121 gen_helper_mfhc0_maar(arg, cpu_env);
7122 register_name = "MAAR";
7123 break;
7124 default:
7125 goto cp0_unimplemented;
7127 break;
7128 case CP0_REGISTER_19:
7129 switch (sel) {
7130 case CP0_REG19__WATCHHI0:
7131 case CP0_REG19__WATCHHI1:
7132 case CP0_REG19__WATCHHI2:
7133 case CP0_REG19__WATCHHI3:
7134 case CP0_REG19__WATCHHI4:
7135 case CP0_REG19__WATCHHI5:
7136 case CP0_REG19__WATCHHI6:
7137 case CP0_REG19__WATCHHI7:
7138 /* upper 32 bits are only available when Config5MI != 0 */
7139 CP0_CHECK(ctx->mi);
7140 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_WatchHi[sel]), 0);
7141 register_name = "WatchHi";
7142 break;
7143 default:
7144 goto cp0_unimplemented;
7146 break;
7147 case CP0_REGISTER_28:
7148 switch (sel) {
7149 case 0:
7150 case 2:
7151 case 4:
7152 case 6:
7153 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
7154 register_name = "TagLo";
7155 break;
7156 default:
7157 goto cp0_unimplemented;
7159 break;
7160 default:
7161 goto cp0_unimplemented;
7163 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
7164 return;
7166 cp0_unimplemented:
7167 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
7168 register_name, reg, sel);
7169 tcg_gen_movi_tl(arg, 0);
7172 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7174 const char *register_name = "invalid";
7175 uint64_t mask = ctx->PAMask >> 36;
7177 switch (reg) {
7178 case CP0_REGISTER_02:
7179 switch (sel) {
7180 case 0:
7181 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
7182 tcg_gen_andi_tl(arg, arg, mask);
7183 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
7184 register_name = "EntryLo0";
7185 break;
7186 default:
7187 goto cp0_unimplemented;
7189 break;
7190 case CP0_REGISTER_03:
7191 switch (sel) {
7192 case CP0_REG03__ENTRYLO1:
7193 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
7194 tcg_gen_andi_tl(arg, arg, mask);
7195 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
7196 register_name = "EntryLo1";
7197 break;
7198 default:
7199 goto cp0_unimplemented;
7201 break;
7202 case CP0_REGISTER_09:
7203 switch (sel) {
7204 case CP0_REG09__SAAR:
7205 CP0_CHECK(ctx->saar);
7206 gen_helper_mthc0_saar(cpu_env, arg);
7207 register_name = "SAAR";
7208 break;
7209 default:
7210 goto cp0_unimplemented;
7212 break;
7213 case CP0_REGISTER_17:
7214 switch (sel) {
7215 case CP0_REG17__LLADDR:
7217 * LLAddr is read-only (the only exception is bit 0 if LLB is
7218 * supported); the CP0_LLAddr_rw_bitmask does not seem to be
7219 * relevant for modern MIPS cores supporting MTHC0, therefore
7220 * treating MTHC0 to LLAddr as NOP.
7222 register_name = "LLAddr";
7223 break;
7224 case CP0_REG17__MAAR:
7225 CP0_CHECK(ctx->mrp);
7226 gen_helper_mthc0_maar(cpu_env, arg);
7227 register_name = "MAAR";
7228 break;
7229 default:
7230 goto cp0_unimplemented;
7232 break;
7233 case CP0_REGISTER_19:
7234 switch (sel) {
7235 case CP0_REG19__WATCHHI0:
7236 case CP0_REG19__WATCHHI1:
7237 case CP0_REG19__WATCHHI2:
7238 case CP0_REG19__WATCHHI3:
7239 case CP0_REG19__WATCHHI4:
7240 case CP0_REG19__WATCHHI5:
7241 case CP0_REG19__WATCHHI6:
7242 case CP0_REG19__WATCHHI7:
7243 /* upper 32 bits are only available when Config5MI != 0 */
7244 CP0_CHECK(ctx->mi);
7245 gen_helper_0e1i(mthc0_watchhi, arg, sel);
7246 register_name = "WatchHi";
7247 break;
7248 default:
7249 goto cp0_unimplemented;
7251 break;
7252 case CP0_REGISTER_28:
7253 switch (sel) {
7254 case 0:
7255 case 2:
7256 case 4:
7257 case 6:
7258 tcg_gen_andi_tl(arg, arg, mask);
7259 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
7260 register_name = "TagLo";
7261 break;
7262 default:
7263 goto cp0_unimplemented;
7265 break;
7266 default:
7267 goto cp0_unimplemented;
7269 trace_mips_translate_c0("mthc0", register_name, reg, sel);
7271 cp0_unimplemented:
7272 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
7273 register_name, reg, sel);
7276 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
7278 if (ctx->insn_flags & ISA_MIPS_R6) {
7279 tcg_gen_movi_tl(arg, 0);
7280 } else {
7281 tcg_gen_movi_tl(arg, ~0);
7285 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7287 const char *register_name = "invalid";
7289 if (sel != 0) {
7290 check_insn(ctx, ISA_MIPS_R1);
7293 switch (reg) {
7294 case CP0_REGISTER_00:
7295 switch (sel) {
7296 case CP0_REG00__INDEX:
7297 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
7298 register_name = "Index";
7299 break;
7300 case CP0_REG00__MVPCONTROL:
7301 CP0_CHECK(ctx->insn_flags & ASE_MT);
7302 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
7303 register_name = "MVPControl";
7304 break;
7305 case CP0_REG00__MVPCONF0:
7306 CP0_CHECK(ctx->insn_flags & ASE_MT);
7307 gen_helper_mfc0_mvpconf0(arg, cpu_env);
7308 register_name = "MVPConf0";
7309 break;
7310 case CP0_REG00__MVPCONF1:
7311 CP0_CHECK(ctx->insn_flags & ASE_MT);
7312 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7313 register_name = "MVPConf1";
7314 break;
7315 case CP0_REG00__VPCONTROL:
7316 CP0_CHECK(ctx->vp);
7317 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
7318 register_name = "VPControl";
7319 break;
7320 default:
7321 goto cp0_unimplemented;
7323 break;
7324 case CP0_REGISTER_01:
7325 switch (sel) {
7326 case CP0_REG01__RANDOM:
7327 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7328 gen_helper_mfc0_random(arg, cpu_env);
7329 register_name = "Random";
7330 break;
7331 case CP0_REG01__VPECONTROL:
7332 CP0_CHECK(ctx->insn_flags & ASE_MT);
7333 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7334 register_name = "VPEControl";
7335 break;
7336 case CP0_REG01__VPECONF0:
7337 CP0_CHECK(ctx->insn_flags & ASE_MT);
7338 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7339 register_name = "VPEConf0";
7340 break;
7341 case CP0_REG01__VPECONF1:
7342 CP0_CHECK(ctx->insn_flags & ASE_MT);
7343 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7344 register_name = "VPEConf1";
7345 break;
7346 case CP0_REG01__YQMASK:
7347 CP0_CHECK(ctx->insn_flags & ASE_MT);
7348 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
7349 register_name = "YQMask";
7350 break;
7351 case CP0_REG01__VPESCHEDULE:
7352 CP0_CHECK(ctx->insn_flags & ASE_MT);
7353 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
7354 register_name = "VPESchedule";
7355 break;
7356 case CP0_REG01__VPESCHEFBACK:
7357 CP0_CHECK(ctx->insn_flags & ASE_MT);
7358 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7359 register_name = "VPEScheFBack";
7360 break;
7361 case CP0_REG01__VPEOPT:
7362 CP0_CHECK(ctx->insn_flags & ASE_MT);
7363 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
7364 register_name = "VPEOpt";
7365 break;
7366 default:
7367 goto cp0_unimplemented;
7369 break;
7370 case CP0_REGISTER_02:
7371 switch (sel) {
7372 case CP0_REG02__ENTRYLO0:
7374 TCGv_i64 tmp = tcg_temp_new_i64();
7375 tcg_gen_ld_i64(tmp, cpu_env,
7376 offsetof(CPUMIPSState, CP0_EntryLo0));
7377 #if defined(TARGET_MIPS64)
7378 if (ctx->rxi) {
7379 /* Move RI/XI fields to bits 31:30 */
7380 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
7381 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
7383 #endif
7384 gen_move_low32(arg, tmp);
7385 tcg_temp_free_i64(tmp);
7387 register_name = "EntryLo0";
7388 break;
7389 case CP0_REG02__TCSTATUS:
7390 CP0_CHECK(ctx->insn_flags & ASE_MT);
7391 gen_helper_mfc0_tcstatus(arg, cpu_env);
7392 register_name = "TCStatus";
7393 break;
7394 case CP0_REG02__TCBIND:
7395 CP0_CHECK(ctx->insn_flags & ASE_MT);
7396 gen_helper_mfc0_tcbind(arg, cpu_env);
7397 register_name = "TCBind";
7398 break;
7399 case CP0_REG02__TCRESTART:
7400 CP0_CHECK(ctx->insn_flags & ASE_MT);
7401 gen_helper_mfc0_tcrestart(arg, cpu_env);
7402 register_name = "TCRestart";
7403 break;
7404 case CP0_REG02__TCHALT:
7405 CP0_CHECK(ctx->insn_flags & ASE_MT);
7406 gen_helper_mfc0_tchalt(arg, cpu_env);
7407 register_name = "TCHalt";
7408 break;
7409 case CP0_REG02__TCCONTEXT:
7410 CP0_CHECK(ctx->insn_flags & ASE_MT);
7411 gen_helper_mfc0_tccontext(arg, cpu_env);
7412 register_name = "TCContext";
7413 break;
7414 case CP0_REG02__TCSCHEDULE:
7415 CP0_CHECK(ctx->insn_flags & ASE_MT);
7416 gen_helper_mfc0_tcschedule(arg, cpu_env);
7417 register_name = "TCSchedule";
7418 break;
7419 case CP0_REG02__TCSCHEFBACK:
7420 CP0_CHECK(ctx->insn_flags & ASE_MT);
7421 gen_helper_mfc0_tcschefback(arg, cpu_env);
7422 register_name = "TCScheFBack";
7423 break;
7424 default:
7425 goto cp0_unimplemented;
7427 break;
7428 case CP0_REGISTER_03:
7429 switch (sel) {
7430 case CP0_REG03__ENTRYLO1:
7432 TCGv_i64 tmp = tcg_temp_new_i64();
7433 tcg_gen_ld_i64(tmp, cpu_env,
7434 offsetof(CPUMIPSState, CP0_EntryLo1));
7435 #if defined(TARGET_MIPS64)
7436 if (ctx->rxi) {
7437 /* Move RI/XI fields to bits 31:30 */
7438 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
7439 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
7441 #endif
7442 gen_move_low32(arg, tmp);
7443 tcg_temp_free_i64(tmp);
7445 register_name = "EntryLo1";
7446 break;
7447 case CP0_REG03__GLOBALNUM:
7448 CP0_CHECK(ctx->vp);
7449 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
7450 register_name = "GlobalNumber";
7451 break;
7452 default:
7453 goto cp0_unimplemented;
7455 break;
7456 case CP0_REGISTER_04:
7457 switch (sel) {
7458 case CP0_REG04__CONTEXT:
7459 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
7460 tcg_gen_ext32s_tl(arg, arg);
7461 register_name = "Context";
7462 break;
7463 case CP0_REG04__CONTEXTCONFIG:
7464 /* SmartMIPS ASE */
7465 /* gen_helper_mfc0_contextconfig(arg); */
7466 register_name = "ContextConfig";
7467 goto cp0_unimplemented;
7468 case CP0_REG04__USERLOCAL:
7469 CP0_CHECK(ctx->ulri);
7470 tcg_gen_ld_tl(arg, cpu_env,
7471 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7472 tcg_gen_ext32s_tl(arg, arg);
7473 register_name = "UserLocal";
7474 break;
7475 case CP0_REG04__MMID:
7476 CP0_CHECK(ctx->mi);
7477 gen_helper_mtc0_memorymapid(cpu_env, arg);
7478 register_name = "MMID";
7479 break;
7480 default:
7481 goto cp0_unimplemented;
7483 break;
7484 case CP0_REGISTER_05:
7485 switch (sel) {
7486 case CP0_REG05__PAGEMASK:
7487 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
7488 register_name = "PageMask";
7489 break;
7490 case CP0_REG05__PAGEGRAIN:
7491 check_insn(ctx, ISA_MIPS_R2);
7492 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
7493 register_name = "PageGrain";
7494 break;
7495 case CP0_REG05__SEGCTL0:
7496 CP0_CHECK(ctx->sc);
7497 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
7498 tcg_gen_ext32s_tl(arg, arg);
7499 register_name = "SegCtl0";
7500 break;
7501 case CP0_REG05__SEGCTL1:
7502 CP0_CHECK(ctx->sc);
7503 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
7504 tcg_gen_ext32s_tl(arg, arg);
7505 register_name = "SegCtl1";
7506 break;
7507 case CP0_REG05__SEGCTL2:
7508 CP0_CHECK(ctx->sc);
7509 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
7510 tcg_gen_ext32s_tl(arg, arg);
7511 register_name = "SegCtl2";
7512 break;
7513 case CP0_REG05__PWBASE:
7514 check_pw(ctx);
7515 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7516 register_name = "PWBase";
7517 break;
7518 case CP0_REG05__PWFIELD:
7519 check_pw(ctx);
7520 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
7521 register_name = "PWField";
7522 break;
7523 case CP0_REG05__PWSIZE:
7524 check_pw(ctx);
7525 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
7526 register_name = "PWSize";
7527 break;
7528 default:
7529 goto cp0_unimplemented;
7531 break;
7532 case CP0_REGISTER_06:
7533 switch (sel) {
7534 case CP0_REG06__WIRED:
7535 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
7536 register_name = "Wired";
7537 break;
7538 case CP0_REG06__SRSCONF0:
7539 check_insn(ctx, ISA_MIPS_R2);
7540 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
7541 register_name = "SRSConf0";
7542 break;
7543 case CP0_REG06__SRSCONF1:
7544 check_insn(ctx, ISA_MIPS_R2);
7545 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
7546 register_name = "SRSConf1";
7547 break;
7548 case CP0_REG06__SRSCONF2:
7549 check_insn(ctx, ISA_MIPS_R2);
7550 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
7551 register_name = "SRSConf2";
7552 break;
7553 case CP0_REG06__SRSCONF3:
7554 check_insn(ctx, ISA_MIPS_R2);
7555 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
7556 register_name = "SRSConf3";
7557 break;
7558 case CP0_REG06__SRSCONF4:
7559 check_insn(ctx, ISA_MIPS_R2);
7560 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
7561 register_name = "SRSConf4";
7562 break;
7563 case CP0_REG06__PWCTL:
7564 check_pw(ctx);
7565 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
7566 register_name = "PWCtl";
7567 break;
7568 default:
7569 goto cp0_unimplemented;
7571 break;
7572 case CP0_REGISTER_07:
7573 switch (sel) {
7574 case CP0_REG07__HWRENA:
7575 check_insn(ctx, ISA_MIPS_R2);
7576 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
7577 register_name = "HWREna";
7578 break;
7579 default:
7580 goto cp0_unimplemented;
7582 break;
7583 case CP0_REGISTER_08:
7584 switch (sel) {
7585 case CP0_REG08__BADVADDR:
7586 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
7587 tcg_gen_ext32s_tl(arg, arg);
7588 register_name = "BadVAddr";
7589 break;
7590 case CP0_REG08__BADINSTR:
7591 CP0_CHECK(ctx->bi);
7592 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
7593 register_name = "BadInstr";
7594 break;
7595 case CP0_REG08__BADINSTRP:
7596 CP0_CHECK(ctx->bp);
7597 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
7598 register_name = "BadInstrP";
7599 break;
7600 case CP0_REG08__BADINSTRX:
7601 CP0_CHECK(ctx->bi);
7602 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7603 tcg_gen_andi_tl(arg, arg, ~0xffff);
7604 register_name = "BadInstrX";
7605 break;
7606 default:
7607 goto cp0_unimplemented;
7609 break;
7610 case CP0_REGISTER_09:
7611 switch (sel) {
7612 case CP0_REG09__COUNT:
7613 /* Mark as an IO operation because we read the time. */
7614 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7615 gen_io_start();
7617 gen_helper_mfc0_count(arg, cpu_env);
7619 * Break the TB to be able to take timer interrupts immediately
7620 * after reading count. DISAS_STOP isn't sufficient, we need to
7621 * ensure we break completely out of translated code.
7623 gen_save_pc(ctx->base.pc_next + 4);
7624 ctx->base.is_jmp = DISAS_EXIT;
7625 register_name = "Count";
7626 break;
7627 case CP0_REG09__SAARI:
7628 CP0_CHECK(ctx->saar);
7629 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
7630 register_name = "SAARI";
7631 break;
7632 case CP0_REG09__SAAR:
7633 CP0_CHECK(ctx->saar);
7634 gen_helper_mfc0_saar(arg, cpu_env);
7635 register_name = "SAAR";
7636 break;
7637 default:
7638 goto cp0_unimplemented;
7640 break;
7641 case CP0_REGISTER_10:
7642 switch (sel) {
7643 case CP0_REG10__ENTRYHI:
7644 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
7645 tcg_gen_ext32s_tl(arg, arg);
7646 register_name = "EntryHi";
7647 break;
7648 default:
7649 goto cp0_unimplemented;
7651 break;
7652 case CP0_REGISTER_11:
7653 switch (sel) {
7654 case CP0_REG11__COMPARE:
7655 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
7656 register_name = "Compare";
7657 break;
7658 /* 6,7 are implementation dependent */
7659 default:
7660 goto cp0_unimplemented;
7662 break;
7663 case CP0_REGISTER_12:
7664 switch (sel) {
7665 case CP0_REG12__STATUS:
7666 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
7667 register_name = "Status";
7668 break;
7669 case CP0_REG12__INTCTL:
7670 check_insn(ctx, ISA_MIPS_R2);
7671 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
7672 register_name = "IntCtl";
7673 break;
7674 case CP0_REG12__SRSCTL:
7675 check_insn(ctx, ISA_MIPS_R2);
7676 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
7677 register_name = "SRSCtl";
7678 break;
7679 case CP0_REG12__SRSMAP:
7680 check_insn(ctx, ISA_MIPS_R2);
7681 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7682 register_name = "SRSMap";
7683 break;
7684 default:
7685 goto cp0_unimplemented;
7687 break;
7688 case CP0_REGISTER_13:
7689 switch (sel) {
7690 case CP0_REG13__CAUSE:
7691 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
7692 register_name = "Cause";
7693 break;
7694 default:
7695 goto cp0_unimplemented;
7697 break;
7698 case CP0_REGISTER_14:
7699 switch (sel) {
7700 case CP0_REG14__EPC:
7701 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7702 tcg_gen_ext32s_tl(arg, arg);
7703 register_name = "EPC";
7704 break;
7705 default:
7706 goto cp0_unimplemented;
7708 break;
7709 case CP0_REGISTER_15:
7710 switch (sel) {
7711 case CP0_REG15__PRID:
7712 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
7713 register_name = "PRid";
7714 break;
7715 case CP0_REG15__EBASE:
7716 check_insn(ctx, ISA_MIPS_R2);
7717 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7718 tcg_gen_ext32s_tl(arg, arg);
7719 register_name = "EBase";
7720 break;
7721 case CP0_REG15__CMGCRBASE:
7722 check_insn(ctx, ISA_MIPS_R2);
7723 CP0_CHECK(ctx->cmgcr);
7724 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7725 tcg_gen_ext32s_tl(arg, arg);
7726 register_name = "CMGCRBase";
7727 break;
7728 default:
7729 goto cp0_unimplemented;
7731 break;
7732 case CP0_REGISTER_16:
7733 switch (sel) {
7734 case CP0_REG16__CONFIG:
7735 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
7736 register_name = "Config";
7737 break;
7738 case CP0_REG16__CONFIG1:
7739 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
7740 register_name = "Config1";
7741 break;
7742 case CP0_REG16__CONFIG2:
7743 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7744 register_name = "Config2";
7745 break;
7746 case CP0_REG16__CONFIG3:
7747 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7748 register_name = "Config3";
7749 break;
7750 case CP0_REG16__CONFIG4:
7751 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7752 register_name = "Config4";
7753 break;
7754 case CP0_REG16__CONFIG5:
7755 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7756 register_name = "Config5";
7757 break;
7758 /* 6,7 are implementation dependent */
7759 case CP0_REG16__CONFIG6:
7760 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
7761 register_name = "Config6";
7762 break;
7763 case CP0_REG16__CONFIG7:
7764 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
7765 register_name = "Config7";
7766 break;
7767 default:
7768 goto cp0_unimplemented;
7770 break;
7771 case CP0_REGISTER_17:
7772 switch (sel) {
7773 case CP0_REG17__LLADDR:
7774 gen_helper_mfc0_lladdr(arg, cpu_env);
7775 register_name = "LLAddr";
7776 break;
7777 case CP0_REG17__MAAR:
7778 CP0_CHECK(ctx->mrp);
7779 gen_helper_mfc0_maar(arg, cpu_env);
7780 register_name = "MAAR";
7781 break;
7782 case CP0_REG17__MAARI:
7783 CP0_CHECK(ctx->mrp);
7784 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7785 register_name = "MAARI";
7786 break;
7787 default:
7788 goto cp0_unimplemented;
7790 break;
7791 case CP0_REGISTER_18:
7792 switch (sel) {
7793 case CP0_REG18__WATCHLO0:
7794 case CP0_REG18__WATCHLO1:
7795 case CP0_REG18__WATCHLO2:
7796 case CP0_REG18__WATCHLO3:
7797 case CP0_REG18__WATCHLO4:
7798 case CP0_REG18__WATCHLO5:
7799 case CP0_REG18__WATCHLO6:
7800 case CP0_REG18__WATCHLO7:
7801 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7802 gen_helper_1e0i(mfc0_watchlo, arg, sel);
7803 register_name = "WatchLo";
7804 break;
7805 default:
7806 goto cp0_unimplemented;
7808 break;
7809 case CP0_REGISTER_19:
7810 switch (sel) {
7811 case CP0_REG19__WATCHHI0:
7812 case CP0_REG19__WATCHHI1:
7813 case CP0_REG19__WATCHHI2:
7814 case CP0_REG19__WATCHHI3:
7815 case CP0_REG19__WATCHHI4:
7816 case CP0_REG19__WATCHHI5:
7817 case CP0_REG19__WATCHHI6:
7818 case CP0_REG19__WATCHHI7:
7819 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7820 gen_helper_1e0i(mfc0_watchhi, arg, sel);
7821 register_name = "WatchHi";
7822 break;
7823 default:
7824 goto cp0_unimplemented;
7826 break;
7827 case CP0_REGISTER_20:
7828 switch (sel) {
7829 case CP0_REG20__XCONTEXT:
7830 #if defined(TARGET_MIPS64)
7831 check_insn(ctx, ISA_MIPS3);
7832 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
7833 tcg_gen_ext32s_tl(arg, arg);
7834 register_name = "XContext";
7835 break;
7836 #endif
7837 default:
7838 goto cp0_unimplemented;
7840 break;
7841 case CP0_REGISTER_21:
7842 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7843 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7844 switch (sel) {
7845 case 0:
7846 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
7847 register_name = "Framemask";
7848 break;
7849 default:
7850 goto cp0_unimplemented;
7852 break;
7853 case CP0_REGISTER_22:
7854 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7855 register_name = "'Diagnostic"; /* implementation dependent */
7856 break;
7857 case CP0_REGISTER_23:
7858 switch (sel) {
7859 case CP0_REG23__DEBUG:
7860 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
7861 register_name = "Debug";
7862 break;
7863 case CP0_REG23__TRACECONTROL:
7864 /* PDtrace support */
7865 /* gen_helper_mfc0_tracecontrol(arg); */
7866 register_name = "TraceControl";
7867 goto cp0_unimplemented;
7868 case CP0_REG23__TRACECONTROL2:
7869 /* PDtrace support */
7870 /* gen_helper_mfc0_tracecontrol2(arg); */
7871 register_name = "TraceControl2";
7872 goto cp0_unimplemented;
7873 case CP0_REG23__USERTRACEDATA1:
7874 /* PDtrace support */
7875 /* gen_helper_mfc0_usertracedata1(arg);*/
7876 register_name = "UserTraceData1";
7877 goto cp0_unimplemented;
7878 case CP0_REG23__TRACEIBPC:
7879 /* PDtrace support */
7880 /* gen_helper_mfc0_traceibpc(arg); */
7881 register_name = "TraceIBPC";
7882 goto cp0_unimplemented;
7883 case CP0_REG23__TRACEDBPC:
7884 /* PDtrace support */
7885 /* gen_helper_mfc0_tracedbpc(arg); */
7886 register_name = "TraceDBPC";
7887 goto cp0_unimplemented;
7888 default:
7889 goto cp0_unimplemented;
7891 break;
7892 case CP0_REGISTER_24:
7893 switch (sel) {
7894 case CP0_REG24__DEPC:
7895 /* EJTAG support */
7896 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7897 tcg_gen_ext32s_tl(arg, arg);
7898 register_name = "DEPC";
7899 break;
7900 default:
7901 goto cp0_unimplemented;
7903 break;
7904 case CP0_REGISTER_25:
7905 switch (sel) {
7906 case CP0_REG25__PERFCTL0:
7907 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
7908 register_name = "Performance0";
7909 break;
7910 case CP0_REG25__PERFCNT0:
7911 /* gen_helper_mfc0_performance1(arg); */
7912 register_name = "Performance1";
7913 goto cp0_unimplemented;
7914 case CP0_REG25__PERFCTL1:
7915 /* gen_helper_mfc0_performance2(arg); */
7916 register_name = "Performance2";
7917 goto cp0_unimplemented;
7918 case CP0_REG25__PERFCNT1:
7919 /* gen_helper_mfc0_performance3(arg); */
7920 register_name = "Performance3";
7921 goto cp0_unimplemented;
7922 case CP0_REG25__PERFCTL2:
7923 /* gen_helper_mfc0_performance4(arg); */
7924 register_name = "Performance4";
7925 goto cp0_unimplemented;
7926 case CP0_REG25__PERFCNT2:
7927 /* gen_helper_mfc0_performance5(arg); */
7928 register_name = "Performance5";
7929 goto cp0_unimplemented;
7930 case CP0_REG25__PERFCTL3:
7931 /* gen_helper_mfc0_performance6(arg); */
7932 register_name = "Performance6";
7933 goto cp0_unimplemented;
7934 case CP0_REG25__PERFCNT3:
7935 /* gen_helper_mfc0_performance7(arg); */
7936 register_name = "Performance7";
7937 goto cp0_unimplemented;
7938 default:
7939 goto cp0_unimplemented;
7941 break;
7942 case CP0_REGISTER_26:
7943 switch (sel) {
7944 case CP0_REG26__ERRCTL:
7945 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7946 register_name = "ErrCtl";
7947 break;
7948 default:
7949 goto cp0_unimplemented;
7951 break;
7952 case CP0_REGISTER_27:
7953 switch (sel) {
7954 case CP0_REG27__CACHERR:
7955 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7956 register_name = "CacheErr";
7957 break;
7958 default:
7959 goto cp0_unimplemented;
7961 break;
7962 case CP0_REGISTER_28:
7963 switch (sel) {
7964 case CP0_REG28__TAGLO:
7965 case CP0_REG28__TAGLO1:
7966 case CP0_REG28__TAGLO2:
7967 case CP0_REG28__TAGLO3:
7969 TCGv_i64 tmp = tcg_temp_new_i64();
7970 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
7971 gen_move_low32(arg, tmp);
7972 tcg_temp_free_i64(tmp);
7974 register_name = "TagLo";
7975 break;
7976 case CP0_REG28__DATALO:
7977 case CP0_REG28__DATALO1:
7978 case CP0_REG28__DATALO2:
7979 case CP0_REG28__DATALO3:
7980 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7981 register_name = "DataLo";
7982 break;
7983 default:
7984 goto cp0_unimplemented;
7986 break;
7987 case CP0_REGISTER_29:
7988 switch (sel) {
7989 case CP0_REG29__TAGHI:
7990 case CP0_REG29__TAGHI1:
7991 case CP0_REG29__TAGHI2:
7992 case CP0_REG29__TAGHI3:
7993 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7994 register_name = "TagHi";
7995 break;
7996 case CP0_REG29__DATAHI:
7997 case CP0_REG29__DATAHI1:
7998 case CP0_REG29__DATAHI2:
7999 case CP0_REG29__DATAHI3:
8000 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
8001 register_name = "DataHi";
8002 break;
8003 default:
8004 goto cp0_unimplemented;
8006 break;
8007 case CP0_REGISTER_30:
8008 switch (sel) {
8009 case CP0_REG30__ERROREPC:
8010 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8011 tcg_gen_ext32s_tl(arg, arg);
8012 register_name = "ErrorEPC";
8013 break;
8014 default:
8015 goto cp0_unimplemented;
8017 break;
8018 case CP0_REGISTER_31:
8019 switch (sel) {
8020 case CP0_REG31__DESAVE:
8021 /* EJTAG support */
8022 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8023 register_name = "DESAVE";
8024 break;
8025 case CP0_REG31__KSCRATCH1:
8026 case CP0_REG31__KSCRATCH2:
8027 case CP0_REG31__KSCRATCH3:
8028 case CP0_REG31__KSCRATCH4:
8029 case CP0_REG31__KSCRATCH5:
8030 case CP0_REG31__KSCRATCH6:
8031 CP0_CHECK(ctx->kscrexist & (1 << sel));
8032 tcg_gen_ld_tl(arg, cpu_env,
8033 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
8034 tcg_gen_ext32s_tl(arg, arg);
8035 register_name = "KScratch";
8036 break;
8037 default:
8038 goto cp0_unimplemented;
8040 break;
8041 default:
8042 goto cp0_unimplemented;
8044 trace_mips_translate_c0("mfc0", register_name, reg, sel);
8045 return;
8047 cp0_unimplemented:
8048 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
8049 register_name, reg, sel);
8050 gen_mfc0_unimplemented(ctx, arg);
8053 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8055 const char *register_name = "invalid";
8057 if (sel != 0) {
8058 check_insn(ctx, ISA_MIPS_R1);
8061 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8062 gen_io_start();
8065 switch (reg) {
8066 case CP0_REGISTER_00:
8067 switch (sel) {
8068 case CP0_REG00__INDEX:
8069 gen_helper_mtc0_index(cpu_env, arg);
8070 register_name = "Index";
8071 break;
8072 case CP0_REG00__MVPCONTROL:
8073 CP0_CHECK(ctx->insn_flags & ASE_MT);
8074 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
8075 register_name = "MVPControl";
8076 break;
8077 case CP0_REG00__MVPCONF0:
8078 CP0_CHECK(ctx->insn_flags & ASE_MT);
8079 /* ignored */
8080 register_name = "MVPConf0";
8081 break;
8082 case CP0_REG00__MVPCONF1:
8083 CP0_CHECK(ctx->insn_flags & ASE_MT);
8084 /* ignored */
8085 register_name = "MVPConf1";
8086 break;
8087 case CP0_REG00__VPCONTROL:
8088 CP0_CHECK(ctx->vp);
8089 /* ignored */
8090 register_name = "VPControl";
8091 break;
8092 default:
8093 goto cp0_unimplemented;
8095 break;
8096 case CP0_REGISTER_01:
8097 switch (sel) {
8098 case CP0_REG01__RANDOM:
8099 /* ignored */
8100 register_name = "Random";
8101 break;
8102 case CP0_REG01__VPECONTROL:
8103 CP0_CHECK(ctx->insn_flags & ASE_MT);
8104 gen_helper_mtc0_vpecontrol(cpu_env, arg);
8105 register_name = "VPEControl";
8106 break;
8107 case CP0_REG01__VPECONF0:
8108 CP0_CHECK(ctx->insn_flags & ASE_MT);
8109 gen_helper_mtc0_vpeconf0(cpu_env, arg);
8110 register_name = "VPEConf0";
8111 break;
8112 case CP0_REG01__VPECONF1:
8113 CP0_CHECK(ctx->insn_flags & ASE_MT);
8114 gen_helper_mtc0_vpeconf1(cpu_env, arg);
8115 register_name = "VPEConf1";
8116 break;
8117 case CP0_REG01__YQMASK:
8118 CP0_CHECK(ctx->insn_flags & ASE_MT);
8119 gen_helper_mtc0_yqmask(cpu_env, arg);
8120 register_name = "YQMask";
8121 break;
8122 case CP0_REG01__VPESCHEDULE:
8123 CP0_CHECK(ctx->insn_flags & ASE_MT);
8124 tcg_gen_st_tl(arg, cpu_env,
8125 offsetof(CPUMIPSState, CP0_VPESchedule));
8126 register_name = "VPESchedule";
8127 break;
8128 case CP0_REG01__VPESCHEFBACK:
8129 CP0_CHECK(ctx->insn_flags & ASE_MT);
8130 tcg_gen_st_tl(arg, cpu_env,
8131 offsetof(CPUMIPSState, CP0_VPEScheFBack));
8132 register_name = "VPEScheFBack";
8133 break;
8134 case CP0_REG01__VPEOPT:
8135 CP0_CHECK(ctx->insn_flags & ASE_MT);
8136 gen_helper_mtc0_vpeopt(cpu_env, arg);
8137 register_name = "VPEOpt";
8138 break;
8139 default:
8140 goto cp0_unimplemented;
8142 break;
8143 case CP0_REGISTER_02:
8144 switch (sel) {
8145 case CP0_REG02__ENTRYLO0:
8146 gen_helper_mtc0_entrylo0(cpu_env, arg);
8147 register_name = "EntryLo0";
8148 break;
8149 case CP0_REG02__TCSTATUS:
8150 CP0_CHECK(ctx->insn_flags & ASE_MT);
8151 gen_helper_mtc0_tcstatus(cpu_env, arg);
8152 register_name = "TCStatus";
8153 break;
8154 case CP0_REG02__TCBIND:
8155 CP0_CHECK(ctx->insn_flags & ASE_MT);
8156 gen_helper_mtc0_tcbind(cpu_env, arg);
8157 register_name = "TCBind";
8158 break;
8159 case CP0_REG02__TCRESTART:
8160 CP0_CHECK(ctx->insn_flags & ASE_MT);
8161 gen_helper_mtc0_tcrestart(cpu_env, arg);
8162 register_name = "TCRestart";
8163 break;
8164 case CP0_REG02__TCHALT:
8165 CP0_CHECK(ctx->insn_flags & ASE_MT);
8166 gen_helper_mtc0_tchalt(cpu_env, arg);
8167 register_name = "TCHalt";
8168 break;
8169 case CP0_REG02__TCCONTEXT:
8170 CP0_CHECK(ctx->insn_flags & ASE_MT);
8171 gen_helper_mtc0_tccontext(cpu_env, arg);
8172 register_name = "TCContext";
8173 break;
8174 case CP0_REG02__TCSCHEDULE:
8175 CP0_CHECK(ctx->insn_flags & ASE_MT);
8176 gen_helper_mtc0_tcschedule(cpu_env, arg);
8177 register_name = "TCSchedule";
8178 break;
8179 case CP0_REG02__TCSCHEFBACK:
8180 CP0_CHECK(ctx->insn_flags & ASE_MT);
8181 gen_helper_mtc0_tcschefback(cpu_env, arg);
8182 register_name = "TCScheFBack";
8183 break;
8184 default:
8185 goto cp0_unimplemented;
8187 break;
8188 case CP0_REGISTER_03:
8189 switch (sel) {
8190 case CP0_REG03__ENTRYLO1:
8191 gen_helper_mtc0_entrylo1(cpu_env, arg);
8192 register_name = "EntryLo1";
8193 break;
8194 case CP0_REG03__GLOBALNUM:
8195 CP0_CHECK(ctx->vp);
8196 /* ignored */
8197 register_name = "GlobalNumber";
8198 break;
8199 default:
8200 goto cp0_unimplemented;
8202 break;
8203 case CP0_REGISTER_04:
8204 switch (sel) {
8205 case CP0_REG04__CONTEXT:
8206 gen_helper_mtc0_context(cpu_env, arg);
8207 register_name = "Context";
8208 break;
8209 case CP0_REG04__CONTEXTCONFIG:
8210 /* SmartMIPS ASE */
8211 /* gen_helper_mtc0_contextconfig(arg); */
8212 register_name = "ContextConfig";
8213 goto cp0_unimplemented;
8214 case CP0_REG04__USERLOCAL:
8215 CP0_CHECK(ctx->ulri);
8216 tcg_gen_st_tl(arg, cpu_env,
8217 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8218 register_name = "UserLocal";
8219 break;
8220 case CP0_REG04__MMID:
8221 CP0_CHECK(ctx->mi);
8222 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
8223 register_name = "MMID";
8224 break;
8225 default:
8226 goto cp0_unimplemented;
8228 break;
8229 case CP0_REGISTER_05:
8230 switch (sel) {
8231 case CP0_REG05__PAGEMASK:
8232 gen_helper_mtc0_pagemask(cpu_env, arg);
8233 register_name = "PageMask";
8234 break;
8235 case CP0_REG05__PAGEGRAIN:
8236 check_insn(ctx, ISA_MIPS_R2);
8237 gen_helper_mtc0_pagegrain(cpu_env, arg);
8238 register_name = "PageGrain";
8239 ctx->base.is_jmp = DISAS_STOP;
8240 break;
8241 case CP0_REG05__SEGCTL0:
8242 CP0_CHECK(ctx->sc);
8243 gen_helper_mtc0_segctl0(cpu_env, arg);
8244 register_name = "SegCtl0";
8245 break;
8246 case CP0_REG05__SEGCTL1:
8247 CP0_CHECK(ctx->sc);
8248 gen_helper_mtc0_segctl1(cpu_env, arg);
8249 register_name = "SegCtl1";
8250 break;
8251 case CP0_REG05__SEGCTL2:
8252 CP0_CHECK(ctx->sc);
8253 gen_helper_mtc0_segctl2(cpu_env, arg);
8254 register_name = "SegCtl2";
8255 break;
8256 case CP0_REG05__PWBASE:
8257 check_pw(ctx);
8258 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
8259 register_name = "PWBase";
8260 break;
8261 case CP0_REG05__PWFIELD:
8262 check_pw(ctx);
8263 gen_helper_mtc0_pwfield(cpu_env, arg);
8264 register_name = "PWField";
8265 break;
8266 case CP0_REG05__PWSIZE:
8267 check_pw(ctx);
8268 gen_helper_mtc0_pwsize(cpu_env, arg);
8269 register_name = "PWSize";
8270 break;
8271 default:
8272 goto cp0_unimplemented;
8274 break;
8275 case CP0_REGISTER_06:
8276 switch (sel) {
8277 case CP0_REG06__WIRED:
8278 gen_helper_mtc0_wired(cpu_env, arg);
8279 register_name = "Wired";
8280 break;
8281 case CP0_REG06__SRSCONF0:
8282 check_insn(ctx, ISA_MIPS_R2);
8283 gen_helper_mtc0_srsconf0(cpu_env, arg);
8284 register_name = "SRSConf0";
8285 break;
8286 case CP0_REG06__SRSCONF1:
8287 check_insn(ctx, ISA_MIPS_R2);
8288 gen_helper_mtc0_srsconf1(cpu_env, arg);
8289 register_name = "SRSConf1";
8290 break;
8291 case CP0_REG06__SRSCONF2:
8292 check_insn(ctx, ISA_MIPS_R2);
8293 gen_helper_mtc0_srsconf2(cpu_env, arg);
8294 register_name = "SRSConf2";
8295 break;
8296 case CP0_REG06__SRSCONF3:
8297 check_insn(ctx, ISA_MIPS_R2);
8298 gen_helper_mtc0_srsconf3(cpu_env, arg);
8299 register_name = "SRSConf3";
8300 break;
8301 case CP0_REG06__SRSCONF4:
8302 check_insn(ctx, ISA_MIPS_R2);
8303 gen_helper_mtc0_srsconf4(cpu_env, arg);
8304 register_name = "SRSConf4";
8305 break;
8306 case CP0_REG06__PWCTL:
8307 check_pw(ctx);
8308 gen_helper_mtc0_pwctl(cpu_env, arg);
8309 register_name = "PWCtl";
8310 break;
8311 default:
8312 goto cp0_unimplemented;
8314 break;
8315 case CP0_REGISTER_07:
8316 switch (sel) {
8317 case CP0_REG07__HWRENA:
8318 check_insn(ctx, ISA_MIPS_R2);
8319 gen_helper_mtc0_hwrena(cpu_env, arg);
8320 ctx->base.is_jmp = DISAS_STOP;
8321 register_name = "HWREna";
8322 break;
8323 default:
8324 goto cp0_unimplemented;
8326 break;
8327 case CP0_REGISTER_08:
8328 switch (sel) {
8329 case CP0_REG08__BADVADDR:
8330 /* ignored */
8331 register_name = "BadVAddr";
8332 break;
8333 case CP0_REG08__BADINSTR:
8334 /* ignored */
8335 register_name = "BadInstr";
8336 break;
8337 case CP0_REG08__BADINSTRP:
8338 /* ignored */
8339 register_name = "BadInstrP";
8340 break;
8341 case CP0_REG08__BADINSTRX:
8342 /* ignored */
8343 register_name = "BadInstrX";
8344 break;
8345 default:
8346 goto cp0_unimplemented;
8348 break;
8349 case CP0_REGISTER_09:
8350 switch (sel) {
8351 case CP0_REG09__COUNT:
8352 gen_helper_mtc0_count(cpu_env, arg);
8353 register_name = "Count";
8354 break;
8355 case CP0_REG09__SAARI:
8356 CP0_CHECK(ctx->saar);
8357 gen_helper_mtc0_saari(cpu_env, arg);
8358 register_name = "SAARI";
8359 break;
8360 case CP0_REG09__SAAR:
8361 CP0_CHECK(ctx->saar);
8362 gen_helper_mtc0_saar(cpu_env, arg);
8363 register_name = "SAAR";
8364 break;
8365 default:
8366 goto cp0_unimplemented;
8368 break;
8369 case CP0_REGISTER_10:
8370 switch (sel) {
8371 case CP0_REG10__ENTRYHI:
8372 gen_helper_mtc0_entryhi(cpu_env, arg);
8373 register_name = "EntryHi";
8374 break;
8375 default:
8376 goto cp0_unimplemented;
8378 break;
8379 case CP0_REGISTER_11:
8380 switch (sel) {
8381 case CP0_REG11__COMPARE:
8382 gen_helper_mtc0_compare(cpu_env, arg);
8383 register_name = "Compare";
8384 break;
8385 /* 6,7 are implementation dependent */
8386 default:
8387 goto cp0_unimplemented;
8389 break;
8390 case CP0_REGISTER_12:
8391 switch (sel) {
8392 case CP0_REG12__STATUS:
8393 save_cpu_state(ctx, 1);
8394 gen_helper_mtc0_status(cpu_env, arg);
8395 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8396 gen_save_pc(ctx->base.pc_next + 4);
8397 ctx->base.is_jmp = DISAS_EXIT;
8398 register_name = "Status";
8399 break;
8400 case CP0_REG12__INTCTL:
8401 check_insn(ctx, ISA_MIPS_R2);
8402 gen_helper_mtc0_intctl(cpu_env, arg);
8403 /* Stop translation as we may have switched the execution mode */
8404 ctx->base.is_jmp = DISAS_STOP;
8405 register_name = "IntCtl";
8406 break;
8407 case CP0_REG12__SRSCTL:
8408 check_insn(ctx, ISA_MIPS_R2);
8409 gen_helper_mtc0_srsctl(cpu_env, arg);
8410 /* Stop translation as we may have switched the execution mode */
8411 ctx->base.is_jmp = DISAS_STOP;
8412 register_name = "SRSCtl";
8413 break;
8414 case CP0_REG12__SRSMAP:
8415 check_insn(ctx, ISA_MIPS_R2);
8416 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8417 /* Stop translation as we may have switched the execution mode */
8418 ctx->base.is_jmp = DISAS_STOP;
8419 register_name = "SRSMap";
8420 break;
8421 default:
8422 goto cp0_unimplemented;
8424 break;
8425 case CP0_REGISTER_13:
8426 switch (sel) {
8427 case CP0_REG13__CAUSE:
8428 save_cpu_state(ctx, 1);
8429 gen_helper_mtc0_cause(cpu_env, arg);
8431 * Stop translation as we may have triggered an interrupt.
8432 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8433 * translated code to check for pending interrupts.
8435 gen_save_pc(ctx->base.pc_next + 4);
8436 ctx->base.is_jmp = DISAS_EXIT;
8437 register_name = "Cause";
8438 break;
8439 default:
8440 goto cp0_unimplemented;
8442 break;
8443 case CP0_REGISTER_14:
8444 switch (sel) {
8445 case CP0_REG14__EPC:
8446 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8447 register_name = "EPC";
8448 break;
8449 default:
8450 goto cp0_unimplemented;
8452 break;
8453 case CP0_REGISTER_15:
8454 switch (sel) {
8455 case CP0_REG15__PRID:
8456 /* ignored */
8457 register_name = "PRid";
8458 break;
8459 case CP0_REG15__EBASE:
8460 check_insn(ctx, ISA_MIPS_R2);
8461 gen_helper_mtc0_ebase(cpu_env, arg);
8462 register_name = "EBase";
8463 break;
8464 default:
8465 goto cp0_unimplemented;
8467 break;
8468 case CP0_REGISTER_16:
8469 switch (sel) {
8470 case CP0_REG16__CONFIG:
8471 gen_helper_mtc0_config0(cpu_env, arg);
8472 register_name = "Config";
8473 /* Stop translation as we may have switched the execution mode */
8474 ctx->base.is_jmp = DISAS_STOP;
8475 break;
8476 case CP0_REG16__CONFIG1:
8477 /* ignored, read only */
8478 register_name = "Config1";
8479 break;
8480 case CP0_REG16__CONFIG2:
8481 gen_helper_mtc0_config2(cpu_env, arg);
8482 register_name = "Config2";
8483 /* Stop translation as we may have switched the execution mode */
8484 ctx->base.is_jmp = DISAS_STOP;
8485 break;
8486 case CP0_REG16__CONFIG3:
8487 gen_helper_mtc0_config3(cpu_env, arg);
8488 register_name = "Config3";
8489 /* Stop translation as we may have switched the execution mode */
8490 ctx->base.is_jmp = DISAS_STOP;
8491 break;
8492 case CP0_REG16__CONFIG4:
8493 gen_helper_mtc0_config4(cpu_env, arg);
8494 register_name = "Config4";
8495 ctx->base.is_jmp = DISAS_STOP;
8496 break;
8497 case CP0_REG16__CONFIG5:
8498 gen_helper_mtc0_config5(cpu_env, arg);
8499 register_name = "Config5";
8500 /* Stop translation as we may have switched the execution mode */
8501 ctx->base.is_jmp = DISAS_STOP;
8502 break;
8503 /* 6,7 are implementation dependent */
8504 case CP0_REG16__CONFIG6:
8505 /* ignored */
8506 register_name = "Config6";
8507 break;
8508 case CP0_REG16__CONFIG7:
8509 /* ignored */
8510 register_name = "Config7";
8511 break;
8512 default:
8513 register_name = "Invalid config selector";
8514 goto cp0_unimplemented;
8516 break;
8517 case CP0_REGISTER_17:
8518 switch (sel) {
8519 case CP0_REG17__LLADDR:
8520 gen_helper_mtc0_lladdr(cpu_env, arg);
8521 register_name = "LLAddr";
8522 break;
8523 case CP0_REG17__MAAR:
8524 CP0_CHECK(ctx->mrp);
8525 gen_helper_mtc0_maar(cpu_env, arg);
8526 register_name = "MAAR";
8527 break;
8528 case CP0_REG17__MAARI:
8529 CP0_CHECK(ctx->mrp);
8530 gen_helper_mtc0_maari(cpu_env, arg);
8531 register_name = "MAARI";
8532 break;
8533 default:
8534 goto cp0_unimplemented;
8536 break;
8537 case CP0_REGISTER_18:
8538 switch (sel) {
8539 case CP0_REG18__WATCHLO0:
8540 case CP0_REG18__WATCHLO1:
8541 case CP0_REG18__WATCHLO2:
8542 case CP0_REG18__WATCHLO3:
8543 case CP0_REG18__WATCHLO4:
8544 case CP0_REG18__WATCHLO5:
8545 case CP0_REG18__WATCHLO6:
8546 case CP0_REG18__WATCHLO7:
8547 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8548 gen_helper_0e1i(mtc0_watchlo, arg, sel);
8549 register_name = "WatchLo";
8550 break;
8551 default:
8552 goto cp0_unimplemented;
8554 break;
8555 case CP0_REGISTER_19:
8556 switch (sel) {
8557 case CP0_REG19__WATCHHI0:
8558 case CP0_REG19__WATCHHI1:
8559 case CP0_REG19__WATCHHI2:
8560 case CP0_REG19__WATCHHI3:
8561 case CP0_REG19__WATCHHI4:
8562 case CP0_REG19__WATCHHI5:
8563 case CP0_REG19__WATCHHI6:
8564 case CP0_REG19__WATCHHI7:
8565 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8566 gen_helper_0e1i(mtc0_watchhi, arg, sel);
8567 register_name = "WatchHi";
8568 break;
8569 default:
8570 goto cp0_unimplemented;
8572 break;
8573 case CP0_REGISTER_20:
8574 switch (sel) {
8575 case CP0_REG20__XCONTEXT:
8576 #if defined(TARGET_MIPS64)
8577 check_insn(ctx, ISA_MIPS3);
8578 gen_helper_mtc0_xcontext(cpu_env, arg);
8579 register_name = "XContext";
8580 break;
8581 #endif
8582 default:
8583 goto cp0_unimplemented;
8585 break;
8586 case CP0_REGISTER_21:
8587 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8588 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
8589 switch (sel) {
8590 case 0:
8591 gen_helper_mtc0_framemask(cpu_env, arg);
8592 register_name = "Framemask";
8593 break;
8594 default:
8595 goto cp0_unimplemented;
8597 break;
8598 case CP0_REGISTER_22:
8599 /* ignored */
8600 register_name = "Diagnostic"; /* implementation dependent */
8601 break;
8602 case CP0_REGISTER_23:
8603 switch (sel) {
8604 case CP0_REG23__DEBUG:
8605 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8606 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8607 gen_save_pc(ctx->base.pc_next + 4);
8608 ctx->base.is_jmp = DISAS_EXIT;
8609 register_name = "Debug";
8610 break;
8611 case CP0_REG23__TRACECONTROL:
8612 /* PDtrace support */
8613 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
8614 register_name = "TraceControl";
8615 /* Stop translation as we may have switched the execution mode */
8616 ctx->base.is_jmp = DISAS_STOP;
8617 goto cp0_unimplemented;
8618 case CP0_REG23__TRACECONTROL2:
8619 /* PDtrace support */
8620 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
8621 register_name = "TraceControl2";
8622 /* Stop translation as we may have switched the execution mode */
8623 ctx->base.is_jmp = DISAS_STOP;
8624 goto cp0_unimplemented;
8625 case CP0_REG23__USERTRACEDATA1:
8626 /* Stop translation as we may have switched the execution mode */
8627 ctx->base.is_jmp = DISAS_STOP;
8628 /* PDtrace support */
8629 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
8630 register_name = "UserTraceData";
8631 /* Stop translation as we may have switched the execution mode */
8632 ctx->base.is_jmp = DISAS_STOP;
8633 goto cp0_unimplemented;
8634 case CP0_REG23__TRACEIBPC:
8635 /* PDtrace support */
8636 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
8637 /* Stop translation as we may have switched the execution mode */
8638 ctx->base.is_jmp = DISAS_STOP;
8639 register_name = "TraceIBPC";
8640 goto cp0_unimplemented;
8641 case CP0_REG23__TRACEDBPC:
8642 /* PDtrace support */
8643 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
8644 /* Stop translation as we may have switched the execution mode */
8645 ctx->base.is_jmp = DISAS_STOP;
8646 register_name = "TraceDBPC";
8647 goto cp0_unimplemented;
8648 default:
8649 goto cp0_unimplemented;
8651 break;
8652 case CP0_REGISTER_24:
8653 switch (sel) {
8654 case CP0_REG24__DEPC:
8655 /* EJTAG support */
8656 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8657 register_name = "DEPC";
8658 break;
8659 default:
8660 goto cp0_unimplemented;
8662 break;
8663 case CP0_REGISTER_25:
8664 switch (sel) {
8665 case CP0_REG25__PERFCTL0:
8666 gen_helper_mtc0_performance0(cpu_env, arg);
8667 register_name = "Performance0";
8668 break;
8669 case CP0_REG25__PERFCNT0:
8670 /* gen_helper_mtc0_performance1(arg); */
8671 register_name = "Performance1";
8672 goto cp0_unimplemented;
8673 case CP0_REG25__PERFCTL1:
8674 /* gen_helper_mtc0_performance2(arg); */
8675 register_name = "Performance2";
8676 goto cp0_unimplemented;
8677 case CP0_REG25__PERFCNT1:
8678 /* gen_helper_mtc0_performance3(arg); */
8679 register_name = "Performance3";
8680 goto cp0_unimplemented;
8681 case CP0_REG25__PERFCTL2:
8682 /* gen_helper_mtc0_performance4(arg); */
8683 register_name = "Performance4";
8684 goto cp0_unimplemented;
8685 case CP0_REG25__PERFCNT2:
8686 /* gen_helper_mtc0_performance5(arg); */
8687 register_name = "Performance5";
8688 goto cp0_unimplemented;
8689 case CP0_REG25__PERFCTL3:
8690 /* gen_helper_mtc0_performance6(arg); */
8691 register_name = "Performance6";
8692 goto cp0_unimplemented;
8693 case CP0_REG25__PERFCNT3:
8694 /* gen_helper_mtc0_performance7(arg); */
8695 register_name = "Performance7";
8696 goto cp0_unimplemented;
8697 default:
8698 goto cp0_unimplemented;
8700 break;
8701 case CP0_REGISTER_26:
8702 switch (sel) {
8703 case CP0_REG26__ERRCTL:
8704 gen_helper_mtc0_errctl(cpu_env, arg);
8705 ctx->base.is_jmp = DISAS_STOP;
8706 register_name = "ErrCtl";
8707 break;
8708 default:
8709 goto cp0_unimplemented;
8711 break;
8712 case CP0_REGISTER_27:
8713 switch (sel) {
8714 case CP0_REG27__CACHERR:
8715 /* ignored */
8716 register_name = "CacheErr";
8717 break;
8718 default:
8719 goto cp0_unimplemented;
8721 break;
8722 case CP0_REGISTER_28:
8723 switch (sel) {
8724 case CP0_REG28__TAGLO:
8725 case CP0_REG28__TAGLO1:
8726 case CP0_REG28__TAGLO2:
8727 case CP0_REG28__TAGLO3:
8728 gen_helper_mtc0_taglo(cpu_env, arg);
8729 register_name = "TagLo";
8730 break;
8731 case CP0_REG28__DATALO:
8732 case CP0_REG28__DATALO1:
8733 case CP0_REG28__DATALO2:
8734 case CP0_REG28__DATALO3:
8735 gen_helper_mtc0_datalo(cpu_env, arg);
8736 register_name = "DataLo";
8737 break;
8738 default:
8739 goto cp0_unimplemented;
8741 break;
8742 case CP0_REGISTER_29:
8743 switch (sel) {
8744 case CP0_REG29__TAGHI:
8745 case CP0_REG29__TAGHI1:
8746 case CP0_REG29__TAGHI2:
8747 case CP0_REG29__TAGHI3:
8748 gen_helper_mtc0_taghi(cpu_env, arg);
8749 register_name = "TagHi";
8750 break;
8751 case CP0_REG29__DATAHI:
8752 case CP0_REG29__DATAHI1:
8753 case CP0_REG29__DATAHI2:
8754 case CP0_REG29__DATAHI3:
8755 gen_helper_mtc0_datahi(cpu_env, arg);
8756 register_name = "DataHi";
8757 break;
8758 default:
8759 register_name = "invalid sel";
8760 goto cp0_unimplemented;
8762 break;
8763 case CP0_REGISTER_30:
8764 switch (sel) {
8765 case CP0_REG30__ERROREPC:
8766 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8767 register_name = "ErrorEPC";
8768 break;
8769 default:
8770 goto cp0_unimplemented;
8772 break;
8773 case CP0_REGISTER_31:
8774 switch (sel) {
8775 case CP0_REG31__DESAVE:
8776 /* EJTAG support */
8777 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8778 register_name = "DESAVE";
8779 break;
8780 case CP0_REG31__KSCRATCH1:
8781 case CP0_REG31__KSCRATCH2:
8782 case CP0_REG31__KSCRATCH3:
8783 case CP0_REG31__KSCRATCH4:
8784 case CP0_REG31__KSCRATCH5:
8785 case CP0_REG31__KSCRATCH6:
8786 CP0_CHECK(ctx->kscrexist & (1 << sel));
8787 tcg_gen_st_tl(arg, cpu_env,
8788 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
8789 register_name = "KScratch";
8790 break;
8791 default:
8792 goto cp0_unimplemented;
8794 break;
8795 default:
8796 goto cp0_unimplemented;
8798 trace_mips_translate_c0("mtc0", register_name, reg, sel);
8800 /* For simplicity assume that all writes can cause interrupts. */
8801 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8803 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8804 * translated code to check for pending interrupts.
8806 gen_save_pc(ctx->base.pc_next + 4);
8807 ctx->base.is_jmp = DISAS_EXIT;
8809 return;
8811 cp0_unimplemented:
8812 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
8813 register_name, reg, sel);
8816 #if defined(TARGET_MIPS64)
8817 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8819 const char *register_name = "invalid";
8821 if (sel != 0) {
8822 check_insn(ctx, ISA_MIPS_R1);
8825 switch (reg) {
8826 case CP0_REGISTER_00:
8827 switch (sel) {
8828 case CP0_REG00__INDEX:
8829 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
8830 register_name = "Index";
8831 break;
8832 case CP0_REG00__MVPCONTROL:
8833 CP0_CHECK(ctx->insn_flags & ASE_MT);
8834 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
8835 register_name = "MVPControl";
8836 break;
8837 case CP0_REG00__MVPCONF0:
8838 CP0_CHECK(ctx->insn_flags & ASE_MT);
8839 gen_helper_mfc0_mvpconf0(arg, cpu_env);
8840 register_name = "MVPConf0";
8841 break;
8842 case CP0_REG00__MVPCONF1:
8843 CP0_CHECK(ctx->insn_flags & ASE_MT);
8844 gen_helper_mfc0_mvpconf1(arg, cpu_env);
8845 register_name = "MVPConf1";
8846 break;
8847 case CP0_REG00__VPCONTROL:
8848 CP0_CHECK(ctx->vp);
8849 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
8850 register_name = "VPControl";
8851 break;
8852 default:
8853 goto cp0_unimplemented;
8855 break;
8856 case CP0_REGISTER_01:
8857 switch (sel) {
8858 case CP0_REG01__RANDOM:
8859 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
8860 gen_helper_mfc0_random(arg, cpu_env);
8861 register_name = "Random";
8862 break;
8863 case CP0_REG01__VPECONTROL:
8864 CP0_CHECK(ctx->insn_flags & ASE_MT);
8865 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
8866 register_name = "VPEControl";
8867 break;
8868 case CP0_REG01__VPECONF0:
8869 CP0_CHECK(ctx->insn_flags & ASE_MT);
8870 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
8871 register_name = "VPEConf0";
8872 break;
8873 case CP0_REG01__VPECONF1:
8874 CP0_CHECK(ctx->insn_flags & ASE_MT);
8875 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
8876 register_name = "VPEConf1";
8877 break;
8878 case CP0_REG01__YQMASK:
8879 CP0_CHECK(ctx->insn_flags & ASE_MT);
8880 tcg_gen_ld_tl(arg, cpu_env,
8881 offsetof(CPUMIPSState, CP0_YQMask));
8882 register_name = "YQMask";
8883 break;
8884 case CP0_REG01__VPESCHEDULE:
8885 CP0_CHECK(ctx->insn_flags & ASE_MT);
8886 tcg_gen_ld_tl(arg, cpu_env,
8887 offsetof(CPUMIPSState, CP0_VPESchedule));
8888 register_name = "VPESchedule";
8889 break;
8890 case CP0_REG01__VPESCHEFBACK:
8891 CP0_CHECK(ctx->insn_flags & ASE_MT);
8892 tcg_gen_ld_tl(arg, cpu_env,
8893 offsetof(CPUMIPSState, CP0_VPEScheFBack));
8894 register_name = "VPEScheFBack";
8895 break;
8896 case CP0_REG01__VPEOPT:
8897 CP0_CHECK(ctx->insn_flags & ASE_MT);
8898 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
8899 register_name = "VPEOpt";
8900 break;
8901 default:
8902 goto cp0_unimplemented;
8904 break;
8905 case CP0_REGISTER_02:
8906 switch (sel) {
8907 case CP0_REG02__ENTRYLO0:
8908 tcg_gen_ld_tl(arg, cpu_env,
8909 offsetof(CPUMIPSState, CP0_EntryLo0));
8910 register_name = "EntryLo0";
8911 break;
8912 case CP0_REG02__TCSTATUS:
8913 CP0_CHECK(ctx->insn_flags & ASE_MT);
8914 gen_helper_mfc0_tcstatus(arg, cpu_env);
8915 register_name = "TCStatus";
8916 break;
8917 case CP0_REG02__TCBIND:
8918 CP0_CHECK(ctx->insn_flags & ASE_MT);
8919 gen_helper_mfc0_tcbind(arg, cpu_env);
8920 register_name = "TCBind";
8921 break;
8922 case CP0_REG02__TCRESTART:
8923 CP0_CHECK(ctx->insn_flags & ASE_MT);
8924 gen_helper_dmfc0_tcrestart(arg, cpu_env);
8925 register_name = "TCRestart";
8926 break;
8927 case CP0_REG02__TCHALT:
8928 CP0_CHECK(ctx->insn_flags & ASE_MT);
8929 gen_helper_dmfc0_tchalt(arg, cpu_env);
8930 register_name = "TCHalt";
8931 break;
8932 case CP0_REG02__TCCONTEXT:
8933 CP0_CHECK(ctx->insn_flags & ASE_MT);
8934 gen_helper_dmfc0_tccontext(arg, cpu_env);
8935 register_name = "TCContext";
8936 break;
8937 case CP0_REG02__TCSCHEDULE:
8938 CP0_CHECK(ctx->insn_flags & ASE_MT);
8939 gen_helper_dmfc0_tcschedule(arg, cpu_env);
8940 register_name = "TCSchedule";
8941 break;
8942 case CP0_REG02__TCSCHEFBACK:
8943 CP0_CHECK(ctx->insn_flags & ASE_MT);
8944 gen_helper_dmfc0_tcschefback(arg, cpu_env);
8945 register_name = "TCScheFBack";
8946 break;
8947 default:
8948 goto cp0_unimplemented;
8950 break;
8951 case CP0_REGISTER_03:
8952 switch (sel) {
8953 case CP0_REG03__ENTRYLO1:
8954 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
8955 register_name = "EntryLo1";
8956 break;
8957 case CP0_REG03__GLOBALNUM:
8958 CP0_CHECK(ctx->vp);
8959 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
8960 register_name = "GlobalNumber";
8961 break;
8962 default:
8963 goto cp0_unimplemented;
8965 break;
8966 case CP0_REGISTER_04:
8967 switch (sel) {
8968 case CP0_REG04__CONTEXT:
8969 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
8970 register_name = "Context";
8971 break;
8972 case CP0_REG04__CONTEXTCONFIG:
8973 /* SmartMIPS ASE */
8974 /* gen_helper_dmfc0_contextconfig(arg); */
8975 register_name = "ContextConfig";
8976 goto cp0_unimplemented;
8977 case CP0_REG04__USERLOCAL:
8978 CP0_CHECK(ctx->ulri);
8979 tcg_gen_ld_tl(arg, cpu_env,
8980 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8981 register_name = "UserLocal";
8982 break;
8983 case CP0_REG04__MMID:
8984 CP0_CHECK(ctx->mi);
8985 gen_helper_mtc0_memorymapid(cpu_env, arg);
8986 register_name = "MMID";
8987 break;
8988 default:
8989 goto cp0_unimplemented;
8991 break;
8992 case CP0_REGISTER_05:
8993 switch (sel) {
8994 case CP0_REG05__PAGEMASK:
8995 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
8996 register_name = "PageMask";
8997 break;
8998 case CP0_REG05__PAGEGRAIN:
8999 check_insn(ctx, ISA_MIPS_R2);
9000 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
9001 register_name = "PageGrain";
9002 break;
9003 case CP0_REG05__SEGCTL0:
9004 CP0_CHECK(ctx->sc);
9005 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
9006 register_name = "SegCtl0";
9007 break;
9008 case CP0_REG05__SEGCTL1:
9009 CP0_CHECK(ctx->sc);
9010 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
9011 register_name = "SegCtl1";
9012 break;
9013 case CP0_REG05__SEGCTL2:
9014 CP0_CHECK(ctx->sc);
9015 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
9016 register_name = "SegCtl2";
9017 break;
9018 case CP0_REG05__PWBASE:
9019 check_pw(ctx);
9020 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
9021 register_name = "PWBase";
9022 break;
9023 case CP0_REG05__PWFIELD:
9024 check_pw(ctx);
9025 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
9026 register_name = "PWField";
9027 break;
9028 case CP0_REG05__PWSIZE:
9029 check_pw(ctx);
9030 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
9031 register_name = "PWSize";
9032 break;
9033 default:
9034 goto cp0_unimplemented;
9036 break;
9037 case CP0_REGISTER_06:
9038 switch (sel) {
9039 case CP0_REG06__WIRED:
9040 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
9041 register_name = "Wired";
9042 break;
9043 case CP0_REG06__SRSCONF0:
9044 check_insn(ctx, ISA_MIPS_R2);
9045 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
9046 register_name = "SRSConf0";
9047 break;
9048 case CP0_REG06__SRSCONF1:
9049 check_insn(ctx, ISA_MIPS_R2);
9050 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
9051 register_name = "SRSConf1";
9052 break;
9053 case CP0_REG06__SRSCONF2:
9054 check_insn(ctx, ISA_MIPS_R2);
9055 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
9056 register_name = "SRSConf2";
9057 break;
9058 case CP0_REG06__SRSCONF3:
9059 check_insn(ctx, ISA_MIPS_R2);
9060 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
9061 register_name = "SRSConf3";
9062 break;
9063 case CP0_REG06__SRSCONF4:
9064 check_insn(ctx, ISA_MIPS_R2);
9065 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
9066 register_name = "SRSConf4";
9067 break;
9068 case CP0_REG06__PWCTL:
9069 check_pw(ctx);
9070 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
9071 register_name = "PWCtl";
9072 break;
9073 default:
9074 goto cp0_unimplemented;
9076 break;
9077 case CP0_REGISTER_07:
9078 switch (sel) {
9079 case CP0_REG07__HWRENA:
9080 check_insn(ctx, ISA_MIPS_R2);
9081 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
9082 register_name = "HWREna";
9083 break;
9084 default:
9085 goto cp0_unimplemented;
9087 break;
9088 case CP0_REGISTER_08:
9089 switch (sel) {
9090 case CP0_REG08__BADVADDR:
9091 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
9092 register_name = "BadVAddr";
9093 break;
9094 case CP0_REG08__BADINSTR:
9095 CP0_CHECK(ctx->bi);
9096 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
9097 register_name = "BadInstr";
9098 break;
9099 case CP0_REG08__BADINSTRP:
9100 CP0_CHECK(ctx->bp);
9101 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
9102 register_name = "BadInstrP";
9103 break;
9104 case CP0_REG08__BADINSTRX:
9105 CP0_CHECK(ctx->bi);
9106 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
9107 tcg_gen_andi_tl(arg, arg, ~0xffff);
9108 register_name = "BadInstrX";
9109 break;
9110 default:
9111 goto cp0_unimplemented;
9113 break;
9114 case CP0_REGISTER_09:
9115 switch (sel) {
9116 case CP0_REG09__COUNT:
9117 /* Mark as an IO operation because we read the time. */
9118 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9119 gen_io_start();
9121 gen_helper_mfc0_count(arg, cpu_env);
9123 * Break the TB to be able to take timer interrupts immediately
9124 * after reading count. DISAS_STOP isn't sufficient, we need to
9125 * ensure we break completely out of translated code.
9127 gen_save_pc(ctx->base.pc_next + 4);
9128 ctx->base.is_jmp = DISAS_EXIT;
9129 register_name = "Count";
9130 break;
9131 case CP0_REG09__SAARI:
9132 CP0_CHECK(ctx->saar);
9133 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
9134 register_name = "SAARI";
9135 break;
9136 case CP0_REG09__SAAR:
9137 CP0_CHECK(ctx->saar);
9138 gen_helper_dmfc0_saar(arg, cpu_env);
9139 register_name = "SAAR";
9140 break;
9141 default:
9142 goto cp0_unimplemented;
9144 break;
9145 case CP0_REGISTER_10:
9146 switch (sel) {
9147 case CP0_REG10__ENTRYHI:
9148 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
9149 register_name = "EntryHi";
9150 break;
9151 default:
9152 goto cp0_unimplemented;
9154 break;
9155 case CP0_REGISTER_11:
9156 switch (sel) {
9157 case CP0_REG11__COMPARE:
9158 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
9159 register_name = "Compare";
9160 break;
9161 /* 6,7 are implementation dependent */
9162 default:
9163 goto cp0_unimplemented;
9165 break;
9166 case CP0_REGISTER_12:
9167 switch (sel) {
9168 case CP0_REG12__STATUS:
9169 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
9170 register_name = "Status";
9171 break;
9172 case CP0_REG12__INTCTL:
9173 check_insn(ctx, ISA_MIPS_R2);
9174 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
9175 register_name = "IntCtl";
9176 break;
9177 case CP0_REG12__SRSCTL:
9178 check_insn(ctx, ISA_MIPS_R2);
9179 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
9180 register_name = "SRSCtl";
9181 break;
9182 case CP0_REG12__SRSMAP:
9183 check_insn(ctx, ISA_MIPS_R2);
9184 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
9185 register_name = "SRSMap";
9186 break;
9187 default:
9188 goto cp0_unimplemented;
9190 break;
9191 case CP0_REGISTER_13:
9192 switch (sel) {
9193 case CP0_REG13__CAUSE:
9194 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
9195 register_name = "Cause";
9196 break;
9197 default:
9198 goto cp0_unimplemented;
9200 break;
9201 case CP0_REGISTER_14:
9202 switch (sel) {
9203 case CP0_REG14__EPC:
9204 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
9205 register_name = "EPC";
9206 break;
9207 default:
9208 goto cp0_unimplemented;
9210 break;
9211 case CP0_REGISTER_15:
9212 switch (sel) {
9213 case CP0_REG15__PRID:
9214 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
9215 register_name = "PRid";
9216 break;
9217 case CP0_REG15__EBASE:
9218 check_insn(ctx, ISA_MIPS_R2);
9219 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
9220 register_name = "EBase";
9221 break;
9222 case CP0_REG15__CMGCRBASE:
9223 check_insn(ctx, ISA_MIPS_R2);
9224 CP0_CHECK(ctx->cmgcr);
9225 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
9226 register_name = "CMGCRBase";
9227 break;
9228 default:
9229 goto cp0_unimplemented;
9231 break;
9232 case CP0_REGISTER_16:
9233 switch (sel) {
9234 case CP0_REG16__CONFIG:
9235 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
9236 register_name = "Config";
9237 break;
9238 case CP0_REG16__CONFIG1:
9239 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
9240 register_name = "Config1";
9241 break;
9242 case CP0_REG16__CONFIG2:
9243 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
9244 register_name = "Config2";
9245 break;
9246 case CP0_REG16__CONFIG3:
9247 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
9248 register_name = "Config3";
9249 break;
9250 case CP0_REG16__CONFIG4:
9251 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
9252 register_name = "Config4";
9253 break;
9254 case CP0_REG16__CONFIG5:
9255 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
9256 register_name = "Config5";
9257 break;
9258 /* 6,7 are implementation dependent */
9259 case CP0_REG16__CONFIG6:
9260 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
9261 register_name = "Config6";
9262 break;
9263 case CP0_REG16__CONFIG7:
9264 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
9265 register_name = "Config7";
9266 break;
9267 default:
9268 goto cp0_unimplemented;
9270 break;
9271 case CP0_REGISTER_17:
9272 switch (sel) {
9273 case CP0_REG17__LLADDR:
9274 gen_helper_dmfc0_lladdr(arg, cpu_env);
9275 register_name = "LLAddr";
9276 break;
9277 case CP0_REG17__MAAR:
9278 CP0_CHECK(ctx->mrp);
9279 gen_helper_dmfc0_maar(arg, cpu_env);
9280 register_name = "MAAR";
9281 break;
9282 case CP0_REG17__MAARI:
9283 CP0_CHECK(ctx->mrp);
9284 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
9285 register_name = "MAARI";
9286 break;
9287 default:
9288 goto cp0_unimplemented;
9290 break;
9291 case CP0_REGISTER_18:
9292 switch (sel) {
9293 case CP0_REG18__WATCHLO0:
9294 case CP0_REG18__WATCHLO1:
9295 case CP0_REG18__WATCHLO2:
9296 case CP0_REG18__WATCHLO3:
9297 case CP0_REG18__WATCHLO4:
9298 case CP0_REG18__WATCHLO5:
9299 case CP0_REG18__WATCHLO6:
9300 case CP0_REG18__WATCHLO7:
9301 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9302 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
9303 register_name = "WatchLo";
9304 break;
9305 default:
9306 goto cp0_unimplemented;
9308 break;
9309 case CP0_REGISTER_19:
9310 switch (sel) {
9311 case CP0_REG19__WATCHHI0:
9312 case CP0_REG19__WATCHHI1:
9313 case CP0_REG19__WATCHHI2:
9314 case CP0_REG19__WATCHHI3:
9315 case CP0_REG19__WATCHHI4:
9316 case CP0_REG19__WATCHHI5:
9317 case CP0_REG19__WATCHHI6:
9318 case CP0_REG19__WATCHHI7:
9319 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9320 gen_helper_1e0i(dmfc0_watchhi, arg, sel);
9321 register_name = "WatchHi";
9322 break;
9323 default:
9324 goto cp0_unimplemented;
9326 break;
9327 case CP0_REGISTER_20:
9328 switch (sel) {
9329 case CP0_REG20__XCONTEXT:
9330 check_insn(ctx, ISA_MIPS3);
9331 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
9332 register_name = "XContext";
9333 break;
9334 default:
9335 goto cp0_unimplemented;
9337 break;
9338 case CP0_REGISTER_21:
9339 /* Officially reserved, but sel 0 is used for R1x000 framemask */
9340 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
9341 switch (sel) {
9342 case 0:
9343 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
9344 register_name = "Framemask";
9345 break;
9346 default:
9347 goto cp0_unimplemented;
9349 break;
9350 case CP0_REGISTER_22:
9351 tcg_gen_movi_tl(arg, 0); /* unimplemented */
9352 register_name = "'Diagnostic"; /* implementation dependent */
9353 break;
9354 case CP0_REGISTER_23:
9355 switch (sel) {
9356 case CP0_REG23__DEBUG:
9357 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
9358 register_name = "Debug";
9359 break;
9360 case CP0_REG23__TRACECONTROL:
9361 /* PDtrace support */
9362 /* gen_helper_dmfc0_tracecontrol(arg, cpu_env); */
9363 register_name = "TraceControl";
9364 goto cp0_unimplemented;
9365 case CP0_REG23__TRACECONTROL2:
9366 /* PDtrace support */
9367 /* gen_helper_dmfc0_tracecontrol2(arg, cpu_env); */
9368 register_name = "TraceControl2";
9369 goto cp0_unimplemented;
9370 case CP0_REG23__USERTRACEDATA1:
9371 /* PDtrace support */
9372 /* gen_helper_dmfc0_usertracedata1(arg, cpu_env);*/
9373 register_name = "UserTraceData1";
9374 goto cp0_unimplemented;
9375 case CP0_REG23__TRACEIBPC:
9376 /* PDtrace support */
9377 /* gen_helper_dmfc0_traceibpc(arg, cpu_env); */
9378 register_name = "TraceIBPC";
9379 goto cp0_unimplemented;
9380 case CP0_REG23__TRACEDBPC:
9381 /* PDtrace support */
9382 /* gen_helper_dmfc0_tracedbpc(arg, cpu_env); */
9383 register_name = "TraceDBPC";
9384 goto cp0_unimplemented;
9385 default:
9386 goto cp0_unimplemented;
9388 break;
9389 case CP0_REGISTER_24:
9390 switch (sel) {
9391 case CP0_REG24__DEPC:
9392 /* EJTAG support */
9393 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
9394 register_name = "DEPC";
9395 break;
9396 default:
9397 goto cp0_unimplemented;
9399 break;
9400 case CP0_REGISTER_25:
9401 switch (sel) {
9402 case CP0_REG25__PERFCTL0:
9403 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
9404 register_name = "Performance0";
9405 break;
9406 case CP0_REG25__PERFCNT0:
9407 /* gen_helper_dmfc0_performance1(arg); */
9408 register_name = "Performance1";
9409 goto cp0_unimplemented;
9410 case CP0_REG25__PERFCTL1:
9411 /* gen_helper_dmfc0_performance2(arg); */
9412 register_name = "Performance2";
9413 goto cp0_unimplemented;
9414 case CP0_REG25__PERFCNT1:
9415 /* gen_helper_dmfc0_performance3(arg); */
9416 register_name = "Performance3";
9417 goto cp0_unimplemented;
9418 case CP0_REG25__PERFCTL2:
9419 /* gen_helper_dmfc0_performance4(arg); */
9420 register_name = "Performance4";
9421 goto cp0_unimplemented;
9422 case CP0_REG25__PERFCNT2:
9423 /* gen_helper_dmfc0_performance5(arg); */
9424 register_name = "Performance5";
9425 goto cp0_unimplemented;
9426 case CP0_REG25__PERFCTL3:
9427 /* gen_helper_dmfc0_performance6(arg); */
9428 register_name = "Performance6";
9429 goto cp0_unimplemented;
9430 case CP0_REG25__PERFCNT3:
9431 /* gen_helper_dmfc0_performance7(arg); */
9432 register_name = "Performance7";
9433 goto cp0_unimplemented;
9434 default:
9435 goto cp0_unimplemented;
9437 break;
9438 case CP0_REGISTER_26:
9439 switch (sel) {
9440 case CP0_REG26__ERRCTL:
9441 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
9442 register_name = "ErrCtl";
9443 break;
9444 default:
9445 goto cp0_unimplemented;
9447 break;
9448 case CP0_REGISTER_27:
9449 switch (sel) {
9450 /* ignored */
9451 case CP0_REG27__CACHERR:
9452 tcg_gen_movi_tl(arg, 0); /* unimplemented */
9453 register_name = "CacheErr";
9454 break;
9455 default:
9456 goto cp0_unimplemented;
9458 break;
9459 case CP0_REGISTER_28:
9460 switch (sel) {
9461 case CP0_REG28__TAGLO:
9462 case CP0_REG28__TAGLO1:
9463 case CP0_REG28__TAGLO2:
9464 case CP0_REG28__TAGLO3:
9465 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
9466 register_name = "TagLo";
9467 break;
9468 case CP0_REG28__DATALO:
9469 case CP0_REG28__DATALO1:
9470 case CP0_REG28__DATALO2:
9471 case CP0_REG28__DATALO3:
9472 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
9473 register_name = "DataLo";
9474 break;
9475 default:
9476 goto cp0_unimplemented;
9478 break;
9479 case CP0_REGISTER_29:
9480 switch (sel) {
9481 case CP0_REG29__TAGHI:
9482 case CP0_REG29__TAGHI1:
9483 case CP0_REG29__TAGHI2:
9484 case CP0_REG29__TAGHI3:
9485 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
9486 register_name = "TagHi";
9487 break;
9488 case CP0_REG29__DATAHI:
9489 case CP0_REG29__DATAHI1:
9490 case CP0_REG29__DATAHI2:
9491 case CP0_REG29__DATAHI3:
9492 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
9493 register_name = "DataHi";
9494 break;
9495 default:
9496 goto cp0_unimplemented;
9498 break;
9499 case CP0_REGISTER_30:
9500 switch (sel) {
9501 case CP0_REG30__ERROREPC:
9502 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9503 register_name = "ErrorEPC";
9504 break;
9505 default:
9506 goto cp0_unimplemented;
9508 break;
9509 case CP0_REGISTER_31:
9510 switch (sel) {
9511 case CP0_REG31__DESAVE:
9512 /* EJTAG support */
9513 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9514 register_name = "DESAVE";
9515 break;
9516 case CP0_REG31__KSCRATCH1:
9517 case CP0_REG31__KSCRATCH2:
9518 case CP0_REG31__KSCRATCH3:
9519 case CP0_REG31__KSCRATCH4:
9520 case CP0_REG31__KSCRATCH5:
9521 case CP0_REG31__KSCRATCH6:
9522 CP0_CHECK(ctx->kscrexist & (1 << sel));
9523 tcg_gen_ld_tl(arg, cpu_env,
9524 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
9525 register_name = "KScratch";
9526 break;
9527 default:
9528 goto cp0_unimplemented;
9530 break;
9531 default:
9532 goto cp0_unimplemented;
9534 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
9535 return;
9537 cp0_unimplemented:
9538 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
9539 register_name, reg, sel);
9540 gen_mfc0_unimplemented(ctx, arg);
9543 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9545 const char *register_name = "invalid";
9547 if (sel != 0) {
9548 check_insn(ctx, ISA_MIPS_R1);
9551 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9552 gen_io_start();
9555 switch (reg) {
9556 case CP0_REGISTER_00:
9557 switch (sel) {
9558 case CP0_REG00__INDEX:
9559 gen_helper_mtc0_index(cpu_env, arg);
9560 register_name = "Index";
9561 break;
9562 case CP0_REG00__MVPCONTROL:
9563 CP0_CHECK(ctx->insn_flags & ASE_MT);
9564 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
9565 register_name = "MVPControl";
9566 break;
9567 case CP0_REG00__MVPCONF0:
9568 CP0_CHECK(ctx->insn_flags & ASE_MT);
9569 /* ignored */
9570 register_name = "MVPConf0";
9571 break;
9572 case CP0_REG00__MVPCONF1:
9573 CP0_CHECK(ctx->insn_flags & ASE_MT);
9574 /* ignored */
9575 register_name = "MVPConf1";
9576 break;
9577 case CP0_REG00__VPCONTROL:
9578 CP0_CHECK(ctx->vp);
9579 /* ignored */
9580 register_name = "VPControl";
9581 break;
9582 default:
9583 goto cp0_unimplemented;
9585 break;
9586 case CP0_REGISTER_01:
9587 switch (sel) {
9588 case CP0_REG01__RANDOM:
9589 /* ignored */
9590 register_name = "Random";
9591 break;
9592 case CP0_REG01__VPECONTROL:
9593 CP0_CHECK(ctx->insn_flags & ASE_MT);
9594 gen_helper_mtc0_vpecontrol(cpu_env, arg);
9595 register_name = "VPEControl";
9596 break;
9597 case CP0_REG01__VPECONF0:
9598 CP0_CHECK(ctx->insn_flags & ASE_MT);
9599 gen_helper_mtc0_vpeconf0(cpu_env, arg);
9600 register_name = "VPEConf0";
9601 break;
9602 case CP0_REG01__VPECONF1:
9603 CP0_CHECK(ctx->insn_flags & ASE_MT);
9604 gen_helper_mtc0_vpeconf1(cpu_env, arg);
9605 register_name = "VPEConf1";
9606 break;
9607 case CP0_REG01__YQMASK:
9608 CP0_CHECK(ctx->insn_flags & ASE_MT);
9609 gen_helper_mtc0_yqmask(cpu_env, arg);
9610 register_name = "YQMask";
9611 break;
9612 case CP0_REG01__VPESCHEDULE:
9613 CP0_CHECK(ctx->insn_flags & ASE_MT);
9614 tcg_gen_st_tl(arg, cpu_env,
9615 offsetof(CPUMIPSState, CP0_VPESchedule));
9616 register_name = "VPESchedule";
9617 break;
9618 case CP0_REG01__VPESCHEFBACK:
9619 CP0_CHECK(ctx->insn_flags & ASE_MT);
9620 tcg_gen_st_tl(arg, cpu_env,
9621 offsetof(CPUMIPSState, CP0_VPEScheFBack));
9622 register_name = "VPEScheFBack";
9623 break;
9624 case CP0_REG01__VPEOPT:
9625 CP0_CHECK(ctx->insn_flags & ASE_MT);
9626 gen_helper_mtc0_vpeopt(cpu_env, arg);
9627 register_name = "VPEOpt";
9628 break;
9629 default:
9630 goto cp0_unimplemented;
9632 break;
9633 case CP0_REGISTER_02:
9634 switch (sel) {
9635 case CP0_REG02__ENTRYLO0:
9636 gen_helper_dmtc0_entrylo0(cpu_env, arg);
9637 register_name = "EntryLo0";
9638 break;
9639 case CP0_REG02__TCSTATUS:
9640 CP0_CHECK(ctx->insn_flags & ASE_MT);
9641 gen_helper_mtc0_tcstatus(cpu_env, arg);
9642 register_name = "TCStatus";
9643 break;
9644 case CP0_REG02__TCBIND:
9645 CP0_CHECK(ctx->insn_flags & ASE_MT);
9646 gen_helper_mtc0_tcbind(cpu_env, arg);
9647 register_name = "TCBind";
9648 break;
9649 case CP0_REG02__TCRESTART:
9650 CP0_CHECK(ctx->insn_flags & ASE_MT);
9651 gen_helper_mtc0_tcrestart(cpu_env, arg);
9652 register_name = "TCRestart";
9653 break;
9654 case CP0_REG02__TCHALT:
9655 CP0_CHECK(ctx->insn_flags & ASE_MT);
9656 gen_helper_mtc0_tchalt(cpu_env, arg);
9657 register_name = "TCHalt";
9658 break;
9659 case CP0_REG02__TCCONTEXT:
9660 CP0_CHECK(ctx->insn_flags & ASE_MT);
9661 gen_helper_mtc0_tccontext(cpu_env, arg);
9662 register_name = "TCContext";
9663 break;
9664 case CP0_REG02__TCSCHEDULE:
9665 CP0_CHECK(ctx->insn_flags & ASE_MT);
9666 gen_helper_mtc0_tcschedule(cpu_env, arg);
9667 register_name = "TCSchedule";
9668 break;
9669 case CP0_REG02__TCSCHEFBACK:
9670 CP0_CHECK(ctx->insn_flags & ASE_MT);
9671 gen_helper_mtc0_tcschefback(cpu_env, arg);
9672 register_name = "TCScheFBack";
9673 break;
9674 default:
9675 goto cp0_unimplemented;
9677 break;
9678 case CP0_REGISTER_03:
9679 switch (sel) {
9680 case CP0_REG03__ENTRYLO1:
9681 gen_helper_dmtc0_entrylo1(cpu_env, arg);
9682 register_name = "EntryLo1";
9683 break;
9684 case CP0_REG03__GLOBALNUM:
9685 CP0_CHECK(ctx->vp);
9686 /* ignored */
9687 register_name = "GlobalNumber";
9688 break;
9689 default:
9690 goto cp0_unimplemented;
9692 break;
9693 case CP0_REGISTER_04:
9694 switch (sel) {
9695 case CP0_REG04__CONTEXT:
9696 gen_helper_mtc0_context(cpu_env, arg);
9697 register_name = "Context";
9698 break;
9699 case CP0_REG04__CONTEXTCONFIG:
9700 /* SmartMIPS ASE */
9701 /* gen_helper_dmtc0_contextconfig(arg); */
9702 register_name = "ContextConfig";
9703 goto cp0_unimplemented;
9704 case CP0_REG04__USERLOCAL:
9705 CP0_CHECK(ctx->ulri);
9706 tcg_gen_st_tl(arg, cpu_env,
9707 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
9708 register_name = "UserLocal";
9709 break;
9710 case CP0_REG04__MMID:
9711 CP0_CHECK(ctx->mi);
9712 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
9713 register_name = "MMID";
9714 break;
9715 default:
9716 goto cp0_unimplemented;
9718 break;
9719 case CP0_REGISTER_05:
9720 switch (sel) {
9721 case CP0_REG05__PAGEMASK:
9722 gen_helper_mtc0_pagemask(cpu_env, arg);
9723 register_name = "PageMask";
9724 break;
9725 case CP0_REG05__PAGEGRAIN:
9726 check_insn(ctx, ISA_MIPS_R2);
9727 gen_helper_mtc0_pagegrain(cpu_env, arg);
9728 register_name = "PageGrain";
9729 break;
9730 case CP0_REG05__SEGCTL0:
9731 CP0_CHECK(ctx->sc);
9732 gen_helper_mtc0_segctl0(cpu_env, arg);
9733 register_name = "SegCtl0";
9734 break;
9735 case CP0_REG05__SEGCTL1:
9736 CP0_CHECK(ctx->sc);
9737 gen_helper_mtc0_segctl1(cpu_env, arg);
9738 register_name = "SegCtl1";
9739 break;
9740 case CP0_REG05__SEGCTL2:
9741 CP0_CHECK(ctx->sc);
9742 gen_helper_mtc0_segctl2(cpu_env, arg);
9743 register_name = "SegCtl2";
9744 break;
9745 case CP0_REG05__PWBASE:
9746 check_pw(ctx);
9747 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
9748 register_name = "PWBase";
9749 break;
9750 case CP0_REG05__PWFIELD:
9751 check_pw(ctx);
9752 gen_helper_mtc0_pwfield(cpu_env, arg);
9753 register_name = "PWField";
9754 break;
9755 case CP0_REG05__PWSIZE:
9756 check_pw(ctx);
9757 gen_helper_mtc0_pwsize(cpu_env, arg);
9758 register_name = "PWSize";
9759 break;
9760 default:
9761 goto cp0_unimplemented;
9763 break;
9764 case CP0_REGISTER_06:
9765 switch (sel) {
9766 case CP0_REG06__WIRED:
9767 gen_helper_mtc0_wired(cpu_env, arg);
9768 register_name = "Wired";
9769 break;
9770 case CP0_REG06__SRSCONF0:
9771 check_insn(ctx, ISA_MIPS_R2);
9772 gen_helper_mtc0_srsconf0(cpu_env, arg);
9773 register_name = "SRSConf0";
9774 break;
9775 case CP0_REG06__SRSCONF1:
9776 check_insn(ctx, ISA_MIPS_R2);
9777 gen_helper_mtc0_srsconf1(cpu_env, arg);
9778 register_name = "SRSConf1";
9779 break;
9780 case CP0_REG06__SRSCONF2:
9781 check_insn(ctx, ISA_MIPS_R2);
9782 gen_helper_mtc0_srsconf2(cpu_env, arg);
9783 register_name = "SRSConf2";
9784 break;
9785 case CP0_REG06__SRSCONF3:
9786 check_insn(ctx, ISA_MIPS_R2);
9787 gen_helper_mtc0_srsconf3(cpu_env, arg);
9788 register_name = "SRSConf3";
9789 break;
9790 case CP0_REG06__SRSCONF4:
9791 check_insn(ctx, ISA_MIPS_R2);
9792 gen_helper_mtc0_srsconf4(cpu_env, arg);
9793 register_name = "SRSConf4";
9794 break;
9795 case CP0_REG06__PWCTL:
9796 check_pw(ctx);
9797 gen_helper_mtc0_pwctl(cpu_env, arg);
9798 register_name = "PWCtl";
9799 break;
9800 default:
9801 goto cp0_unimplemented;
9803 break;
9804 case CP0_REGISTER_07:
9805 switch (sel) {
9806 case CP0_REG07__HWRENA:
9807 check_insn(ctx, ISA_MIPS_R2);
9808 gen_helper_mtc0_hwrena(cpu_env, arg);
9809 ctx->base.is_jmp = DISAS_STOP;
9810 register_name = "HWREna";
9811 break;
9812 default:
9813 goto cp0_unimplemented;
9815 break;
9816 case CP0_REGISTER_08:
9817 switch (sel) {
9818 case CP0_REG08__BADVADDR:
9819 /* ignored */
9820 register_name = "BadVAddr";
9821 break;
9822 case CP0_REG08__BADINSTR:
9823 /* ignored */
9824 register_name = "BadInstr";
9825 break;
9826 case CP0_REG08__BADINSTRP:
9827 /* ignored */
9828 register_name = "BadInstrP";
9829 break;
9830 case CP0_REG08__BADINSTRX:
9831 /* ignored */
9832 register_name = "BadInstrX";
9833 break;
9834 default:
9835 goto cp0_unimplemented;
9837 break;
9838 case CP0_REGISTER_09:
9839 switch (sel) {
9840 case CP0_REG09__COUNT:
9841 gen_helper_mtc0_count(cpu_env, arg);
9842 register_name = "Count";
9843 break;
9844 case CP0_REG09__SAARI:
9845 CP0_CHECK(ctx->saar);
9846 gen_helper_mtc0_saari(cpu_env, arg);
9847 register_name = "SAARI";
9848 break;
9849 case CP0_REG09__SAAR:
9850 CP0_CHECK(ctx->saar);
9851 gen_helper_mtc0_saar(cpu_env, arg);
9852 register_name = "SAAR";
9853 break;
9854 default:
9855 goto cp0_unimplemented;
9857 /* Stop translation as we may have switched the execution mode */
9858 ctx->base.is_jmp = DISAS_STOP;
9859 break;
9860 case CP0_REGISTER_10:
9861 switch (sel) {
9862 case CP0_REG10__ENTRYHI:
9863 gen_helper_mtc0_entryhi(cpu_env, arg);
9864 register_name = "EntryHi";
9865 break;
9866 default:
9867 goto cp0_unimplemented;
9869 break;
9870 case CP0_REGISTER_11:
9871 switch (sel) {
9872 case CP0_REG11__COMPARE:
9873 gen_helper_mtc0_compare(cpu_env, arg);
9874 register_name = "Compare";
9875 break;
9876 /* 6,7 are implementation dependent */
9877 default:
9878 goto cp0_unimplemented;
9880 /* Stop translation as we may have switched the execution mode */
9881 ctx->base.is_jmp = DISAS_STOP;
9882 break;
9883 case CP0_REGISTER_12:
9884 switch (sel) {
9885 case CP0_REG12__STATUS:
9886 save_cpu_state(ctx, 1);
9887 gen_helper_mtc0_status(cpu_env, arg);
9888 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9889 gen_save_pc(ctx->base.pc_next + 4);
9890 ctx->base.is_jmp = DISAS_EXIT;
9891 register_name = "Status";
9892 break;
9893 case CP0_REG12__INTCTL:
9894 check_insn(ctx, ISA_MIPS_R2);
9895 gen_helper_mtc0_intctl(cpu_env, arg);
9896 /* Stop translation as we may have switched the execution mode */
9897 ctx->base.is_jmp = DISAS_STOP;
9898 register_name = "IntCtl";
9899 break;
9900 case CP0_REG12__SRSCTL:
9901 check_insn(ctx, ISA_MIPS_R2);
9902 gen_helper_mtc0_srsctl(cpu_env, arg);
9903 /* Stop translation as we may have switched the execution mode */
9904 ctx->base.is_jmp = DISAS_STOP;
9905 register_name = "SRSCtl";
9906 break;
9907 case CP0_REG12__SRSMAP:
9908 check_insn(ctx, ISA_MIPS_R2);
9909 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
9910 /* Stop translation as we may have switched the execution mode */
9911 ctx->base.is_jmp = DISAS_STOP;
9912 register_name = "SRSMap";
9913 break;
9914 default:
9915 goto cp0_unimplemented;
9917 break;
9918 case CP0_REGISTER_13:
9919 switch (sel) {
9920 case CP0_REG13__CAUSE:
9921 save_cpu_state(ctx, 1);
9922 gen_helper_mtc0_cause(cpu_env, arg);
9924 * Stop translation as we may have triggered an interrupt.
9925 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9926 * translated code to check for pending interrupts.
9928 gen_save_pc(ctx->base.pc_next + 4);
9929 ctx->base.is_jmp = DISAS_EXIT;
9930 register_name = "Cause";
9931 break;
9932 default:
9933 goto cp0_unimplemented;
9935 break;
9936 case CP0_REGISTER_14:
9937 switch (sel) {
9938 case CP0_REG14__EPC:
9939 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
9940 register_name = "EPC";
9941 break;
9942 default:
9943 goto cp0_unimplemented;
9945 break;
9946 case CP0_REGISTER_15:
9947 switch (sel) {
9948 case CP0_REG15__PRID:
9949 /* ignored */
9950 register_name = "PRid";
9951 break;
9952 case CP0_REG15__EBASE:
9953 check_insn(ctx, ISA_MIPS_R2);
9954 gen_helper_mtc0_ebase(cpu_env, arg);
9955 register_name = "EBase";
9956 break;
9957 default:
9958 goto cp0_unimplemented;
9960 break;
9961 case CP0_REGISTER_16:
9962 switch (sel) {
9963 case CP0_REG16__CONFIG:
9964 gen_helper_mtc0_config0(cpu_env, arg);
9965 register_name = "Config";
9966 /* Stop translation as we may have switched the execution mode */
9967 ctx->base.is_jmp = DISAS_STOP;
9968 break;
9969 case CP0_REG16__CONFIG1:
9970 /* ignored, read only */
9971 register_name = "Config1";
9972 break;
9973 case CP0_REG16__CONFIG2:
9974 gen_helper_mtc0_config2(cpu_env, arg);
9975 register_name = "Config2";
9976 /* Stop translation as we may have switched the execution mode */
9977 ctx->base.is_jmp = DISAS_STOP;
9978 break;
9979 case CP0_REG16__CONFIG3:
9980 gen_helper_mtc0_config3(cpu_env, arg);
9981 register_name = "Config3";
9982 /* Stop translation as we may have switched the execution mode */
9983 ctx->base.is_jmp = DISAS_STOP;
9984 break;
9985 case CP0_REG16__CONFIG4:
9986 /* currently ignored */
9987 register_name = "Config4";
9988 break;
9989 case CP0_REG16__CONFIG5:
9990 gen_helper_mtc0_config5(cpu_env, arg);
9991 register_name = "Config5";
9992 /* Stop translation as we may have switched the execution mode */
9993 ctx->base.is_jmp = DISAS_STOP;
9994 break;
9995 /* 6,7 are implementation dependent */
9996 default:
9997 register_name = "Invalid config selector";
9998 goto cp0_unimplemented;
10000 break;
10001 case CP0_REGISTER_17:
10002 switch (sel) {
10003 case CP0_REG17__LLADDR:
10004 gen_helper_mtc0_lladdr(cpu_env, arg);
10005 register_name = "LLAddr";
10006 break;
10007 case CP0_REG17__MAAR:
10008 CP0_CHECK(ctx->mrp);
10009 gen_helper_mtc0_maar(cpu_env, arg);
10010 register_name = "MAAR";
10011 break;
10012 case CP0_REG17__MAARI:
10013 CP0_CHECK(ctx->mrp);
10014 gen_helper_mtc0_maari(cpu_env, arg);
10015 register_name = "MAARI";
10016 break;
10017 default:
10018 goto cp0_unimplemented;
10020 break;
10021 case CP0_REGISTER_18:
10022 switch (sel) {
10023 case CP0_REG18__WATCHLO0:
10024 case CP0_REG18__WATCHLO1:
10025 case CP0_REG18__WATCHLO2:
10026 case CP0_REG18__WATCHLO3:
10027 case CP0_REG18__WATCHLO4:
10028 case CP0_REG18__WATCHLO5:
10029 case CP0_REG18__WATCHLO6:
10030 case CP0_REG18__WATCHLO7:
10031 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
10032 gen_helper_0e1i(mtc0_watchlo, arg, sel);
10033 register_name = "WatchLo";
10034 break;
10035 default:
10036 goto cp0_unimplemented;
10038 break;
10039 case CP0_REGISTER_19:
10040 switch (sel) {
10041 case CP0_REG19__WATCHHI0:
10042 case CP0_REG19__WATCHHI1:
10043 case CP0_REG19__WATCHHI2:
10044 case CP0_REG19__WATCHHI3:
10045 case CP0_REG19__WATCHHI4:
10046 case CP0_REG19__WATCHHI5:
10047 case CP0_REG19__WATCHHI6:
10048 case CP0_REG19__WATCHHI7:
10049 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
10050 gen_helper_0e1i(mtc0_watchhi, arg, sel);
10051 register_name = "WatchHi";
10052 break;
10053 default:
10054 goto cp0_unimplemented;
10056 break;
10057 case CP0_REGISTER_20:
10058 switch (sel) {
10059 case CP0_REG20__XCONTEXT:
10060 check_insn(ctx, ISA_MIPS3);
10061 gen_helper_mtc0_xcontext(cpu_env, arg);
10062 register_name = "XContext";
10063 break;
10064 default:
10065 goto cp0_unimplemented;
10067 break;
10068 case CP0_REGISTER_21:
10069 /* Officially reserved, but sel 0 is used for R1x000 framemask */
10070 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
10071 switch (sel) {
10072 case 0:
10073 gen_helper_mtc0_framemask(cpu_env, arg);
10074 register_name = "Framemask";
10075 break;
10076 default:
10077 goto cp0_unimplemented;
10079 break;
10080 case CP0_REGISTER_22:
10081 /* ignored */
10082 register_name = "Diagnostic"; /* implementation dependent */
10083 break;
10084 case CP0_REGISTER_23:
10085 switch (sel) {
10086 case CP0_REG23__DEBUG:
10087 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
10088 /* DISAS_STOP isn't good enough here, hflags may have changed. */
10089 gen_save_pc(ctx->base.pc_next + 4);
10090 ctx->base.is_jmp = DISAS_EXIT;
10091 register_name = "Debug";
10092 break;
10093 case CP0_REG23__TRACECONTROL:
10094 /* PDtrace support */
10095 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
10096 /* Stop translation as we may have switched the execution mode */
10097 ctx->base.is_jmp = DISAS_STOP;
10098 register_name = "TraceControl";
10099 goto cp0_unimplemented;
10100 case CP0_REG23__TRACECONTROL2:
10101 /* PDtrace support */
10102 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
10103 /* Stop translation as we may have switched the execution mode */
10104 ctx->base.is_jmp = DISAS_STOP;
10105 register_name = "TraceControl2";
10106 goto cp0_unimplemented;
10107 case CP0_REG23__USERTRACEDATA1:
10108 /* PDtrace support */
10109 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
10110 /* Stop translation as we may have switched the execution mode */
10111 ctx->base.is_jmp = DISAS_STOP;
10112 register_name = "UserTraceData1";
10113 goto cp0_unimplemented;
10114 case CP0_REG23__TRACEIBPC:
10115 /* PDtrace support */
10116 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
10117 /* Stop translation as we may have switched the execution mode */
10118 ctx->base.is_jmp = DISAS_STOP;
10119 register_name = "TraceIBPC";
10120 goto cp0_unimplemented;
10121 case CP0_REG23__TRACEDBPC:
10122 /* PDtrace support */
10123 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
10124 /* Stop translation as we may have switched the execution mode */
10125 ctx->base.is_jmp = DISAS_STOP;
10126 register_name = "TraceDBPC";
10127 goto cp0_unimplemented;
10128 default:
10129 goto cp0_unimplemented;
10131 break;
10132 case CP0_REGISTER_24:
10133 switch (sel) {
10134 case CP0_REG24__DEPC:
10135 /* EJTAG support */
10136 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
10137 register_name = "DEPC";
10138 break;
10139 default:
10140 goto cp0_unimplemented;
10142 break;
10143 case CP0_REGISTER_25:
10144 switch (sel) {
10145 case CP0_REG25__PERFCTL0:
10146 gen_helper_mtc0_performance0(cpu_env, arg);
10147 register_name = "Performance0";
10148 break;
10149 case CP0_REG25__PERFCNT0:
10150 /* gen_helper_mtc0_performance1(cpu_env, arg); */
10151 register_name = "Performance1";
10152 goto cp0_unimplemented;
10153 case CP0_REG25__PERFCTL1:
10154 /* gen_helper_mtc0_performance2(cpu_env, arg); */
10155 register_name = "Performance2";
10156 goto cp0_unimplemented;
10157 case CP0_REG25__PERFCNT1:
10158 /* gen_helper_mtc0_performance3(cpu_env, arg); */
10159 register_name = "Performance3";
10160 goto cp0_unimplemented;
10161 case CP0_REG25__PERFCTL2:
10162 /* gen_helper_mtc0_performance4(cpu_env, arg); */
10163 register_name = "Performance4";
10164 goto cp0_unimplemented;
10165 case CP0_REG25__PERFCNT2:
10166 /* gen_helper_mtc0_performance5(cpu_env, arg); */
10167 register_name = "Performance5";
10168 goto cp0_unimplemented;
10169 case CP0_REG25__PERFCTL3:
10170 /* gen_helper_mtc0_performance6(cpu_env, arg); */
10171 register_name = "Performance6";
10172 goto cp0_unimplemented;
10173 case CP0_REG25__PERFCNT3:
10174 /* gen_helper_mtc0_performance7(cpu_env, arg); */
10175 register_name = "Performance7";
10176 goto cp0_unimplemented;
10177 default:
10178 goto cp0_unimplemented;
10180 break;
10181 case CP0_REGISTER_26:
10182 switch (sel) {
10183 case CP0_REG26__ERRCTL:
10184 gen_helper_mtc0_errctl(cpu_env, arg);
10185 ctx->base.is_jmp = DISAS_STOP;
10186 register_name = "ErrCtl";
10187 break;
10188 default:
10189 goto cp0_unimplemented;
10191 break;
10192 case CP0_REGISTER_27:
10193 switch (sel) {
10194 case CP0_REG27__CACHERR:
10195 /* ignored */
10196 register_name = "CacheErr";
10197 break;
10198 default:
10199 goto cp0_unimplemented;
10201 break;
10202 case CP0_REGISTER_28:
10203 switch (sel) {
10204 case CP0_REG28__TAGLO:
10205 case CP0_REG28__TAGLO1:
10206 case CP0_REG28__TAGLO2:
10207 case CP0_REG28__TAGLO3:
10208 gen_helper_mtc0_taglo(cpu_env, arg);
10209 register_name = "TagLo";
10210 break;
10211 case CP0_REG28__DATALO:
10212 case CP0_REG28__DATALO1:
10213 case CP0_REG28__DATALO2:
10214 case CP0_REG28__DATALO3:
10215 gen_helper_mtc0_datalo(cpu_env, arg);
10216 register_name = "DataLo";
10217 break;
10218 default:
10219 goto cp0_unimplemented;
10221 break;
10222 case CP0_REGISTER_29:
10223 switch (sel) {
10224 case CP0_REG29__TAGHI:
10225 case CP0_REG29__TAGHI1:
10226 case CP0_REG29__TAGHI2:
10227 case CP0_REG29__TAGHI3:
10228 gen_helper_mtc0_taghi(cpu_env, arg);
10229 register_name = "TagHi";
10230 break;
10231 case CP0_REG29__DATAHI:
10232 case CP0_REG29__DATAHI1:
10233 case CP0_REG29__DATAHI2:
10234 case CP0_REG29__DATAHI3:
10235 gen_helper_mtc0_datahi(cpu_env, arg);
10236 register_name = "DataHi";
10237 break;
10238 default:
10239 register_name = "invalid sel";
10240 goto cp0_unimplemented;
10242 break;
10243 case CP0_REGISTER_30:
10244 switch (sel) {
10245 case CP0_REG30__ERROREPC:
10246 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
10247 register_name = "ErrorEPC";
10248 break;
10249 default:
10250 goto cp0_unimplemented;
10252 break;
10253 case CP0_REGISTER_31:
10254 switch (sel) {
10255 case CP0_REG31__DESAVE:
10256 /* EJTAG support */
10257 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
10258 register_name = "DESAVE";
10259 break;
10260 case CP0_REG31__KSCRATCH1:
10261 case CP0_REG31__KSCRATCH2:
10262 case CP0_REG31__KSCRATCH3:
10263 case CP0_REG31__KSCRATCH4:
10264 case CP0_REG31__KSCRATCH5:
10265 case CP0_REG31__KSCRATCH6:
10266 CP0_CHECK(ctx->kscrexist & (1 << sel));
10267 tcg_gen_st_tl(arg, cpu_env,
10268 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
10269 register_name = "KScratch";
10270 break;
10271 default:
10272 goto cp0_unimplemented;
10274 break;
10275 default:
10276 goto cp0_unimplemented;
10278 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
10280 /* For simplicity assume that all writes can cause interrupts. */
10281 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
10283 * DISAS_STOP isn't sufficient, we need to ensure we break out of
10284 * translated code to check for pending interrupts.
10286 gen_save_pc(ctx->base.pc_next + 4);
10287 ctx->base.is_jmp = DISAS_EXIT;
10289 return;
10291 cp0_unimplemented:
10292 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
10293 register_name, reg, sel);
10295 #endif /* TARGET_MIPS64 */
10297 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
10298 int u, int sel, int h)
10300 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
10301 TCGv t0 = tcg_temp_local_new();
10303 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
10304 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
10305 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
10306 tcg_gen_movi_tl(t0, -1);
10307 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
10308 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
10309 tcg_gen_movi_tl(t0, -1);
10310 } else if (u == 0) {
10311 switch (rt) {
10312 case 1:
10313 switch (sel) {
10314 case 1:
10315 gen_helper_mftc0_vpecontrol(t0, cpu_env);
10316 break;
10317 case 2:
10318 gen_helper_mftc0_vpeconf0(t0, cpu_env);
10319 break;
10320 default:
10321 goto die;
10322 break;
10324 break;
10325 case 2:
10326 switch (sel) {
10327 case 1:
10328 gen_helper_mftc0_tcstatus(t0, cpu_env);
10329 break;
10330 case 2:
10331 gen_helper_mftc0_tcbind(t0, cpu_env);
10332 break;
10333 case 3:
10334 gen_helper_mftc0_tcrestart(t0, cpu_env);
10335 break;
10336 case 4:
10337 gen_helper_mftc0_tchalt(t0, cpu_env);
10338 break;
10339 case 5:
10340 gen_helper_mftc0_tccontext(t0, cpu_env);
10341 break;
10342 case 6:
10343 gen_helper_mftc0_tcschedule(t0, cpu_env);
10344 break;
10345 case 7:
10346 gen_helper_mftc0_tcschefback(t0, cpu_env);
10347 break;
10348 default:
10349 gen_mfc0(ctx, t0, rt, sel);
10350 break;
10352 break;
10353 case 10:
10354 switch (sel) {
10355 case 0:
10356 gen_helper_mftc0_entryhi(t0, cpu_env);
10357 break;
10358 default:
10359 gen_mfc0(ctx, t0, rt, sel);
10360 break;
10362 break;
10363 case 12:
10364 switch (sel) {
10365 case 0:
10366 gen_helper_mftc0_status(t0, cpu_env);
10367 break;
10368 default:
10369 gen_mfc0(ctx, t0, rt, sel);
10370 break;
10372 break;
10373 case 13:
10374 switch (sel) {
10375 case 0:
10376 gen_helper_mftc0_cause(t0, cpu_env);
10377 break;
10378 default:
10379 goto die;
10380 break;
10382 break;
10383 case 14:
10384 switch (sel) {
10385 case 0:
10386 gen_helper_mftc0_epc(t0, cpu_env);
10387 break;
10388 default:
10389 goto die;
10390 break;
10392 break;
10393 case 15:
10394 switch (sel) {
10395 case 1:
10396 gen_helper_mftc0_ebase(t0, cpu_env);
10397 break;
10398 default:
10399 goto die;
10400 break;
10402 break;
10403 case 16:
10404 switch (sel) {
10405 case 0:
10406 case 1:
10407 case 2:
10408 case 3:
10409 case 4:
10410 case 5:
10411 case 6:
10412 case 7:
10413 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
10414 break;
10415 default:
10416 goto die;
10417 break;
10419 break;
10420 case 23:
10421 switch (sel) {
10422 case 0:
10423 gen_helper_mftc0_debug(t0, cpu_env);
10424 break;
10425 default:
10426 gen_mfc0(ctx, t0, rt, sel);
10427 break;
10429 break;
10430 default:
10431 gen_mfc0(ctx, t0, rt, sel);
10433 } else {
10434 switch (sel) {
10435 /* GPR registers. */
10436 case 0:
10437 gen_helper_1e0i(mftgpr, t0, rt);
10438 break;
10439 /* Auxiliary CPU registers */
10440 case 1:
10441 switch (rt) {
10442 case 0:
10443 gen_helper_1e0i(mftlo, t0, 0);
10444 break;
10445 case 1:
10446 gen_helper_1e0i(mfthi, t0, 0);
10447 break;
10448 case 2:
10449 gen_helper_1e0i(mftacx, t0, 0);
10450 break;
10451 case 4:
10452 gen_helper_1e0i(mftlo, t0, 1);
10453 break;
10454 case 5:
10455 gen_helper_1e0i(mfthi, t0, 1);
10456 break;
10457 case 6:
10458 gen_helper_1e0i(mftacx, t0, 1);
10459 break;
10460 case 8:
10461 gen_helper_1e0i(mftlo, t0, 2);
10462 break;
10463 case 9:
10464 gen_helper_1e0i(mfthi, t0, 2);
10465 break;
10466 case 10:
10467 gen_helper_1e0i(mftacx, t0, 2);
10468 break;
10469 case 12:
10470 gen_helper_1e0i(mftlo, t0, 3);
10471 break;
10472 case 13:
10473 gen_helper_1e0i(mfthi, t0, 3);
10474 break;
10475 case 14:
10476 gen_helper_1e0i(mftacx, t0, 3);
10477 break;
10478 case 16:
10479 gen_helper_mftdsp(t0, cpu_env);
10480 break;
10481 default:
10482 goto die;
10484 break;
10485 /* Floating point (COP1). */
10486 case 2:
10487 /* XXX: For now we support only a single FPU context. */
10488 if (h == 0) {
10489 TCGv_i32 fp0 = tcg_temp_new_i32();
10491 gen_load_fpr32(ctx, fp0, rt);
10492 tcg_gen_ext_i32_tl(t0, fp0);
10493 tcg_temp_free_i32(fp0);
10494 } else {
10495 TCGv_i32 fp0 = tcg_temp_new_i32();
10497 gen_load_fpr32h(ctx, fp0, rt);
10498 tcg_gen_ext_i32_tl(t0, fp0);
10499 tcg_temp_free_i32(fp0);
10501 break;
10502 case 3:
10503 /* XXX: For now we support only a single FPU context. */
10504 gen_helper_1e0i(cfc1, t0, rt);
10505 break;
10506 /* COP2: Not implemented. */
10507 case 4:
10508 case 5:
10509 /* fall through */
10510 default:
10511 goto die;
10514 trace_mips_translate_tr("mftr", rt, u, sel, h);
10515 gen_store_gpr(t0, rd);
10516 tcg_temp_free(t0);
10517 return;
10519 die:
10520 tcg_temp_free(t0);
10521 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
10522 gen_reserved_instruction(ctx);
10525 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
10526 int u, int sel, int h)
10528 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
10529 TCGv t0 = tcg_temp_local_new();
10531 gen_load_gpr(t0, rt);
10532 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
10533 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
10534 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
10535 /* NOP */
10537 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
10538 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
10539 /* NOP */
10541 } else if (u == 0) {
10542 switch (rd) {
10543 case 1:
10544 switch (sel) {
10545 case 1:
10546 gen_helper_mttc0_vpecontrol(cpu_env, t0);
10547 break;
10548 case 2:
10549 gen_helper_mttc0_vpeconf0(cpu_env, t0);
10550 break;
10551 default:
10552 goto die;
10553 break;
10555 break;
10556 case 2:
10557 switch (sel) {
10558 case 1:
10559 gen_helper_mttc0_tcstatus(cpu_env, t0);
10560 break;
10561 case 2:
10562 gen_helper_mttc0_tcbind(cpu_env, t0);
10563 break;
10564 case 3:
10565 gen_helper_mttc0_tcrestart(cpu_env, t0);
10566 break;
10567 case 4:
10568 gen_helper_mttc0_tchalt(cpu_env, t0);
10569 break;
10570 case 5:
10571 gen_helper_mttc0_tccontext(cpu_env, t0);
10572 break;
10573 case 6:
10574 gen_helper_mttc0_tcschedule(cpu_env, t0);
10575 break;
10576 case 7:
10577 gen_helper_mttc0_tcschefback(cpu_env, t0);
10578 break;
10579 default:
10580 gen_mtc0(ctx, t0, rd, sel);
10581 break;
10583 break;
10584 case 10:
10585 switch (sel) {
10586 case 0:
10587 gen_helper_mttc0_entryhi(cpu_env, t0);
10588 break;
10589 default:
10590 gen_mtc0(ctx, t0, rd, sel);
10591 break;
10593 break;
10594 case 12:
10595 switch (sel) {
10596 case 0:
10597 gen_helper_mttc0_status(cpu_env, t0);
10598 break;
10599 default:
10600 gen_mtc0(ctx, t0, rd, sel);
10601 break;
10603 break;
10604 case 13:
10605 switch (sel) {
10606 case 0:
10607 gen_helper_mttc0_cause(cpu_env, t0);
10608 break;
10609 default:
10610 goto die;
10611 break;
10613 break;
10614 case 15:
10615 switch (sel) {
10616 case 1:
10617 gen_helper_mttc0_ebase(cpu_env, t0);
10618 break;
10619 default:
10620 goto die;
10621 break;
10623 break;
10624 case 23:
10625 switch (sel) {
10626 case 0:
10627 gen_helper_mttc0_debug(cpu_env, t0);
10628 break;
10629 default:
10630 gen_mtc0(ctx, t0, rd, sel);
10631 break;
10633 break;
10634 default:
10635 gen_mtc0(ctx, t0, rd, sel);
10637 } else {
10638 switch (sel) {
10639 /* GPR registers. */
10640 case 0:
10641 gen_helper_0e1i(mttgpr, t0, rd);
10642 break;
10643 /* Auxiliary CPU registers */
10644 case 1:
10645 switch (rd) {
10646 case 0:
10647 gen_helper_0e1i(mttlo, t0, 0);
10648 break;
10649 case 1:
10650 gen_helper_0e1i(mtthi, t0, 0);
10651 break;
10652 case 2:
10653 gen_helper_0e1i(mttacx, t0, 0);
10654 break;
10655 case 4:
10656 gen_helper_0e1i(mttlo, t0, 1);
10657 break;
10658 case 5:
10659 gen_helper_0e1i(mtthi, t0, 1);
10660 break;
10661 case 6:
10662 gen_helper_0e1i(mttacx, t0, 1);
10663 break;
10664 case 8:
10665 gen_helper_0e1i(mttlo, t0, 2);
10666 break;
10667 case 9:
10668 gen_helper_0e1i(mtthi, t0, 2);
10669 break;
10670 case 10:
10671 gen_helper_0e1i(mttacx, t0, 2);
10672 break;
10673 case 12:
10674 gen_helper_0e1i(mttlo, t0, 3);
10675 break;
10676 case 13:
10677 gen_helper_0e1i(mtthi, t0, 3);
10678 break;
10679 case 14:
10680 gen_helper_0e1i(mttacx, t0, 3);
10681 break;
10682 case 16:
10683 gen_helper_mttdsp(cpu_env, t0);
10684 break;
10685 default:
10686 goto die;
10688 break;
10689 /* Floating point (COP1). */
10690 case 2:
10691 /* XXX: For now we support only a single FPU context. */
10692 if (h == 0) {
10693 TCGv_i32 fp0 = tcg_temp_new_i32();
10695 tcg_gen_trunc_tl_i32(fp0, t0);
10696 gen_store_fpr32(ctx, fp0, rd);
10697 tcg_temp_free_i32(fp0);
10698 } else {
10699 TCGv_i32 fp0 = tcg_temp_new_i32();
10701 tcg_gen_trunc_tl_i32(fp0, t0);
10702 gen_store_fpr32h(ctx, fp0, rd);
10703 tcg_temp_free_i32(fp0);
10705 break;
10706 case 3:
10707 /* XXX: For now we support only a single FPU context. */
10709 TCGv_i32 fs_tmp = tcg_const_i32(rd);
10711 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10712 tcg_temp_free_i32(fs_tmp);
10714 /* Stop translation as we may have changed hflags */
10715 ctx->base.is_jmp = DISAS_STOP;
10716 break;
10717 /* COP2: Not implemented. */
10718 case 4:
10719 case 5:
10720 /* fall through */
10721 default:
10722 goto die;
10725 trace_mips_translate_tr("mttr", rd, u, sel, h);
10726 tcg_temp_free(t0);
10727 return;
10729 die:
10730 tcg_temp_free(t0);
10731 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
10732 gen_reserved_instruction(ctx);
10735 static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
10736 int rt, int rd)
10738 const char *opn = "ldst";
10740 check_cp0_enabled(ctx);
10741 switch (opc) {
10742 case OPC_MFC0:
10743 if (rt == 0) {
10744 /* Treat as NOP. */
10745 return;
10747 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10748 opn = "mfc0";
10749 break;
10750 case OPC_MTC0:
10752 TCGv t0 = tcg_temp_new();
10754 gen_load_gpr(t0, rt);
10755 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
10756 tcg_temp_free(t0);
10758 opn = "mtc0";
10759 break;
10760 #if defined(TARGET_MIPS64)
10761 case OPC_DMFC0:
10762 check_insn(ctx, ISA_MIPS3);
10763 if (rt == 0) {
10764 /* Treat as NOP. */
10765 return;
10767 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10768 opn = "dmfc0";
10769 break;
10770 case OPC_DMTC0:
10771 check_insn(ctx, ISA_MIPS3);
10773 TCGv t0 = tcg_temp_new();
10775 gen_load_gpr(t0, rt);
10776 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
10777 tcg_temp_free(t0);
10779 opn = "dmtc0";
10780 break;
10781 #endif
10782 case OPC_MFHC0:
10783 check_mvh(ctx);
10784 if (rt == 0) {
10785 /* Treat as NOP. */
10786 return;
10788 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10789 opn = "mfhc0";
10790 break;
10791 case OPC_MTHC0:
10792 check_mvh(ctx);
10794 TCGv t0 = tcg_temp_new();
10795 gen_load_gpr(t0, rt);
10796 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
10797 tcg_temp_free(t0);
10799 opn = "mthc0";
10800 break;
10801 case OPC_MFTR:
10802 check_cp0_enabled(ctx);
10803 if (rd == 0) {
10804 /* Treat as NOP. */
10805 return;
10807 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
10808 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10809 opn = "mftr";
10810 break;
10811 case OPC_MTTR:
10812 check_cp0_enabled(ctx);
10813 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
10814 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10815 opn = "mttr";
10816 break;
10817 case OPC_TLBWI:
10818 opn = "tlbwi";
10819 if (!env->tlb->helper_tlbwi) {
10820 goto die;
10822 gen_helper_tlbwi(cpu_env);
10823 break;
10824 case OPC_TLBINV:
10825 opn = "tlbinv";
10826 if (ctx->ie >= 2) {
10827 if (!env->tlb->helper_tlbinv) {
10828 goto die;
10830 gen_helper_tlbinv(cpu_env);
10831 } /* treat as nop if TLBINV not supported */
10832 break;
10833 case OPC_TLBINVF:
10834 opn = "tlbinvf";
10835 if (ctx->ie >= 2) {
10836 if (!env->tlb->helper_tlbinvf) {
10837 goto die;
10839 gen_helper_tlbinvf(cpu_env);
10840 } /* treat as nop if TLBINV not supported */
10841 break;
10842 case OPC_TLBWR:
10843 opn = "tlbwr";
10844 if (!env->tlb->helper_tlbwr) {
10845 goto die;
10847 gen_helper_tlbwr(cpu_env);
10848 break;
10849 case OPC_TLBP:
10850 opn = "tlbp";
10851 if (!env->tlb->helper_tlbp) {
10852 goto die;
10854 gen_helper_tlbp(cpu_env);
10855 break;
10856 case OPC_TLBR:
10857 opn = "tlbr";
10858 if (!env->tlb->helper_tlbr) {
10859 goto die;
10861 gen_helper_tlbr(cpu_env);
10862 break;
10863 case OPC_ERET: /* OPC_ERETNC */
10864 if ((ctx->insn_flags & ISA_MIPS_R6) &&
10865 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10866 goto die;
10867 } else {
10868 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
10869 if (ctx->opcode & (1 << bit_shift)) {
10870 /* OPC_ERETNC */
10871 opn = "eretnc";
10872 check_insn(ctx, ISA_MIPS_R5);
10873 gen_helper_eretnc(cpu_env);
10874 } else {
10875 /* OPC_ERET */
10876 opn = "eret";
10877 check_insn(ctx, ISA_MIPS2);
10878 gen_helper_eret(cpu_env);
10880 ctx->base.is_jmp = DISAS_EXIT;
10882 break;
10883 case OPC_DERET:
10884 opn = "deret";
10885 check_insn(ctx, ISA_MIPS_R1);
10886 if ((ctx->insn_flags & ISA_MIPS_R6) &&
10887 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10888 goto die;
10890 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10891 MIPS_INVAL(opn);
10892 gen_reserved_instruction(ctx);
10893 } else {
10894 gen_helper_deret(cpu_env);
10895 ctx->base.is_jmp = DISAS_EXIT;
10897 break;
10898 case OPC_WAIT:
10899 opn = "wait";
10900 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
10901 if ((ctx->insn_flags & ISA_MIPS_R6) &&
10902 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10903 goto die;
10905 /* If we get an exception, we want to restart at next instruction */
10906 ctx->base.pc_next += 4;
10907 save_cpu_state(ctx, 1);
10908 ctx->base.pc_next -= 4;
10909 gen_helper_wait(cpu_env);
10910 ctx->base.is_jmp = DISAS_NORETURN;
10911 break;
10912 default:
10913 die:
10914 MIPS_INVAL(opn);
10915 gen_reserved_instruction(ctx);
10916 return;
10918 (void)opn; /* avoid a compiler warning */
10920 #endif /* !CONFIG_USER_ONLY */
10922 /* CP1 Branches (before delay slot) */
10923 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
10924 int32_t cc, int32_t offset)
10926 target_ulong btarget;
10927 TCGv_i32 t0 = tcg_temp_new_i32();
10929 if ((ctx->insn_flags & ISA_MIPS_R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
10930 gen_reserved_instruction(ctx);
10931 goto out;
10934 if (cc != 0) {
10935 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
10938 btarget = ctx->base.pc_next + 4 + offset;
10940 switch (op) {
10941 case OPC_BC1F:
10942 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10943 tcg_gen_not_i32(t0, t0);
10944 tcg_gen_andi_i32(t0, t0, 1);
10945 tcg_gen_extu_i32_tl(bcond, t0);
10946 goto not_likely;
10947 case OPC_BC1FL:
10948 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10949 tcg_gen_not_i32(t0, t0);
10950 tcg_gen_andi_i32(t0, t0, 1);
10951 tcg_gen_extu_i32_tl(bcond, t0);
10952 goto likely;
10953 case OPC_BC1T:
10954 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10955 tcg_gen_andi_i32(t0, t0, 1);
10956 tcg_gen_extu_i32_tl(bcond, t0);
10957 goto not_likely;
10958 case OPC_BC1TL:
10959 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10960 tcg_gen_andi_i32(t0, t0, 1);
10961 tcg_gen_extu_i32_tl(bcond, t0);
10962 likely:
10963 ctx->hflags |= MIPS_HFLAG_BL;
10964 break;
10965 case OPC_BC1FANY2:
10967 TCGv_i32 t1 = tcg_temp_new_i32();
10968 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10969 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10970 tcg_gen_nand_i32(t0, t0, t1);
10971 tcg_temp_free_i32(t1);
10972 tcg_gen_andi_i32(t0, t0, 1);
10973 tcg_gen_extu_i32_tl(bcond, t0);
10975 goto not_likely;
10976 case OPC_BC1TANY2:
10978 TCGv_i32 t1 = tcg_temp_new_i32();
10979 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10980 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10981 tcg_gen_or_i32(t0, t0, t1);
10982 tcg_temp_free_i32(t1);
10983 tcg_gen_andi_i32(t0, t0, 1);
10984 tcg_gen_extu_i32_tl(bcond, t0);
10986 goto not_likely;
10987 case OPC_BC1FANY4:
10989 TCGv_i32 t1 = tcg_temp_new_i32();
10990 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10991 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10992 tcg_gen_and_i32(t0, t0, t1);
10993 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
10994 tcg_gen_and_i32(t0, t0, t1);
10995 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
10996 tcg_gen_nand_i32(t0, t0, t1);
10997 tcg_temp_free_i32(t1);
10998 tcg_gen_andi_i32(t0, t0, 1);
10999 tcg_gen_extu_i32_tl(bcond, t0);
11001 goto not_likely;
11002 case OPC_BC1TANY4:
11004 TCGv_i32 t1 = tcg_temp_new_i32();
11005 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
11006 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
11007 tcg_gen_or_i32(t0, t0, t1);
11008 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
11009 tcg_gen_or_i32(t0, t0, t1);
11010 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
11011 tcg_gen_or_i32(t0, t0, t1);
11012 tcg_temp_free_i32(t1);
11013 tcg_gen_andi_i32(t0, t0, 1);
11014 tcg_gen_extu_i32_tl(bcond, t0);
11016 not_likely:
11017 ctx->hflags |= MIPS_HFLAG_BC;
11018 break;
11019 default:
11020 MIPS_INVAL("cp1 cond branch");
11021 gen_reserved_instruction(ctx);
11022 goto out;
11024 ctx->btarget = btarget;
11025 ctx->hflags |= MIPS_HFLAG_BDS32;
11026 out:
11027 tcg_temp_free_i32(t0);
11030 /* R6 CP1 Branches */
11031 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
11032 int32_t ft, int32_t offset,
11033 int delayslot_size)
11035 target_ulong btarget;
11036 TCGv_i64 t0 = tcg_temp_new_i64();
11038 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11039 #ifdef MIPS_DEBUG_DISAS
11040 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
11041 "\n", ctx->base.pc_next);
11042 #endif
11043 gen_reserved_instruction(ctx);
11044 goto out;
11047 gen_load_fpr64(ctx, t0, ft);
11048 tcg_gen_andi_i64(t0, t0, 1);
11050 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11052 switch (op) {
11053 case OPC_BC1EQZ:
11054 tcg_gen_xori_i64(t0, t0, 1);
11055 ctx->hflags |= MIPS_HFLAG_BC;
11056 break;
11057 case OPC_BC1NEZ:
11058 /* t0 already set */
11059 ctx->hflags |= MIPS_HFLAG_BC;
11060 break;
11061 default:
11062 MIPS_INVAL("cp1 cond branch");
11063 gen_reserved_instruction(ctx);
11064 goto out;
11067 tcg_gen_trunc_i64_tl(bcond, t0);
11069 ctx->btarget = btarget;
11071 switch (delayslot_size) {
11072 case 2:
11073 ctx->hflags |= MIPS_HFLAG_BDS16;
11074 break;
11075 case 4:
11076 ctx->hflags |= MIPS_HFLAG_BDS32;
11077 break;
11080 out:
11081 tcg_temp_free_i64(t0);
11084 /* Coprocessor 1 (FPU) */
11086 #define FOP(func, fmt) (((fmt) << 21) | (func))
11088 enum fopcode {
11089 OPC_ADD_S = FOP(0, FMT_S),
11090 OPC_SUB_S = FOP(1, FMT_S),
11091 OPC_MUL_S = FOP(2, FMT_S),
11092 OPC_DIV_S = FOP(3, FMT_S),
11093 OPC_SQRT_S = FOP(4, FMT_S),
11094 OPC_ABS_S = FOP(5, FMT_S),
11095 OPC_MOV_S = FOP(6, FMT_S),
11096 OPC_NEG_S = FOP(7, FMT_S),
11097 OPC_ROUND_L_S = FOP(8, FMT_S),
11098 OPC_TRUNC_L_S = FOP(9, FMT_S),
11099 OPC_CEIL_L_S = FOP(10, FMT_S),
11100 OPC_FLOOR_L_S = FOP(11, FMT_S),
11101 OPC_ROUND_W_S = FOP(12, FMT_S),
11102 OPC_TRUNC_W_S = FOP(13, FMT_S),
11103 OPC_CEIL_W_S = FOP(14, FMT_S),
11104 OPC_FLOOR_W_S = FOP(15, FMT_S),
11105 OPC_SEL_S = FOP(16, FMT_S),
11106 OPC_MOVCF_S = FOP(17, FMT_S),
11107 OPC_MOVZ_S = FOP(18, FMT_S),
11108 OPC_MOVN_S = FOP(19, FMT_S),
11109 OPC_SELEQZ_S = FOP(20, FMT_S),
11110 OPC_RECIP_S = FOP(21, FMT_S),
11111 OPC_RSQRT_S = FOP(22, FMT_S),
11112 OPC_SELNEZ_S = FOP(23, FMT_S),
11113 OPC_MADDF_S = FOP(24, FMT_S),
11114 OPC_MSUBF_S = FOP(25, FMT_S),
11115 OPC_RINT_S = FOP(26, FMT_S),
11116 OPC_CLASS_S = FOP(27, FMT_S),
11117 OPC_MIN_S = FOP(28, FMT_S),
11118 OPC_RECIP2_S = FOP(28, FMT_S),
11119 OPC_MINA_S = FOP(29, FMT_S),
11120 OPC_RECIP1_S = FOP(29, FMT_S),
11121 OPC_MAX_S = FOP(30, FMT_S),
11122 OPC_RSQRT1_S = FOP(30, FMT_S),
11123 OPC_MAXA_S = FOP(31, FMT_S),
11124 OPC_RSQRT2_S = FOP(31, FMT_S),
11125 OPC_CVT_D_S = FOP(33, FMT_S),
11126 OPC_CVT_W_S = FOP(36, FMT_S),
11127 OPC_CVT_L_S = FOP(37, FMT_S),
11128 OPC_CVT_PS_S = FOP(38, FMT_S),
11129 OPC_CMP_F_S = FOP(48, FMT_S),
11130 OPC_CMP_UN_S = FOP(49, FMT_S),
11131 OPC_CMP_EQ_S = FOP(50, FMT_S),
11132 OPC_CMP_UEQ_S = FOP(51, FMT_S),
11133 OPC_CMP_OLT_S = FOP(52, FMT_S),
11134 OPC_CMP_ULT_S = FOP(53, FMT_S),
11135 OPC_CMP_OLE_S = FOP(54, FMT_S),
11136 OPC_CMP_ULE_S = FOP(55, FMT_S),
11137 OPC_CMP_SF_S = FOP(56, FMT_S),
11138 OPC_CMP_NGLE_S = FOP(57, FMT_S),
11139 OPC_CMP_SEQ_S = FOP(58, FMT_S),
11140 OPC_CMP_NGL_S = FOP(59, FMT_S),
11141 OPC_CMP_LT_S = FOP(60, FMT_S),
11142 OPC_CMP_NGE_S = FOP(61, FMT_S),
11143 OPC_CMP_LE_S = FOP(62, FMT_S),
11144 OPC_CMP_NGT_S = FOP(63, FMT_S),
11146 OPC_ADD_D = FOP(0, FMT_D),
11147 OPC_SUB_D = FOP(1, FMT_D),
11148 OPC_MUL_D = FOP(2, FMT_D),
11149 OPC_DIV_D = FOP(3, FMT_D),
11150 OPC_SQRT_D = FOP(4, FMT_D),
11151 OPC_ABS_D = FOP(5, FMT_D),
11152 OPC_MOV_D = FOP(6, FMT_D),
11153 OPC_NEG_D = FOP(7, FMT_D),
11154 OPC_ROUND_L_D = FOP(8, FMT_D),
11155 OPC_TRUNC_L_D = FOP(9, FMT_D),
11156 OPC_CEIL_L_D = FOP(10, FMT_D),
11157 OPC_FLOOR_L_D = FOP(11, FMT_D),
11158 OPC_ROUND_W_D = FOP(12, FMT_D),
11159 OPC_TRUNC_W_D = FOP(13, FMT_D),
11160 OPC_CEIL_W_D = FOP(14, FMT_D),
11161 OPC_FLOOR_W_D = FOP(15, FMT_D),
11162 OPC_SEL_D = FOP(16, FMT_D),
11163 OPC_MOVCF_D = FOP(17, FMT_D),
11164 OPC_MOVZ_D = FOP(18, FMT_D),
11165 OPC_MOVN_D = FOP(19, FMT_D),
11166 OPC_SELEQZ_D = FOP(20, FMT_D),
11167 OPC_RECIP_D = FOP(21, FMT_D),
11168 OPC_RSQRT_D = FOP(22, FMT_D),
11169 OPC_SELNEZ_D = FOP(23, FMT_D),
11170 OPC_MADDF_D = FOP(24, FMT_D),
11171 OPC_MSUBF_D = FOP(25, FMT_D),
11172 OPC_RINT_D = FOP(26, FMT_D),
11173 OPC_CLASS_D = FOP(27, FMT_D),
11174 OPC_MIN_D = FOP(28, FMT_D),
11175 OPC_RECIP2_D = FOP(28, FMT_D),
11176 OPC_MINA_D = FOP(29, FMT_D),
11177 OPC_RECIP1_D = FOP(29, FMT_D),
11178 OPC_MAX_D = FOP(30, FMT_D),
11179 OPC_RSQRT1_D = FOP(30, FMT_D),
11180 OPC_MAXA_D = FOP(31, FMT_D),
11181 OPC_RSQRT2_D = FOP(31, FMT_D),
11182 OPC_CVT_S_D = FOP(32, FMT_D),
11183 OPC_CVT_W_D = FOP(36, FMT_D),
11184 OPC_CVT_L_D = FOP(37, FMT_D),
11185 OPC_CMP_F_D = FOP(48, FMT_D),
11186 OPC_CMP_UN_D = FOP(49, FMT_D),
11187 OPC_CMP_EQ_D = FOP(50, FMT_D),
11188 OPC_CMP_UEQ_D = FOP(51, FMT_D),
11189 OPC_CMP_OLT_D = FOP(52, FMT_D),
11190 OPC_CMP_ULT_D = FOP(53, FMT_D),
11191 OPC_CMP_OLE_D = FOP(54, FMT_D),
11192 OPC_CMP_ULE_D = FOP(55, FMT_D),
11193 OPC_CMP_SF_D = FOP(56, FMT_D),
11194 OPC_CMP_NGLE_D = FOP(57, FMT_D),
11195 OPC_CMP_SEQ_D = FOP(58, FMT_D),
11196 OPC_CMP_NGL_D = FOP(59, FMT_D),
11197 OPC_CMP_LT_D = FOP(60, FMT_D),
11198 OPC_CMP_NGE_D = FOP(61, FMT_D),
11199 OPC_CMP_LE_D = FOP(62, FMT_D),
11200 OPC_CMP_NGT_D = FOP(63, FMT_D),
11202 OPC_CVT_S_W = FOP(32, FMT_W),
11203 OPC_CVT_D_W = FOP(33, FMT_W),
11204 OPC_CVT_S_L = FOP(32, FMT_L),
11205 OPC_CVT_D_L = FOP(33, FMT_L),
11206 OPC_CVT_PS_PW = FOP(38, FMT_W),
11208 OPC_ADD_PS = FOP(0, FMT_PS),
11209 OPC_SUB_PS = FOP(1, FMT_PS),
11210 OPC_MUL_PS = FOP(2, FMT_PS),
11211 OPC_DIV_PS = FOP(3, FMT_PS),
11212 OPC_ABS_PS = FOP(5, FMT_PS),
11213 OPC_MOV_PS = FOP(6, FMT_PS),
11214 OPC_NEG_PS = FOP(7, FMT_PS),
11215 OPC_MOVCF_PS = FOP(17, FMT_PS),
11216 OPC_MOVZ_PS = FOP(18, FMT_PS),
11217 OPC_MOVN_PS = FOP(19, FMT_PS),
11218 OPC_ADDR_PS = FOP(24, FMT_PS),
11219 OPC_MULR_PS = FOP(26, FMT_PS),
11220 OPC_RECIP2_PS = FOP(28, FMT_PS),
11221 OPC_RECIP1_PS = FOP(29, FMT_PS),
11222 OPC_RSQRT1_PS = FOP(30, FMT_PS),
11223 OPC_RSQRT2_PS = FOP(31, FMT_PS),
11225 OPC_CVT_S_PU = FOP(32, FMT_PS),
11226 OPC_CVT_PW_PS = FOP(36, FMT_PS),
11227 OPC_CVT_S_PL = FOP(40, FMT_PS),
11228 OPC_PLL_PS = FOP(44, FMT_PS),
11229 OPC_PLU_PS = FOP(45, FMT_PS),
11230 OPC_PUL_PS = FOP(46, FMT_PS),
11231 OPC_PUU_PS = FOP(47, FMT_PS),
11232 OPC_CMP_F_PS = FOP(48, FMT_PS),
11233 OPC_CMP_UN_PS = FOP(49, FMT_PS),
11234 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
11235 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
11236 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
11237 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
11238 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
11239 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
11240 OPC_CMP_SF_PS = FOP(56, FMT_PS),
11241 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
11242 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
11243 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
11244 OPC_CMP_LT_PS = FOP(60, FMT_PS),
11245 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
11246 OPC_CMP_LE_PS = FOP(62, FMT_PS),
11247 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
11250 enum r6_f_cmp_op {
11251 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
11252 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
11253 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
11254 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
11255 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
11256 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
11257 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
11258 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
11259 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
11260 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
11261 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
11262 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
11263 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
11264 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
11265 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
11266 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
11267 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
11268 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
11269 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
11270 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
11271 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
11272 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
11274 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
11275 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
11276 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
11277 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
11278 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
11279 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
11280 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
11281 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
11282 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
11283 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
11284 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
11285 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
11286 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
11287 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
11288 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
11289 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
11290 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
11291 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
11292 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
11293 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
11294 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
11295 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
11298 static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
11300 TCGv t0 = tcg_temp_new();
11302 switch (opc) {
11303 case OPC_MFC1:
11305 TCGv_i32 fp0 = tcg_temp_new_i32();
11307 gen_load_fpr32(ctx, fp0, fs);
11308 tcg_gen_ext_i32_tl(t0, fp0);
11309 tcg_temp_free_i32(fp0);
11311 gen_store_gpr(t0, rt);
11312 break;
11313 case OPC_MTC1:
11314 gen_load_gpr(t0, rt);
11316 TCGv_i32 fp0 = tcg_temp_new_i32();
11318 tcg_gen_trunc_tl_i32(fp0, t0);
11319 gen_store_fpr32(ctx, fp0, fs);
11320 tcg_temp_free_i32(fp0);
11322 break;
11323 case OPC_CFC1:
11324 gen_helper_1e0i(cfc1, t0, fs);
11325 gen_store_gpr(t0, rt);
11326 break;
11327 case OPC_CTC1:
11328 gen_load_gpr(t0, rt);
11329 save_cpu_state(ctx, 0);
11331 TCGv_i32 fs_tmp = tcg_const_i32(fs);
11333 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
11334 tcg_temp_free_i32(fs_tmp);
11336 /* Stop translation as we may have changed hflags */
11337 ctx->base.is_jmp = DISAS_STOP;
11338 break;
11339 #if defined(TARGET_MIPS64)
11340 case OPC_DMFC1:
11341 gen_load_fpr64(ctx, t0, fs);
11342 gen_store_gpr(t0, rt);
11343 break;
11344 case OPC_DMTC1:
11345 gen_load_gpr(t0, rt);
11346 gen_store_fpr64(ctx, t0, fs);
11347 break;
11348 #endif
11349 case OPC_MFHC1:
11351 TCGv_i32 fp0 = tcg_temp_new_i32();
11353 gen_load_fpr32h(ctx, fp0, fs);
11354 tcg_gen_ext_i32_tl(t0, fp0);
11355 tcg_temp_free_i32(fp0);
11357 gen_store_gpr(t0, rt);
11358 break;
11359 case OPC_MTHC1:
11360 gen_load_gpr(t0, rt);
11362 TCGv_i32 fp0 = tcg_temp_new_i32();
11364 tcg_gen_trunc_tl_i32(fp0, t0);
11365 gen_store_fpr32h(ctx, fp0, fs);
11366 tcg_temp_free_i32(fp0);
11368 break;
11369 default:
11370 MIPS_INVAL("cp1 move");
11371 gen_reserved_instruction(ctx);
11372 goto out;
11375 out:
11376 tcg_temp_free(t0);
11379 static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
11381 TCGLabel *l1;
11382 TCGCond cond;
11383 TCGv_i32 t0;
11385 if (rd == 0) {
11386 /* Treat as NOP. */
11387 return;
11390 if (tf) {
11391 cond = TCG_COND_EQ;
11392 } else {
11393 cond = TCG_COND_NE;
11396 l1 = gen_new_label();
11397 t0 = tcg_temp_new_i32();
11398 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11399 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11400 tcg_temp_free_i32(t0);
11401 if (rs == 0) {
11402 tcg_gen_movi_tl(cpu_gpr[rd], 0);
11403 } else {
11404 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
11406 gen_set_label(l1);
11409 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
11410 int tf)
11412 int cond;
11413 TCGv_i32 t0 = tcg_temp_new_i32();
11414 TCGLabel *l1 = gen_new_label();
11416 if (tf) {
11417 cond = TCG_COND_EQ;
11418 } else {
11419 cond = TCG_COND_NE;
11422 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11423 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11424 gen_load_fpr32(ctx, t0, fs);
11425 gen_store_fpr32(ctx, t0, fd);
11426 gen_set_label(l1);
11427 tcg_temp_free_i32(t0);
11430 static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
11431 int tf)
11433 int cond;
11434 TCGv_i32 t0 = tcg_temp_new_i32();
11435 TCGv_i64 fp0;
11436 TCGLabel *l1 = gen_new_label();
11438 if (tf) {
11439 cond = TCG_COND_EQ;
11440 } else {
11441 cond = TCG_COND_NE;
11444 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11445 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11446 tcg_temp_free_i32(t0);
11447 fp0 = tcg_temp_new_i64();
11448 gen_load_fpr64(ctx, fp0, fs);
11449 gen_store_fpr64(ctx, fp0, fd);
11450 tcg_temp_free_i64(fp0);
11451 gen_set_label(l1);
11454 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
11455 int cc, int tf)
11457 int cond;
11458 TCGv_i32 t0 = tcg_temp_new_i32();
11459 TCGLabel *l1 = gen_new_label();
11460 TCGLabel *l2 = gen_new_label();
11462 if (tf) {
11463 cond = TCG_COND_EQ;
11464 } else {
11465 cond = TCG_COND_NE;
11468 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11469 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11470 gen_load_fpr32(ctx, t0, fs);
11471 gen_store_fpr32(ctx, t0, fd);
11472 gen_set_label(l1);
11474 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc + 1));
11475 tcg_gen_brcondi_i32(cond, t0, 0, l2);
11476 gen_load_fpr32h(ctx, t0, fs);
11477 gen_store_fpr32h(ctx, t0, fd);
11478 tcg_temp_free_i32(t0);
11479 gen_set_label(l2);
11482 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
11483 int fs)
11485 TCGv_i32 t1 = tcg_const_i32(0);
11486 TCGv_i32 fp0 = tcg_temp_new_i32();
11487 TCGv_i32 fp1 = tcg_temp_new_i32();
11488 TCGv_i32 fp2 = tcg_temp_new_i32();
11489 gen_load_fpr32(ctx, fp0, fd);
11490 gen_load_fpr32(ctx, fp1, ft);
11491 gen_load_fpr32(ctx, fp2, fs);
11493 switch (op1) {
11494 case OPC_SEL_S:
11495 tcg_gen_andi_i32(fp0, fp0, 1);
11496 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11497 break;
11498 case OPC_SELEQZ_S:
11499 tcg_gen_andi_i32(fp1, fp1, 1);
11500 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11501 break;
11502 case OPC_SELNEZ_S:
11503 tcg_gen_andi_i32(fp1, fp1, 1);
11504 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11505 break;
11506 default:
11507 MIPS_INVAL("gen_sel_s");
11508 gen_reserved_instruction(ctx);
11509 break;
11512 gen_store_fpr32(ctx, fp0, fd);
11513 tcg_temp_free_i32(fp2);
11514 tcg_temp_free_i32(fp1);
11515 tcg_temp_free_i32(fp0);
11516 tcg_temp_free_i32(t1);
11519 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
11520 int fs)
11522 TCGv_i64 t1 = tcg_const_i64(0);
11523 TCGv_i64 fp0 = tcg_temp_new_i64();
11524 TCGv_i64 fp1 = tcg_temp_new_i64();
11525 TCGv_i64 fp2 = tcg_temp_new_i64();
11526 gen_load_fpr64(ctx, fp0, fd);
11527 gen_load_fpr64(ctx, fp1, ft);
11528 gen_load_fpr64(ctx, fp2, fs);
11530 switch (op1) {
11531 case OPC_SEL_D:
11532 tcg_gen_andi_i64(fp0, fp0, 1);
11533 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11534 break;
11535 case OPC_SELEQZ_D:
11536 tcg_gen_andi_i64(fp1, fp1, 1);
11537 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11538 break;
11539 case OPC_SELNEZ_D:
11540 tcg_gen_andi_i64(fp1, fp1, 1);
11541 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11542 break;
11543 default:
11544 MIPS_INVAL("gen_sel_d");
11545 gen_reserved_instruction(ctx);
11546 break;
11549 gen_store_fpr64(ctx, fp0, fd);
11550 tcg_temp_free_i64(fp2);
11551 tcg_temp_free_i64(fp1);
11552 tcg_temp_free_i64(fp0);
11553 tcg_temp_free_i64(t1);
11556 static void gen_farith(DisasContext *ctx, enum fopcode op1,
11557 int ft, int fs, int fd, int cc)
11559 uint32_t func = ctx->opcode & 0x3f;
11560 switch (op1) {
11561 case OPC_ADD_S:
11563 TCGv_i32 fp0 = tcg_temp_new_i32();
11564 TCGv_i32 fp1 = tcg_temp_new_i32();
11566 gen_load_fpr32(ctx, fp0, fs);
11567 gen_load_fpr32(ctx, fp1, ft);
11568 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
11569 tcg_temp_free_i32(fp1);
11570 gen_store_fpr32(ctx, fp0, fd);
11571 tcg_temp_free_i32(fp0);
11573 break;
11574 case OPC_SUB_S:
11576 TCGv_i32 fp0 = tcg_temp_new_i32();
11577 TCGv_i32 fp1 = tcg_temp_new_i32();
11579 gen_load_fpr32(ctx, fp0, fs);
11580 gen_load_fpr32(ctx, fp1, ft);
11581 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
11582 tcg_temp_free_i32(fp1);
11583 gen_store_fpr32(ctx, fp0, fd);
11584 tcg_temp_free_i32(fp0);
11586 break;
11587 case OPC_MUL_S:
11589 TCGv_i32 fp0 = tcg_temp_new_i32();
11590 TCGv_i32 fp1 = tcg_temp_new_i32();
11592 gen_load_fpr32(ctx, fp0, fs);
11593 gen_load_fpr32(ctx, fp1, ft);
11594 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
11595 tcg_temp_free_i32(fp1);
11596 gen_store_fpr32(ctx, fp0, fd);
11597 tcg_temp_free_i32(fp0);
11599 break;
11600 case OPC_DIV_S:
11602 TCGv_i32 fp0 = tcg_temp_new_i32();
11603 TCGv_i32 fp1 = tcg_temp_new_i32();
11605 gen_load_fpr32(ctx, fp0, fs);
11606 gen_load_fpr32(ctx, fp1, ft);
11607 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
11608 tcg_temp_free_i32(fp1);
11609 gen_store_fpr32(ctx, fp0, fd);
11610 tcg_temp_free_i32(fp0);
11612 break;
11613 case OPC_SQRT_S:
11615 TCGv_i32 fp0 = tcg_temp_new_i32();
11617 gen_load_fpr32(ctx, fp0, fs);
11618 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
11619 gen_store_fpr32(ctx, fp0, fd);
11620 tcg_temp_free_i32(fp0);
11622 break;
11623 case OPC_ABS_S:
11625 TCGv_i32 fp0 = tcg_temp_new_i32();
11627 gen_load_fpr32(ctx, fp0, fs);
11628 if (ctx->abs2008) {
11629 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
11630 } else {
11631 gen_helper_float_abs_s(fp0, fp0);
11633 gen_store_fpr32(ctx, fp0, fd);
11634 tcg_temp_free_i32(fp0);
11636 break;
11637 case OPC_MOV_S:
11639 TCGv_i32 fp0 = tcg_temp_new_i32();
11641 gen_load_fpr32(ctx, fp0, fs);
11642 gen_store_fpr32(ctx, fp0, fd);
11643 tcg_temp_free_i32(fp0);
11645 break;
11646 case OPC_NEG_S:
11648 TCGv_i32 fp0 = tcg_temp_new_i32();
11650 gen_load_fpr32(ctx, fp0, fs);
11651 if (ctx->abs2008) {
11652 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
11653 } else {
11654 gen_helper_float_chs_s(fp0, fp0);
11656 gen_store_fpr32(ctx, fp0, fd);
11657 tcg_temp_free_i32(fp0);
11659 break;
11660 case OPC_ROUND_L_S:
11661 check_cp1_64bitmode(ctx);
11663 TCGv_i32 fp32 = tcg_temp_new_i32();
11664 TCGv_i64 fp64 = tcg_temp_new_i64();
11666 gen_load_fpr32(ctx, fp32, fs);
11667 if (ctx->nan2008) {
11668 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
11669 } else {
11670 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
11672 tcg_temp_free_i32(fp32);
11673 gen_store_fpr64(ctx, fp64, fd);
11674 tcg_temp_free_i64(fp64);
11676 break;
11677 case OPC_TRUNC_L_S:
11678 check_cp1_64bitmode(ctx);
11680 TCGv_i32 fp32 = tcg_temp_new_i32();
11681 TCGv_i64 fp64 = tcg_temp_new_i64();
11683 gen_load_fpr32(ctx, fp32, fs);
11684 if (ctx->nan2008) {
11685 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
11686 } else {
11687 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
11689 tcg_temp_free_i32(fp32);
11690 gen_store_fpr64(ctx, fp64, fd);
11691 tcg_temp_free_i64(fp64);
11693 break;
11694 case OPC_CEIL_L_S:
11695 check_cp1_64bitmode(ctx);
11697 TCGv_i32 fp32 = tcg_temp_new_i32();
11698 TCGv_i64 fp64 = tcg_temp_new_i64();
11700 gen_load_fpr32(ctx, fp32, fs);
11701 if (ctx->nan2008) {
11702 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
11703 } else {
11704 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
11706 tcg_temp_free_i32(fp32);
11707 gen_store_fpr64(ctx, fp64, fd);
11708 tcg_temp_free_i64(fp64);
11710 break;
11711 case OPC_FLOOR_L_S:
11712 check_cp1_64bitmode(ctx);
11714 TCGv_i32 fp32 = tcg_temp_new_i32();
11715 TCGv_i64 fp64 = tcg_temp_new_i64();
11717 gen_load_fpr32(ctx, fp32, fs);
11718 if (ctx->nan2008) {
11719 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
11720 } else {
11721 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
11723 tcg_temp_free_i32(fp32);
11724 gen_store_fpr64(ctx, fp64, fd);
11725 tcg_temp_free_i64(fp64);
11727 break;
11728 case OPC_ROUND_W_S:
11730 TCGv_i32 fp0 = tcg_temp_new_i32();
11732 gen_load_fpr32(ctx, fp0, fs);
11733 if (ctx->nan2008) {
11734 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
11735 } else {
11736 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
11738 gen_store_fpr32(ctx, fp0, fd);
11739 tcg_temp_free_i32(fp0);
11741 break;
11742 case OPC_TRUNC_W_S:
11744 TCGv_i32 fp0 = tcg_temp_new_i32();
11746 gen_load_fpr32(ctx, fp0, fs);
11747 if (ctx->nan2008) {
11748 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
11749 } else {
11750 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
11752 gen_store_fpr32(ctx, fp0, fd);
11753 tcg_temp_free_i32(fp0);
11755 break;
11756 case OPC_CEIL_W_S:
11758 TCGv_i32 fp0 = tcg_temp_new_i32();
11760 gen_load_fpr32(ctx, fp0, fs);
11761 if (ctx->nan2008) {
11762 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
11763 } else {
11764 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
11766 gen_store_fpr32(ctx, fp0, fd);
11767 tcg_temp_free_i32(fp0);
11769 break;
11770 case OPC_FLOOR_W_S:
11772 TCGv_i32 fp0 = tcg_temp_new_i32();
11774 gen_load_fpr32(ctx, fp0, fs);
11775 if (ctx->nan2008) {
11776 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
11777 } else {
11778 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
11780 gen_store_fpr32(ctx, fp0, fd);
11781 tcg_temp_free_i32(fp0);
11783 break;
11784 case OPC_SEL_S:
11785 check_insn(ctx, ISA_MIPS_R6);
11786 gen_sel_s(ctx, op1, fd, ft, fs);
11787 break;
11788 case OPC_SELEQZ_S:
11789 check_insn(ctx, ISA_MIPS_R6);
11790 gen_sel_s(ctx, op1, fd, ft, fs);
11791 break;
11792 case OPC_SELNEZ_S:
11793 check_insn(ctx, ISA_MIPS_R6);
11794 gen_sel_s(ctx, op1, fd, ft, fs);
11795 break;
11796 case OPC_MOVCF_S:
11797 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11798 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11799 break;
11800 case OPC_MOVZ_S:
11801 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11803 TCGLabel *l1 = gen_new_label();
11804 TCGv_i32 fp0;
11806 if (ft != 0) {
11807 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11809 fp0 = tcg_temp_new_i32();
11810 gen_load_fpr32(ctx, fp0, fs);
11811 gen_store_fpr32(ctx, fp0, fd);
11812 tcg_temp_free_i32(fp0);
11813 gen_set_label(l1);
11815 break;
11816 case OPC_MOVN_S:
11817 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11819 TCGLabel *l1 = gen_new_label();
11820 TCGv_i32 fp0;
11822 if (ft != 0) {
11823 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11824 fp0 = tcg_temp_new_i32();
11825 gen_load_fpr32(ctx, fp0, fs);
11826 gen_store_fpr32(ctx, fp0, fd);
11827 tcg_temp_free_i32(fp0);
11828 gen_set_label(l1);
11831 break;
11832 case OPC_RECIP_S:
11834 TCGv_i32 fp0 = tcg_temp_new_i32();
11836 gen_load_fpr32(ctx, fp0, fs);
11837 gen_helper_float_recip_s(fp0, cpu_env, fp0);
11838 gen_store_fpr32(ctx, fp0, fd);
11839 tcg_temp_free_i32(fp0);
11841 break;
11842 case OPC_RSQRT_S:
11844 TCGv_i32 fp0 = tcg_temp_new_i32();
11846 gen_load_fpr32(ctx, fp0, fs);
11847 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
11848 gen_store_fpr32(ctx, fp0, fd);
11849 tcg_temp_free_i32(fp0);
11851 break;
11852 case OPC_MADDF_S:
11853 check_insn(ctx, ISA_MIPS_R6);
11855 TCGv_i32 fp0 = tcg_temp_new_i32();
11856 TCGv_i32 fp1 = tcg_temp_new_i32();
11857 TCGv_i32 fp2 = tcg_temp_new_i32();
11858 gen_load_fpr32(ctx, fp0, fs);
11859 gen_load_fpr32(ctx, fp1, ft);
11860 gen_load_fpr32(ctx, fp2, fd);
11861 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
11862 gen_store_fpr32(ctx, fp2, fd);
11863 tcg_temp_free_i32(fp2);
11864 tcg_temp_free_i32(fp1);
11865 tcg_temp_free_i32(fp0);
11867 break;
11868 case OPC_MSUBF_S:
11869 check_insn(ctx, ISA_MIPS_R6);
11871 TCGv_i32 fp0 = tcg_temp_new_i32();
11872 TCGv_i32 fp1 = tcg_temp_new_i32();
11873 TCGv_i32 fp2 = tcg_temp_new_i32();
11874 gen_load_fpr32(ctx, fp0, fs);
11875 gen_load_fpr32(ctx, fp1, ft);
11876 gen_load_fpr32(ctx, fp2, fd);
11877 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
11878 gen_store_fpr32(ctx, fp2, fd);
11879 tcg_temp_free_i32(fp2);
11880 tcg_temp_free_i32(fp1);
11881 tcg_temp_free_i32(fp0);
11883 break;
11884 case OPC_RINT_S:
11885 check_insn(ctx, ISA_MIPS_R6);
11887 TCGv_i32 fp0 = tcg_temp_new_i32();
11888 gen_load_fpr32(ctx, fp0, fs);
11889 gen_helper_float_rint_s(fp0, cpu_env, fp0);
11890 gen_store_fpr32(ctx, fp0, fd);
11891 tcg_temp_free_i32(fp0);
11893 break;
11894 case OPC_CLASS_S:
11895 check_insn(ctx, ISA_MIPS_R6);
11897 TCGv_i32 fp0 = tcg_temp_new_i32();
11898 gen_load_fpr32(ctx, fp0, fs);
11899 gen_helper_float_class_s(fp0, cpu_env, fp0);
11900 gen_store_fpr32(ctx, fp0, fd);
11901 tcg_temp_free_i32(fp0);
11903 break;
11904 case OPC_MIN_S: /* OPC_RECIP2_S */
11905 if (ctx->insn_flags & ISA_MIPS_R6) {
11906 /* OPC_MIN_S */
11907 TCGv_i32 fp0 = tcg_temp_new_i32();
11908 TCGv_i32 fp1 = tcg_temp_new_i32();
11909 TCGv_i32 fp2 = tcg_temp_new_i32();
11910 gen_load_fpr32(ctx, fp0, fs);
11911 gen_load_fpr32(ctx, fp1, ft);
11912 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
11913 gen_store_fpr32(ctx, fp2, fd);
11914 tcg_temp_free_i32(fp2);
11915 tcg_temp_free_i32(fp1);
11916 tcg_temp_free_i32(fp0);
11917 } else {
11918 /* OPC_RECIP2_S */
11919 check_cp1_64bitmode(ctx);
11921 TCGv_i32 fp0 = tcg_temp_new_i32();
11922 TCGv_i32 fp1 = tcg_temp_new_i32();
11924 gen_load_fpr32(ctx, fp0, fs);
11925 gen_load_fpr32(ctx, fp1, ft);
11926 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
11927 tcg_temp_free_i32(fp1);
11928 gen_store_fpr32(ctx, fp0, fd);
11929 tcg_temp_free_i32(fp0);
11932 break;
11933 case OPC_MINA_S: /* OPC_RECIP1_S */
11934 if (ctx->insn_flags & ISA_MIPS_R6) {
11935 /* OPC_MINA_S */
11936 TCGv_i32 fp0 = tcg_temp_new_i32();
11937 TCGv_i32 fp1 = tcg_temp_new_i32();
11938 TCGv_i32 fp2 = tcg_temp_new_i32();
11939 gen_load_fpr32(ctx, fp0, fs);
11940 gen_load_fpr32(ctx, fp1, ft);
11941 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
11942 gen_store_fpr32(ctx, fp2, fd);
11943 tcg_temp_free_i32(fp2);
11944 tcg_temp_free_i32(fp1);
11945 tcg_temp_free_i32(fp0);
11946 } else {
11947 /* OPC_RECIP1_S */
11948 check_cp1_64bitmode(ctx);
11950 TCGv_i32 fp0 = tcg_temp_new_i32();
11952 gen_load_fpr32(ctx, fp0, fs);
11953 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
11954 gen_store_fpr32(ctx, fp0, fd);
11955 tcg_temp_free_i32(fp0);
11958 break;
11959 case OPC_MAX_S: /* OPC_RSQRT1_S */
11960 if (ctx->insn_flags & ISA_MIPS_R6) {
11961 /* OPC_MAX_S */
11962 TCGv_i32 fp0 = tcg_temp_new_i32();
11963 TCGv_i32 fp1 = tcg_temp_new_i32();
11964 gen_load_fpr32(ctx, fp0, fs);
11965 gen_load_fpr32(ctx, fp1, ft);
11966 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
11967 gen_store_fpr32(ctx, fp1, fd);
11968 tcg_temp_free_i32(fp1);
11969 tcg_temp_free_i32(fp0);
11970 } else {
11971 /* OPC_RSQRT1_S */
11972 check_cp1_64bitmode(ctx);
11974 TCGv_i32 fp0 = tcg_temp_new_i32();
11976 gen_load_fpr32(ctx, fp0, fs);
11977 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
11978 gen_store_fpr32(ctx, fp0, fd);
11979 tcg_temp_free_i32(fp0);
11982 break;
11983 case OPC_MAXA_S: /* OPC_RSQRT2_S */
11984 if (ctx->insn_flags & ISA_MIPS_R6) {
11985 /* OPC_MAXA_S */
11986 TCGv_i32 fp0 = tcg_temp_new_i32();
11987 TCGv_i32 fp1 = tcg_temp_new_i32();
11988 gen_load_fpr32(ctx, fp0, fs);
11989 gen_load_fpr32(ctx, fp1, ft);
11990 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
11991 gen_store_fpr32(ctx, fp1, fd);
11992 tcg_temp_free_i32(fp1);
11993 tcg_temp_free_i32(fp0);
11994 } else {
11995 /* OPC_RSQRT2_S */
11996 check_cp1_64bitmode(ctx);
11998 TCGv_i32 fp0 = tcg_temp_new_i32();
11999 TCGv_i32 fp1 = tcg_temp_new_i32();
12001 gen_load_fpr32(ctx, fp0, fs);
12002 gen_load_fpr32(ctx, fp1, ft);
12003 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
12004 tcg_temp_free_i32(fp1);
12005 gen_store_fpr32(ctx, fp0, fd);
12006 tcg_temp_free_i32(fp0);
12009 break;
12010 case OPC_CVT_D_S:
12011 check_cp1_registers(ctx, fd);
12013 TCGv_i32 fp32 = tcg_temp_new_i32();
12014 TCGv_i64 fp64 = tcg_temp_new_i64();
12016 gen_load_fpr32(ctx, fp32, fs);
12017 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
12018 tcg_temp_free_i32(fp32);
12019 gen_store_fpr64(ctx, fp64, fd);
12020 tcg_temp_free_i64(fp64);
12022 break;
12023 case OPC_CVT_W_S:
12025 TCGv_i32 fp0 = tcg_temp_new_i32();
12027 gen_load_fpr32(ctx, fp0, fs);
12028 if (ctx->nan2008) {
12029 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
12030 } else {
12031 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
12033 gen_store_fpr32(ctx, fp0, fd);
12034 tcg_temp_free_i32(fp0);
12036 break;
12037 case OPC_CVT_L_S:
12038 check_cp1_64bitmode(ctx);
12040 TCGv_i32 fp32 = tcg_temp_new_i32();
12041 TCGv_i64 fp64 = tcg_temp_new_i64();
12043 gen_load_fpr32(ctx, fp32, fs);
12044 if (ctx->nan2008) {
12045 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
12046 } else {
12047 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
12049 tcg_temp_free_i32(fp32);
12050 gen_store_fpr64(ctx, fp64, fd);
12051 tcg_temp_free_i64(fp64);
12053 break;
12054 case OPC_CVT_PS_S:
12055 check_ps(ctx);
12057 TCGv_i64 fp64 = tcg_temp_new_i64();
12058 TCGv_i32 fp32_0 = tcg_temp_new_i32();
12059 TCGv_i32 fp32_1 = tcg_temp_new_i32();
12061 gen_load_fpr32(ctx, fp32_0, fs);
12062 gen_load_fpr32(ctx, fp32_1, ft);
12063 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
12064 tcg_temp_free_i32(fp32_1);
12065 tcg_temp_free_i32(fp32_0);
12066 gen_store_fpr64(ctx, fp64, fd);
12067 tcg_temp_free_i64(fp64);
12069 break;
12070 case OPC_CMP_F_S:
12071 case OPC_CMP_UN_S:
12072 case OPC_CMP_EQ_S:
12073 case OPC_CMP_UEQ_S:
12074 case OPC_CMP_OLT_S:
12075 case OPC_CMP_ULT_S:
12076 case OPC_CMP_OLE_S:
12077 case OPC_CMP_ULE_S:
12078 case OPC_CMP_SF_S:
12079 case OPC_CMP_NGLE_S:
12080 case OPC_CMP_SEQ_S:
12081 case OPC_CMP_NGL_S:
12082 case OPC_CMP_LT_S:
12083 case OPC_CMP_NGE_S:
12084 case OPC_CMP_LE_S:
12085 case OPC_CMP_NGT_S:
12086 check_insn_opc_removed(ctx, ISA_MIPS_R6);
12087 if (ctx->opcode & (1 << 6)) {
12088 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
12089 } else {
12090 gen_cmp_s(ctx, func - 48, ft, fs, cc);
12092 break;
12093 case OPC_ADD_D:
12094 check_cp1_registers(ctx, fs | ft | fd);
12096 TCGv_i64 fp0 = tcg_temp_new_i64();
12097 TCGv_i64 fp1 = tcg_temp_new_i64();
12099 gen_load_fpr64(ctx, fp0, fs);
12100 gen_load_fpr64(ctx, fp1, ft);
12101 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
12102 tcg_temp_free_i64(fp1);
12103 gen_store_fpr64(ctx, fp0, fd);
12104 tcg_temp_free_i64(fp0);
12106 break;
12107 case OPC_SUB_D:
12108 check_cp1_registers(ctx, fs | ft | fd);
12110 TCGv_i64 fp0 = tcg_temp_new_i64();
12111 TCGv_i64 fp1 = tcg_temp_new_i64();
12113 gen_load_fpr64(ctx, fp0, fs);
12114 gen_load_fpr64(ctx, fp1, ft);
12115 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
12116 tcg_temp_free_i64(fp1);
12117 gen_store_fpr64(ctx, fp0, fd);
12118 tcg_temp_free_i64(fp0);
12120 break;
12121 case OPC_MUL_D:
12122 check_cp1_registers(ctx, fs | ft | fd);
12124 TCGv_i64 fp0 = tcg_temp_new_i64();
12125 TCGv_i64 fp1 = tcg_temp_new_i64();
12127 gen_load_fpr64(ctx, fp0, fs);
12128 gen_load_fpr64(ctx, fp1, ft);
12129 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
12130 tcg_temp_free_i64(fp1);
12131 gen_store_fpr64(ctx, fp0, fd);
12132 tcg_temp_free_i64(fp0);
12134 break;
12135 case OPC_DIV_D:
12136 check_cp1_registers(ctx, fs | ft | fd);
12138 TCGv_i64 fp0 = tcg_temp_new_i64();
12139 TCGv_i64 fp1 = tcg_temp_new_i64();
12141 gen_load_fpr64(ctx, fp0, fs);
12142 gen_load_fpr64(ctx, fp1, ft);
12143 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
12144 tcg_temp_free_i64(fp1);
12145 gen_store_fpr64(ctx, fp0, fd);
12146 tcg_temp_free_i64(fp0);
12148 break;
12149 case OPC_SQRT_D:
12150 check_cp1_registers(ctx, fs | fd);
12152 TCGv_i64 fp0 = tcg_temp_new_i64();
12154 gen_load_fpr64(ctx, fp0, fs);
12155 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
12156 gen_store_fpr64(ctx, fp0, fd);
12157 tcg_temp_free_i64(fp0);
12159 break;
12160 case OPC_ABS_D:
12161 check_cp1_registers(ctx, fs | fd);
12163 TCGv_i64 fp0 = tcg_temp_new_i64();
12165 gen_load_fpr64(ctx, fp0, fs);
12166 if (ctx->abs2008) {
12167 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
12168 } else {
12169 gen_helper_float_abs_d(fp0, fp0);
12171 gen_store_fpr64(ctx, fp0, fd);
12172 tcg_temp_free_i64(fp0);
12174 break;
12175 case OPC_MOV_D:
12176 check_cp1_registers(ctx, fs | fd);
12178 TCGv_i64 fp0 = tcg_temp_new_i64();
12180 gen_load_fpr64(ctx, fp0, fs);
12181 gen_store_fpr64(ctx, fp0, fd);
12182 tcg_temp_free_i64(fp0);
12184 break;
12185 case OPC_NEG_D:
12186 check_cp1_registers(ctx, fs | fd);
12188 TCGv_i64 fp0 = tcg_temp_new_i64();
12190 gen_load_fpr64(ctx, fp0, fs);
12191 if (ctx->abs2008) {
12192 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
12193 } else {
12194 gen_helper_float_chs_d(fp0, fp0);
12196 gen_store_fpr64(ctx, fp0, fd);
12197 tcg_temp_free_i64(fp0);
12199 break;
12200 case OPC_ROUND_L_D:
12201 check_cp1_64bitmode(ctx);
12203 TCGv_i64 fp0 = tcg_temp_new_i64();
12205 gen_load_fpr64(ctx, fp0, fs);
12206 if (ctx->nan2008) {
12207 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
12208 } else {
12209 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
12211 gen_store_fpr64(ctx, fp0, fd);
12212 tcg_temp_free_i64(fp0);
12214 break;
12215 case OPC_TRUNC_L_D:
12216 check_cp1_64bitmode(ctx);
12218 TCGv_i64 fp0 = tcg_temp_new_i64();
12220 gen_load_fpr64(ctx, fp0, fs);
12221 if (ctx->nan2008) {
12222 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
12223 } else {
12224 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
12226 gen_store_fpr64(ctx, fp0, fd);
12227 tcg_temp_free_i64(fp0);
12229 break;
12230 case OPC_CEIL_L_D:
12231 check_cp1_64bitmode(ctx);
12233 TCGv_i64 fp0 = tcg_temp_new_i64();
12235 gen_load_fpr64(ctx, fp0, fs);
12236 if (ctx->nan2008) {
12237 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
12238 } else {
12239 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
12241 gen_store_fpr64(ctx, fp0, fd);
12242 tcg_temp_free_i64(fp0);
12244 break;
12245 case OPC_FLOOR_L_D:
12246 check_cp1_64bitmode(ctx);
12248 TCGv_i64 fp0 = tcg_temp_new_i64();
12250 gen_load_fpr64(ctx, fp0, fs);
12251 if (ctx->nan2008) {
12252 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
12253 } else {
12254 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
12256 gen_store_fpr64(ctx, fp0, fd);
12257 tcg_temp_free_i64(fp0);
12259 break;
12260 case OPC_ROUND_W_D:
12261 check_cp1_registers(ctx, fs);
12263 TCGv_i32 fp32 = tcg_temp_new_i32();
12264 TCGv_i64 fp64 = tcg_temp_new_i64();
12266 gen_load_fpr64(ctx, fp64, fs);
12267 if (ctx->nan2008) {
12268 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
12269 } else {
12270 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
12272 tcg_temp_free_i64(fp64);
12273 gen_store_fpr32(ctx, fp32, fd);
12274 tcg_temp_free_i32(fp32);
12276 break;
12277 case OPC_TRUNC_W_D:
12278 check_cp1_registers(ctx, fs);
12280 TCGv_i32 fp32 = tcg_temp_new_i32();
12281 TCGv_i64 fp64 = tcg_temp_new_i64();
12283 gen_load_fpr64(ctx, fp64, fs);
12284 if (ctx->nan2008) {
12285 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
12286 } else {
12287 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
12289 tcg_temp_free_i64(fp64);
12290 gen_store_fpr32(ctx, fp32, fd);
12291 tcg_temp_free_i32(fp32);
12293 break;
12294 case OPC_CEIL_W_D:
12295 check_cp1_registers(ctx, fs);
12297 TCGv_i32 fp32 = tcg_temp_new_i32();
12298 TCGv_i64 fp64 = tcg_temp_new_i64();
12300 gen_load_fpr64(ctx, fp64, fs);
12301 if (ctx->nan2008) {
12302 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
12303 } else {
12304 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
12306 tcg_temp_free_i64(fp64);
12307 gen_store_fpr32(ctx, fp32, fd);
12308 tcg_temp_free_i32(fp32);
12310 break;
12311 case OPC_FLOOR_W_D:
12312 check_cp1_registers(ctx, fs);
12314 TCGv_i32 fp32 = tcg_temp_new_i32();
12315 TCGv_i64 fp64 = tcg_temp_new_i64();
12317 gen_load_fpr64(ctx, fp64, fs);
12318 if (ctx->nan2008) {
12319 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
12320 } else {
12321 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
12323 tcg_temp_free_i64(fp64);
12324 gen_store_fpr32(ctx, fp32, fd);
12325 tcg_temp_free_i32(fp32);
12327 break;
12328 case OPC_SEL_D:
12329 check_insn(ctx, ISA_MIPS_R6);
12330 gen_sel_d(ctx, op1, fd, ft, fs);
12331 break;
12332 case OPC_SELEQZ_D:
12333 check_insn(ctx, ISA_MIPS_R6);
12334 gen_sel_d(ctx, op1, fd, ft, fs);
12335 break;
12336 case OPC_SELNEZ_D:
12337 check_insn(ctx, ISA_MIPS_R6);
12338 gen_sel_d(ctx, op1, fd, ft, fs);
12339 break;
12340 case OPC_MOVCF_D:
12341 check_insn_opc_removed(ctx, ISA_MIPS_R6);
12342 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
12343 break;
12344 case OPC_MOVZ_D:
12345 check_insn_opc_removed(ctx, ISA_MIPS_R6);
12347 TCGLabel *l1 = gen_new_label();
12348 TCGv_i64 fp0;
12350 if (ft != 0) {
12351 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
12353 fp0 = tcg_temp_new_i64();
12354 gen_load_fpr64(ctx, fp0, fs);
12355 gen_store_fpr64(ctx, fp0, fd);
12356 tcg_temp_free_i64(fp0);
12357 gen_set_label(l1);
12359 break;
12360 case OPC_MOVN_D:
12361 check_insn_opc_removed(ctx, ISA_MIPS_R6);
12363 TCGLabel *l1 = gen_new_label();
12364 TCGv_i64 fp0;
12366 if (ft != 0) {
12367 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12368 fp0 = tcg_temp_new_i64();
12369 gen_load_fpr64(ctx, fp0, fs);
12370 gen_store_fpr64(ctx, fp0, fd);
12371 tcg_temp_free_i64(fp0);
12372 gen_set_label(l1);
12375 break;
12376 case OPC_RECIP_D:
12377 check_cp1_registers(ctx, fs | fd);
12379 TCGv_i64 fp0 = tcg_temp_new_i64();
12381 gen_load_fpr64(ctx, fp0, fs);
12382 gen_helper_float_recip_d(fp0, cpu_env, fp0);
12383 gen_store_fpr64(ctx, fp0, fd);
12384 tcg_temp_free_i64(fp0);
12386 break;
12387 case OPC_RSQRT_D:
12388 check_cp1_registers(ctx, fs | fd);
12390 TCGv_i64 fp0 = tcg_temp_new_i64();
12392 gen_load_fpr64(ctx, fp0, fs);
12393 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
12394 gen_store_fpr64(ctx, fp0, fd);
12395 tcg_temp_free_i64(fp0);
12397 break;
12398 case OPC_MADDF_D:
12399 check_insn(ctx, ISA_MIPS_R6);
12401 TCGv_i64 fp0 = tcg_temp_new_i64();
12402 TCGv_i64 fp1 = tcg_temp_new_i64();
12403 TCGv_i64 fp2 = tcg_temp_new_i64();
12404 gen_load_fpr64(ctx, fp0, fs);
12405 gen_load_fpr64(ctx, fp1, ft);
12406 gen_load_fpr64(ctx, fp2, fd);
12407 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
12408 gen_store_fpr64(ctx, fp2, fd);
12409 tcg_temp_free_i64(fp2);
12410 tcg_temp_free_i64(fp1);
12411 tcg_temp_free_i64(fp0);
12413 break;
12414 case OPC_MSUBF_D:
12415 check_insn(ctx, ISA_MIPS_R6);
12417 TCGv_i64 fp0 = tcg_temp_new_i64();
12418 TCGv_i64 fp1 = tcg_temp_new_i64();
12419 TCGv_i64 fp2 = tcg_temp_new_i64();
12420 gen_load_fpr64(ctx, fp0, fs);
12421 gen_load_fpr64(ctx, fp1, ft);
12422 gen_load_fpr64(ctx, fp2, fd);
12423 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
12424 gen_store_fpr64(ctx, fp2, fd);
12425 tcg_temp_free_i64(fp2);
12426 tcg_temp_free_i64(fp1);
12427 tcg_temp_free_i64(fp0);
12429 break;
12430 case OPC_RINT_D:
12431 check_insn(ctx, ISA_MIPS_R6);
12433 TCGv_i64 fp0 = tcg_temp_new_i64();
12434 gen_load_fpr64(ctx, fp0, fs);
12435 gen_helper_float_rint_d(fp0, cpu_env, fp0);
12436 gen_store_fpr64(ctx, fp0, fd);
12437 tcg_temp_free_i64(fp0);
12439 break;
12440 case OPC_CLASS_D:
12441 check_insn(ctx, ISA_MIPS_R6);
12443 TCGv_i64 fp0 = tcg_temp_new_i64();
12444 gen_load_fpr64(ctx, fp0, fs);
12445 gen_helper_float_class_d(fp0, cpu_env, fp0);
12446 gen_store_fpr64(ctx, fp0, fd);
12447 tcg_temp_free_i64(fp0);
12449 break;
12450 case OPC_MIN_D: /* OPC_RECIP2_D */
12451 if (ctx->insn_flags & ISA_MIPS_R6) {
12452 /* OPC_MIN_D */
12453 TCGv_i64 fp0 = tcg_temp_new_i64();
12454 TCGv_i64 fp1 = tcg_temp_new_i64();
12455 gen_load_fpr64(ctx, fp0, fs);
12456 gen_load_fpr64(ctx, fp1, ft);
12457 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
12458 gen_store_fpr64(ctx, fp1, fd);
12459 tcg_temp_free_i64(fp1);
12460 tcg_temp_free_i64(fp0);
12461 } else {
12462 /* OPC_RECIP2_D */
12463 check_cp1_64bitmode(ctx);
12465 TCGv_i64 fp0 = tcg_temp_new_i64();
12466 TCGv_i64 fp1 = tcg_temp_new_i64();
12468 gen_load_fpr64(ctx, fp0, fs);
12469 gen_load_fpr64(ctx, fp1, ft);
12470 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
12471 tcg_temp_free_i64(fp1);
12472 gen_store_fpr64(ctx, fp0, fd);
12473 tcg_temp_free_i64(fp0);
12476 break;
12477 case OPC_MINA_D: /* OPC_RECIP1_D */
12478 if (ctx->insn_flags & ISA_MIPS_R6) {
12479 /* OPC_MINA_D */
12480 TCGv_i64 fp0 = tcg_temp_new_i64();
12481 TCGv_i64 fp1 = tcg_temp_new_i64();
12482 gen_load_fpr64(ctx, fp0, fs);
12483 gen_load_fpr64(ctx, fp1, ft);
12484 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
12485 gen_store_fpr64(ctx, fp1, fd);
12486 tcg_temp_free_i64(fp1);
12487 tcg_temp_free_i64(fp0);
12488 } else {
12489 /* OPC_RECIP1_D */
12490 check_cp1_64bitmode(ctx);
12492 TCGv_i64 fp0 = tcg_temp_new_i64();
12494 gen_load_fpr64(ctx, fp0, fs);
12495 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
12496 gen_store_fpr64(ctx, fp0, fd);
12497 tcg_temp_free_i64(fp0);
12500 break;
12501 case OPC_MAX_D: /* OPC_RSQRT1_D */
12502 if (ctx->insn_flags & ISA_MIPS_R6) {
12503 /* OPC_MAX_D */
12504 TCGv_i64 fp0 = tcg_temp_new_i64();
12505 TCGv_i64 fp1 = tcg_temp_new_i64();
12506 gen_load_fpr64(ctx, fp0, fs);
12507 gen_load_fpr64(ctx, fp1, ft);
12508 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
12509 gen_store_fpr64(ctx, fp1, fd);
12510 tcg_temp_free_i64(fp1);
12511 tcg_temp_free_i64(fp0);
12512 } else {
12513 /* OPC_RSQRT1_D */
12514 check_cp1_64bitmode(ctx);
12516 TCGv_i64 fp0 = tcg_temp_new_i64();
12518 gen_load_fpr64(ctx, fp0, fs);
12519 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
12520 gen_store_fpr64(ctx, fp0, fd);
12521 tcg_temp_free_i64(fp0);
12524 break;
12525 case OPC_MAXA_D: /* OPC_RSQRT2_D */
12526 if (ctx->insn_flags & ISA_MIPS_R6) {
12527 /* OPC_MAXA_D */
12528 TCGv_i64 fp0 = tcg_temp_new_i64();
12529 TCGv_i64 fp1 = tcg_temp_new_i64();
12530 gen_load_fpr64(ctx, fp0, fs);
12531 gen_load_fpr64(ctx, fp1, ft);
12532 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
12533 gen_store_fpr64(ctx, fp1, fd);
12534 tcg_temp_free_i64(fp1);
12535 tcg_temp_free_i64(fp0);
12536 } else {
12537 /* OPC_RSQRT2_D */
12538 check_cp1_64bitmode(ctx);
12540 TCGv_i64 fp0 = tcg_temp_new_i64();
12541 TCGv_i64 fp1 = tcg_temp_new_i64();
12543 gen_load_fpr64(ctx, fp0, fs);
12544 gen_load_fpr64(ctx, fp1, ft);
12545 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
12546 tcg_temp_free_i64(fp1);
12547 gen_store_fpr64(ctx, fp0, fd);
12548 tcg_temp_free_i64(fp0);
12551 break;
12552 case OPC_CMP_F_D:
12553 case OPC_CMP_UN_D:
12554 case OPC_CMP_EQ_D:
12555 case OPC_CMP_UEQ_D:
12556 case OPC_CMP_OLT_D:
12557 case OPC_CMP_ULT_D:
12558 case OPC_CMP_OLE_D:
12559 case OPC_CMP_ULE_D:
12560 case OPC_CMP_SF_D:
12561 case OPC_CMP_NGLE_D:
12562 case OPC_CMP_SEQ_D:
12563 case OPC_CMP_NGL_D:
12564 case OPC_CMP_LT_D:
12565 case OPC_CMP_NGE_D:
12566 case OPC_CMP_LE_D:
12567 case OPC_CMP_NGT_D:
12568 check_insn_opc_removed(ctx, ISA_MIPS_R6);
12569 if (ctx->opcode & (1 << 6)) {
12570 gen_cmpabs_d(ctx, func - 48, ft, fs, cc);
12571 } else {
12572 gen_cmp_d(ctx, func - 48, ft, fs, cc);
12574 break;
12575 case OPC_CVT_S_D:
12576 check_cp1_registers(ctx, fs);
12578 TCGv_i32 fp32 = tcg_temp_new_i32();
12579 TCGv_i64 fp64 = tcg_temp_new_i64();
12581 gen_load_fpr64(ctx, fp64, fs);
12582 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
12583 tcg_temp_free_i64(fp64);
12584 gen_store_fpr32(ctx, fp32, fd);
12585 tcg_temp_free_i32(fp32);
12587 break;
12588 case OPC_CVT_W_D:
12589 check_cp1_registers(ctx, fs);
12591 TCGv_i32 fp32 = tcg_temp_new_i32();
12592 TCGv_i64 fp64 = tcg_temp_new_i64();
12594 gen_load_fpr64(ctx, fp64, fs);
12595 if (ctx->nan2008) {
12596 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
12597 } else {
12598 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
12600 tcg_temp_free_i64(fp64);
12601 gen_store_fpr32(ctx, fp32, fd);
12602 tcg_temp_free_i32(fp32);
12604 break;
12605 case OPC_CVT_L_D:
12606 check_cp1_64bitmode(ctx);
12608 TCGv_i64 fp0 = tcg_temp_new_i64();
12610 gen_load_fpr64(ctx, fp0, fs);
12611 if (ctx->nan2008) {
12612 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
12613 } else {
12614 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
12616 gen_store_fpr64(ctx, fp0, fd);
12617 tcg_temp_free_i64(fp0);
12619 break;
12620 case OPC_CVT_S_W:
12622 TCGv_i32 fp0 = tcg_temp_new_i32();
12624 gen_load_fpr32(ctx, fp0, fs);
12625 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
12626 gen_store_fpr32(ctx, fp0, fd);
12627 tcg_temp_free_i32(fp0);
12629 break;
12630 case OPC_CVT_D_W:
12631 check_cp1_registers(ctx, fd);
12633 TCGv_i32 fp32 = tcg_temp_new_i32();
12634 TCGv_i64 fp64 = tcg_temp_new_i64();
12636 gen_load_fpr32(ctx, fp32, fs);
12637 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
12638 tcg_temp_free_i32(fp32);
12639 gen_store_fpr64(ctx, fp64, fd);
12640 tcg_temp_free_i64(fp64);
12642 break;
12643 case OPC_CVT_S_L:
12644 check_cp1_64bitmode(ctx);
12646 TCGv_i32 fp32 = tcg_temp_new_i32();
12647 TCGv_i64 fp64 = tcg_temp_new_i64();
12649 gen_load_fpr64(ctx, fp64, fs);
12650 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
12651 tcg_temp_free_i64(fp64);
12652 gen_store_fpr32(ctx, fp32, fd);
12653 tcg_temp_free_i32(fp32);
12655 break;
12656 case OPC_CVT_D_L:
12657 check_cp1_64bitmode(ctx);
12659 TCGv_i64 fp0 = tcg_temp_new_i64();
12661 gen_load_fpr64(ctx, fp0, fs);
12662 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
12663 gen_store_fpr64(ctx, fp0, fd);
12664 tcg_temp_free_i64(fp0);
12666 break;
12667 case OPC_CVT_PS_PW:
12668 check_ps(ctx);
12670 TCGv_i64 fp0 = tcg_temp_new_i64();
12672 gen_load_fpr64(ctx, fp0, fs);
12673 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
12674 gen_store_fpr64(ctx, fp0, fd);
12675 tcg_temp_free_i64(fp0);
12677 break;
12678 case OPC_ADD_PS:
12679 check_ps(ctx);
12681 TCGv_i64 fp0 = tcg_temp_new_i64();
12682 TCGv_i64 fp1 = tcg_temp_new_i64();
12684 gen_load_fpr64(ctx, fp0, fs);
12685 gen_load_fpr64(ctx, fp1, ft);
12686 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
12687 tcg_temp_free_i64(fp1);
12688 gen_store_fpr64(ctx, fp0, fd);
12689 tcg_temp_free_i64(fp0);
12691 break;
12692 case OPC_SUB_PS:
12693 check_ps(ctx);
12695 TCGv_i64 fp0 = tcg_temp_new_i64();
12696 TCGv_i64 fp1 = tcg_temp_new_i64();
12698 gen_load_fpr64(ctx, fp0, fs);
12699 gen_load_fpr64(ctx, fp1, ft);
12700 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
12701 tcg_temp_free_i64(fp1);
12702 gen_store_fpr64(ctx, fp0, fd);
12703 tcg_temp_free_i64(fp0);
12705 break;
12706 case OPC_MUL_PS:
12707 check_ps(ctx);
12709 TCGv_i64 fp0 = tcg_temp_new_i64();
12710 TCGv_i64 fp1 = tcg_temp_new_i64();
12712 gen_load_fpr64(ctx, fp0, fs);
12713 gen_load_fpr64(ctx, fp1, ft);
12714 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
12715 tcg_temp_free_i64(fp1);
12716 gen_store_fpr64(ctx, fp0, fd);
12717 tcg_temp_free_i64(fp0);
12719 break;
12720 case OPC_ABS_PS:
12721 check_ps(ctx);
12723 TCGv_i64 fp0 = tcg_temp_new_i64();
12725 gen_load_fpr64(ctx, fp0, fs);
12726 gen_helper_float_abs_ps(fp0, fp0);
12727 gen_store_fpr64(ctx, fp0, fd);
12728 tcg_temp_free_i64(fp0);
12730 break;
12731 case OPC_MOV_PS:
12732 check_ps(ctx);
12734 TCGv_i64 fp0 = tcg_temp_new_i64();
12736 gen_load_fpr64(ctx, fp0, fs);
12737 gen_store_fpr64(ctx, fp0, fd);
12738 tcg_temp_free_i64(fp0);
12740 break;
12741 case OPC_NEG_PS:
12742 check_ps(ctx);
12744 TCGv_i64 fp0 = tcg_temp_new_i64();
12746 gen_load_fpr64(ctx, fp0, fs);
12747 gen_helper_float_chs_ps(fp0, fp0);
12748 gen_store_fpr64(ctx, fp0, fd);
12749 tcg_temp_free_i64(fp0);
12751 break;
12752 case OPC_MOVCF_PS:
12753 check_ps(ctx);
12754 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
12755 break;
12756 case OPC_MOVZ_PS:
12757 check_ps(ctx);
12759 TCGLabel *l1 = gen_new_label();
12760 TCGv_i64 fp0;
12762 if (ft != 0) {
12763 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
12765 fp0 = tcg_temp_new_i64();
12766 gen_load_fpr64(ctx, fp0, fs);
12767 gen_store_fpr64(ctx, fp0, fd);
12768 tcg_temp_free_i64(fp0);
12769 gen_set_label(l1);
12771 break;
12772 case OPC_MOVN_PS:
12773 check_ps(ctx);
12775 TCGLabel *l1 = gen_new_label();
12776 TCGv_i64 fp0;
12778 if (ft != 0) {
12779 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12780 fp0 = tcg_temp_new_i64();
12781 gen_load_fpr64(ctx, fp0, fs);
12782 gen_store_fpr64(ctx, fp0, fd);
12783 tcg_temp_free_i64(fp0);
12784 gen_set_label(l1);
12787 break;
12788 case OPC_ADDR_PS:
12789 check_ps(ctx);
12791 TCGv_i64 fp0 = tcg_temp_new_i64();
12792 TCGv_i64 fp1 = tcg_temp_new_i64();
12794 gen_load_fpr64(ctx, fp0, ft);
12795 gen_load_fpr64(ctx, fp1, fs);
12796 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
12797 tcg_temp_free_i64(fp1);
12798 gen_store_fpr64(ctx, fp0, fd);
12799 tcg_temp_free_i64(fp0);
12801 break;
12802 case OPC_MULR_PS:
12803 check_ps(ctx);
12805 TCGv_i64 fp0 = tcg_temp_new_i64();
12806 TCGv_i64 fp1 = tcg_temp_new_i64();
12808 gen_load_fpr64(ctx, fp0, ft);
12809 gen_load_fpr64(ctx, fp1, fs);
12810 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
12811 tcg_temp_free_i64(fp1);
12812 gen_store_fpr64(ctx, fp0, fd);
12813 tcg_temp_free_i64(fp0);
12815 break;
12816 case OPC_RECIP2_PS:
12817 check_ps(ctx);
12819 TCGv_i64 fp0 = tcg_temp_new_i64();
12820 TCGv_i64 fp1 = tcg_temp_new_i64();
12822 gen_load_fpr64(ctx, fp0, fs);
12823 gen_load_fpr64(ctx, fp1, ft);
12824 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
12825 tcg_temp_free_i64(fp1);
12826 gen_store_fpr64(ctx, fp0, fd);
12827 tcg_temp_free_i64(fp0);
12829 break;
12830 case OPC_RECIP1_PS:
12831 check_ps(ctx);
12833 TCGv_i64 fp0 = tcg_temp_new_i64();
12835 gen_load_fpr64(ctx, fp0, fs);
12836 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
12837 gen_store_fpr64(ctx, fp0, fd);
12838 tcg_temp_free_i64(fp0);
12840 break;
12841 case OPC_RSQRT1_PS:
12842 check_ps(ctx);
12844 TCGv_i64 fp0 = tcg_temp_new_i64();
12846 gen_load_fpr64(ctx, fp0, fs);
12847 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
12848 gen_store_fpr64(ctx, fp0, fd);
12849 tcg_temp_free_i64(fp0);
12851 break;
12852 case OPC_RSQRT2_PS:
12853 check_ps(ctx);
12855 TCGv_i64 fp0 = tcg_temp_new_i64();
12856 TCGv_i64 fp1 = tcg_temp_new_i64();
12858 gen_load_fpr64(ctx, fp0, fs);
12859 gen_load_fpr64(ctx, fp1, ft);
12860 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
12861 tcg_temp_free_i64(fp1);
12862 gen_store_fpr64(ctx, fp0, fd);
12863 tcg_temp_free_i64(fp0);
12865 break;
12866 case OPC_CVT_S_PU:
12867 check_cp1_64bitmode(ctx);
12869 TCGv_i32 fp0 = tcg_temp_new_i32();
12871 gen_load_fpr32h(ctx, fp0, fs);
12872 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
12873 gen_store_fpr32(ctx, fp0, fd);
12874 tcg_temp_free_i32(fp0);
12876 break;
12877 case OPC_CVT_PW_PS:
12878 check_ps(ctx);
12880 TCGv_i64 fp0 = tcg_temp_new_i64();
12882 gen_load_fpr64(ctx, fp0, fs);
12883 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
12884 gen_store_fpr64(ctx, fp0, fd);
12885 tcg_temp_free_i64(fp0);
12887 break;
12888 case OPC_CVT_S_PL:
12889 check_cp1_64bitmode(ctx);
12891 TCGv_i32 fp0 = tcg_temp_new_i32();
12893 gen_load_fpr32(ctx, fp0, fs);
12894 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
12895 gen_store_fpr32(ctx, fp0, fd);
12896 tcg_temp_free_i32(fp0);
12898 break;
12899 case OPC_PLL_PS:
12900 check_ps(ctx);
12902 TCGv_i32 fp0 = tcg_temp_new_i32();
12903 TCGv_i32 fp1 = tcg_temp_new_i32();
12905 gen_load_fpr32(ctx, fp0, fs);
12906 gen_load_fpr32(ctx, fp1, ft);
12907 gen_store_fpr32h(ctx, fp0, fd);
12908 gen_store_fpr32(ctx, fp1, fd);
12909 tcg_temp_free_i32(fp0);
12910 tcg_temp_free_i32(fp1);
12912 break;
12913 case OPC_PLU_PS:
12914 check_ps(ctx);
12916 TCGv_i32 fp0 = tcg_temp_new_i32();
12917 TCGv_i32 fp1 = tcg_temp_new_i32();
12919 gen_load_fpr32(ctx, fp0, fs);
12920 gen_load_fpr32h(ctx, fp1, ft);
12921 gen_store_fpr32(ctx, fp1, fd);
12922 gen_store_fpr32h(ctx, fp0, fd);
12923 tcg_temp_free_i32(fp0);
12924 tcg_temp_free_i32(fp1);
12926 break;
12927 case OPC_PUL_PS:
12928 check_ps(ctx);
12930 TCGv_i32 fp0 = tcg_temp_new_i32();
12931 TCGv_i32 fp1 = tcg_temp_new_i32();
12933 gen_load_fpr32h(ctx, fp0, fs);
12934 gen_load_fpr32(ctx, fp1, ft);
12935 gen_store_fpr32(ctx, fp1, fd);
12936 gen_store_fpr32h(ctx, fp0, fd);
12937 tcg_temp_free_i32(fp0);
12938 tcg_temp_free_i32(fp1);
12940 break;
12941 case OPC_PUU_PS:
12942 check_ps(ctx);
12944 TCGv_i32 fp0 = tcg_temp_new_i32();
12945 TCGv_i32 fp1 = tcg_temp_new_i32();
12947 gen_load_fpr32h(ctx, fp0, fs);
12948 gen_load_fpr32h(ctx, fp1, ft);
12949 gen_store_fpr32(ctx, fp1, fd);
12950 gen_store_fpr32h(ctx, fp0, fd);
12951 tcg_temp_free_i32(fp0);
12952 tcg_temp_free_i32(fp1);
12954 break;
12955 case OPC_CMP_F_PS:
12956 case OPC_CMP_UN_PS:
12957 case OPC_CMP_EQ_PS:
12958 case OPC_CMP_UEQ_PS:
12959 case OPC_CMP_OLT_PS:
12960 case OPC_CMP_ULT_PS:
12961 case OPC_CMP_OLE_PS:
12962 case OPC_CMP_ULE_PS:
12963 case OPC_CMP_SF_PS:
12964 case OPC_CMP_NGLE_PS:
12965 case OPC_CMP_SEQ_PS:
12966 case OPC_CMP_NGL_PS:
12967 case OPC_CMP_LT_PS:
12968 case OPC_CMP_NGE_PS:
12969 case OPC_CMP_LE_PS:
12970 case OPC_CMP_NGT_PS:
12971 if (ctx->opcode & (1 << 6)) {
12972 gen_cmpabs_ps(ctx, func - 48, ft, fs, cc);
12973 } else {
12974 gen_cmp_ps(ctx, func - 48, ft, fs, cc);
12976 break;
12977 default:
12978 MIPS_INVAL("farith");
12979 gen_reserved_instruction(ctx);
12980 return;
12984 /* Coprocessor 3 (FPU) */
12985 static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
12986 int fd, int fs, int base, int index)
12988 TCGv t0 = tcg_temp_new();
12990 if (base == 0) {
12991 gen_load_gpr(t0, index);
12992 } else if (index == 0) {
12993 gen_load_gpr(t0, base);
12994 } else {
12995 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
12998 * Don't do NOP if destination is zero: we must perform the actual
12999 * memory access.
13001 switch (opc) {
13002 case OPC_LWXC1:
13003 check_cop1x(ctx);
13005 TCGv_i32 fp0 = tcg_temp_new_i32();
13007 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
13008 tcg_gen_trunc_tl_i32(fp0, t0);
13009 gen_store_fpr32(ctx, fp0, fd);
13010 tcg_temp_free_i32(fp0);
13012 break;
13013 case OPC_LDXC1:
13014 check_cop1x(ctx);
13015 check_cp1_registers(ctx, fd);
13017 TCGv_i64 fp0 = tcg_temp_new_i64();
13018 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
13019 gen_store_fpr64(ctx, fp0, fd);
13020 tcg_temp_free_i64(fp0);
13022 break;
13023 case OPC_LUXC1:
13024 check_cp1_64bitmode(ctx);
13025 tcg_gen_andi_tl(t0, t0, ~0x7);
13027 TCGv_i64 fp0 = tcg_temp_new_i64();
13029 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
13030 gen_store_fpr64(ctx, fp0, fd);
13031 tcg_temp_free_i64(fp0);
13033 break;
13034 case OPC_SWXC1:
13035 check_cop1x(ctx);
13037 TCGv_i32 fp0 = tcg_temp_new_i32();
13038 gen_load_fpr32(ctx, fp0, fs);
13039 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
13040 tcg_temp_free_i32(fp0);
13042 break;
13043 case OPC_SDXC1:
13044 check_cop1x(ctx);
13045 check_cp1_registers(ctx, fs);
13047 TCGv_i64 fp0 = tcg_temp_new_i64();
13048 gen_load_fpr64(ctx, fp0, fs);
13049 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
13050 tcg_temp_free_i64(fp0);
13052 break;
13053 case OPC_SUXC1:
13054 check_cp1_64bitmode(ctx);
13055 tcg_gen_andi_tl(t0, t0, ~0x7);
13057 TCGv_i64 fp0 = tcg_temp_new_i64();
13058 gen_load_fpr64(ctx, fp0, fs);
13059 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
13060 tcg_temp_free_i64(fp0);
13062 break;
13064 tcg_temp_free(t0);
13067 static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
13068 int fd, int fr, int fs, int ft)
13070 switch (opc) {
13071 case OPC_ALNV_PS:
13072 check_ps(ctx);
13074 TCGv t0 = tcg_temp_local_new();
13075 TCGv_i32 fp = tcg_temp_new_i32();
13076 TCGv_i32 fph = tcg_temp_new_i32();
13077 TCGLabel *l1 = gen_new_label();
13078 TCGLabel *l2 = gen_new_label();
13080 gen_load_gpr(t0, fr);
13081 tcg_gen_andi_tl(t0, t0, 0x7);
13083 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
13084 gen_load_fpr32(ctx, fp, fs);
13085 gen_load_fpr32h(ctx, fph, fs);
13086 gen_store_fpr32(ctx, fp, fd);
13087 gen_store_fpr32h(ctx, fph, fd);
13088 tcg_gen_br(l2);
13089 gen_set_label(l1);
13090 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
13091 tcg_temp_free(t0);
13092 #ifdef TARGET_WORDS_BIGENDIAN
13093 gen_load_fpr32(ctx, fp, fs);
13094 gen_load_fpr32h(ctx, fph, ft);
13095 gen_store_fpr32h(ctx, fp, fd);
13096 gen_store_fpr32(ctx, fph, fd);
13097 #else
13098 gen_load_fpr32h(ctx, fph, fs);
13099 gen_load_fpr32(ctx, fp, ft);
13100 gen_store_fpr32(ctx, fph, fd);
13101 gen_store_fpr32h(ctx, fp, fd);
13102 #endif
13103 gen_set_label(l2);
13104 tcg_temp_free_i32(fp);
13105 tcg_temp_free_i32(fph);
13107 break;
13108 case OPC_MADD_S:
13109 check_cop1x(ctx);
13111 TCGv_i32 fp0 = tcg_temp_new_i32();
13112 TCGv_i32 fp1 = tcg_temp_new_i32();
13113 TCGv_i32 fp2 = tcg_temp_new_i32();
13115 gen_load_fpr32(ctx, fp0, fs);
13116 gen_load_fpr32(ctx, fp1, ft);
13117 gen_load_fpr32(ctx, fp2, fr);
13118 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
13119 tcg_temp_free_i32(fp0);
13120 tcg_temp_free_i32(fp1);
13121 gen_store_fpr32(ctx, fp2, fd);
13122 tcg_temp_free_i32(fp2);
13124 break;
13125 case OPC_MADD_D:
13126 check_cop1x(ctx);
13127 check_cp1_registers(ctx, fd | fs | ft | fr);
13129 TCGv_i64 fp0 = tcg_temp_new_i64();
13130 TCGv_i64 fp1 = tcg_temp_new_i64();
13131 TCGv_i64 fp2 = tcg_temp_new_i64();
13133 gen_load_fpr64(ctx, fp0, fs);
13134 gen_load_fpr64(ctx, fp1, ft);
13135 gen_load_fpr64(ctx, fp2, fr);
13136 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
13137 tcg_temp_free_i64(fp0);
13138 tcg_temp_free_i64(fp1);
13139 gen_store_fpr64(ctx, fp2, fd);
13140 tcg_temp_free_i64(fp2);
13142 break;
13143 case OPC_MADD_PS:
13144 check_ps(ctx);
13146 TCGv_i64 fp0 = tcg_temp_new_i64();
13147 TCGv_i64 fp1 = tcg_temp_new_i64();
13148 TCGv_i64 fp2 = tcg_temp_new_i64();
13150 gen_load_fpr64(ctx, fp0, fs);
13151 gen_load_fpr64(ctx, fp1, ft);
13152 gen_load_fpr64(ctx, fp2, fr);
13153 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
13154 tcg_temp_free_i64(fp0);
13155 tcg_temp_free_i64(fp1);
13156 gen_store_fpr64(ctx, fp2, fd);
13157 tcg_temp_free_i64(fp2);
13159 break;
13160 case OPC_MSUB_S:
13161 check_cop1x(ctx);
13163 TCGv_i32 fp0 = tcg_temp_new_i32();
13164 TCGv_i32 fp1 = tcg_temp_new_i32();
13165 TCGv_i32 fp2 = tcg_temp_new_i32();
13167 gen_load_fpr32(ctx, fp0, fs);
13168 gen_load_fpr32(ctx, fp1, ft);
13169 gen_load_fpr32(ctx, fp2, fr);
13170 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
13171 tcg_temp_free_i32(fp0);
13172 tcg_temp_free_i32(fp1);
13173 gen_store_fpr32(ctx, fp2, fd);
13174 tcg_temp_free_i32(fp2);
13176 break;
13177 case OPC_MSUB_D:
13178 check_cop1x(ctx);
13179 check_cp1_registers(ctx, fd | fs | ft | fr);
13181 TCGv_i64 fp0 = tcg_temp_new_i64();
13182 TCGv_i64 fp1 = tcg_temp_new_i64();
13183 TCGv_i64 fp2 = tcg_temp_new_i64();
13185 gen_load_fpr64(ctx, fp0, fs);
13186 gen_load_fpr64(ctx, fp1, ft);
13187 gen_load_fpr64(ctx, fp2, fr);
13188 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
13189 tcg_temp_free_i64(fp0);
13190 tcg_temp_free_i64(fp1);
13191 gen_store_fpr64(ctx, fp2, fd);
13192 tcg_temp_free_i64(fp2);
13194 break;
13195 case OPC_MSUB_PS:
13196 check_ps(ctx);
13198 TCGv_i64 fp0 = tcg_temp_new_i64();
13199 TCGv_i64 fp1 = tcg_temp_new_i64();
13200 TCGv_i64 fp2 = tcg_temp_new_i64();
13202 gen_load_fpr64(ctx, fp0, fs);
13203 gen_load_fpr64(ctx, fp1, ft);
13204 gen_load_fpr64(ctx, fp2, fr);
13205 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
13206 tcg_temp_free_i64(fp0);
13207 tcg_temp_free_i64(fp1);
13208 gen_store_fpr64(ctx, fp2, fd);
13209 tcg_temp_free_i64(fp2);
13211 break;
13212 case OPC_NMADD_S:
13213 check_cop1x(ctx);
13215 TCGv_i32 fp0 = tcg_temp_new_i32();
13216 TCGv_i32 fp1 = tcg_temp_new_i32();
13217 TCGv_i32 fp2 = tcg_temp_new_i32();
13219 gen_load_fpr32(ctx, fp0, fs);
13220 gen_load_fpr32(ctx, fp1, ft);
13221 gen_load_fpr32(ctx, fp2, fr);
13222 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
13223 tcg_temp_free_i32(fp0);
13224 tcg_temp_free_i32(fp1);
13225 gen_store_fpr32(ctx, fp2, fd);
13226 tcg_temp_free_i32(fp2);
13228 break;
13229 case OPC_NMADD_D:
13230 check_cop1x(ctx);
13231 check_cp1_registers(ctx, fd | fs | ft | fr);
13233 TCGv_i64 fp0 = tcg_temp_new_i64();
13234 TCGv_i64 fp1 = tcg_temp_new_i64();
13235 TCGv_i64 fp2 = tcg_temp_new_i64();
13237 gen_load_fpr64(ctx, fp0, fs);
13238 gen_load_fpr64(ctx, fp1, ft);
13239 gen_load_fpr64(ctx, fp2, fr);
13240 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
13241 tcg_temp_free_i64(fp0);
13242 tcg_temp_free_i64(fp1);
13243 gen_store_fpr64(ctx, fp2, fd);
13244 tcg_temp_free_i64(fp2);
13246 break;
13247 case OPC_NMADD_PS:
13248 check_ps(ctx);
13250 TCGv_i64 fp0 = tcg_temp_new_i64();
13251 TCGv_i64 fp1 = tcg_temp_new_i64();
13252 TCGv_i64 fp2 = tcg_temp_new_i64();
13254 gen_load_fpr64(ctx, fp0, fs);
13255 gen_load_fpr64(ctx, fp1, ft);
13256 gen_load_fpr64(ctx, fp2, fr);
13257 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
13258 tcg_temp_free_i64(fp0);
13259 tcg_temp_free_i64(fp1);
13260 gen_store_fpr64(ctx, fp2, fd);
13261 tcg_temp_free_i64(fp2);
13263 break;
13264 case OPC_NMSUB_S:
13265 check_cop1x(ctx);
13267 TCGv_i32 fp0 = tcg_temp_new_i32();
13268 TCGv_i32 fp1 = tcg_temp_new_i32();
13269 TCGv_i32 fp2 = tcg_temp_new_i32();
13271 gen_load_fpr32(ctx, fp0, fs);
13272 gen_load_fpr32(ctx, fp1, ft);
13273 gen_load_fpr32(ctx, fp2, fr);
13274 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
13275 tcg_temp_free_i32(fp0);
13276 tcg_temp_free_i32(fp1);
13277 gen_store_fpr32(ctx, fp2, fd);
13278 tcg_temp_free_i32(fp2);
13280 break;
13281 case OPC_NMSUB_D:
13282 check_cop1x(ctx);
13283 check_cp1_registers(ctx, fd | fs | ft | fr);
13285 TCGv_i64 fp0 = tcg_temp_new_i64();
13286 TCGv_i64 fp1 = tcg_temp_new_i64();
13287 TCGv_i64 fp2 = tcg_temp_new_i64();
13289 gen_load_fpr64(ctx, fp0, fs);
13290 gen_load_fpr64(ctx, fp1, ft);
13291 gen_load_fpr64(ctx, fp2, fr);
13292 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
13293 tcg_temp_free_i64(fp0);
13294 tcg_temp_free_i64(fp1);
13295 gen_store_fpr64(ctx, fp2, fd);
13296 tcg_temp_free_i64(fp2);
13298 break;
13299 case OPC_NMSUB_PS:
13300 check_ps(ctx);
13302 TCGv_i64 fp0 = tcg_temp_new_i64();
13303 TCGv_i64 fp1 = tcg_temp_new_i64();
13304 TCGv_i64 fp2 = tcg_temp_new_i64();
13306 gen_load_fpr64(ctx, fp0, fs);
13307 gen_load_fpr64(ctx, fp1, ft);
13308 gen_load_fpr64(ctx, fp2, fr);
13309 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
13310 tcg_temp_free_i64(fp0);
13311 tcg_temp_free_i64(fp1);
13312 gen_store_fpr64(ctx, fp2, fd);
13313 tcg_temp_free_i64(fp2);
13315 break;
13316 default:
13317 MIPS_INVAL("flt3_arith");
13318 gen_reserved_instruction(ctx);
13319 return;
13323 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
13325 TCGv t0;
13327 #if !defined(CONFIG_USER_ONLY)
13329 * The Linux kernel will emulate rdhwr if it's not supported natively.
13330 * Therefore only check the ISA in system mode.
13332 check_insn(ctx, ISA_MIPS_R2);
13333 #endif
13334 t0 = tcg_temp_new();
13336 switch (rd) {
13337 case 0:
13338 gen_helper_rdhwr_cpunum(t0, cpu_env);
13339 gen_store_gpr(t0, rt);
13340 break;
13341 case 1:
13342 gen_helper_rdhwr_synci_step(t0, cpu_env);
13343 gen_store_gpr(t0, rt);
13344 break;
13345 case 2:
13346 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
13347 gen_io_start();
13349 gen_helper_rdhwr_cc(t0, cpu_env);
13350 gen_store_gpr(t0, rt);
13352 * Break the TB to be able to take timer interrupts immediately
13353 * after reading count. DISAS_STOP isn't sufficient, we need to ensure
13354 * we break completely out of translated code.
13356 gen_save_pc(ctx->base.pc_next + 4);
13357 ctx->base.is_jmp = DISAS_EXIT;
13358 break;
13359 case 3:
13360 gen_helper_rdhwr_ccres(t0, cpu_env);
13361 gen_store_gpr(t0, rt);
13362 break;
13363 case 4:
13364 check_insn(ctx, ISA_MIPS_R6);
13365 if (sel != 0) {
13367 * Performance counter registers are not implemented other than
13368 * control register 0.
13370 generate_exception(ctx, EXCP_RI);
13372 gen_helper_rdhwr_performance(t0, cpu_env);
13373 gen_store_gpr(t0, rt);
13374 break;
13375 case 5:
13376 check_insn(ctx, ISA_MIPS_R6);
13377 gen_helper_rdhwr_xnp(t0, cpu_env);
13378 gen_store_gpr(t0, rt);
13379 break;
13380 case 29:
13381 #if defined(CONFIG_USER_ONLY)
13382 tcg_gen_ld_tl(t0, cpu_env,
13383 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
13384 gen_store_gpr(t0, rt);
13385 break;
13386 #else
13387 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
13388 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
13389 tcg_gen_ld_tl(t0, cpu_env,
13390 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
13391 gen_store_gpr(t0, rt);
13392 } else {
13393 gen_reserved_instruction(ctx);
13395 break;
13396 #endif
13397 default: /* Invalid */
13398 MIPS_INVAL("rdhwr");
13399 gen_reserved_instruction(ctx);
13400 break;
13402 tcg_temp_free(t0);
13405 static inline void clear_branch_hflags(DisasContext *ctx)
13407 ctx->hflags &= ~MIPS_HFLAG_BMASK;
13408 if (ctx->base.is_jmp == DISAS_NEXT) {
13409 save_cpu_state(ctx, 0);
13410 } else {
13412 * It is not safe to save ctx->hflags as hflags may be changed
13413 * in execution time by the instruction in delay / forbidden slot.
13415 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
13419 static void gen_branch(DisasContext *ctx, int insn_bytes)
13421 if (ctx->hflags & MIPS_HFLAG_BMASK) {
13422 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
13423 /* Branches completion */
13424 clear_branch_hflags(ctx);
13425 ctx->base.is_jmp = DISAS_NORETURN;
13426 /* FIXME: Need to clear can_do_io. */
13427 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
13428 case MIPS_HFLAG_FBNSLOT:
13429 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
13430 break;
13431 case MIPS_HFLAG_B:
13432 /* unconditional branch */
13433 if (proc_hflags & MIPS_HFLAG_BX) {
13434 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
13436 gen_goto_tb(ctx, 0, ctx->btarget);
13437 break;
13438 case MIPS_HFLAG_BL:
13439 /* blikely taken case */
13440 gen_goto_tb(ctx, 0, ctx->btarget);
13441 break;
13442 case MIPS_HFLAG_BC:
13443 /* Conditional branch */
13445 TCGLabel *l1 = gen_new_label();
13447 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
13448 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
13449 gen_set_label(l1);
13450 gen_goto_tb(ctx, 0, ctx->btarget);
13452 break;
13453 case MIPS_HFLAG_BR:
13454 /* unconditional branch to register */
13455 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
13456 TCGv t0 = tcg_temp_new();
13457 TCGv_i32 t1 = tcg_temp_new_i32();
13459 tcg_gen_andi_tl(t0, btarget, 0x1);
13460 tcg_gen_trunc_tl_i32(t1, t0);
13461 tcg_temp_free(t0);
13462 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
13463 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
13464 tcg_gen_or_i32(hflags, hflags, t1);
13465 tcg_temp_free_i32(t1);
13467 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
13468 } else {
13469 tcg_gen_mov_tl(cpu_PC, btarget);
13471 if (ctx->base.singlestep_enabled) {
13472 save_cpu_state(ctx, 0);
13473 gen_helper_raise_exception_debug(cpu_env);
13475 tcg_gen_lookup_and_goto_ptr();
13476 break;
13477 default:
13478 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
13479 abort();
13484 /* Compact Branches */
13485 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
13486 int rs, int rt, int32_t offset)
13488 int bcond_compute = 0;
13489 TCGv t0 = tcg_temp_new();
13490 TCGv t1 = tcg_temp_new();
13491 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
13493 if (ctx->hflags & MIPS_HFLAG_BMASK) {
13494 #ifdef MIPS_DEBUG_DISAS
13495 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
13496 "\n", ctx->base.pc_next);
13497 #endif
13498 gen_reserved_instruction(ctx);
13499 goto out;
13502 /* Load needed operands and calculate btarget */
13503 switch (opc) {
13504 /* compact branch */
13505 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13506 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13507 gen_load_gpr(t0, rs);
13508 gen_load_gpr(t1, rt);
13509 bcond_compute = 1;
13510 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13511 if (rs <= rt && rs == 0) {
13512 /* OPC_BEQZALC, OPC_BNEZALC */
13513 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13515 break;
13516 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13517 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13518 gen_load_gpr(t0, rs);
13519 gen_load_gpr(t1, rt);
13520 bcond_compute = 1;
13521 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13522 break;
13523 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13524 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13525 if (rs == 0 || rs == rt) {
13526 /* OPC_BLEZALC, OPC_BGEZALC */
13527 /* OPC_BGTZALC, OPC_BLTZALC */
13528 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13530 gen_load_gpr(t0, rs);
13531 gen_load_gpr(t1, rt);
13532 bcond_compute = 1;
13533 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13534 break;
13535 case OPC_BC:
13536 case OPC_BALC:
13537 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13538 break;
13539 case OPC_BEQZC:
13540 case OPC_BNEZC:
13541 if (rs != 0) {
13542 /* OPC_BEQZC, OPC_BNEZC */
13543 gen_load_gpr(t0, rs);
13544 bcond_compute = 1;
13545 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13546 } else {
13547 /* OPC_JIC, OPC_JIALC */
13548 TCGv tbase = tcg_temp_new();
13549 TCGv toffset = tcg_temp_new();
13551 gen_load_gpr(tbase, rt);
13552 tcg_gen_movi_tl(toffset, offset);
13553 gen_op_addr_add(ctx, btarget, tbase, toffset);
13554 tcg_temp_free(tbase);
13555 tcg_temp_free(toffset);
13557 break;
13558 default:
13559 MIPS_INVAL("Compact branch/jump");
13560 gen_reserved_instruction(ctx);
13561 goto out;
13564 if (bcond_compute == 0) {
13565 /* Uncoditional compact branch */
13566 switch (opc) {
13567 case OPC_JIALC:
13568 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13569 /* Fallthrough */
13570 case OPC_JIC:
13571 ctx->hflags |= MIPS_HFLAG_BR;
13572 break;
13573 case OPC_BALC:
13574 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13575 /* Fallthrough */
13576 case OPC_BC:
13577 ctx->hflags |= MIPS_HFLAG_B;
13578 break;
13579 default:
13580 MIPS_INVAL("Compact branch/jump");
13581 gen_reserved_instruction(ctx);
13582 goto out;
13585 /* Generating branch here as compact branches don't have delay slot */
13586 gen_branch(ctx, 4);
13587 } else {
13588 /* Conditional compact branch */
13589 TCGLabel *fs = gen_new_label();
13590 save_cpu_state(ctx, 0);
13592 switch (opc) {
13593 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13594 if (rs == 0 && rt != 0) {
13595 /* OPC_BLEZALC */
13596 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13597 } else if (rs != 0 && rt != 0 && rs == rt) {
13598 /* OPC_BGEZALC */
13599 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13600 } else {
13601 /* OPC_BGEUC */
13602 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
13604 break;
13605 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13606 if (rs == 0 && rt != 0) {
13607 /* OPC_BGTZALC */
13608 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13609 } else if (rs != 0 && rt != 0 && rs == rt) {
13610 /* OPC_BLTZALC */
13611 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13612 } else {
13613 /* OPC_BLTUC */
13614 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
13616 break;
13617 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13618 if (rs == 0 && rt != 0) {
13619 /* OPC_BLEZC */
13620 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13621 } else if (rs != 0 && rt != 0 && rs == rt) {
13622 /* OPC_BGEZC */
13623 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13624 } else {
13625 /* OPC_BGEC */
13626 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
13628 break;
13629 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13630 if (rs == 0 && rt != 0) {
13631 /* OPC_BGTZC */
13632 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13633 } else if (rs != 0 && rt != 0 && rs == rt) {
13634 /* OPC_BLTZC */
13635 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13636 } else {
13637 /* OPC_BLTC */
13638 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
13640 break;
13641 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13642 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13643 if (rs >= rt) {
13644 /* OPC_BOVC, OPC_BNVC */
13645 TCGv t2 = tcg_temp_new();
13646 TCGv t3 = tcg_temp_new();
13647 TCGv t4 = tcg_temp_new();
13648 TCGv input_overflow = tcg_temp_new();
13650 gen_load_gpr(t0, rs);
13651 gen_load_gpr(t1, rt);
13652 tcg_gen_ext32s_tl(t2, t0);
13653 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
13654 tcg_gen_ext32s_tl(t3, t1);
13655 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
13656 tcg_gen_or_tl(input_overflow, input_overflow, t4);
13658 tcg_gen_add_tl(t4, t2, t3);
13659 tcg_gen_ext32s_tl(t4, t4);
13660 tcg_gen_xor_tl(t2, t2, t3);
13661 tcg_gen_xor_tl(t3, t4, t3);
13662 tcg_gen_andc_tl(t2, t3, t2);
13663 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
13664 tcg_gen_or_tl(t4, t4, input_overflow);
13665 if (opc == OPC_BOVC) {
13666 /* OPC_BOVC */
13667 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
13668 } else {
13669 /* OPC_BNVC */
13670 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
13672 tcg_temp_free(input_overflow);
13673 tcg_temp_free(t4);
13674 tcg_temp_free(t3);
13675 tcg_temp_free(t2);
13676 } else if (rs < rt && rs == 0) {
13677 /* OPC_BEQZALC, OPC_BNEZALC */
13678 if (opc == OPC_BEQZALC) {
13679 /* OPC_BEQZALC */
13680 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
13681 } else {
13682 /* OPC_BNEZALC */
13683 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
13685 } else {
13686 /* OPC_BEQC, OPC_BNEC */
13687 if (opc == OPC_BEQC) {
13688 /* OPC_BEQC */
13689 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
13690 } else {
13691 /* OPC_BNEC */
13692 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
13695 break;
13696 case OPC_BEQZC:
13697 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
13698 break;
13699 case OPC_BNEZC:
13700 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
13701 break;
13702 default:
13703 MIPS_INVAL("Compact conditional branch/jump");
13704 gen_reserved_instruction(ctx);
13705 goto out;
13708 /* Generating branch here as compact branches don't have delay slot */
13709 gen_goto_tb(ctx, 1, ctx->btarget);
13710 gen_set_label(fs);
13712 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
13715 out:
13716 tcg_temp_free(t0);
13717 tcg_temp_free(t1);
13720 /* ISA extensions (ASEs) */
13721 /* MIPS16 extension to MIPS32 */
13723 /* MIPS16 major opcodes */
13724 enum {
13725 M16_OPC_ADDIUSP = 0x00,
13726 M16_OPC_ADDIUPC = 0x01,
13727 M16_OPC_B = 0x02,
13728 M16_OPC_JAL = 0x03,
13729 M16_OPC_BEQZ = 0x04,
13730 M16_OPC_BNEQZ = 0x05,
13731 M16_OPC_SHIFT = 0x06,
13732 M16_OPC_LD = 0x07,
13733 M16_OPC_RRIA = 0x08,
13734 M16_OPC_ADDIU8 = 0x09,
13735 M16_OPC_SLTI = 0x0a,
13736 M16_OPC_SLTIU = 0x0b,
13737 M16_OPC_I8 = 0x0c,
13738 M16_OPC_LI = 0x0d,
13739 M16_OPC_CMPI = 0x0e,
13740 M16_OPC_SD = 0x0f,
13741 M16_OPC_LB = 0x10,
13742 M16_OPC_LH = 0x11,
13743 M16_OPC_LWSP = 0x12,
13744 M16_OPC_LW = 0x13,
13745 M16_OPC_LBU = 0x14,
13746 M16_OPC_LHU = 0x15,
13747 M16_OPC_LWPC = 0x16,
13748 M16_OPC_LWU = 0x17,
13749 M16_OPC_SB = 0x18,
13750 M16_OPC_SH = 0x19,
13751 M16_OPC_SWSP = 0x1a,
13752 M16_OPC_SW = 0x1b,
13753 M16_OPC_RRR = 0x1c,
13754 M16_OPC_RR = 0x1d,
13755 M16_OPC_EXTEND = 0x1e,
13756 M16_OPC_I64 = 0x1f
13759 /* I8 funct field */
13760 enum {
13761 I8_BTEQZ = 0x0,
13762 I8_BTNEZ = 0x1,
13763 I8_SWRASP = 0x2,
13764 I8_ADJSP = 0x3,
13765 I8_SVRS = 0x4,
13766 I8_MOV32R = 0x5,
13767 I8_MOVR32 = 0x7
13770 /* RRR f field */
13771 enum {
13772 RRR_DADDU = 0x0,
13773 RRR_ADDU = 0x1,
13774 RRR_DSUBU = 0x2,
13775 RRR_SUBU = 0x3
13778 /* RR funct field */
13779 enum {
13780 RR_JR = 0x00,
13781 RR_SDBBP = 0x01,
13782 RR_SLT = 0x02,
13783 RR_SLTU = 0x03,
13784 RR_SLLV = 0x04,
13785 RR_BREAK = 0x05,
13786 RR_SRLV = 0x06,
13787 RR_SRAV = 0x07,
13788 RR_DSRL = 0x08,
13789 RR_CMP = 0x0a,
13790 RR_NEG = 0x0b,
13791 RR_AND = 0x0c,
13792 RR_OR = 0x0d,
13793 RR_XOR = 0x0e,
13794 RR_NOT = 0x0f,
13795 RR_MFHI = 0x10,
13796 RR_CNVT = 0x11,
13797 RR_MFLO = 0x12,
13798 RR_DSRA = 0x13,
13799 RR_DSLLV = 0x14,
13800 RR_DSRLV = 0x16,
13801 RR_DSRAV = 0x17,
13802 RR_MULT = 0x18,
13803 RR_MULTU = 0x19,
13804 RR_DIV = 0x1a,
13805 RR_DIVU = 0x1b,
13806 RR_DMULT = 0x1c,
13807 RR_DMULTU = 0x1d,
13808 RR_DDIV = 0x1e,
13809 RR_DDIVU = 0x1f
13812 /* I64 funct field */
13813 enum {
13814 I64_LDSP = 0x0,
13815 I64_SDSP = 0x1,
13816 I64_SDRASP = 0x2,
13817 I64_DADJSP = 0x3,
13818 I64_LDPC = 0x4,
13819 I64_DADDIU5 = 0x5,
13820 I64_DADDIUPC = 0x6,
13821 I64_DADDIUSP = 0x7
13824 /* RR ry field for CNVT */
13825 enum {
13826 RR_RY_CNVT_ZEB = 0x0,
13827 RR_RY_CNVT_ZEH = 0x1,
13828 RR_RY_CNVT_ZEW = 0x2,
13829 RR_RY_CNVT_SEB = 0x4,
13830 RR_RY_CNVT_SEH = 0x5,
13831 RR_RY_CNVT_SEW = 0x6,
13834 static int xlat(int r)
13836 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
13838 return map[r];
13841 static void gen_mips16_save(DisasContext *ctx,
13842 int xsregs, int aregs,
13843 int do_ra, int do_s0, int do_s1,
13844 int framesize)
13846 TCGv t0 = tcg_temp_new();
13847 TCGv t1 = tcg_temp_new();
13848 TCGv t2 = tcg_temp_new();
13849 int args, astatic;
13851 switch (aregs) {
13852 case 0:
13853 case 1:
13854 case 2:
13855 case 3:
13856 case 11:
13857 args = 0;
13858 break;
13859 case 4:
13860 case 5:
13861 case 6:
13862 case 7:
13863 args = 1;
13864 break;
13865 case 8:
13866 case 9:
13867 case 10:
13868 args = 2;
13869 break;
13870 case 12:
13871 case 13:
13872 args = 3;
13873 break;
13874 case 14:
13875 args = 4;
13876 break;
13877 default:
13878 gen_reserved_instruction(ctx);
13879 return;
13882 switch (args) {
13883 case 4:
13884 gen_base_offset_addr(ctx, t0, 29, 12);
13885 gen_load_gpr(t1, 7);
13886 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13887 /* Fall through */
13888 case 3:
13889 gen_base_offset_addr(ctx, t0, 29, 8);
13890 gen_load_gpr(t1, 6);
13891 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13892 /* Fall through */
13893 case 2:
13894 gen_base_offset_addr(ctx, t0, 29, 4);
13895 gen_load_gpr(t1, 5);
13896 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13897 /* Fall through */
13898 case 1:
13899 gen_base_offset_addr(ctx, t0, 29, 0);
13900 gen_load_gpr(t1, 4);
13901 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13904 gen_load_gpr(t0, 29);
13906 #define DECR_AND_STORE(reg) do { \
13907 tcg_gen_movi_tl(t2, -4); \
13908 gen_op_addr_add(ctx, t0, t0, t2); \
13909 gen_load_gpr(t1, reg); \
13910 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
13911 } while (0)
13913 if (do_ra) {
13914 DECR_AND_STORE(31);
13917 switch (xsregs) {
13918 case 7:
13919 DECR_AND_STORE(30);
13920 /* Fall through */
13921 case 6:
13922 DECR_AND_STORE(23);
13923 /* Fall through */
13924 case 5:
13925 DECR_AND_STORE(22);
13926 /* Fall through */
13927 case 4:
13928 DECR_AND_STORE(21);
13929 /* Fall through */
13930 case 3:
13931 DECR_AND_STORE(20);
13932 /* Fall through */
13933 case 2:
13934 DECR_AND_STORE(19);
13935 /* Fall through */
13936 case 1:
13937 DECR_AND_STORE(18);
13940 if (do_s1) {
13941 DECR_AND_STORE(17);
13943 if (do_s0) {
13944 DECR_AND_STORE(16);
13947 switch (aregs) {
13948 case 0:
13949 case 4:
13950 case 8:
13951 case 12:
13952 case 14:
13953 astatic = 0;
13954 break;
13955 case 1:
13956 case 5:
13957 case 9:
13958 case 13:
13959 astatic = 1;
13960 break;
13961 case 2:
13962 case 6:
13963 case 10:
13964 astatic = 2;
13965 break;
13966 case 3:
13967 case 7:
13968 astatic = 3;
13969 break;
13970 case 11:
13971 astatic = 4;
13972 break;
13973 default:
13974 gen_reserved_instruction(ctx);
13975 return;
13978 if (astatic > 0) {
13979 DECR_AND_STORE(7);
13980 if (astatic > 1) {
13981 DECR_AND_STORE(6);
13982 if (astatic > 2) {
13983 DECR_AND_STORE(5);
13984 if (astatic > 3) {
13985 DECR_AND_STORE(4);
13990 #undef DECR_AND_STORE
13992 tcg_gen_movi_tl(t2, -framesize);
13993 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13994 tcg_temp_free(t0);
13995 tcg_temp_free(t1);
13996 tcg_temp_free(t2);
13999 static void gen_mips16_restore(DisasContext *ctx,
14000 int xsregs, int aregs,
14001 int do_ra, int do_s0, int do_s1,
14002 int framesize)
14004 int astatic;
14005 TCGv t0 = tcg_temp_new();
14006 TCGv t1 = tcg_temp_new();
14007 TCGv t2 = tcg_temp_new();
14009 tcg_gen_movi_tl(t2, framesize);
14010 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
14012 #define DECR_AND_LOAD(reg) do { \
14013 tcg_gen_movi_tl(t2, -4); \
14014 gen_op_addr_add(ctx, t0, t0, t2); \
14015 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
14016 gen_store_gpr(t1, reg); \
14017 } while (0)
14019 if (do_ra) {
14020 DECR_AND_LOAD(31);
14023 switch (xsregs) {
14024 case 7:
14025 DECR_AND_LOAD(30);
14026 /* Fall through */
14027 case 6:
14028 DECR_AND_LOAD(23);
14029 /* Fall through */
14030 case 5:
14031 DECR_AND_LOAD(22);
14032 /* Fall through */
14033 case 4:
14034 DECR_AND_LOAD(21);
14035 /* Fall through */
14036 case 3:
14037 DECR_AND_LOAD(20);
14038 /* Fall through */
14039 case 2:
14040 DECR_AND_LOAD(19);
14041 /* Fall through */
14042 case 1:
14043 DECR_AND_LOAD(18);
14046 if (do_s1) {
14047 DECR_AND_LOAD(17);
14049 if (do_s0) {
14050 DECR_AND_LOAD(16);
14053 switch (aregs) {
14054 case 0:
14055 case 4:
14056 case 8:
14057 case 12:
14058 case 14:
14059 astatic = 0;
14060 break;
14061 case 1:
14062 case 5:
14063 case 9:
14064 case 13:
14065 astatic = 1;
14066 break;
14067 case 2:
14068 case 6:
14069 case 10:
14070 astatic = 2;
14071 break;
14072 case 3:
14073 case 7:
14074 astatic = 3;
14075 break;
14076 case 11:
14077 astatic = 4;
14078 break;
14079 default:
14080 gen_reserved_instruction(ctx);
14081 return;
14084 if (astatic > 0) {
14085 DECR_AND_LOAD(7);
14086 if (astatic > 1) {
14087 DECR_AND_LOAD(6);
14088 if (astatic > 2) {
14089 DECR_AND_LOAD(5);
14090 if (astatic > 3) {
14091 DECR_AND_LOAD(4);
14096 #undef DECR_AND_LOAD
14098 tcg_gen_movi_tl(t2, framesize);
14099 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
14100 tcg_temp_free(t0);
14101 tcg_temp_free(t1);
14102 tcg_temp_free(t2);
14105 static void gen_addiupc(DisasContext *ctx, int rx, int imm,
14106 int is_64_bit, int extended)
14108 TCGv t0;
14110 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
14111 gen_reserved_instruction(ctx);
14112 return;
14115 t0 = tcg_temp_new();
14117 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
14118 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
14119 if (!is_64_bit) {
14120 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14123 tcg_temp_free(t0);
14126 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
14127 int16_t offset)
14129 TCGv_i32 t0 = tcg_const_i32(op);
14130 TCGv t1 = tcg_temp_new();
14131 gen_base_offset_addr(ctx, t1, base, offset);
14132 gen_helper_cache(cpu_env, t1, t0);
14135 #if defined(TARGET_MIPS64)
14136 static void decode_i64_mips16(DisasContext *ctx,
14137 int ry, int funct, int16_t offset,
14138 int extended)
14140 switch (funct) {
14141 case I64_LDSP:
14142 check_insn(ctx, ISA_MIPS3);
14143 check_mips_64(ctx);
14144 offset = extended ? offset : offset << 3;
14145 gen_ld(ctx, OPC_LD, ry, 29, offset);
14146 break;
14147 case I64_SDSP:
14148 check_insn(ctx, ISA_MIPS3);
14149 check_mips_64(ctx);
14150 offset = extended ? offset : offset << 3;
14151 gen_st(ctx, OPC_SD, ry, 29, offset);
14152 break;
14153 case I64_SDRASP:
14154 check_insn(ctx, ISA_MIPS3);
14155 check_mips_64(ctx);
14156 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
14157 gen_st(ctx, OPC_SD, 31, 29, offset);
14158 break;
14159 case I64_DADJSP:
14160 check_insn(ctx, ISA_MIPS3);
14161 check_mips_64(ctx);
14162 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
14163 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
14164 break;
14165 case I64_LDPC:
14166 check_insn(ctx, ISA_MIPS3);
14167 check_mips_64(ctx);
14168 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
14169 gen_reserved_instruction(ctx);
14170 } else {
14171 offset = extended ? offset : offset << 3;
14172 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
14174 break;
14175 case I64_DADDIU5:
14176 check_insn(ctx, ISA_MIPS3);
14177 check_mips_64(ctx);
14178 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
14179 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
14180 break;
14181 case I64_DADDIUPC:
14182 check_insn(ctx, ISA_MIPS3);
14183 check_mips_64(ctx);
14184 offset = extended ? offset : offset << 2;
14185 gen_addiupc(ctx, ry, offset, 1, extended);
14186 break;
14187 case I64_DADDIUSP:
14188 check_insn(ctx, ISA_MIPS3);
14189 check_mips_64(ctx);
14190 offset = extended ? offset : offset << 2;
14191 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
14192 break;
14195 #endif
14197 static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
14199 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
14200 int op, rx, ry, funct, sa;
14201 int16_t imm, offset;
14203 ctx->opcode = (ctx->opcode << 16) | extend;
14204 op = (ctx->opcode >> 11) & 0x1f;
14205 sa = (ctx->opcode >> 22) & 0x1f;
14206 funct = (ctx->opcode >> 8) & 0x7;
14207 rx = xlat((ctx->opcode >> 8) & 0x7);
14208 ry = xlat((ctx->opcode >> 5) & 0x7);
14209 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
14210 | ((ctx->opcode >> 21) & 0x3f) << 5
14211 | (ctx->opcode & 0x1f));
14214 * The extended opcodes cleverly reuse the opcodes from their 16-bit
14215 * counterparts.
14217 switch (op) {
14218 case M16_OPC_ADDIUSP:
14219 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
14220 break;
14221 case M16_OPC_ADDIUPC:
14222 gen_addiupc(ctx, rx, imm, 0, 1);
14223 break;
14224 case M16_OPC_B:
14225 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
14226 /* No delay slot, so just process as a normal instruction */
14227 break;
14228 case M16_OPC_BEQZ:
14229 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
14230 /* No delay slot, so just process as a normal instruction */
14231 break;
14232 case M16_OPC_BNEQZ:
14233 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
14234 /* No delay slot, so just process as a normal instruction */
14235 break;
14236 case M16_OPC_SHIFT:
14237 switch (ctx->opcode & 0x3) {
14238 case 0x0:
14239 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
14240 break;
14241 case 0x1:
14242 #if defined(TARGET_MIPS64)
14243 check_mips_64(ctx);
14244 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
14245 #else
14246 gen_reserved_instruction(ctx);
14247 #endif
14248 break;
14249 case 0x2:
14250 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
14251 break;
14252 case 0x3:
14253 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
14254 break;
14256 break;
14257 #if defined(TARGET_MIPS64)
14258 case M16_OPC_LD:
14259 check_insn(ctx, ISA_MIPS3);
14260 check_mips_64(ctx);
14261 gen_ld(ctx, OPC_LD, ry, rx, offset);
14262 break;
14263 #endif
14264 case M16_OPC_RRIA:
14265 imm = ctx->opcode & 0xf;
14266 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
14267 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
14268 imm = (int16_t) (imm << 1) >> 1;
14269 if ((ctx->opcode >> 4) & 0x1) {
14270 #if defined(TARGET_MIPS64)
14271 check_mips_64(ctx);
14272 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
14273 #else
14274 gen_reserved_instruction(ctx);
14275 #endif
14276 } else {
14277 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
14279 break;
14280 case M16_OPC_ADDIU8:
14281 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
14282 break;
14283 case M16_OPC_SLTI:
14284 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
14285 break;
14286 case M16_OPC_SLTIU:
14287 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
14288 break;
14289 case M16_OPC_I8:
14290 switch (funct) {
14291 case I8_BTEQZ:
14292 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
14293 break;
14294 case I8_BTNEZ:
14295 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
14296 break;
14297 case I8_SWRASP:
14298 gen_st(ctx, OPC_SW, 31, 29, imm);
14299 break;
14300 case I8_ADJSP:
14301 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
14302 break;
14303 case I8_SVRS:
14304 check_insn(ctx, ISA_MIPS_R1);
14306 int xsregs = (ctx->opcode >> 24) & 0x7;
14307 int aregs = (ctx->opcode >> 16) & 0xf;
14308 int do_ra = (ctx->opcode >> 6) & 0x1;
14309 int do_s0 = (ctx->opcode >> 5) & 0x1;
14310 int do_s1 = (ctx->opcode >> 4) & 0x1;
14311 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
14312 | (ctx->opcode & 0xf)) << 3;
14314 if (ctx->opcode & (1 << 7)) {
14315 gen_mips16_save(ctx, xsregs, aregs,
14316 do_ra, do_s0, do_s1,
14317 framesize);
14318 } else {
14319 gen_mips16_restore(ctx, xsregs, aregs,
14320 do_ra, do_s0, do_s1,
14321 framesize);
14324 break;
14325 default:
14326 gen_reserved_instruction(ctx);
14327 break;
14329 break;
14330 case M16_OPC_LI:
14331 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
14332 break;
14333 case M16_OPC_CMPI:
14334 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
14335 break;
14336 #if defined(TARGET_MIPS64)
14337 case M16_OPC_SD:
14338 check_insn(ctx, ISA_MIPS3);
14339 check_mips_64(ctx);
14340 gen_st(ctx, OPC_SD, ry, rx, offset);
14341 break;
14342 #endif
14343 case M16_OPC_LB:
14344 gen_ld(ctx, OPC_LB, ry, rx, offset);
14345 break;
14346 case M16_OPC_LH:
14347 gen_ld(ctx, OPC_LH, ry, rx, offset);
14348 break;
14349 case M16_OPC_LWSP:
14350 gen_ld(ctx, OPC_LW, rx, 29, offset);
14351 break;
14352 case M16_OPC_LW:
14353 gen_ld(ctx, OPC_LW, ry, rx, offset);
14354 break;
14355 case M16_OPC_LBU:
14356 gen_ld(ctx, OPC_LBU, ry, rx, offset);
14357 break;
14358 case M16_OPC_LHU:
14359 gen_ld(ctx, OPC_LHU, ry, rx, offset);
14360 break;
14361 case M16_OPC_LWPC:
14362 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
14363 break;
14364 #if defined(TARGET_MIPS64)
14365 case M16_OPC_LWU:
14366 check_insn(ctx, ISA_MIPS3);
14367 check_mips_64(ctx);
14368 gen_ld(ctx, OPC_LWU, ry, rx, offset);
14369 break;
14370 #endif
14371 case M16_OPC_SB:
14372 gen_st(ctx, OPC_SB, ry, rx, offset);
14373 break;
14374 case M16_OPC_SH:
14375 gen_st(ctx, OPC_SH, ry, rx, offset);
14376 break;
14377 case M16_OPC_SWSP:
14378 gen_st(ctx, OPC_SW, rx, 29, offset);
14379 break;
14380 case M16_OPC_SW:
14381 gen_st(ctx, OPC_SW, ry, rx, offset);
14382 break;
14383 #if defined(TARGET_MIPS64)
14384 case M16_OPC_I64:
14385 decode_i64_mips16(ctx, ry, funct, offset, 1);
14386 break;
14387 #endif
14388 default:
14389 gen_reserved_instruction(ctx);
14390 break;
14393 return 4;
14396 static inline bool is_uhi(int sdbbp_code)
14398 #ifdef CONFIG_USER_ONLY
14399 return false;
14400 #else
14401 return semihosting_enabled() && sdbbp_code == 1;
14402 #endif
14405 #ifdef CONFIG_USER_ONLY
14406 /* The above should dead-code away any calls to this..*/
14407 static inline void gen_helper_do_semihosting(void *env)
14409 g_assert_not_reached();
14411 #endif
14413 static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
14415 int rx, ry;
14416 int sa;
14417 int op, cnvt_op, op1, offset;
14418 int funct;
14419 int n_bytes;
14421 op = (ctx->opcode >> 11) & 0x1f;
14422 sa = (ctx->opcode >> 2) & 0x7;
14423 sa = sa == 0 ? 8 : sa;
14424 rx = xlat((ctx->opcode >> 8) & 0x7);
14425 cnvt_op = (ctx->opcode >> 5) & 0x7;
14426 ry = xlat((ctx->opcode >> 5) & 0x7);
14427 op1 = offset = ctx->opcode & 0x1f;
14429 n_bytes = 2;
14431 switch (op) {
14432 case M16_OPC_ADDIUSP:
14434 int16_t imm = ((uint8_t) ctx->opcode) << 2;
14436 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
14438 break;
14439 case M16_OPC_ADDIUPC:
14440 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
14441 break;
14442 case M16_OPC_B:
14443 offset = (ctx->opcode & 0x7ff) << 1;
14444 offset = (int16_t)(offset << 4) >> 4;
14445 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
14446 /* No delay slot, so just process as a normal instruction */
14447 break;
14448 case M16_OPC_JAL:
14449 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
14450 offset = (((ctx->opcode & 0x1f) << 21)
14451 | ((ctx->opcode >> 5) & 0x1f) << 16
14452 | offset) << 2;
14453 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
14454 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
14455 n_bytes = 4;
14456 break;
14457 case M16_OPC_BEQZ:
14458 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
14459 ((int8_t)ctx->opcode) << 1, 0);
14460 /* No delay slot, so just process as a normal instruction */
14461 break;
14462 case M16_OPC_BNEQZ:
14463 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
14464 ((int8_t)ctx->opcode) << 1, 0);
14465 /* No delay slot, so just process as a normal instruction */
14466 break;
14467 case M16_OPC_SHIFT:
14468 switch (ctx->opcode & 0x3) {
14469 case 0x0:
14470 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
14471 break;
14472 case 0x1:
14473 #if defined(TARGET_MIPS64)
14474 check_insn(ctx, ISA_MIPS3);
14475 check_mips_64(ctx);
14476 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
14477 #else
14478 gen_reserved_instruction(ctx);
14479 #endif
14480 break;
14481 case 0x2:
14482 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
14483 break;
14484 case 0x3:
14485 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
14486 break;
14488 break;
14489 #if defined(TARGET_MIPS64)
14490 case M16_OPC_LD:
14491 check_insn(ctx, ISA_MIPS3);
14492 check_mips_64(ctx);
14493 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
14494 break;
14495 #endif
14496 case M16_OPC_RRIA:
14498 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
14500 if ((ctx->opcode >> 4) & 1) {
14501 #if defined(TARGET_MIPS64)
14502 check_insn(ctx, ISA_MIPS3);
14503 check_mips_64(ctx);
14504 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
14505 #else
14506 gen_reserved_instruction(ctx);
14507 #endif
14508 } else {
14509 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
14512 break;
14513 case M16_OPC_ADDIU8:
14515 int16_t imm = (int8_t) ctx->opcode;
14517 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
14519 break;
14520 case M16_OPC_SLTI:
14522 int16_t imm = (uint8_t) ctx->opcode;
14523 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
14525 break;
14526 case M16_OPC_SLTIU:
14528 int16_t imm = (uint8_t) ctx->opcode;
14529 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
14531 break;
14532 case M16_OPC_I8:
14534 int reg32;
14536 funct = (ctx->opcode >> 8) & 0x7;
14537 switch (funct) {
14538 case I8_BTEQZ:
14539 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
14540 ((int8_t)ctx->opcode) << 1, 0);
14541 break;
14542 case I8_BTNEZ:
14543 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
14544 ((int8_t)ctx->opcode) << 1, 0);
14545 break;
14546 case I8_SWRASP:
14547 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
14548 break;
14549 case I8_ADJSP:
14550 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
14551 ((int8_t)ctx->opcode) << 3);
14552 break;
14553 case I8_SVRS:
14554 check_insn(ctx, ISA_MIPS_R1);
14556 int do_ra = ctx->opcode & (1 << 6);
14557 int do_s0 = ctx->opcode & (1 << 5);
14558 int do_s1 = ctx->opcode & (1 << 4);
14559 int framesize = ctx->opcode & 0xf;
14561 if (framesize == 0) {
14562 framesize = 128;
14563 } else {
14564 framesize = framesize << 3;
14567 if (ctx->opcode & (1 << 7)) {
14568 gen_mips16_save(ctx, 0, 0,
14569 do_ra, do_s0, do_s1, framesize);
14570 } else {
14571 gen_mips16_restore(ctx, 0, 0,
14572 do_ra, do_s0, do_s1, framesize);
14575 break;
14576 case I8_MOV32R:
14578 int rz = xlat(ctx->opcode & 0x7);
14580 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
14581 ((ctx->opcode >> 5) & 0x7);
14582 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
14584 break;
14585 case I8_MOVR32:
14586 reg32 = ctx->opcode & 0x1f;
14587 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
14588 break;
14589 default:
14590 gen_reserved_instruction(ctx);
14591 break;
14594 break;
14595 case M16_OPC_LI:
14597 int16_t imm = (uint8_t) ctx->opcode;
14599 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
14601 break;
14602 case M16_OPC_CMPI:
14604 int16_t imm = (uint8_t) ctx->opcode;
14605 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
14607 break;
14608 #if defined(TARGET_MIPS64)
14609 case M16_OPC_SD:
14610 check_insn(ctx, ISA_MIPS3);
14611 check_mips_64(ctx);
14612 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
14613 break;
14614 #endif
14615 case M16_OPC_LB:
14616 gen_ld(ctx, OPC_LB, ry, rx, offset);
14617 break;
14618 case M16_OPC_LH:
14619 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
14620 break;
14621 case M16_OPC_LWSP:
14622 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14623 break;
14624 case M16_OPC_LW:
14625 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
14626 break;
14627 case M16_OPC_LBU:
14628 gen_ld(ctx, OPC_LBU, ry, rx, offset);
14629 break;
14630 case M16_OPC_LHU:
14631 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
14632 break;
14633 case M16_OPC_LWPC:
14634 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
14635 break;
14636 #if defined(TARGET_MIPS64)
14637 case M16_OPC_LWU:
14638 check_insn(ctx, ISA_MIPS3);
14639 check_mips_64(ctx);
14640 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
14641 break;
14642 #endif
14643 case M16_OPC_SB:
14644 gen_st(ctx, OPC_SB, ry, rx, offset);
14645 break;
14646 case M16_OPC_SH:
14647 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
14648 break;
14649 case M16_OPC_SWSP:
14650 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14651 break;
14652 case M16_OPC_SW:
14653 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
14654 break;
14655 case M16_OPC_RRR:
14657 int rz = xlat((ctx->opcode >> 2) & 0x7);
14658 int mips32_op;
14660 switch (ctx->opcode & 0x3) {
14661 case RRR_ADDU:
14662 mips32_op = OPC_ADDU;
14663 break;
14664 case RRR_SUBU:
14665 mips32_op = OPC_SUBU;
14666 break;
14667 #if defined(TARGET_MIPS64)
14668 case RRR_DADDU:
14669 mips32_op = OPC_DADDU;
14670 check_insn(ctx, ISA_MIPS3);
14671 check_mips_64(ctx);
14672 break;
14673 case RRR_DSUBU:
14674 mips32_op = OPC_DSUBU;
14675 check_insn(ctx, ISA_MIPS3);
14676 check_mips_64(ctx);
14677 break;
14678 #endif
14679 default:
14680 gen_reserved_instruction(ctx);
14681 goto done;
14684 gen_arith(ctx, mips32_op, rz, rx, ry);
14685 done:
14688 break;
14689 case M16_OPC_RR:
14690 switch (op1) {
14691 case RR_JR:
14693 int nd = (ctx->opcode >> 7) & 0x1;
14694 int link = (ctx->opcode >> 6) & 0x1;
14695 int ra = (ctx->opcode >> 5) & 0x1;
14697 if (nd) {
14698 check_insn(ctx, ISA_MIPS_R1);
14701 if (link) {
14702 op = OPC_JALR;
14703 } else {
14704 op = OPC_JR;
14707 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
14708 (nd ? 0 : 2));
14710 break;
14711 case RR_SDBBP:
14712 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
14713 gen_helper_do_semihosting(cpu_env);
14714 } else {
14716 * XXX: not clear which exception should be raised
14717 * when in debug mode...
14719 check_insn(ctx, ISA_MIPS_R1);
14720 generate_exception_end(ctx, EXCP_DBp);
14722 break;
14723 case RR_SLT:
14724 gen_slt(ctx, OPC_SLT, 24, rx, ry);
14725 break;
14726 case RR_SLTU:
14727 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
14728 break;
14729 case RR_BREAK:
14730 generate_exception_end(ctx, EXCP_BREAK);
14731 break;
14732 case RR_SLLV:
14733 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
14734 break;
14735 case RR_SRLV:
14736 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
14737 break;
14738 case RR_SRAV:
14739 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
14740 break;
14741 #if defined(TARGET_MIPS64)
14742 case RR_DSRL:
14743 check_insn(ctx, ISA_MIPS3);
14744 check_mips_64(ctx);
14745 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
14746 break;
14747 #endif
14748 case RR_CMP:
14749 gen_logic(ctx, OPC_XOR, 24, rx, ry);
14750 break;
14751 case RR_NEG:
14752 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
14753 break;
14754 case RR_AND:
14755 gen_logic(ctx, OPC_AND, rx, rx, ry);
14756 break;
14757 case RR_OR:
14758 gen_logic(ctx, OPC_OR, rx, rx, ry);
14759 break;
14760 case RR_XOR:
14761 gen_logic(ctx, OPC_XOR, rx, rx, ry);
14762 break;
14763 case RR_NOT:
14764 gen_logic(ctx, OPC_NOR, rx, ry, 0);
14765 break;
14766 case RR_MFHI:
14767 gen_HILO(ctx, OPC_MFHI, 0, rx);
14768 break;
14769 case RR_CNVT:
14770 check_insn(ctx, ISA_MIPS_R1);
14771 switch (cnvt_op) {
14772 case RR_RY_CNVT_ZEB:
14773 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14774 break;
14775 case RR_RY_CNVT_ZEH:
14776 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14777 break;
14778 case RR_RY_CNVT_SEB:
14779 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14780 break;
14781 case RR_RY_CNVT_SEH:
14782 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14783 break;
14784 #if defined(TARGET_MIPS64)
14785 case RR_RY_CNVT_ZEW:
14786 check_insn(ctx, ISA_MIPS_R1);
14787 check_mips_64(ctx);
14788 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14789 break;
14790 case RR_RY_CNVT_SEW:
14791 check_insn(ctx, ISA_MIPS_R1);
14792 check_mips_64(ctx);
14793 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14794 break;
14795 #endif
14796 default:
14797 gen_reserved_instruction(ctx);
14798 break;
14800 break;
14801 case RR_MFLO:
14802 gen_HILO(ctx, OPC_MFLO, 0, rx);
14803 break;
14804 #if defined(TARGET_MIPS64)
14805 case RR_DSRA:
14806 check_insn(ctx, ISA_MIPS3);
14807 check_mips_64(ctx);
14808 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
14809 break;
14810 case RR_DSLLV:
14811 check_insn(ctx, ISA_MIPS3);
14812 check_mips_64(ctx);
14813 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
14814 break;
14815 case RR_DSRLV:
14816 check_insn(ctx, ISA_MIPS3);
14817 check_mips_64(ctx);
14818 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
14819 break;
14820 case RR_DSRAV:
14821 check_insn(ctx, ISA_MIPS3);
14822 check_mips_64(ctx);
14823 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
14824 break;
14825 #endif
14826 case RR_MULT:
14827 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
14828 break;
14829 case RR_MULTU:
14830 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
14831 break;
14832 case RR_DIV:
14833 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
14834 break;
14835 case RR_DIVU:
14836 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
14837 break;
14838 #if defined(TARGET_MIPS64)
14839 case RR_DMULT:
14840 check_insn(ctx, ISA_MIPS3);
14841 check_mips_64(ctx);
14842 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
14843 break;
14844 case RR_DMULTU:
14845 check_insn(ctx, ISA_MIPS3);
14846 check_mips_64(ctx);
14847 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
14848 break;
14849 case RR_DDIV:
14850 check_insn(ctx, ISA_MIPS3);
14851 check_mips_64(ctx);
14852 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
14853 break;
14854 case RR_DDIVU:
14855 check_insn(ctx, ISA_MIPS3);
14856 check_mips_64(ctx);
14857 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
14858 break;
14859 #endif
14860 default:
14861 gen_reserved_instruction(ctx);
14862 break;
14864 break;
14865 case M16_OPC_EXTEND:
14866 decode_extended_mips16_opc(env, ctx);
14867 n_bytes = 4;
14868 break;
14869 #if defined(TARGET_MIPS64)
14870 case M16_OPC_I64:
14871 funct = (ctx->opcode >> 8) & 0x7;
14872 decode_i64_mips16(ctx, ry, funct, offset, 0);
14873 break;
14874 #endif
14875 default:
14876 gen_reserved_instruction(ctx);
14877 break;
14880 return n_bytes;
14883 /* microMIPS extension to MIPS32/MIPS64 */
14886 * microMIPS32/microMIPS64 major opcodes
14888 * 1. MIPS Architecture for Programmers Volume II-B:
14889 * The microMIPS32 Instruction Set (Revision 3.05)
14891 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
14893 * 2. MIPS Architecture For Programmers Volume II-A:
14894 * The MIPS64 Instruction Set (Revision 3.51)
14897 enum {
14898 POOL32A = 0x00,
14899 POOL16A = 0x01,
14900 LBU16 = 0x02,
14901 MOVE16 = 0x03,
14902 ADDI32 = 0x04,
14903 R6_LUI = 0x04,
14904 AUI = 0x04,
14905 LBU32 = 0x05,
14906 SB32 = 0x06,
14907 LB32 = 0x07,
14909 POOL32B = 0x08,
14910 POOL16B = 0x09,
14911 LHU16 = 0x0a,
14912 ANDI16 = 0x0b,
14913 ADDIU32 = 0x0c,
14914 LHU32 = 0x0d,
14915 SH32 = 0x0e,
14916 LH32 = 0x0f,
14918 POOL32I = 0x10,
14919 POOL16C = 0x11,
14920 LWSP16 = 0x12,
14921 POOL16D = 0x13,
14922 ORI32 = 0x14,
14923 POOL32F = 0x15,
14924 POOL32S = 0x16, /* MIPS64 */
14925 DADDIU32 = 0x17, /* MIPS64 */
14927 POOL32C = 0x18,
14928 LWGP16 = 0x19,
14929 LW16 = 0x1a,
14930 POOL16E = 0x1b,
14931 XORI32 = 0x1c,
14932 JALS32 = 0x1d,
14933 BOVC = 0x1d,
14934 BEQC = 0x1d,
14935 BEQZALC = 0x1d,
14936 ADDIUPC = 0x1e,
14937 PCREL = 0x1e,
14938 BNVC = 0x1f,
14939 BNEC = 0x1f,
14940 BNEZALC = 0x1f,
14942 R6_BEQZC = 0x20,
14943 JIC = 0x20,
14944 POOL16F = 0x21,
14945 SB16 = 0x22,
14946 BEQZ16 = 0x23,
14947 BEQZC16 = 0x23,
14948 SLTI32 = 0x24,
14949 BEQ32 = 0x25,
14950 BC = 0x25,
14951 SWC132 = 0x26,
14952 LWC132 = 0x27,
14954 /* 0x29 is reserved */
14955 RES_29 = 0x29,
14956 R6_BNEZC = 0x28,
14957 JIALC = 0x28,
14958 SH16 = 0x2a,
14959 BNEZ16 = 0x2b,
14960 BNEZC16 = 0x2b,
14961 SLTIU32 = 0x2c,
14962 BNE32 = 0x2d,
14963 BALC = 0x2d,
14964 SDC132 = 0x2e,
14965 LDC132 = 0x2f,
14967 /* 0x31 is reserved */
14968 RES_31 = 0x31,
14969 BLEZALC = 0x30,
14970 BGEZALC = 0x30,
14971 BGEUC = 0x30,
14972 SWSP16 = 0x32,
14973 B16 = 0x33,
14974 BC16 = 0x33,
14975 ANDI32 = 0x34,
14976 J32 = 0x35,
14977 BGTZC = 0x35,
14978 BLTZC = 0x35,
14979 BLTC = 0x35,
14980 SD32 = 0x36, /* MIPS64 */
14981 LD32 = 0x37, /* MIPS64 */
14983 /* 0x39 is reserved */
14984 RES_39 = 0x39,
14985 BGTZALC = 0x38,
14986 BLTZALC = 0x38,
14987 BLTUC = 0x38,
14988 SW16 = 0x3a,
14989 LI16 = 0x3b,
14990 JALX32 = 0x3c,
14991 JAL32 = 0x3d,
14992 BLEZC = 0x3d,
14993 BGEZC = 0x3d,
14994 BGEC = 0x3d,
14995 SW32 = 0x3e,
14996 LW32 = 0x3f
14999 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
15000 enum {
15001 ADDIUPC_00 = 0x00,
15002 ADDIUPC_01 = 0x01,
15003 ADDIUPC_02 = 0x02,
15004 ADDIUPC_03 = 0x03,
15005 ADDIUPC_04 = 0x04,
15006 ADDIUPC_05 = 0x05,
15007 ADDIUPC_06 = 0x06,
15008 ADDIUPC_07 = 0x07,
15009 AUIPC = 0x1e,
15010 ALUIPC = 0x1f,
15011 LWPC_08 = 0x08,
15012 LWPC_09 = 0x09,
15013 LWPC_0A = 0x0A,
15014 LWPC_0B = 0x0B,
15015 LWPC_0C = 0x0C,
15016 LWPC_0D = 0x0D,
15017 LWPC_0E = 0x0E,
15018 LWPC_0F = 0x0F,
15021 /* POOL32A encoding of minor opcode field */
15023 enum {
15025 * These opcodes are distinguished only by bits 9..6; those bits are
15026 * what are recorded below.
15028 SLL32 = 0x0,
15029 SRL32 = 0x1,
15030 SRA = 0x2,
15031 ROTR = 0x3,
15032 SELEQZ = 0x5,
15033 SELNEZ = 0x6,
15034 R6_RDHWR = 0x7,
15036 SLLV = 0x0,
15037 SRLV = 0x1,
15038 SRAV = 0x2,
15039 ROTRV = 0x3,
15040 ADD = 0x4,
15041 ADDU32 = 0x5,
15042 SUB = 0x6,
15043 SUBU32 = 0x7,
15044 MUL = 0x8,
15045 AND = 0x9,
15046 OR32 = 0xa,
15047 NOR = 0xb,
15048 XOR32 = 0xc,
15049 SLT = 0xd,
15050 SLTU = 0xe,
15052 MOVN = 0x0,
15053 R6_MUL = 0x0,
15054 MOVZ = 0x1,
15055 MUH = 0x1,
15056 MULU = 0x2,
15057 MUHU = 0x3,
15058 LWXS = 0x4,
15059 R6_DIV = 0x4,
15060 MOD = 0x5,
15061 R6_DIVU = 0x6,
15062 MODU = 0x7,
15064 /* The following can be distinguished by their lower 6 bits. */
15065 BREAK32 = 0x07,
15066 INS = 0x0c,
15067 LSA = 0x0f,
15068 ALIGN = 0x1f,
15069 EXT = 0x2c,
15070 POOL32AXF = 0x3c,
15071 SIGRIE = 0x3f
15074 /* POOL32AXF encoding of minor opcode field extension */
15077 * 1. MIPS Architecture for Programmers Volume II-B:
15078 * The microMIPS32 Instruction Set (Revision 3.05)
15080 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
15082 * 2. MIPS Architecture for Programmers VolumeIV-e:
15083 * The MIPS DSP Application-Specific Extension
15084 * to the microMIPS32 Architecture (Revision 2.34)
15086 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
15089 enum {
15090 /* bits 11..6 */
15091 TEQ = 0x00,
15092 TGE = 0x08,
15093 TGEU = 0x10,
15094 TLT = 0x20,
15095 TLTU = 0x28,
15096 TNE = 0x30,
15098 MFC0 = 0x03,
15099 MTC0 = 0x0b,
15101 /* begin of microMIPS32 DSP */
15103 /* bits 13..12 for 0x01 */
15104 MFHI_ACC = 0x0,
15105 MFLO_ACC = 0x1,
15106 MTHI_ACC = 0x2,
15107 MTLO_ACC = 0x3,
15109 /* bits 13..12 for 0x2a */
15110 MADD_ACC = 0x0,
15111 MADDU_ACC = 0x1,
15112 MSUB_ACC = 0x2,
15113 MSUBU_ACC = 0x3,
15115 /* bits 13..12 for 0x32 */
15116 MULT_ACC = 0x0,
15117 MULTU_ACC = 0x1,
15119 /* end of microMIPS32 DSP */
15121 /* bits 15..12 for 0x2c */
15122 BITSWAP = 0x0,
15123 SEB = 0x2,
15124 SEH = 0x3,
15125 CLO = 0x4,
15126 CLZ = 0x5,
15127 RDHWR = 0x6,
15128 WSBH = 0x7,
15129 MULT = 0x8,
15130 MULTU = 0x9,
15131 DIV = 0xa,
15132 DIVU = 0xb,
15133 MADD = 0xc,
15134 MADDU = 0xd,
15135 MSUB = 0xe,
15136 MSUBU = 0xf,
15138 /* bits 15..12 for 0x34 */
15139 MFC2 = 0x4,
15140 MTC2 = 0x5,
15141 MFHC2 = 0x8,
15142 MTHC2 = 0x9,
15143 CFC2 = 0xc,
15144 CTC2 = 0xd,
15146 /* bits 15..12 for 0x3c */
15147 JALR = 0x0,
15148 JR = 0x0, /* alias */
15149 JALRC = 0x0,
15150 JRC = 0x0,
15151 JALR_HB = 0x1,
15152 JALRC_HB = 0x1,
15153 JALRS = 0x4,
15154 JALRS_HB = 0x5,
15156 /* bits 15..12 for 0x05 */
15157 RDPGPR = 0xe,
15158 WRPGPR = 0xf,
15160 /* bits 15..12 for 0x0d */
15161 TLBP = 0x0,
15162 TLBR = 0x1,
15163 TLBWI = 0x2,
15164 TLBWR = 0x3,
15165 TLBINV = 0x4,
15166 TLBINVF = 0x5,
15167 WAIT = 0x9,
15168 IRET = 0xd,
15169 DERET = 0xe,
15170 ERET = 0xf,
15172 /* bits 15..12 for 0x15 */
15173 DMT = 0x0,
15174 DVPE = 0x1,
15175 EMT = 0x2,
15176 EVPE = 0x3,
15178 /* bits 15..12 for 0x1d */
15179 DI = 0x4,
15180 EI = 0x5,
15182 /* bits 15..12 for 0x2d */
15183 SYNC = 0x6,
15184 SYSCALL = 0x8,
15185 SDBBP = 0xd,
15187 /* bits 15..12 for 0x35 */
15188 MFHI32 = 0x0,
15189 MFLO32 = 0x1,
15190 MTHI32 = 0x2,
15191 MTLO32 = 0x3,
15194 /* POOL32B encoding of minor opcode field (bits 15..12) */
15196 enum {
15197 LWC2 = 0x0,
15198 LWP = 0x1,
15199 LDP = 0x4,
15200 LWM32 = 0x5,
15201 CACHE = 0x6,
15202 LDM = 0x7,
15203 SWC2 = 0x8,
15204 SWP = 0x9,
15205 SDP = 0xc,
15206 SWM32 = 0xd,
15207 SDM = 0xf
15210 /* POOL32C encoding of minor opcode field (bits 15..12) */
15212 enum {
15213 LWL = 0x0,
15214 SWL = 0x8,
15215 LWR = 0x1,
15216 SWR = 0x9,
15217 PREF = 0x2,
15218 ST_EVA = 0xa,
15219 LL = 0x3,
15220 SC = 0xb,
15221 LDL = 0x4,
15222 SDL = 0xc,
15223 LDR = 0x5,
15224 SDR = 0xd,
15225 LD_EVA = 0x6,
15226 LWU = 0xe,
15227 LLD = 0x7,
15228 SCD = 0xf
15231 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
15233 enum {
15234 LBUE = 0x0,
15235 LHUE = 0x1,
15236 LWLE = 0x2,
15237 LWRE = 0x3,
15238 LBE = 0x4,
15239 LHE = 0x5,
15240 LLE = 0x6,
15241 LWE = 0x7,
15244 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
15246 enum {
15247 SWLE = 0x0,
15248 SWRE = 0x1,
15249 PREFE = 0x2,
15250 CACHEE = 0x3,
15251 SBE = 0x4,
15252 SHE = 0x5,
15253 SCE = 0x6,
15254 SWE = 0x7,
15257 /* POOL32F encoding of minor opcode field (bits 5..0) */
15259 enum {
15260 /* These are the bit 7..6 values */
15261 ADD_FMT = 0x0,
15263 SUB_FMT = 0x1,
15265 MUL_FMT = 0x2,
15267 DIV_FMT = 0x3,
15269 /* These are the bit 8..6 values */
15270 MOVN_FMT = 0x0,
15271 RSQRT2_FMT = 0x0,
15272 MOVF_FMT = 0x0,
15273 RINT_FMT = 0x0,
15274 SELNEZ_FMT = 0x0,
15276 MOVZ_FMT = 0x1,
15277 LWXC1 = 0x1,
15278 MOVT_FMT = 0x1,
15279 CLASS_FMT = 0x1,
15280 SELEQZ_FMT = 0x1,
15282 PLL_PS = 0x2,
15283 SWXC1 = 0x2,
15284 SEL_FMT = 0x2,
15286 PLU_PS = 0x3,
15287 LDXC1 = 0x3,
15289 MOVN_FMT_04 = 0x4,
15290 PUL_PS = 0x4,
15291 SDXC1 = 0x4,
15292 RECIP2_FMT = 0x4,
15294 MOVZ_FMT_05 = 0x05,
15295 PUU_PS = 0x5,
15296 LUXC1 = 0x5,
15298 CVT_PS_S = 0x6,
15299 SUXC1 = 0x6,
15300 ADDR_PS = 0x6,
15301 PREFX = 0x6,
15302 MADDF_FMT = 0x6,
15304 MULR_PS = 0x7,
15305 MSUBF_FMT = 0x7,
15307 MADD_S = 0x01,
15308 MADD_D = 0x09,
15309 MADD_PS = 0x11,
15310 ALNV_PS = 0x19,
15311 MSUB_S = 0x21,
15312 MSUB_D = 0x29,
15313 MSUB_PS = 0x31,
15315 NMADD_S = 0x02,
15316 NMADD_D = 0x0a,
15317 NMADD_PS = 0x12,
15318 NMSUB_S = 0x22,
15319 NMSUB_D = 0x2a,
15320 NMSUB_PS = 0x32,
15322 MIN_FMT = 0x3,
15323 MAX_FMT = 0xb,
15324 MINA_FMT = 0x23,
15325 MAXA_FMT = 0x2b,
15326 POOL32FXF = 0x3b,
15328 CABS_COND_FMT = 0x1c, /* MIPS3D */
15329 C_COND_FMT = 0x3c,
15331 CMP_CONDN_S = 0x5,
15332 CMP_CONDN_D = 0x15
15335 /* POOL32Fxf encoding of minor opcode extension field */
15337 enum {
15338 CVT_L = 0x04,
15339 RSQRT_FMT = 0x08,
15340 FLOOR_L = 0x0c,
15341 CVT_PW_PS = 0x1c,
15342 CVT_W = 0x24,
15343 SQRT_FMT = 0x28,
15344 FLOOR_W = 0x2c,
15345 CVT_PS_PW = 0x3c,
15346 CFC1 = 0x40,
15347 RECIP_FMT = 0x48,
15348 CEIL_L = 0x4c,
15349 CTC1 = 0x60,
15350 CEIL_W = 0x6c,
15351 MFC1 = 0x80,
15352 CVT_S_PL = 0x84,
15353 TRUNC_L = 0x8c,
15354 MTC1 = 0xa0,
15355 CVT_S_PU = 0xa4,
15356 TRUNC_W = 0xac,
15357 MFHC1 = 0xc0,
15358 ROUND_L = 0xcc,
15359 MTHC1 = 0xe0,
15360 ROUND_W = 0xec,
15362 MOV_FMT = 0x01,
15363 MOVF = 0x05,
15364 ABS_FMT = 0x0d,
15365 RSQRT1_FMT = 0x1d,
15366 MOVT = 0x25,
15367 NEG_FMT = 0x2d,
15368 CVT_D = 0x4d,
15369 RECIP1_FMT = 0x5d,
15370 CVT_S = 0x6d
15373 /* POOL32I encoding of minor opcode field (bits 25..21) */
15375 enum {
15376 BLTZ = 0x00,
15377 BLTZAL = 0x01,
15378 BGEZ = 0x02,
15379 BGEZAL = 0x03,
15380 BLEZ = 0x04,
15381 BNEZC = 0x05,
15382 BGTZ = 0x06,
15383 BEQZC = 0x07,
15384 TLTI = 0x08,
15385 BC1EQZC = 0x08,
15386 TGEI = 0x09,
15387 BC1NEZC = 0x09,
15388 TLTIU = 0x0a,
15389 BC2EQZC = 0x0a,
15390 TGEIU = 0x0b,
15391 BC2NEZC = 0x0a,
15392 TNEI = 0x0c,
15393 R6_SYNCI = 0x0c,
15394 LUI = 0x0d,
15395 TEQI = 0x0e,
15396 SYNCI = 0x10,
15397 BLTZALS = 0x11,
15398 BGEZALS = 0x13,
15399 BC2F = 0x14,
15400 BC2T = 0x15,
15401 BPOSGE64 = 0x1a,
15402 BPOSGE32 = 0x1b,
15403 /* These overlap and are distinguished by bit16 of the instruction */
15404 BC1F = 0x1c,
15405 BC1T = 0x1d,
15406 BC1ANY2F = 0x1c,
15407 BC1ANY2T = 0x1d,
15408 BC1ANY4F = 0x1e,
15409 BC1ANY4T = 0x1f
15412 /* POOL16A encoding of minor opcode field */
15414 enum {
15415 ADDU16 = 0x0,
15416 SUBU16 = 0x1
15419 /* POOL16B encoding of minor opcode field */
15421 enum {
15422 SLL16 = 0x0,
15423 SRL16 = 0x1
15426 /* POOL16C encoding of minor opcode field */
15428 enum {
15429 NOT16 = 0x00,
15430 XOR16 = 0x04,
15431 AND16 = 0x08,
15432 OR16 = 0x0c,
15433 LWM16 = 0x10,
15434 SWM16 = 0x14,
15435 JR16 = 0x18,
15436 JRC16 = 0x1a,
15437 JALR16 = 0x1c,
15438 JALR16S = 0x1e,
15439 MFHI16 = 0x20,
15440 MFLO16 = 0x24,
15441 BREAK16 = 0x28,
15442 SDBBP16 = 0x2c,
15443 JRADDIUSP = 0x30
15446 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
15448 enum {
15449 R6_NOT16 = 0x00,
15450 R6_AND16 = 0x01,
15451 R6_LWM16 = 0x02,
15452 R6_JRC16 = 0x03,
15453 MOVEP = 0x04,
15454 MOVEP_05 = 0x05,
15455 MOVEP_06 = 0x06,
15456 MOVEP_07 = 0x07,
15457 R6_XOR16 = 0x08,
15458 R6_OR16 = 0x09,
15459 R6_SWM16 = 0x0a,
15460 JALRC16 = 0x0b,
15461 MOVEP_0C = 0x0c,
15462 MOVEP_0D = 0x0d,
15463 MOVEP_0E = 0x0e,
15464 MOVEP_0F = 0x0f,
15465 JRCADDIUSP = 0x13,
15466 R6_BREAK16 = 0x1b,
15467 R6_SDBBP16 = 0x3b
15470 /* POOL16D encoding of minor opcode field */
15472 enum {
15473 ADDIUS5 = 0x0,
15474 ADDIUSP = 0x1
15477 /* POOL16E encoding of minor opcode field */
15479 enum {
15480 ADDIUR2 = 0x0,
15481 ADDIUR1SP = 0x1
15484 static int mmreg(int r)
15486 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
15488 return map[r];
15491 /* Used for 16-bit store instructions. */
15492 static int mmreg2(int r)
15494 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
15496 return map[r];
15499 #define uMIPS_RD(op) ((op >> 7) & 0x7)
15500 #define uMIPS_RS(op) ((op >> 4) & 0x7)
15501 #define uMIPS_RS2(op) uMIPS_RS(op)
15502 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
15503 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
15504 #define uMIPS_RS5(op) (op & 0x1f)
15506 /* Signed immediate */
15507 #define SIMM(op, start, width) \
15508 ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \
15509 << (32 - width)) \
15510 >> (32 - width))
15511 /* Zero-extended immediate */
15512 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width)))
15514 static void gen_addiur1sp(DisasContext *ctx)
15516 int rd = mmreg(uMIPS_RD(ctx->opcode));
15518 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
15521 static void gen_addiur2(DisasContext *ctx)
15523 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
15524 int rd = mmreg(uMIPS_RD(ctx->opcode));
15525 int rs = mmreg(uMIPS_RS(ctx->opcode));
15527 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
15530 static void gen_addiusp(DisasContext *ctx)
15532 int encoded = ZIMM(ctx->opcode, 1, 9);
15533 int decoded;
15535 if (encoded <= 1) {
15536 decoded = 256 + encoded;
15537 } else if (encoded <= 255) {
15538 decoded = encoded;
15539 } else if (encoded <= 509) {
15540 decoded = encoded - 512;
15541 } else {
15542 decoded = encoded - 768;
15545 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
15548 static void gen_addius5(DisasContext *ctx)
15550 int imm = SIMM(ctx->opcode, 1, 4);
15551 int rd = (ctx->opcode >> 5) & 0x1f;
15553 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
15556 static void gen_andi16(DisasContext *ctx)
15558 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
15559 31, 32, 63, 64, 255, 32768, 65535 };
15560 int rd = mmreg(uMIPS_RD(ctx->opcode));
15561 int rs = mmreg(uMIPS_RS(ctx->opcode));
15562 int encoded = ZIMM(ctx->opcode, 0, 4);
15564 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
15567 static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist,
15568 int base, int16_t offset)
15570 TCGv t0, t1;
15571 TCGv_i32 t2;
15573 if (ctx->hflags & MIPS_HFLAG_BMASK) {
15574 gen_reserved_instruction(ctx);
15575 return;
15578 t0 = tcg_temp_new();
15580 gen_base_offset_addr(ctx, t0, base, offset);
15582 t1 = tcg_const_tl(reglist);
15583 t2 = tcg_const_i32(ctx->mem_idx);
15585 save_cpu_state(ctx, 1);
15586 switch (opc) {
15587 case LWM32:
15588 gen_helper_lwm(cpu_env, t0, t1, t2);
15589 break;
15590 case SWM32:
15591 gen_helper_swm(cpu_env, t0, t1, t2);
15592 break;
15593 #ifdef TARGET_MIPS64
15594 case LDM:
15595 gen_helper_ldm(cpu_env, t0, t1, t2);
15596 break;
15597 case SDM:
15598 gen_helper_sdm(cpu_env, t0, t1, t2);
15599 break;
15600 #endif
15602 tcg_temp_free(t0);
15603 tcg_temp_free(t1);
15604 tcg_temp_free_i32(t2);
15608 static void gen_pool16c_insn(DisasContext *ctx)
15610 int rd = mmreg((ctx->opcode >> 3) & 0x7);
15611 int rs = mmreg(ctx->opcode & 0x7);
15613 switch (((ctx->opcode) >> 4) & 0x3f) {
15614 case NOT16 + 0:
15615 case NOT16 + 1:
15616 case NOT16 + 2:
15617 case NOT16 + 3:
15618 gen_logic(ctx, OPC_NOR, rd, rs, 0);
15619 break;
15620 case XOR16 + 0:
15621 case XOR16 + 1:
15622 case XOR16 + 2:
15623 case XOR16 + 3:
15624 gen_logic(ctx, OPC_XOR, rd, rd, rs);
15625 break;
15626 case AND16 + 0:
15627 case AND16 + 1:
15628 case AND16 + 2:
15629 case AND16 + 3:
15630 gen_logic(ctx, OPC_AND, rd, rd, rs);
15631 break;
15632 case OR16 + 0:
15633 case OR16 + 1:
15634 case OR16 + 2:
15635 case OR16 + 3:
15636 gen_logic(ctx, OPC_OR, rd, rd, rs);
15637 break;
15638 case LWM16 + 0:
15639 case LWM16 + 1:
15640 case LWM16 + 2:
15641 case LWM16 + 3:
15643 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15644 int offset = ZIMM(ctx->opcode, 0, 4);
15646 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
15647 29, offset << 2);
15649 break;
15650 case SWM16 + 0:
15651 case SWM16 + 1:
15652 case SWM16 + 2:
15653 case SWM16 + 3:
15655 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15656 int offset = ZIMM(ctx->opcode, 0, 4);
15658 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
15659 29, offset << 2);
15661 break;
15662 case JR16 + 0:
15663 case JR16 + 1:
15665 int reg = ctx->opcode & 0x1f;
15667 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
15669 break;
15670 case JRC16 + 0:
15671 case JRC16 + 1:
15673 int reg = ctx->opcode & 0x1f;
15674 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
15676 * Let normal delay slot handling in our caller take us
15677 * to the branch target.
15680 break;
15681 case JALR16 + 0:
15682 case JALR16 + 1:
15683 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
15684 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15685 break;
15686 case JALR16S + 0:
15687 case JALR16S + 1:
15688 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
15689 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15690 break;
15691 case MFHI16 + 0:
15692 case MFHI16 + 1:
15693 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
15694 break;
15695 case MFLO16 + 0:
15696 case MFLO16 + 1:
15697 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
15698 break;
15699 case BREAK16:
15700 generate_exception_end(ctx, EXCP_BREAK);
15701 break;
15702 case SDBBP16:
15703 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
15704 gen_helper_do_semihosting(cpu_env);
15705 } else {
15707 * XXX: not clear which exception should be raised
15708 * when in debug mode...
15710 check_insn(ctx, ISA_MIPS_R1);
15711 generate_exception_end(ctx, EXCP_DBp);
15713 break;
15714 case JRADDIUSP + 0:
15715 case JRADDIUSP + 1:
15717 int imm = ZIMM(ctx->opcode, 0, 5);
15718 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15719 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15721 * Let normal delay slot handling in our caller take us
15722 * to the branch target.
15725 break;
15726 default:
15727 gen_reserved_instruction(ctx);
15728 break;
15732 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
15733 int enc_rs)
15735 int rd, rs, re, rt;
15736 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
15737 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
15738 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
15739 rd = rd_enc[enc_dest];
15740 re = re_enc[enc_dest];
15741 rs = rs_rt_enc[enc_rs];
15742 rt = rs_rt_enc[enc_rt];
15743 if (rs) {
15744 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
15745 } else {
15746 tcg_gen_movi_tl(cpu_gpr[rd], 0);
15748 if (rt) {
15749 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
15750 } else {
15751 tcg_gen_movi_tl(cpu_gpr[re], 0);
15755 static void gen_pool16c_r6_insn(DisasContext *ctx)
15757 int rt = mmreg((ctx->opcode >> 7) & 0x7);
15758 int rs = mmreg((ctx->opcode >> 4) & 0x7);
15760 switch (ctx->opcode & 0xf) {
15761 case R6_NOT16:
15762 gen_logic(ctx, OPC_NOR, rt, rs, 0);
15763 break;
15764 case R6_AND16:
15765 gen_logic(ctx, OPC_AND, rt, rt, rs);
15766 break;
15767 case R6_LWM16:
15769 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15770 int offset = extract32(ctx->opcode, 4, 4);
15771 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
15773 break;
15774 case R6_JRC16: /* JRCADDIUSP */
15775 if ((ctx->opcode >> 4) & 1) {
15776 /* JRCADDIUSP */
15777 int imm = extract32(ctx->opcode, 5, 5);
15778 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15779 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15780 } else {
15781 /* JRC16 */
15782 rs = extract32(ctx->opcode, 5, 5);
15783 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
15785 break;
15786 case MOVEP:
15787 case MOVEP_05:
15788 case MOVEP_06:
15789 case MOVEP_07:
15790 case MOVEP_0C:
15791 case MOVEP_0D:
15792 case MOVEP_0E:
15793 case MOVEP_0F:
15795 int enc_dest = uMIPS_RD(ctx->opcode);
15796 int enc_rt = uMIPS_RS2(ctx->opcode);
15797 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
15798 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15800 break;
15801 case R6_XOR16:
15802 gen_logic(ctx, OPC_XOR, rt, rt, rs);
15803 break;
15804 case R6_OR16:
15805 gen_logic(ctx, OPC_OR, rt, rt, rs);
15806 break;
15807 case R6_SWM16:
15809 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15810 int offset = extract32(ctx->opcode, 4, 4);
15811 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
15813 break;
15814 case JALRC16: /* BREAK16, SDBBP16 */
15815 switch (ctx->opcode & 0x3f) {
15816 case JALRC16:
15817 case JALRC16 + 0x20:
15818 /* JALRC16 */
15819 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
15820 31, 0, 0);
15821 break;
15822 case R6_BREAK16:
15823 /* BREAK16 */
15824 generate_exception(ctx, EXCP_BREAK);
15825 break;
15826 case R6_SDBBP16:
15827 /* SDBBP16 */
15828 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
15829 gen_helper_do_semihosting(cpu_env);
15830 } else {
15831 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15832 generate_exception(ctx, EXCP_RI);
15833 } else {
15834 generate_exception(ctx, EXCP_DBp);
15837 break;
15839 break;
15840 default:
15841 generate_exception(ctx, EXCP_RI);
15842 break;
15846 static void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
15848 TCGv t0 = tcg_temp_new();
15849 TCGv t1 = tcg_temp_new();
15851 gen_load_gpr(t0, base);
15853 if (index != 0) {
15854 gen_load_gpr(t1, index);
15855 tcg_gen_shli_tl(t1, t1, 2);
15856 gen_op_addr_add(ctx, t0, t1, t0);
15859 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15860 gen_store_gpr(t1, rd);
15862 tcg_temp_free(t0);
15863 tcg_temp_free(t1);
15866 static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd,
15867 int base, int16_t offset)
15869 TCGv t0, t1;
15871 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
15872 gen_reserved_instruction(ctx);
15873 return;
15876 t0 = tcg_temp_new();
15877 t1 = tcg_temp_new();
15879 gen_base_offset_addr(ctx, t0, base, offset);
15881 switch (opc) {
15882 case LWP:
15883 if (rd == base) {
15884 gen_reserved_instruction(ctx);
15885 return;
15887 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15888 gen_store_gpr(t1, rd);
15889 tcg_gen_movi_tl(t1, 4);
15890 gen_op_addr_add(ctx, t0, t0, t1);
15891 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15892 gen_store_gpr(t1, rd + 1);
15893 break;
15894 case SWP:
15895 gen_load_gpr(t1, rd);
15896 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15897 tcg_gen_movi_tl(t1, 4);
15898 gen_op_addr_add(ctx, t0, t0, t1);
15899 gen_load_gpr(t1, rd + 1);
15900 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15901 break;
15902 #ifdef TARGET_MIPS64
15903 case LDP:
15904 if (rd == base) {
15905 gen_reserved_instruction(ctx);
15906 return;
15908 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15909 gen_store_gpr(t1, rd);
15910 tcg_gen_movi_tl(t1, 8);
15911 gen_op_addr_add(ctx, t0, t0, t1);
15912 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15913 gen_store_gpr(t1, rd + 1);
15914 break;
15915 case SDP:
15916 gen_load_gpr(t1, rd);
15917 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15918 tcg_gen_movi_tl(t1, 8);
15919 gen_op_addr_add(ctx, t0, t0, t1);
15920 gen_load_gpr(t1, rd + 1);
15921 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15922 break;
15923 #endif
15925 tcg_temp_free(t0);
15926 tcg_temp_free(t1);
15929 static void gen_sync(int stype)
15931 TCGBar tcg_mo = TCG_BAR_SC;
15933 switch (stype) {
15934 case 0x4: /* SYNC_WMB */
15935 tcg_mo |= TCG_MO_ST_ST;
15936 break;
15937 case 0x10: /* SYNC_MB */
15938 tcg_mo |= TCG_MO_ALL;
15939 break;
15940 case 0x11: /* SYNC_ACQUIRE */
15941 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
15942 break;
15943 case 0x12: /* SYNC_RELEASE */
15944 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
15945 break;
15946 case 0x13: /* SYNC_RMB */
15947 tcg_mo |= TCG_MO_LD_LD;
15948 break;
15949 default:
15950 tcg_mo |= TCG_MO_ALL;
15951 break;
15954 tcg_gen_mb(tcg_mo);
15957 static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
15959 int extension = (ctx->opcode >> 6) & 0x3f;
15960 int minor = (ctx->opcode >> 12) & 0xf;
15961 uint32_t mips32_op;
15963 switch (extension) {
15964 case TEQ:
15965 mips32_op = OPC_TEQ;
15966 goto do_trap;
15967 case TGE:
15968 mips32_op = OPC_TGE;
15969 goto do_trap;
15970 case TGEU:
15971 mips32_op = OPC_TGEU;
15972 goto do_trap;
15973 case TLT:
15974 mips32_op = OPC_TLT;
15975 goto do_trap;
15976 case TLTU:
15977 mips32_op = OPC_TLTU;
15978 goto do_trap;
15979 case TNE:
15980 mips32_op = OPC_TNE;
15981 do_trap:
15982 gen_trap(ctx, mips32_op, rs, rt, -1);
15983 break;
15984 #ifndef CONFIG_USER_ONLY
15985 case MFC0:
15986 case MFC0 + 32:
15987 check_cp0_enabled(ctx);
15988 if (rt == 0) {
15989 /* Treat as NOP. */
15990 break;
15992 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
15993 break;
15994 case MTC0:
15995 case MTC0 + 32:
15996 check_cp0_enabled(ctx);
15998 TCGv t0 = tcg_temp_new();
16000 gen_load_gpr(t0, rt);
16001 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
16002 tcg_temp_free(t0);
16004 break;
16005 #endif
16006 case 0x2a:
16007 switch (minor & 3) {
16008 case MADD_ACC:
16009 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
16010 break;
16011 case MADDU_ACC:
16012 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
16013 break;
16014 case MSUB_ACC:
16015 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
16016 break;
16017 case MSUBU_ACC:
16018 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
16019 break;
16020 default:
16021 goto pool32axf_invalid;
16023 break;
16024 case 0x32:
16025 switch (minor & 3) {
16026 case MULT_ACC:
16027 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
16028 break;
16029 case MULTU_ACC:
16030 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
16031 break;
16032 default:
16033 goto pool32axf_invalid;
16035 break;
16036 case 0x2c:
16037 switch (minor) {
16038 case BITSWAP:
16039 check_insn(ctx, ISA_MIPS_R6);
16040 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
16041 break;
16042 case SEB:
16043 gen_bshfl(ctx, OPC_SEB, rs, rt);
16044 break;
16045 case SEH:
16046 gen_bshfl(ctx, OPC_SEH, rs, rt);
16047 break;
16048 case CLO:
16049 mips32_op = OPC_CLO;
16050 goto do_cl;
16051 case CLZ:
16052 mips32_op = OPC_CLZ;
16053 do_cl:
16054 check_insn(ctx, ISA_MIPS_R1);
16055 gen_cl(ctx, mips32_op, rt, rs);
16056 break;
16057 case RDHWR:
16058 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16059 gen_rdhwr(ctx, rt, rs, 0);
16060 break;
16061 case WSBH:
16062 gen_bshfl(ctx, OPC_WSBH, rs, rt);
16063 break;
16064 case MULT:
16065 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16066 mips32_op = OPC_MULT;
16067 goto do_mul;
16068 case MULTU:
16069 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16070 mips32_op = OPC_MULTU;
16071 goto do_mul;
16072 case DIV:
16073 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16074 mips32_op = OPC_DIV;
16075 goto do_div;
16076 case DIVU:
16077 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16078 mips32_op = OPC_DIVU;
16079 goto do_div;
16080 do_div:
16081 check_insn(ctx, ISA_MIPS_R1);
16082 gen_muldiv(ctx, mips32_op, 0, rs, rt);
16083 break;
16084 case MADD:
16085 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16086 mips32_op = OPC_MADD;
16087 goto do_mul;
16088 case MADDU:
16089 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16090 mips32_op = OPC_MADDU;
16091 goto do_mul;
16092 case MSUB:
16093 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16094 mips32_op = OPC_MSUB;
16095 goto do_mul;
16096 case MSUBU:
16097 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16098 mips32_op = OPC_MSUBU;
16099 do_mul:
16100 check_insn(ctx, ISA_MIPS_R1);
16101 gen_muldiv(ctx, mips32_op, 0, rs, rt);
16102 break;
16103 default:
16104 goto pool32axf_invalid;
16106 break;
16107 case 0x34:
16108 switch (minor) {
16109 case MFC2:
16110 case MTC2:
16111 case MFHC2:
16112 case MTHC2:
16113 case CFC2:
16114 case CTC2:
16115 generate_exception_err(ctx, EXCP_CpU, 2);
16116 break;
16117 default:
16118 goto pool32axf_invalid;
16120 break;
16121 case 0x3c:
16122 switch (minor) {
16123 case JALR: /* JALRC */
16124 case JALR_HB: /* JALRC_HB */
16125 if (ctx->insn_flags & ISA_MIPS_R6) {
16126 /* JALRC, JALRC_HB */
16127 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
16128 } else {
16129 /* JALR, JALR_HB */
16130 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
16131 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16133 break;
16134 case JALRS:
16135 case JALRS_HB:
16136 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16137 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
16138 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16139 break;
16140 default:
16141 goto pool32axf_invalid;
16143 break;
16144 case 0x05:
16145 switch (minor) {
16146 case RDPGPR:
16147 check_cp0_enabled(ctx);
16148 check_insn(ctx, ISA_MIPS_R2);
16149 gen_load_srsgpr(rs, rt);
16150 break;
16151 case WRPGPR:
16152 check_cp0_enabled(ctx);
16153 check_insn(ctx, ISA_MIPS_R2);
16154 gen_store_srsgpr(rs, rt);
16155 break;
16156 default:
16157 goto pool32axf_invalid;
16159 break;
16160 #ifndef CONFIG_USER_ONLY
16161 case 0x0d:
16162 switch (minor) {
16163 case TLBP:
16164 mips32_op = OPC_TLBP;
16165 goto do_cp0;
16166 case TLBR:
16167 mips32_op = OPC_TLBR;
16168 goto do_cp0;
16169 case TLBWI:
16170 mips32_op = OPC_TLBWI;
16171 goto do_cp0;
16172 case TLBWR:
16173 mips32_op = OPC_TLBWR;
16174 goto do_cp0;
16175 case TLBINV:
16176 mips32_op = OPC_TLBINV;
16177 goto do_cp0;
16178 case TLBINVF:
16179 mips32_op = OPC_TLBINVF;
16180 goto do_cp0;
16181 case WAIT:
16182 mips32_op = OPC_WAIT;
16183 goto do_cp0;
16184 case DERET:
16185 mips32_op = OPC_DERET;
16186 goto do_cp0;
16187 case ERET:
16188 mips32_op = OPC_ERET;
16189 do_cp0:
16190 gen_cp0(env, ctx, mips32_op, rt, rs);
16191 break;
16192 default:
16193 goto pool32axf_invalid;
16195 break;
16196 case 0x1d:
16197 switch (minor) {
16198 case DI:
16199 check_cp0_enabled(ctx);
16201 TCGv t0 = tcg_temp_new();
16203 save_cpu_state(ctx, 1);
16204 gen_helper_di(t0, cpu_env);
16205 gen_store_gpr(t0, rs);
16207 * Stop translation as we may have switched the execution
16208 * mode.
16210 ctx->base.is_jmp = DISAS_STOP;
16211 tcg_temp_free(t0);
16213 break;
16214 case EI:
16215 check_cp0_enabled(ctx);
16217 TCGv t0 = tcg_temp_new();
16219 save_cpu_state(ctx, 1);
16220 gen_helper_ei(t0, cpu_env);
16221 gen_store_gpr(t0, rs);
16223 * DISAS_STOP isn't sufficient, we need to ensure we break out
16224 * of translated code to check for pending interrupts.
16226 gen_save_pc(ctx->base.pc_next + 4);
16227 ctx->base.is_jmp = DISAS_EXIT;
16228 tcg_temp_free(t0);
16230 break;
16231 default:
16232 goto pool32axf_invalid;
16234 break;
16235 #endif
16236 case 0x2d:
16237 switch (minor) {
16238 case SYNC:
16239 gen_sync(extract32(ctx->opcode, 16, 5));
16240 break;
16241 case SYSCALL:
16242 generate_exception_end(ctx, EXCP_SYSCALL);
16243 break;
16244 case SDBBP:
16245 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
16246 gen_helper_do_semihosting(cpu_env);
16247 } else {
16248 check_insn(ctx, ISA_MIPS_R1);
16249 if (ctx->hflags & MIPS_HFLAG_SBRI) {
16250 gen_reserved_instruction(ctx);
16251 } else {
16252 generate_exception_end(ctx, EXCP_DBp);
16255 break;
16256 default:
16257 goto pool32axf_invalid;
16259 break;
16260 case 0x01:
16261 switch (minor & 3) {
16262 case MFHI_ACC:
16263 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
16264 break;
16265 case MFLO_ACC:
16266 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
16267 break;
16268 case MTHI_ACC:
16269 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
16270 break;
16271 case MTLO_ACC:
16272 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
16273 break;
16274 default:
16275 goto pool32axf_invalid;
16277 break;
16278 case 0x35:
16279 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16280 switch (minor) {
16281 case MFHI32:
16282 gen_HILO(ctx, OPC_MFHI, 0, rs);
16283 break;
16284 case MFLO32:
16285 gen_HILO(ctx, OPC_MFLO, 0, rs);
16286 break;
16287 case MTHI32:
16288 gen_HILO(ctx, OPC_MTHI, 0, rs);
16289 break;
16290 case MTLO32:
16291 gen_HILO(ctx, OPC_MTLO, 0, rs);
16292 break;
16293 default:
16294 goto pool32axf_invalid;
16296 break;
16297 default:
16298 pool32axf_invalid:
16299 MIPS_INVAL("pool32axf");
16300 gen_reserved_instruction(ctx);
16301 break;
16306 * Values for microMIPS fmt field. Variable-width, depending on which
16307 * formats the instruction supports.
16309 enum {
16310 FMT_SD_S = 0,
16311 FMT_SD_D = 1,
16313 FMT_SDPS_S = 0,
16314 FMT_SDPS_D = 1,
16315 FMT_SDPS_PS = 2,
16317 FMT_SWL_S = 0,
16318 FMT_SWL_W = 1,
16319 FMT_SWL_L = 2,
16321 FMT_DWL_D = 0,
16322 FMT_DWL_W = 1,
16323 FMT_DWL_L = 2
16326 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
16328 int extension = (ctx->opcode >> 6) & 0x3ff;
16329 uint32_t mips32_op;
16331 #define FLOAT_1BIT_FMT(opc, fmt) ((fmt << 8) | opc)
16332 #define FLOAT_2BIT_FMT(opc, fmt) ((fmt << 7) | opc)
16333 #define COND_FLOAT_MOV(opc, cond) ((cond << 7) | opc)
16335 switch (extension) {
16336 case FLOAT_1BIT_FMT(CFC1, 0):
16337 mips32_op = OPC_CFC1;
16338 goto do_cp1;
16339 case FLOAT_1BIT_FMT(CTC1, 0):
16340 mips32_op = OPC_CTC1;
16341 goto do_cp1;
16342 case FLOAT_1BIT_FMT(MFC1, 0):
16343 mips32_op = OPC_MFC1;
16344 goto do_cp1;
16345 case FLOAT_1BIT_FMT(MTC1, 0):
16346 mips32_op = OPC_MTC1;
16347 goto do_cp1;
16348 case FLOAT_1BIT_FMT(MFHC1, 0):
16349 mips32_op = OPC_MFHC1;
16350 goto do_cp1;
16351 case FLOAT_1BIT_FMT(MTHC1, 0):
16352 mips32_op = OPC_MTHC1;
16353 do_cp1:
16354 gen_cp1(ctx, mips32_op, rt, rs);
16355 break;
16357 /* Reciprocal square root */
16358 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
16359 mips32_op = OPC_RSQRT_S;
16360 goto do_unaryfp;
16361 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
16362 mips32_op = OPC_RSQRT_D;
16363 goto do_unaryfp;
16365 /* Square root */
16366 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
16367 mips32_op = OPC_SQRT_S;
16368 goto do_unaryfp;
16369 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
16370 mips32_op = OPC_SQRT_D;
16371 goto do_unaryfp;
16373 /* Reciprocal */
16374 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
16375 mips32_op = OPC_RECIP_S;
16376 goto do_unaryfp;
16377 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
16378 mips32_op = OPC_RECIP_D;
16379 goto do_unaryfp;
16381 /* Floor */
16382 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
16383 mips32_op = OPC_FLOOR_L_S;
16384 goto do_unaryfp;
16385 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
16386 mips32_op = OPC_FLOOR_L_D;
16387 goto do_unaryfp;
16388 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
16389 mips32_op = OPC_FLOOR_W_S;
16390 goto do_unaryfp;
16391 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
16392 mips32_op = OPC_FLOOR_W_D;
16393 goto do_unaryfp;
16395 /* Ceiling */
16396 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
16397 mips32_op = OPC_CEIL_L_S;
16398 goto do_unaryfp;
16399 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
16400 mips32_op = OPC_CEIL_L_D;
16401 goto do_unaryfp;
16402 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
16403 mips32_op = OPC_CEIL_W_S;
16404 goto do_unaryfp;
16405 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
16406 mips32_op = OPC_CEIL_W_D;
16407 goto do_unaryfp;
16409 /* Truncation */
16410 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
16411 mips32_op = OPC_TRUNC_L_S;
16412 goto do_unaryfp;
16413 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
16414 mips32_op = OPC_TRUNC_L_D;
16415 goto do_unaryfp;
16416 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
16417 mips32_op = OPC_TRUNC_W_S;
16418 goto do_unaryfp;
16419 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
16420 mips32_op = OPC_TRUNC_W_D;
16421 goto do_unaryfp;
16423 /* Round */
16424 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
16425 mips32_op = OPC_ROUND_L_S;
16426 goto do_unaryfp;
16427 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
16428 mips32_op = OPC_ROUND_L_D;
16429 goto do_unaryfp;
16430 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
16431 mips32_op = OPC_ROUND_W_S;
16432 goto do_unaryfp;
16433 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
16434 mips32_op = OPC_ROUND_W_D;
16435 goto do_unaryfp;
16437 /* Integer to floating-point conversion */
16438 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
16439 mips32_op = OPC_CVT_L_S;
16440 goto do_unaryfp;
16441 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
16442 mips32_op = OPC_CVT_L_D;
16443 goto do_unaryfp;
16444 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
16445 mips32_op = OPC_CVT_W_S;
16446 goto do_unaryfp;
16447 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
16448 mips32_op = OPC_CVT_W_D;
16449 goto do_unaryfp;
16451 /* Paired-foo conversions */
16452 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
16453 mips32_op = OPC_CVT_S_PL;
16454 goto do_unaryfp;
16455 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
16456 mips32_op = OPC_CVT_S_PU;
16457 goto do_unaryfp;
16458 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
16459 mips32_op = OPC_CVT_PW_PS;
16460 goto do_unaryfp;
16461 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
16462 mips32_op = OPC_CVT_PS_PW;
16463 goto do_unaryfp;
16465 /* Floating-point moves */
16466 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
16467 mips32_op = OPC_MOV_S;
16468 goto do_unaryfp;
16469 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
16470 mips32_op = OPC_MOV_D;
16471 goto do_unaryfp;
16472 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
16473 mips32_op = OPC_MOV_PS;
16474 goto do_unaryfp;
16476 /* Absolute value */
16477 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
16478 mips32_op = OPC_ABS_S;
16479 goto do_unaryfp;
16480 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
16481 mips32_op = OPC_ABS_D;
16482 goto do_unaryfp;
16483 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
16484 mips32_op = OPC_ABS_PS;
16485 goto do_unaryfp;
16487 /* Negation */
16488 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
16489 mips32_op = OPC_NEG_S;
16490 goto do_unaryfp;
16491 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
16492 mips32_op = OPC_NEG_D;
16493 goto do_unaryfp;
16494 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
16495 mips32_op = OPC_NEG_PS;
16496 goto do_unaryfp;
16498 /* Reciprocal square root step */
16499 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
16500 mips32_op = OPC_RSQRT1_S;
16501 goto do_unaryfp;
16502 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
16503 mips32_op = OPC_RSQRT1_D;
16504 goto do_unaryfp;
16505 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
16506 mips32_op = OPC_RSQRT1_PS;
16507 goto do_unaryfp;
16509 /* Reciprocal step */
16510 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
16511 mips32_op = OPC_RECIP1_S;
16512 goto do_unaryfp;
16513 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
16514 mips32_op = OPC_RECIP1_S;
16515 goto do_unaryfp;
16516 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
16517 mips32_op = OPC_RECIP1_PS;
16518 goto do_unaryfp;
16520 /* Conversions from double */
16521 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
16522 mips32_op = OPC_CVT_D_S;
16523 goto do_unaryfp;
16524 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
16525 mips32_op = OPC_CVT_D_W;
16526 goto do_unaryfp;
16527 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
16528 mips32_op = OPC_CVT_D_L;
16529 goto do_unaryfp;
16531 /* Conversions from single */
16532 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
16533 mips32_op = OPC_CVT_S_D;
16534 goto do_unaryfp;
16535 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
16536 mips32_op = OPC_CVT_S_W;
16537 goto do_unaryfp;
16538 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
16539 mips32_op = OPC_CVT_S_L;
16540 do_unaryfp:
16541 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
16542 break;
16544 /* Conditional moves on floating-point codes */
16545 case COND_FLOAT_MOV(MOVT, 0):
16546 case COND_FLOAT_MOV(MOVT, 1):
16547 case COND_FLOAT_MOV(MOVT, 2):
16548 case COND_FLOAT_MOV(MOVT, 3):
16549 case COND_FLOAT_MOV(MOVT, 4):
16550 case COND_FLOAT_MOV(MOVT, 5):
16551 case COND_FLOAT_MOV(MOVT, 6):
16552 case COND_FLOAT_MOV(MOVT, 7):
16553 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16554 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
16555 break;
16556 case COND_FLOAT_MOV(MOVF, 0):
16557 case COND_FLOAT_MOV(MOVF, 1):
16558 case COND_FLOAT_MOV(MOVF, 2):
16559 case COND_FLOAT_MOV(MOVF, 3):
16560 case COND_FLOAT_MOV(MOVF, 4):
16561 case COND_FLOAT_MOV(MOVF, 5):
16562 case COND_FLOAT_MOV(MOVF, 6):
16563 case COND_FLOAT_MOV(MOVF, 7):
16564 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16565 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
16566 break;
16567 default:
16568 MIPS_INVAL("pool32fxf");
16569 gen_reserved_instruction(ctx);
16570 break;
16574 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
16576 int32_t offset;
16577 uint16_t insn;
16578 int rt, rs, rd, rr;
16579 int16_t imm;
16580 uint32_t op, minor, minor2, mips32_op;
16581 uint32_t cond, fmt, cc;
16583 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
16584 ctx->opcode = (ctx->opcode << 16) | insn;
16586 rt = (ctx->opcode >> 21) & 0x1f;
16587 rs = (ctx->opcode >> 16) & 0x1f;
16588 rd = (ctx->opcode >> 11) & 0x1f;
16589 rr = (ctx->opcode >> 6) & 0x1f;
16590 imm = (int16_t) ctx->opcode;
16592 op = (ctx->opcode >> 26) & 0x3f;
16593 switch (op) {
16594 case POOL32A:
16595 minor = ctx->opcode & 0x3f;
16596 switch (minor) {
16597 case 0x00:
16598 minor = (ctx->opcode >> 6) & 0xf;
16599 switch (minor) {
16600 case SLL32:
16601 mips32_op = OPC_SLL;
16602 goto do_shifti;
16603 case SRA:
16604 mips32_op = OPC_SRA;
16605 goto do_shifti;
16606 case SRL32:
16607 mips32_op = OPC_SRL;
16608 goto do_shifti;
16609 case ROTR:
16610 mips32_op = OPC_ROTR;
16611 do_shifti:
16612 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
16613 break;
16614 case SELEQZ:
16615 check_insn(ctx, ISA_MIPS_R6);
16616 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
16617 break;
16618 case SELNEZ:
16619 check_insn(ctx, ISA_MIPS_R6);
16620 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
16621 break;
16622 case R6_RDHWR:
16623 check_insn(ctx, ISA_MIPS_R6);
16624 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
16625 break;
16626 default:
16627 goto pool32a_invalid;
16629 break;
16630 case 0x10:
16631 minor = (ctx->opcode >> 6) & 0xf;
16632 switch (minor) {
16633 /* Arithmetic */
16634 case ADD:
16635 mips32_op = OPC_ADD;
16636 goto do_arith;
16637 case ADDU32:
16638 mips32_op = OPC_ADDU;
16639 goto do_arith;
16640 case SUB:
16641 mips32_op = OPC_SUB;
16642 goto do_arith;
16643 case SUBU32:
16644 mips32_op = OPC_SUBU;
16645 goto do_arith;
16646 case MUL:
16647 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16648 mips32_op = OPC_MUL;
16649 do_arith:
16650 gen_arith(ctx, mips32_op, rd, rs, rt);
16651 break;
16652 /* Shifts */
16653 case SLLV:
16654 mips32_op = OPC_SLLV;
16655 goto do_shift;
16656 case SRLV:
16657 mips32_op = OPC_SRLV;
16658 goto do_shift;
16659 case SRAV:
16660 mips32_op = OPC_SRAV;
16661 goto do_shift;
16662 case ROTRV:
16663 mips32_op = OPC_ROTRV;
16664 do_shift:
16665 gen_shift(ctx, mips32_op, rd, rs, rt);
16666 break;
16667 /* Logical operations */
16668 case AND:
16669 mips32_op = OPC_AND;
16670 goto do_logic;
16671 case OR32:
16672 mips32_op = OPC_OR;
16673 goto do_logic;
16674 case NOR:
16675 mips32_op = OPC_NOR;
16676 goto do_logic;
16677 case XOR32:
16678 mips32_op = OPC_XOR;
16679 do_logic:
16680 gen_logic(ctx, mips32_op, rd, rs, rt);
16681 break;
16682 /* Set less than */
16683 case SLT:
16684 mips32_op = OPC_SLT;
16685 goto do_slt;
16686 case SLTU:
16687 mips32_op = OPC_SLTU;
16688 do_slt:
16689 gen_slt(ctx, mips32_op, rd, rs, rt);
16690 break;
16691 default:
16692 goto pool32a_invalid;
16694 break;
16695 case 0x18:
16696 minor = (ctx->opcode >> 6) & 0xf;
16697 switch (minor) {
16698 /* Conditional moves */
16699 case MOVN: /* MUL */
16700 if (ctx->insn_flags & ISA_MIPS_R6) {
16701 /* MUL */
16702 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
16703 } else {
16704 /* MOVN */
16705 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
16707 break;
16708 case MOVZ: /* MUH */
16709 if (ctx->insn_flags & ISA_MIPS_R6) {
16710 /* MUH */
16711 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
16712 } else {
16713 /* MOVZ */
16714 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
16716 break;
16717 case MULU:
16718 check_insn(ctx, ISA_MIPS_R6);
16719 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
16720 break;
16721 case MUHU:
16722 check_insn(ctx, ISA_MIPS_R6);
16723 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
16724 break;
16725 case LWXS: /* DIV */
16726 if (ctx->insn_flags & ISA_MIPS_R6) {
16727 /* DIV */
16728 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
16729 } else {
16730 /* LWXS */
16731 gen_ldxs(ctx, rs, rt, rd);
16733 break;
16734 case MOD:
16735 check_insn(ctx, ISA_MIPS_R6);
16736 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
16737 break;
16738 case R6_DIVU:
16739 check_insn(ctx, ISA_MIPS_R6);
16740 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
16741 break;
16742 case MODU:
16743 check_insn(ctx, ISA_MIPS_R6);
16744 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
16745 break;
16746 default:
16747 goto pool32a_invalid;
16749 break;
16750 case INS:
16751 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
16752 return;
16753 case LSA:
16754 check_insn(ctx, ISA_MIPS_R6);
16755 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
16756 extract32(ctx->opcode, 9, 2));
16757 break;
16758 case ALIGN:
16759 check_insn(ctx, ISA_MIPS_R6);
16760 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
16761 break;
16762 case EXT:
16763 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
16764 return;
16765 case POOL32AXF:
16766 gen_pool32axf(env, ctx, rt, rs);
16767 break;
16768 case BREAK32:
16769 generate_exception_end(ctx, EXCP_BREAK);
16770 break;
16771 case SIGRIE:
16772 check_insn(ctx, ISA_MIPS_R6);
16773 gen_reserved_instruction(ctx);
16774 break;
16775 default:
16776 pool32a_invalid:
16777 MIPS_INVAL("pool32a");
16778 gen_reserved_instruction(ctx);
16779 break;
16781 break;
16782 case POOL32B:
16783 minor = (ctx->opcode >> 12) & 0xf;
16784 switch (minor) {
16785 case CACHE:
16786 check_cp0_enabled(ctx);
16787 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16788 gen_cache_operation(ctx, rt, rs, imm);
16790 break;
16791 case LWC2:
16792 case SWC2:
16793 /* COP2: Not implemented. */
16794 generate_exception_err(ctx, EXCP_CpU, 2);
16795 break;
16796 #ifdef TARGET_MIPS64
16797 case LDP:
16798 case SDP:
16799 check_insn(ctx, ISA_MIPS3);
16800 check_mips_64(ctx);
16801 #endif
16802 /* fall through */
16803 case LWP:
16804 case SWP:
16805 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16806 break;
16807 #ifdef TARGET_MIPS64
16808 case LDM:
16809 case SDM:
16810 check_insn(ctx, ISA_MIPS3);
16811 check_mips_64(ctx);
16812 #endif
16813 /* fall through */
16814 case LWM32:
16815 case SWM32:
16816 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16817 break;
16818 default:
16819 MIPS_INVAL("pool32b");
16820 gen_reserved_instruction(ctx);
16821 break;
16823 break;
16824 case POOL32F:
16825 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
16826 minor = ctx->opcode & 0x3f;
16827 check_cp1_enabled(ctx);
16828 switch (minor) {
16829 case ALNV_PS:
16830 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16831 mips32_op = OPC_ALNV_PS;
16832 goto do_madd;
16833 case MADD_S:
16834 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16835 mips32_op = OPC_MADD_S;
16836 goto do_madd;
16837 case MADD_D:
16838 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16839 mips32_op = OPC_MADD_D;
16840 goto do_madd;
16841 case MADD_PS:
16842 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16843 mips32_op = OPC_MADD_PS;
16844 goto do_madd;
16845 case MSUB_S:
16846 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16847 mips32_op = OPC_MSUB_S;
16848 goto do_madd;
16849 case MSUB_D:
16850 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16851 mips32_op = OPC_MSUB_D;
16852 goto do_madd;
16853 case MSUB_PS:
16854 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16855 mips32_op = OPC_MSUB_PS;
16856 goto do_madd;
16857 case NMADD_S:
16858 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16859 mips32_op = OPC_NMADD_S;
16860 goto do_madd;
16861 case NMADD_D:
16862 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16863 mips32_op = OPC_NMADD_D;
16864 goto do_madd;
16865 case NMADD_PS:
16866 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16867 mips32_op = OPC_NMADD_PS;
16868 goto do_madd;
16869 case NMSUB_S:
16870 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16871 mips32_op = OPC_NMSUB_S;
16872 goto do_madd;
16873 case NMSUB_D:
16874 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16875 mips32_op = OPC_NMSUB_D;
16876 goto do_madd;
16877 case NMSUB_PS:
16878 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16879 mips32_op = OPC_NMSUB_PS;
16880 do_madd:
16881 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
16882 break;
16883 case CABS_COND_FMT:
16884 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16885 cond = (ctx->opcode >> 6) & 0xf;
16886 cc = (ctx->opcode >> 13) & 0x7;
16887 fmt = (ctx->opcode >> 10) & 0x3;
16888 switch (fmt) {
16889 case 0x0:
16890 gen_cmpabs_s(ctx, cond, rt, rs, cc);
16891 break;
16892 case 0x1:
16893 gen_cmpabs_d(ctx, cond, rt, rs, cc);
16894 break;
16895 case 0x2:
16896 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
16897 break;
16898 default:
16899 goto pool32f_invalid;
16901 break;
16902 case C_COND_FMT:
16903 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16904 cond = (ctx->opcode >> 6) & 0xf;
16905 cc = (ctx->opcode >> 13) & 0x7;
16906 fmt = (ctx->opcode >> 10) & 0x3;
16907 switch (fmt) {
16908 case 0x0:
16909 gen_cmp_s(ctx, cond, rt, rs, cc);
16910 break;
16911 case 0x1:
16912 gen_cmp_d(ctx, cond, rt, rs, cc);
16913 break;
16914 case 0x2:
16915 gen_cmp_ps(ctx, cond, rt, rs, cc);
16916 break;
16917 default:
16918 goto pool32f_invalid;
16920 break;
16921 case CMP_CONDN_S:
16922 check_insn(ctx, ISA_MIPS_R6);
16923 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16924 break;
16925 case CMP_CONDN_D:
16926 check_insn(ctx, ISA_MIPS_R6);
16927 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16928 break;
16929 case POOL32FXF:
16930 gen_pool32fxf(ctx, rt, rs);
16931 break;
16932 case 0x00:
16933 /* PLL foo */
16934 switch ((ctx->opcode >> 6) & 0x7) {
16935 case PLL_PS:
16936 mips32_op = OPC_PLL_PS;
16937 goto do_ps;
16938 case PLU_PS:
16939 mips32_op = OPC_PLU_PS;
16940 goto do_ps;
16941 case PUL_PS:
16942 mips32_op = OPC_PUL_PS;
16943 goto do_ps;
16944 case PUU_PS:
16945 mips32_op = OPC_PUU_PS;
16946 goto do_ps;
16947 case CVT_PS_S:
16948 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16949 mips32_op = OPC_CVT_PS_S;
16950 do_ps:
16951 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16952 break;
16953 default:
16954 goto pool32f_invalid;
16956 break;
16957 case MIN_FMT:
16958 check_insn(ctx, ISA_MIPS_R6);
16959 switch ((ctx->opcode >> 9) & 0x3) {
16960 case FMT_SDPS_S:
16961 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
16962 break;
16963 case FMT_SDPS_D:
16964 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
16965 break;
16966 default:
16967 goto pool32f_invalid;
16969 break;
16970 case 0x08:
16971 /* [LS][WDU]XC1 */
16972 switch ((ctx->opcode >> 6) & 0x7) {
16973 case LWXC1:
16974 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16975 mips32_op = OPC_LWXC1;
16976 goto do_ldst_cp1;
16977 case SWXC1:
16978 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16979 mips32_op = OPC_SWXC1;
16980 goto do_ldst_cp1;
16981 case LDXC1:
16982 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16983 mips32_op = OPC_LDXC1;
16984 goto do_ldst_cp1;
16985 case SDXC1:
16986 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16987 mips32_op = OPC_SDXC1;
16988 goto do_ldst_cp1;
16989 case LUXC1:
16990 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16991 mips32_op = OPC_LUXC1;
16992 goto do_ldst_cp1;
16993 case SUXC1:
16994 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16995 mips32_op = OPC_SUXC1;
16996 do_ldst_cp1:
16997 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
16998 break;
16999 default:
17000 goto pool32f_invalid;
17002 break;
17003 case MAX_FMT:
17004 check_insn(ctx, ISA_MIPS_R6);
17005 switch ((ctx->opcode >> 9) & 0x3) {
17006 case FMT_SDPS_S:
17007 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
17008 break;
17009 case FMT_SDPS_D:
17010 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
17011 break;
17012 default:
17013 goto pool32f_invalid;
17015 break;
17016 case 0x18:
17017 /* 3D insns */
17018 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17019 fmt = (ctx->opcode >> 9) & 0x3;
17020 switch ((ctx->opcode >> 6) & 0x7) {
17021 case RSQRT2_FMT:
17022 switch (fmt) {
17023 case FMT_SDPS_S:
17024 mips32_op = OPC_RSQRT2_S;
17025 goto do_3d;
17026 case FMT_SDPS_D:
17027 mips32_op = OPC_RSQRT2_D;
17028 goto do_3d;
17029 case FMT_SDPS_PS:
17030 mips32_op = OPC_RSQRT2_PS;
17031 goto do_3d;
17032 default:
17033 goto pool32f_invalid;
17035 break;
17036 case RECIP2_FMT:
17037 switch (fmt) {
17038 case FMT_SDPS_S:
17039 mips32_op = OPC_RECIP2_S;
17040 goto do_3d;
17041 case FMT_SDPS_D:
17042 mips32_op = OPC_RECIP2_D;
17043 goto do_3d;
17044 case FMT_SDPS_PS:
17045 mips32_op = OPC_RECIP2_PS;
17046 goto do_3d;
17047 default:
17048 goto pool32f_invalid;
17050 break;
17051 case ADDR_PS:
17052 mips32_op = OPC_ADDR_PS;
17053 goto do_3d;
17054 case MULR_PS:
17055 mips32_op = OPC_MULR_PS;
17056 do_3d:
17057 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
17058 break;
17059 default:
17060 goto pool32f_invalid;
17062 break;
17063 case 0x20:
17064 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
17065 cc = (ctx->opcode >> 13) & 0x7;
17066 fmt = (ctx->opcode >> 9) & 0x3;
17067 switch ((ctx->opcode >> 6) & 0x7) {
17068 case MOVF_FMT: /* RINT_FMT */
17069 if (ctx->insn_flags & ISA_MIPS_R6) {
17070 /* RINT_FMT */
17071 switch (fmt) {
17072 case FMT_SDPS_S:
17073 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
17074 break;
17075 case FMT_SDPS_D:
17076 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
17077 break;
17078 default:
17079 goto pool32f_invalid;
17081 } else {
17082 /* MOVF_FMT */
17083 switch (fmt) {
17084 case FMT_SDPS_S:
17085 gen_movcf_s(ctx, rs, rt, cc, 0);
17086 break;
17087 case FMT_SDPS_D:
17088 gen_movcf_d(ctx, rs, rt, cc, 0);
17089 break;
17090 case FMT_SDPS_PS:
17091 check_ps(ctx);
17092 gen_movcf_ps(ctx, rs, rt, cc, 0);
17093 break;
17094 default:
17095 goto pool32f_invalid;
17098 break;
17099 case MOVT_FMT: /* CLASS_FMT */
17100 if (ctx->insn_flags & ISA_MIPS_R6) {
17101 /* CLASS_FMT */
17102 switch (fmt) {
17103 case FMT_SDPS_S:
17104 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
17105 break;
17106 case FMT_SDPS_D:
17107 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
17108 break;
17109 default:
17110 goto pool32f_invalid;
17112 } else {
17113 /* MOVT_FMT */
17114 switch (fmt) {
17115 case FMT_SDPS_S:
17116 gen_movcf_s(ctx, rs, rt, cc, 1);
17117 break;
17118 case FMT_SDPS_D:
17119 gen_movcf_d(ctx, rs, rt, cc, 1);
17120 break;
17121 case FMT_SDPS_PS:
17122 check_ps(ctx);
17123 gen_movcf_ps(ctx, rs, rt, cc, 1);
17124 break;
17125 default:
17126 goto pool32f_invalid;
17129 break;
17130 case PREFX:
17131 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17132 break;
17133 default:
17134 goto pool32f_invalid;
17136 break;
17137 #define FINSN_3ARG_SDPS(prfx) \
17138 switch ((ctx->opcode >> 8) & 0x3) { \
17139 case FMT_SDPS_S: \
17140 mips32_op = OPC_##prfx##_S; \
17141 goto do_fpop; \
17142 case FMT_SDPS_D: \
17143 mips32_op = OPC_##prfx##_D; \
17144 goto do_fpop; \
17145 case FMT_SDPS_PS: \
17146 check_ps(ctx); \
17147 mips32_op = OPC_##prfx##_PS; \
17148 goto do_fpop; \
17149 default: \
17150 goto pool32f_invalid; \
17152 case MINA_FMT:
17153 check_insn(ctx, ISA_MIPS_R6);
17154 switch ((ctx->opcode >> 9) & 0x3) {
17155 case FMT_SDPS_S:
17156 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
17157 break;
17158 case FMT_SDPS_D:
17159 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
17160 break;
17161 default:
17162 goto pool32f_invalid;
17164 break;
17165 case MAXA_FMT:
17166 check_insn(ctx, ISA_MIPS_R6);
17167 switch ((ctx->opcode >> 9) & 0x3) {
17168 case FMT_SDPS_S:
17169 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
17170 break;
17171 case FMT_SDPS_D:
17172 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
17173 break;
17174 default:
17175 goto pool32f_invalid;
17177 break;
17178 case 0x30:
17179 /* regular FP ops */
17180 switch ((ctx->opcode >> 6) & 0x3) {
17181 case ADD_FMT:
17182 FINSN_3ARG_SDPS(ADD);
17183 break;
17184 case SUB_FMT:
17185 FINSN_3ARG_SDPS(SUB);
17186 break;
17187 case MUL_FMT:
17188 FINSN_3ARG_SDPS(MUL);
17189 break;
17190 case DIV_FMT:
17191 fmt = (ctx->opcode >> 8) & 0x3;
17192 if (fmt == 1) {
17193 mips32_op = OPC_DIV_D;
17194 } else if (fmt == 0) {
17195 mips32_op = OPC_DIV_S;
17196 } else {
17197 goto pool32f_invalid;
17199 goto do_fpop;
17200 default:
17201 goto pool32f_invalid;
17203 break;
17204 case 0x38:
17205 /* cmovs */
17206 switch ((ctx->opcode >> 6) & 0x7) {
17207 case MOVN_FMT: /* SELEQZ_FMT */
17208 if (ctx->insn_flags & ISA_MIPS_R6) {
17209 /* SELEQZ_FMT */
17210 switch ((ctx->opcode >> 9) & 0x3) {
17211 case FMT_SDPS_S:
17212 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
17213 break;
17214 case FMT_SDPS_D:
17215 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
17216 break;
17217 default:
17218 goto pool32f_invalid;
17220 } else {
17221 /* MOVN_FMT */
17222 FINSN_3ARG_SDPS(MOVN);
17224 break;
17225 case MOVN_FMT_04:
17226 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17227 FINSN_3ARG_SDPS(MOVN);
17228 break;
17229 case MOVZ_FMT: /* SELNEZ_FMT */
17230 if (ctx->insn_flags & ISA_MIPS_R6) {
17231 /* SELNEZ_FMT */
17232 switch ((ctx->opcode >> 9) & 0x3) {
17233 case FMT_SDPS_S:
17234 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
17235 break;
17236 case FMT_SDPS_D:
17237 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
17238 break;
17239 default:
17240 goto pool32f_invalid;
17242 } else {
17243 /* MOVZ_FMT */
17244 FINSN_3ARG_SDPS(MOVZ);
17246 break;
17247 case MOVZ_FMT_05:
17248 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17249 FINSN_3ARG_SDPS(MOVZ);
17250 break;
17251 case SEL_FMT:
17252 check_insn(ctx, ISA_MIPS_R6);
17253 switch ((ctx->opcode >> 9) & 0x3) {
17254 case FMT_SDPS_S:
17255 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
17256 break;
17257 case FMT_SDPS_D:
17258 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
17259 break;
17260 default:
17261 goto pool32f_invalid;
17263 break;
17264 case MADDF_FMT:
17265 check_insn(ctx, ISA_MIPS_R6);
17266 switch ((ctx->opcode >> 9) & 0x3) {
17267 case FMT_SDPS_S:
17268 mips32_op = OPC_MADDF_S;
17269 goto do_fpop;
17270 case FMT_SDPS_D:
17271 mips32_op = OPC_MADDF_D;
17272 goto do_fpop;
17273 default:
17274 goto pool32f_invalid;
17276 break;
17277 case MSUBF_FMT:
17278 check_insn(ctx, ISA_MIPS_R6);
17279 switch ((ctx->opcode >> 9) & 0x3) {
17280 case FMT_SDPS_S:
17281 mips32_op = OPC_MSUBF_S;
17282 goto do_fpop;
17283 case FMT_SDPS_D:
17284 mips32_op = OPC_MSUBF_D;
17285 goto do_fpop;
17286 default:
17287 goto pool32f_invalid;
17289 break;
17290 default:
17291 goto pool32f_invalid;
17293 break;
17294 do_fpop:
17295 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
17296 break;
17297 default:
17298 pool32f_invalid:
17299 MIPS_INVAL("pool32f");
17300 gen_reserved_instruction(ctx);
17301 break;
17303 } else {
17304 generate_exception_err(ctx, EXCP_CpU, 1);
17306 break;
17307 case POOL32I:
17308 minor = (ctx->opcode >> 21) & 0x1f;
17309 switch (minor) {
17310 case BLTZ:
17311 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17312 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
17313 break;
17314 case BLTZAL:
17315 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17316 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
17317 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17318 break;
17319 case BLTZALS:
17320 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17321 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
17322 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17323 break;
17324 case BGEZ:
17325 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17326 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
17327 break;
17328 case BGEZAL:
17329 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17330 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
17331 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17332 break;
17333 case BGEZALS:
17334 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17335 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
17336 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17337 break;
17338 case BLEZ:
17339 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17340 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
17341 break;
17342 case BGTZ:
17343 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17344 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
17345 break;
17347 /* Traps */
17348 case TLTI: /* BC1EQZC */
17349 if (ctx->insn_flags & ISA_MIPS_R6) {
17350 /* BC1EQZC */
17351 check_cp1_enabled(ctx);
17352 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
17353 } else {
17354 /* TLTI */
17355 mips32_op = OPC_TLTI;
17356 goto do_trapi;
17358 break;
17359 case TGEI: /* BC1NEZC */
17360 if (ctx->insn_flags & ISA_MIPS_R6) {
17361 /* BC1NEZC */
17362 check_cp1_enabled(ctx);
17363 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
17364 } else {
17365 /* TGEI */
17366 mips32_op = OPC_TGEI;
17367 goto do_trapi;
17369 break;
17370 case TLTIU:
17371 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17372 mips32_op = OPC_TLTIU;
17373 goto do_trapi;
17374 case TGEIU:
17375 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17376 mips32_op = OPC_TGEIU;
17377 goto do_trapi;
17378 case TNEI: /* SYNCI */
17379 if (ctx->insn_flags & ISA_MIPS_R6) {
17380 /* SYNCI */
17382 * Break the TB to be able to sync copied instructions
17383 * immediately.
17385 ctx->base.is_jmp = DISAS_STOP;
17386 } else {
17387 /* TNEI */
17388 mips32_op = OPC_TNEI;
17389 goto do_trapi;
17391 break;
17392 case TEQI:
17393 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17394 mips32_op = OPC_TEQI;
17395 do_trapi:
17396 gen_trap(ctx, mips32_op, rs, -1, imm);
17397 break;
17399 case BNEZC:
17400 case BEQZC:
17401 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17402 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
17403 4, rs, 0, imm << 1, 0);
17405 * Compact branches don't have a delay slot, so just let
17406 * the normal delay slot handling take us to the branch
17407 * target.
17409 break;
17410 case LUI:
17411 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17412 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
17413 break;
17414 case SYNCI:
17415 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17417 * Break the TB to be able to sync copied instructions
17418 * immediately.
17420 ctx->base.is_jmp = DISAS_STOP;
17421 break;
17422 case BC2F:
17423 case BC2T:
17424 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17425 /* COP2: Not implemented. */
17426 generate_exception_err(ctx, EXCP_CpU, 2);
17427 break;
17428 case BC1F:
17429 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17430 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
17431 goto do_cp1branch;
17432 case BC1T:
17433 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17434 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
17435 goto do_cp1branch;
17436 case BC1ANY4F:
17437 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17438 mips32_op = OPC_BC1FANY4;
17439 goto do_cp1mips3d;
17440 case BC1ANY4T:
17441 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17442 mips32_op = OPC_BC1TANY4;
17443 do_cp1mips3d:
17444 check_cop1x(ctx);
17445 check_insn(ctx, ASE_MIPS3D);
17446 /* Fall through */
17447 do_cp1branch:
17448 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
17449 check_cp1_enabled(ctx);
17450 gen_compute_branch1(ctx, mips32_op,
17451 (ctx->opcode >> 18) & 0x7, imm << 1);
17452 } else {
17453 generate_exception_err(ctx, EXCP_CpU, 1);
17455 break;
17456 case BPOSGE64:
17457 case BPOSGE32:
17458 /* MIPS DSP: not implemented */
17459 /* Fall through */
17460 default:
17461 MIPS_INVAL("pool32i");
17462 gen_reserved_instruction(ctx);
17463 break;
17465 break;
17466 case POOL32C:
17467 minor = (ctx->opcode >> 12) & 0xf;
17468 offset = sextract32(ctx->opcode, 0,
17469 (ctx->insn_flags & ISA_MIPS_R6) ? 9 : 12);
17470 switch (minor) {
17471 case LWL:
17472 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17473 mips32_op = OPC_LWL;
17474 goto do_ld_lr;
17475 case SWL:
17476 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17477 mips32_op = OPC_SWL;
17478 goto do_st_lr;
17479 case LWR:
17480 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17481 mips32_op = OPC_LWR;
17482 goto do_ld_lr;
17483 case SWR:
17484 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17485 mips32_op = OPC_SWR;
17486 goto do_st_lr;
17487 #if defined(TARGET_MIPS64)
17488 case LDL:
17489 check_insn(ctx, ISA_MIPS3);
17490 check_mips_64(ctx);
17491 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17492 mips32_op = OPC_LDL;
17493 goto do_ld_lr;
17494 case SDL:
17495 check_insn(ctx, ISA_MIPS3);
17496 check_mips_64(ctx);
17497 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17498 mips32_op = OPC_SDL;
17499 goto do_st_lr;
17500 case LDR:
17501 check_insn(ctx, ISA_MIPS3);
17502 check_mips_64(ctx);
17503 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17504 mips32_op = OPC_LDR;
17505 goto do_ld_lr;
17506 case SDR:
17507 check_insn(ctx, ISA_MIPS3);
17508 check_mips_64(ctx);
17509 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17510 mips32_op = OPC_SDR;
17511 goto do_st_lr;
17512 case LWU:
17513 check_insn(ctx, ISA_MIPS3);
17514 check_mips_64(ctx);
17515 mips32_op = OPC_LWU;
17516 goto do_ld_lr;
17517 case LLD:
17518 check_insn(ctx, ISA_MIPS3);
17519 check_mips_64(ctx);
17520 mips32_op = OPC_LLD;
17521 goto do_ld_lr;
17522 #endif
17523 case LL:
17524 mips32_op = OPC_LL;
17525 goto do_ld_lr;
17526 do_ld_lr:
17527 gen_ld(ctx, mips32_op, rt, rs, offset);
17528 break;
17529 do_st_lr:
17530 gen_st(ctx, mips32_op, rt, rs, offset);
17531 break;
17532 case SC:
17533 gen_st_cond(ctx, rt, rs, offset, MO_TESL, false);
17534 break;
17535 #if defined(TARGET_MIPS64)
17536 case SCD:
17537 check_insn(ctx, ISA_MIPS3);
17538 check_mips_64(ctx);
17539 gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false);
17540 break;
17541 #endif
17542 case LD_EVA:
17543 if (!ctx->eva) {
17544 MIPS_INVAL("pool32c ld-eva");
17545 gen_reserved_instruction(ctx);
17546 break;
17548 check_cp0_enabled(ctx);
17550 minor2 = (ctx->opcode >> 9) & 0x7;
17551 offset = sextract32(ctx->opcode, 0, 9);
17552 switch (minor2) {
17553 case LBUE:
17554 mips32_op = OPC_LBUE;
17555 goto do_ld_lr;
17556 case LHUE:
17557 mips32_op = OPC_LHUE;
17558 goto do_ld_lr;
17559 case LWLE:
17560 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17561 mips32_op = OPC_LWLE;
17562 goto do_ld_lr;
17563 case LWRE:
17564 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17565 mips32_op = OPC_LWRE;
17566 goto do_ld_lr;
17567 case LBE:
17568 mips32_op = OPC_LBE;
17569 goto do_ld_lr;
17570 case LHE:
17571 mips32_op = OPC_LHE;
17572 goto do_ld_lr;
17573 case LLE:
17574 mips32_op = OPC_LLE;
17575 goto do_ld_lr;
17576 case LWE:
17577 mips32_op = OPC_LWE;
17578 goto do_ld_lr;
17580 break;
17581 case ST_EVA:
17582 if (!ctx->eva) {
17583 MIPS_INVAL("pool32c st-eva");
17584 gen_reserved_instruction(ctx);
17585 break;
17587 check_cp0_enabled(ctx);
17589 minor2 = (ctx->opcode >> 9) & 0x7;
17590 offset = sextract32(ctx->opcode, 0, 9);
17591 switch (minor2) {
17592 case SWLE:
17593 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17594 mips32_op = OPC_SWLE;
17595 goto do_st_lr;
17596 case SWRE:
17597 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17598 mips32_op = OPC_SWRE;
17599 goto do_st_lr;
17600 case PREFE:
17601 /* Treat as no-op */
17602 if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >= 24)) {
17603 /* hint codes 24-31 are reserved and signal RI */
17604 generate_exception(ctx, EXCP_RI);
17606 break;
17607 case CACHEE:
17608 /* Treat as no-op */
17609 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
17610 gen_cache_operation(ctx, rt, rs, offset);
17612 break;
17613 case SBE:
17614 mips32_op = OPC_SBE;
17615 goto do_st_lr;
17616 case SHE:
17617 mips32_op = OPC_SHE;
17618 goto do_st_lr;
17619 case SCE:
17620 gen_st_cond(ctx, rt, rs, offset, MO_TESL, true);
17621 break;
17622 case SWE:
17623 mips32_op = OPC_SWE;
17624 goto do_st_lr;
17626 break;
17627 case PREF:
17628 /* Treat as no-op */
17629 if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >= 24)) {
17630 /* hint codes 24-31 are reserved and signal RI */
17631 generate_exception(ctx, EXCP_RI);
17633 break;
17634 default:
17635 MIPS_INVAL("pool32c");
17636 gen_reserved_instruction(ctx);
17637 break;
17639 break;
17640 case ADDI32: /* AUI, LUI */
17641 if (ctx->insn_flags & ISA_MIPS_R6) {
17642 /* AUI, LUI */
17643 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
17644 } else {
17645 /* ADDI32 */
17646 mips32_op = OPC_ADDI;
17647 goto do_addi;
17649 break;
17650 case ADDIU32:
17651 mips32_op = OPC_ADDIU;
17652 do_addi:
17653 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
17654 break;
17656 /* Logical operations */
17657 case ORI32:
17658 mips32_op = OPC_ORI;
17659 goto do_logici;
17660 case XORI32:
17661 mips32_op = OPC_XORI;
17662 goto do_logici;
17663 case ANDI32:
17664 mips32_op = OPC_ANDI;
17665 do_logici:
17666 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
17667 break;
17669 /* Set less than immediate */
17670 case SLTI32:
17671 mips32_op = OPC_SLTI;
17672 goto do_slti;
17673 case SLTIU32:
17674 mips32_op = OPC_SLTIU;
17675 do_slti:
17676 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
17677 break;
17678 case JALX32:
17679 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17680 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
17681 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
17682 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17683 break;
17684 case JALS32: /* BOVC, BEQC, BEQZALC */
17685 if (ctx->insn_flags & ISA_MIPS_R6) {
17686 if (rs >= rt) {
17687 /* BOVC */
17688 mips32_op = OPC_BOVC;
17689 } else if (rs < rt && rs == 0) {
17690 /* BEQZALC */
17691 mips32_op = OPC_BEQZALC;
17692 } else {
17693 /* BEQC */
17694 mips32_op = OPC_BEQC;
17696 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17697 } else {
17698 /* JALS32 */
17699 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
17700 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
17701 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17703 break;
17704 case BEQ32: /* BC */
17705 if (ctx->insn_flags & ISA_MIPS_R6) {
17706 /* BC */
17707 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
17708 sextract32(ctx->opcode << 1, 0, 27));
17709 } else {
17710 /* BEQ32 */
17711 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
17713 break;
17714 case BNE32: /* BALC */
17715 if (ctx->insn_flags & ISA_MIPS_R6) {
17716 /* BALC */
17717 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
17718 sextract32(ctx->opcode << 1, 0, 27));
17719 } else {
17720 /* BNE32 */
17721 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
17723 break;
17724 case J32: /* BGTZC, BLTZC, BLTC */
17725 if (ctx->insn_flags & ISA_MIPS_R6) {
17726 if (rs == 0 && rt != 0) {
17727 /* BGTZC */
17728 mips32_op = OPC_BGTZC;
17729 } else if (rs != 0 && rt != 0 && rs == rt) {
17730 /* BLTZC */
17731 mips32_op = OPC_BLTZC;
17732 } else {
17733 /* BLTC */
17734 mips32_op = OPC_BLTC;
17736 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17737 } else {
17738 /* J32 */
17739 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
17740 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17742 break;
17743 case JAL32: /* BLEZC, BGEZC, BGEC */
17744 if (ctx->insn_flags & ISA_MIPS_R6) {
17745 if (rs == 0 && rt != 0) {
17746 /* BLEZC */
17747 mips32_op = OPC_BLEZC;
17748 } else if (rs != 0 && rt != 0 && rs == rt) {
17749 /* BGEZC */
17750 mips32_op = OPC_BGEZC;
17751 } else {
17752 /* BGEC */
17753 mips32_op = OPC_BGEC;
17755 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17756 } else {
17757 /* JAL32 */
17758 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
17759 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17760 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17762 break;
17763 /* Floating point (COP1) */
17764 case LWC132:
17765 mips32_op = OPC_LWC1;
17766 goto do_cop1;
17767 case LDC132:
17768 mips32_op = OPC_LDC1;
17769 goto do_cop1;
17770 case SWC132:
17771 mips32_op = OPC_SWC1;
17772 goto do_cop1;
17773 case SDC132:
17774 mips32_op = OPC_SDC1;
17775 do_cop1:
17776 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
17777 break;
17778 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17779 if (ctx->insn_flags & ISA_MIPS_R6) {
17780 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17781 switch ((ctx->opcode >> 16) & 0x1f) {
17782 case ADDIUPC_00:
17783 case ADDIUPC_01:
17784 case ADDIUPC_02:
17785 case ADDIUPC_03:
17786 case ADDIUPC_04:
17787 case ADDIUPC_05:
17788 case ADDIUPC_06:
17789 case ADDIUPC_07:
17790 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
17791 break;
17792 case AUIPC:
17793 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
17794 break;
17795 case ALUIPC:
17796 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
17797 break;
17798 case LWPC_08:
17799 case LWPC_09:
17800 case LWPC_0A:
17801 case LWPC_0B:
17802 case LWPC_0C:
17803 case LWPC_0D:
17804 case LWPC_0E:
17805 case LWPC_0F:
17806 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
17807 break;
17808 default:
17809 generate_exception(ctx, EXCP_RI);
17810 break;
17812 } else {
17813 /* ADDIUPC */
17814 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
17815 offset = SIMM(ctx->opcode, 0, 23) << 2;
17817 gen_addiupc(ctx, reg, offset, 0, 0);
17819 break;
17820 case BNVC: /* BNEC, BNEZALC */
17821 check_insn(ctx, ISA_MIPS_R6);
17822 if (rs >= rt) {
17823 /* BNVC */
17824 mips32_op = OPC_BNVC;
17825 } else if (rs < rt && rs == 0) {
17826 /* BNEZALC */
17827 mips32_op = OPC_BNEZALC;
17828 } else {
17829 /* BNEC */
17830 mips32_op = OPC_BNEC;
17832 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17833 break;
17834 case R6_BNEZC: /* JIALC */
17835 check_insn(ctx, ISA_MIPS_R6);
17836 if (rt != 0) {
17837 /* BNEZC */
17838 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
17839 sextract32(ctx->opcode << 1, 0, 22));
17840 } else {
17841 /* JIALC */
17842 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
17844 break;
17845 case R6_BEQZC: /* JIC */
17846 check_insn(ctx, ISA_MIPS_R6);
17847 if (rt != 0) {
17848 /* BEQZC */
17849 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
17850 sextract32(ctx->opcode << 1, 0, 22));
17851 } else {
17852 /* JIC */
17853 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
17855 break;
17856 case BLEZALC: /* BGEZALC, BGEUC */
17857 check_insn(ctx, ISA_MIPS_R6);
17858 if (rs == 0 && rt != 0) {
17859 /* BLEZALC */
17860 mips32_op = OPC_BLEZALC;
17861 } else if (rs != 0 && rt != 0 && rs == rt) {
17862 /* BGEZALC */
17863 mips32_op = OPC_BGEZALC;
17864 } else {
17865 /* BGEUC */
17866 mips32_op = OPC_BGEUC;
17868 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17869 break;
17870 case BGTZALC: /* BLTZALC, BLTUC */
17871 check_insn(ctx, ISA_MIPS_R6);
17872 if (rs == 0 && rt != 0) {
17873 /* BGTZALC */
17874 mips32_op = OPC_BGTZALC;
17875 } else if (rs != 0 && rt != 0 && rs == rt) {
17876 /* BLTZALC */
17877 mips32_op = OPC_BLTZALC;
17878 } else {
17879 /* BLTUC */
17880 mips32_op = OPC_BLTUC;
17882 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17883 break;
17884 /* Loads and stores */
17885 case LB32:
17886 mips32_op = OPC_LB;
17887 goto do_ld;
17888 case LBU32:
17889 mips32_op = OPC_LBU;
17890 goto do_ld;
17891 case LH32:
17892 mips32_op = OPC_LH;
17893 goto do_ld;
17894 case LHU32:
17895 mips32_op = OPC_LHU;
17896 goto do_ld;
17897 case LW32:
17898 mips32_op = OPC_LW;
17899 goto do_ld;
17900 #ifdef TARGET_MIPS64
17901 case LD32:
17902 check_insn(ctx, ISA_MIPS3);
17903 check_mips_64(ctx);
17904 mips32_op = OPC_LD;
17905 goto do_ld;
17906 case SD32:
17907 check_insn(ctx, ISA_MIPS3);
17908 check_mips_64(ctx);
17909 mips32_op = OPC_SD;
17910 goto do_st;
17911 #endif
17912 case SB32:
17913 mips32_op = OPC_SB;
17914 goto do_st;
17915 case SH32:
17916 mips32_op = OPC_SH;
17917 goto do_st;
17918 case SW32:
17919 mips32_op = OPC_SW;
17920 goto do_st;
17921 do_ld:
17922 gen_ld(ctx, mips32_op, rt, rs, imm);
17923 break;
17924 do_st:
17925 gen_st(ctx, mips32_op, rt, rs, imm);
17926 break;
17927 default:
17928 gen_reserved_instruction(ctx);
17929 break;
17933 static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx)
17935 uint32_t op;
17937 /* make sure instructions are on a halfword boundary */
17938 if (ctx->base.pc_next & 0x1) {
17939 env->CP0_BadVAddr = ctx->base.pc_next;
17940 generate_exception_end(ctx, EXCP_AdEL);
17941 return 2;
17944 op = (ctx->opcode >> 10) & 0x3f;
17945 /* Enforce properly-sized instructions in a delay slot */
17946 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
17947 switch (op & 0x7) { /* MSB-3..MSB-5 */
17948 case 0:
17949 /* POOL32A, POOL32B, POOL32I, POOL32C */
17950 case 4:
17951 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
17952 case 5:
17953 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
17954 case 6:
17955 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
17956 case 7:
17957 /* LB32, LH32, LWC132, LDC132, LW32 */
17958 if (ctx->hflags & MIPS_HFLAG_BDS16) {
17959 gen_reserved_instruction(ctx);
17960 return 2;
17962 break;
17963 case 1:
17964 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
17965 case 2:
17966 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
17967 case 3:
17968 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
17969 if (ctx->hflags & MIPS_HFLAG_BDS32) {
17970 gen_reserved_instruction(ctx);
17971 return 2;
17973 break;
17977 switch (op) {
17978 case POOL16A:
17980 int rd = mmreg(uMIPS_RD(ctx->opcode));
17981 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
17982 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
17983 uint32_t opc = 0;
17985 switch (ctx->opcode & 0x1) {
17986 case ADDU16:
17987 opc = OPC_ADDU;
17988 break;
17989 case SUBU16:
17990 opc = OPC_SUBU;
17991 break;
17993 if (ctx->insn_flags & ISA_MIPS_R6) {
17995 * In the Release 6, the register number location in
17996 * the instruction encoding has changed.
17998 gen_arith(ctx, opc, rs1, rd, rs2);
17999 } else {
18000 gen_arith(ctx, opc, rd, rs1, rs2);
18003 break;
18004 case POOL16B:
18006 int rd = mmreg(uMIPS_RD(ctx->opcode));
18007 int rs = mmreg(uMIPS_RS(ctx->opcode));
18008 int amount = (ctx->opcode >> 1) & 0x7;
18009 uint32_t opc = 0;
18010 amount = amount == 0 ? 8 : amount;
18012 switch (ctx->opcode & 0x1) {
18013 case SLL16:
18014 opc = OPC_SLL;
18015 break;
18016 case SRL16:
18017 opc = OPC_SRL;
18018 break;
18021 gen_shift_imm(ctx, opc, rd, rs, amount);
18023 break;
18024 case POOL16C:
18025 if (ctx->insn_flags & ISA_MIPS_R6) {
18026 gen_pool16c_r6_insn(ctx);
18027 } else {
18028 gen_pool16c_insn(ctx);
18030 break;
18031 case LWGP16:
18033 int rd = mmreg(uMIPS_RD(ctx->opcode));
18034 int rb = 28; /* GP */
18035 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
18037 gen_ld(ctx, OPC_LW, rd, rb, offset);
18039 break;
18040 case POOL16F:
18041 check_insn_opc_removed(ctx, ISA_MIPS_R6);
18042 if (ctx->opcode & 1) {
18043 gen_reserved_instruction(ctx);
18044 } else {
18045 /* MOVEP */
18046 int enc_dest = uMIPS_RD(ctx->opcode);
18047 int enc_rt = uMIPS_RS2(ctx->opcode);
18048 int enc_rs = uMIPS_RS1(ctx->opcode);
18049 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
18051 break;
18052 case LBU16:
18054 int rd = mmreg(uMIPS_RD(ctx->opcode));
18055 int rb = mmreg(uMIPS_RS(ctx->opcode));
18056 int16_t offset = ZIMM(ctx->opcode, 0, 4);
18057 offset = (offset == 0xf ? -1 : offset);
18059 gen_ld(ctx, OPC_LBU, rd, rb, offset);
18061 break;
18062 case LHU16:
18064 int rd = mmreg(uMIPS_RD(ctx->opcode));
18065 int rb = mmreg(uMIPS_RS(ctx->opcode));
18066 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
18068 gen_ld(ctx, OPC_LHU, rd, rb, offset);
18070 break;
18071 case LWSP16:
18073 int rd = (ctx->opcode >> 5) & 0x1f;
18074 int rb = 29; /* SP */
18075 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
18077 gen_ld(ctx, OPC_LW, rd, rb, offset);
18079 break;
18080 case LW16:
18082 int rd = mmreg(uMIPS_RD(ctx->opcode));
18083 int rb = mmreg(uMIPS_RS(ctx->opcode));
18084 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
18086 gen_ld(ctx, OPC_LW, rd, rb, offset);
18088 break;
18089 case SB16:
18091 int rd = mmreg2(uMIPS_RD(ctx->opcode));
18092 int rb = mmreg(uMIPS_RS(ctx->opcode));
18093 int16_t offset = ZIMM(ctx->opcode, 0, 4);
18095 gen_st(ctx, OPC_SB, rd, rb, offset);
18097 break;
18098 case SH16:
18100 int rd = mmreg2(uMIPS_RD(ctx->opcode));
18101 int rb = mmreg(uMIPS_RS(ctx->opcode));
18102 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
18104 gen_st(ctx, OPC_SH, rd, rb, offset);
18106 break;
18107 case SWSP16:
18109 int rd = (ctx->opcode >> 5) & 0x1f;
18110 int rb = 29; /* SP */
18111 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
18113 gen_st(ctx, OPC_SW, rd, rb, offset);
18115 break;
18116 case SW16:
18118 int rd = mmreg2(uMIPS_RD(ctx->opcode));
18119 int rb = mmreg(uMIPS_RS(ctx->opcode));
18120 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
18122 gen_st(ctx, OPC_SW, rd, rb, offset);
18124 break;
18125 case MOVE16:
18127 int rd = uMIPS_RD5(ctx->opcode);
18128 int rs = uMIPS_RS5(ctx->opcode);
18130 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
18132 break;
18133 case ANDI16:
18134 gen_andi16(ctx);
18135 break;
18136 case POOL16D:
18137 switch (ctx->opcode & 0x1) {
18138 case ADDIUS5:
18139 gen_addius5(ctx);
18140 break;
18141 case ADDIUSP:
18142 gen_addiusp(ctx);
18143 break;
18145 break;
18146 case POOL16E:
18147 switch (ctx->opcode & 0x1) {
18148 case ADDIUR2:
18149 gen_addiur2(ctx);
18150 break;
18151 case ADDIUR1SP:
18152 gen_addiur1sp(ctx);
18153 break;
18155 break;
18156 case B16: /* BC16 */
18157 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
18158 sextract32(ctx->opcode, 0, 10) << 1,
18159 (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4);
18160 break;
18161 case BNEZ16: /* BNEZC16 */
18162 case BEQZ16: /* BEQZC16 */
18163 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
18164 mmreg(uMIPS_RD(ctx->opcode)),
18165 0, sextract32(ctx->opcode, 0, 7) << 1,
18166 (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4);
18168 break;
18169 case LI16:
18171 int reg = mmreg(uMIPS_RD(ctx->opcode));
18172 int imm = ZIMM(ctx->opcode, 0, 7);
18174 imm = (imm == 0x7f ? -1 : imm);
18175 tcg_gen_movi_tl(cpu_gpr[reg], imm);
18177 break;
18178 case RES_29:
18179 case RES_31:
18180 case RES_39:
18181 gen_reserved_instruction(ctx);
18182 break;
18183 default:
18184 decode_micromips32_opc(env, ctx);
18185 return 4;
18188 return 2;
18193 * nanoMIPS opcodes
18197 /* MAJOR, P16, and P32 pools opcodes */
18198 enum {
18199 NM_P_ADDIU = 0x00,
18200 NM_ADDIUPC = 0x01,
18201 NM_MOVE_BALC = 0x02,
18202 NM_P16_MV = 0x04,
18203 NM_LW16 = 0x05,
18204 NM_BC16 = 0x06,
18205 NM_P16_SR = 0x07,
18207 NM_POOL32A = 0x08,
18208 NM_P_BAL = 0x0a,
18209 NM_P16_SHIFT = 0x0c,
18210 NM_LWSP16 = 0x0d,
18211 NM_BALC16 = 0x0e,
18212 NM_P16_4X4 = 0x0f,
18214 NM_P_GP_W = 0x10,
18215 NM_P_GP_BH = 0x11,
18216 NM_P_J = 0x12,
18217 NM_P16C = 0x14,
18218 NM_LWGP16 = 0x15,
18219 NM_P16_LB = 0x17,
18221 NM_P48I = 0x18,
18222 NM_P16_A1 = 0x1c,
18223 NM_LW4X4 = 0x1d,
18224 NM_P16_LH = 0x1f,
18226 NM_P_U12 = 0x20,
18227 NM_P_LS_U12 = 0x21,
18228 NM_P_BR1 = 0x22,
18229 NM_P16_A2 = 0x24,
18230 NM_SW16 = 0x25,
18231 NM_BEQZC16 = 0x26,
18233 NM_POOL32F = 0x28,
18234 NM_P_LS_S9 = 0x29,
18235 NM_P_BR2 = 0x2a,
18237 NM_P16_ADDU = 0x2c,
18238 NM_SWSP16 = 0x2d,
18239 NM_BNEZC16 = 0x2e,
18240 NM_MOVEP = 0x2f,
18242 NM_POOL32S = 0x30,
18243 NM_P_BRI = 0x32,
18244 NM_LI16 = 0x34,
18245 NM_SWGP16 = 0x35,
18246 NM_P16_BR = 0x36,
18248 NM_P_LUI = 0x38,
18249 NM_ANDI16 = 0x3c,
18250 NM_SW4X4 = 0x3d,
18251 NM_MOVEPREV = 0x3f,
18254 /* POOL32A instruction pool */
18255 enum {
18256 NM_POOL32A0 = 0x00,
18257 NM_SPECIAL2 = 0x01,
18258 NM_COP2_1 = 0x02,
18259 NM_UDI = 0x03,
18260 NM_POOL32A5 = 0x05,
18261 NM_POOL32A7 = 0x07,
18264 /* P.GP.W instruction pool */
18265 enum {
18266 NM_ADDIUGP_W = 0x00,
18267 NM_LWGP = 0x02,
18268 NM_SWGP = 0x03,
18271 /* P48I instruction pool */
18272 enum {
18273 NM_LI48 = 0x00,
18274 NM_ADDIU48 = 0x01,
18275 NM_ADDIUGP48 = 0x02,
18276 NM_ADDIUPC48 = 0x03,
18277 NM_LWPC48 = 0x0b,
18278 NM_SWPC48 = 0x0f,
18281 /* P.U12 instruction pool */
18282 enum {
18283 NM_ORI = 0x00,
18284 NM_XORI = 0x01,
18285 NM_ANDI = 0x02,
18286 NM_P_SR = 0x03,
18287 NM_SLTI = 0x04,
18288 NM_SLTIU = 0x05,
18289 NM_SEQI = 0x06,
18290 NM_ADDIUNEG = 0x08,
18291 NM_P_SHIFT = 0x0c,
18292 NM_P_ROTX = 0x0d,
18293 NM_P_INS = 0x0e,
18294 NM_P_EXT = 0x0f,
18297 /* POOL32F instruction pool */
18298 enum {
18299 NM_POOL32F_0 = 0x00,
18300 NM_POOL32F_3 = 0x03,
18301 NM_POOL32F_5 = 0x05,
18304 /* POOL32S instruction pool */
18305 enum {
18306 NM_POOL32S_0 = 0x00,
18307 NM_POOL32S_4 = 0x04,
18310 /* P.LUI instruction pool */
18311 enum {
18312 NM_LUI = 0x00,
18313 NM_ALUIPC = 0x01,
18316 /* P.GP.BH instruction pool */
18317 enum {
18318 NM_LBGP = 0x00,
18319 NM_SBGP = 0x01,
18320 NM_LBUGP = 0x02,
18321 NM_ADDIUGP_B = 0x03,
18322 NM_P_GP_LH = 0x04,
18323 NM_P_GP_SH = 0x05,
18324 NM_P_GP_CP1 = 0x06,
18327 /* P.LS.U12 instruction pool */
18328 enum {
18329 NM_LB = 0x00,
18330 NM_SB = 0x01,
18331 NM_LBU = 0x02,
18332 NM_P_PREFU12 = 0x03,
18333 NM_LH = 0x04,
18334 NM_SH = 0x05,
18335 NM_LHU = 0x06,
18336 NM_LWU = 0x07,
18337 NM_LW = 0x08,
18338 NM_SW = 0x09,
18339 NM_LWC1 = 0x0a,
18340 NM_SWC1 = 0x0b,
18341 NM_LDC1 = 0x0e,
18342 NM_SDC1 = 0x0f,
18345 /* P.LS.S9 instruction pool */
18346 enum {
18347 NM_P_LS_S0 = 0x00,
18348 NM_P_LS_S1 = 0x01,
18349 NM_P_LS_E0 = 0x02,
18350 NM_P_LS_WM = 0x04,
18351 NM_P_LS_UAWM = 0x05,
18354 /* P.BAL instruction pool */
18355 enum {
18356 NM_BC = 0x00,
18357 NM_BALC = 0x01,
18360 /* P.J instruction pool */
18361 enum {
18362 NM_JALRC = 0x00,
18363 NM_JALRC_HB = 0x01,
18364 NM_P_BALRSC = 0x08,
18367 /* P.BR1 instruction pool */
18368 enum {
18369 NM_BEQC = 0x00,
18370 NM_P_BR3A = 0x01,
18371 NM_BGEC = 0x02,
18372 NM_BGEUC = 0x03,
18375 /* P.BR2 instruction pool */
18376 enum {
18377 NM_BNEC = 0x00,
18378 NM_BLTC = 0x02,
18379 NM_BLTUC = 0x03,
18382 /* P.BRI instruction pool */
18383 enum {
18384 NM_BEQIC = 0x00,
18385 NM_BBEQZC = 0x01,
18386 NM_BGEIC = 0x02,
18387 NM_BGEIUC = 0x03,
18388 NM_BNEIC = 0x04,
18389 NM_BBNEZC = 0x05,
18390 NM_BLTIC = 0x06,
18391 NM_BLTIUC = 0x07,
18394 /* P16.SHIFT instruction pool */
18395 enum {
18396 NM_SLL16 = 0x00,
18397 NM_SRL16 = 0x01,
18400 /* POOL16C instruction pool */
18401 enum {
18402 NM_POOL16C_0 = 0x00,
18403 NM_LWXS16 = 0x01,
18406 /* P16.A1 instruction pool */
18407 enum {
18408 NM_ADDIUR1SP = 0x01,
18411 /* P16.A2 instruction pool */
18412 enum {
18413 NM_ADDIUR2 = 0x00,
18414 NM_P_ADDIURS5 = 0x01,
18417 /* P16.ADDU instruction pool */
18418 enum {
18419 NM_ADDU16 = 0x00,
18420 NM_SUBU16 = 0x01,
18423 /* P16.SR instruction pool */
18424 enum {
18425 NM_SAVE16 = 0x00,
18426 NM_RESTORE_JRC16 = 0x01,
18429 /* P16.4X4 instruction pool */
18430 enum {
18431 NM_ADDU4X4 = 0x00,
18432 NM_MUL4X4 = 0x01,
18435 /* P16.LB instruction pool */
18436 enum {
18437 NM_LB16 = 0x00,
18438 NM_SB16 = 0x01,
18439 NM_LBU16 = 0x02,
18442 /* P16.LH instruction pool */
18443 enum {
18444 NM_LH16 = 0x00,
18445 NM_SH16 = 0x01,
18446 NM_LHU16 = 0x02,
18449 /* P.RI instruction pool */
18450 enum {
18451 NM_SIGRIE = 0x00,
18452 NM_P_SYSCALL = 0x01,
18453 NM_BREAK = 0x02,
18454 NM_SDBBP = 0x03,
18457 /* POOL32A0 instruction pool */
18458 enum {
18459 NM_P_TRAP = 0x00,
18460 NM_SEB = 0x01,
18461 NM_SLLV = 0x02,
18462 NM_MUL = 0x03,
18463 NM_MFC0 = 0x06,
18464 NM_MFHC0 = 0x07,
18465 NM_SEH = 0x09,
18466 NM_SRLV = 0x0a,
18467 NM_MUH = 0x0b,
18468 NM_MTC0 = 0x0e,
18469 NM_MTHC0 = 0x0f,
18470 NM_SRAV = 0x12,
18471 NM_MULU = 0x13,
18472 NM_ROTRV = 0x1a,
18473 NM_MUHU = 0x1b,
18474 NM_ADD = 0x22,
18475 NM_DIV = 0x23,
18476 NM_ADDU = 0x2a,
18477 NM_MOD = 0x2b,
18478 NM_SUB = 0x32,
18479 NM_DIVU = 0x33,
18480 NM_RDHWR = 0x38,
18481 NM_SUBU = 0x3a,
18482 NM_MODU = 0x3b,
18483 NM_P_CMOVE = 0x42,
18484 NM_FORK = 0x45,
18485 NM_MFTR = 0x46,
18486 NM_MFHTR = 0x47,
18487 NM_AND = 0x4a,
18488 NM_YIELD = 0x4d,
18489 NM_MTTR = 0x4e,
18490 NM_MTHTR = 0x4f,
18491 NM_OR = 0x52,
18492 NM_D_E_MT_VPE = 0x56,
18493 NM_NOR = 0x5a,
18494 NM_XOR = 0x62,
18495 NM_SLT = 0x6a,
18496 NM_P_SLTU = 0x72,
18497 NM_SOV = 0x7a,
18500 /* CRC32 instruction pool */
18501 enum {
18502 NM_CRC32B = 0x00,
18503 NM_CRC32H = 0x01,
18504 NM_CRC32W = 0x02,
18505 NM_CRC32CB = 0x04,
18506 NM_CRC32CH = 0x05,
18507 NM_CRC32CW = 0x06,
18510 /* POOL32A5 instruction pool */
18511 enum {
18512 NM_CMP_EQ_PH = 0x00,
18513 NM_CMP_LT_PH = 0x08,
18514 NM_CMP_LE_PH = 0x10,
18515 NM_CMPGU_EQ_QB = 0x18,
18516 NM_CMPGU_LT_QB = 0x20,
18517 NM_CMPGU_LE_QB = 0x28,
18518 NM_CMPGDU_EQ_QB = 0x30,
18519 NM_CMPGDU_LT_QB = 0x38,
18520 NM_CMPGDU_LE_QB = 0x40,
18521 NM_CMPU_EQ_QB = 0x48,
18522 NM_CMPU_LT_QB = 0x50,
18523 NM_CMPU_LE_QB = 0x58,
18524 NM_ADDQ_S_W = 0x60,
18525 NM_SUBQ_S_W = 0x68,
18526 NM_ADDSC = 0x70,
18527 NM_ADDWC = 0x78,
18529 NM_ADDQ_S_PH = 0x01,
18530 NM_ADDQH_R_PH = 0x09,
18531 NM_ADDQH_R_W = 0x11,
18532 NM_ADDU_S_QB = 0x19,
18533 NM_ADDU_S_PH = 0x21,
18534 NM_ADDUH_R_QB = 0x29,
18535 NM_SHRAV_R_PH = 0x31,
18536 NM_SHRAV_R_QB = 0x39,
18537 NM_SUBQ_S_PH = 0x41,
18538 NM_SUBQH_R_PH = 0x49,
18539 NM_SUBQH_R_W = 0x51,
18540 NM_SUBU_S_QB = 0x59,
18541 NM_SUBU_S_PH = 0x61,
18542 NM_SUBUH_R_QB = 0x69,
18543 NM_SHLLV_S_PH = 0x71,
18544 NM_PRECR_SRA_R_PH_W = 0x79,
18546 NM_MULEU_S_PH_QBL = 0x12,
18547 NM_MULEU_S_PH_QBR = 0x1a,
18548 NM_MULQ_RS_PH = 0x22,
18549 NM_MULQ_S_PH = 0x2a,
18550 NM_MULQ_RS_W = 0x32,
18551 NM_MULQ_S_W = 0x3a,
18552 NM_APPEND = 0x42,
18553 NM_MODSUB = 0x52,
18554 NM_SHRAV_R_W = 0x5a,
18555 NM_SHRLV_PH = 0x62,
18556 NM_SHRLV_QB = 0x6a,
18557 NM_SHLLV_QB = 0x72,
18558 NM_SHLLV_S_W = 0x7a,
18560 NM_SHILO = 0x03,
18562 NM_MULEQ_S_W_PHL = 0x04,
18563 NM_MULEQ_S_W_PHR = 0x0c,
18565 NM_MUL_S_PH = 0x05,
18566 NM_PRECR_QB_PH = 0x0d,
18567 NM_PRECRQ_QB_PH = 0x15,
18568 NM_PRECRQ_PH_W = 0x1d,
18569 NM_PRECRQ_RS_PH_W = 0x25,
18570 NM_PRECRQU_S_QB_PH = 0x2d,
18571 NM_PACKRL_PH = 0x35,
18572 NM_PICK_QB = 0x3d,
18573 NM_PICK_PH = 0x45,
18575 NM_SHRA_R_W = 0x5e,
18576 NM_SHRA_R_PH = 0x66,
18577 NM_SHLL_S_PH = 0x76,
18578 NM_SHLL_S_W = 0x7e,
18580 NM_REPL_PH = 0x07
18583 /* POOL32A7 instruction pool */
18584 enum {
18585 NM_P_LSX = 0x00,
18586 NM_LSA = 0x01,
18587 NM_EXTW = 0x03,
18588 NM_POOL32AXF = 0x07,
18591 /* P.SR instruction pool */
18592 enum {
18593 NM_PP_SR = 0x00,
18594 NM_P_SR_F = 0x01,
18597 /* P.SHIFT instruction pool */
18598 enum {
18599 NM_P_SLL = 0x00,
18600 NM_SRL = 0x02,
18601 NM_SRA = 0x04,
18602 NM_ROTR = 0x06,
18605 /* P.ROTX instruction pool */
18606 enum {
18607 NM_ROTX = 0x00,
18610 /* P.INS instruction pool */
18611 enum {
18612 NM_INS = 0x00,
18615 /* P.EXT instruction pool */
18616 enum {
18617 NM_EXT = 0x00,
18620 /* POOL32F_0 (fmt) instruction pool */
18621 enum {
18622 NM_RINT_S = 0x04,
18623 NM_RINT_D = 0x44,
18624 NM_ADD_S = 0x06,
18625 NM_SELEQZ_S = 0x07,
18626 NM_SELEQZ_D = 0x47,
18627 NM_CLASS_S = 0x0c,
18628 NM_CLASS_D = 0x4c,
18629 NM_SUB_S = 0x0e,
18630 NM_SELNEZ_S = 0x0f,
18631 NM_SELNEZ_D = 0x4f,
18632 NM_MUL_S = 0x16,
18633 NM_SEL_S = 0x17,
18634 NM_SEL_D = 0x57,
18635 NM_DIV_S = 0x1e,
18636 NM_ADD_D = 0x26,
18637 NM_SUB_D = 0x2e,
18638 NM_MUL_D = 0x36,
18639 NM_MADDF_S = 0x37,
18640 NM_MADDF_D = 0x77,
18641 NM_DIV_D = 0x3e,
18642 NM_MSUBF_S = 0x3f,
18643 NM_MSUBF_D = 0x7f,
18646 /* POOL32F_3 instruction pool */
18647 enum {
18648 NM_MIN_FMT = 0x00,
18649 NM_MAX_FMT = 0x01,
18650 NM_MINA_FMT = 0x04,
18651 NM_MAXA_FMT = 0x05,
18652 NM_POOL32FXF = 0x07,
18655 /* POOL32F_5 instruction pool */
18656 enum {
18657 NM_CMP_CONDN_S = 0x00,
18658 NM_CMP_CONDN_D = 0x02,
18661 /* P.GP.LH instruction pool */
18662 enum {
18663 NM_LHGP = 0x00,
18664 NM_LHUGP = 0x01,
18667 /* P.GP.SH instruction pool */
18668 enum {
18669 NM_SHGP = 0x00,
18672 /* P.GP.CP1 instruction pool */
18673 enum {
18674 NM_LWC1GP = 0x00,
18675 NM_SWC1GP = 0x01,
18676 NM_LDC1GP = 0x02,
18677 NM_SDC1GP = 0x03,
18680 /* P.LS.S0 instruction pool */
18681 enum {
18682 NM_LBS9 = 0x00,
18683 NM_LHS9 = 0x04,
18684 NM_LWS9 = 0x08,
18685 NM_LDS9 = 0x0c,
18687 NM_SBS9 = 0x01,
18688 NM_SHS9 = 0x05,
18689 NM_SWS9 = 0x09,
18690 NM_SDS9 = 0x0d,
18692 NM_LBUS9 = 0x02,
18693 NM_LHUS9 = 0x06,
18694 NM_LWC1S9 = 0x0a,
18695 NM_LDC1S9 = 0x0e,
18697 NM_P_PREFS9 = 0x03,
18698 NM_LWUS9 = 0x07,
18699 NM_SWC1S9 = 0x0b,
18700 NM_SDC1S9 = 0x0f,
18703 /* P.LS.S1 instruction pool */
18704 enum {
18705 NM_ASET_ACLR = 0x02,
18706 NM_UALH = 0x04,
18707 NM_UASH = 0x05,
18708 NM_CACHE = 0x07,
18709 NM_P_LL = 0x0a,
18710 NM_P_SC = 0x0b,
18713 /* P.LS.E0 instruction pool */
18714 enum {
18715 NM_LBE = 0x00,
18716 NM_SBE = 0x01,
18717 NM_LBUE = 0x02,
18718 NM_P_PREFE = 0x03,
18719 NM_LHE = 0x04,
18720 NM_SHE = 0x05,
18721 NM_LHUE = 0x06,
18722 NM_CACHEE = 0x07,
18723 NM_LWE = 0x08,
18724 NM_SWE = 0x09,
18725 NM_P_LLE = 0x0a,
18726 NM_P_SCE = 0x0b,
18729 /* P.PREFE instruction pool */
18730 enum {
18731 NM_SYNCIE = 0x00,
18732 NM_PREFE = 0x01,
18735 /* P.LLE instruction pool */
18736 enum {
18737 NM_LLE = 0x00,
18738 NM_LLWPE = 0x01,
18741 /* P.SCE instruction pool */
18742 enum {
18743 NM_SCE = 0x00,
18744 NM_SCWPE = 0x01,
18747 /* P.LS.WM instruction pool */
18748 enum {
18749 NM_LWM = 0x00,
18750 NM_SWM = 0x01,
18753 /* P.LS.UAWM instruction pool */
18754 enum {
18755 NM_UALWM = 0x00,
18756 NM_UASWM = 0x01,
18759 /* P.BR3A instruction pool */
18760 enum {
18761 NM_BC1EQZC = 0x00,
18762 NM_BC1NEZC = 0x01,
18763 NM_BC2EQZC = 0x02,
18764 NM_BC2NEZC = 0x03,
18765 NM_BPOSGE32C = 0x04,
18768 /* P16.RI instruction pool */
18769 enum {
18770 NM_P16_SYSCALL = 0x01,
18771 NM_BREAK16 = 0x02,
18772 NM_SDBBP16 = 0x03,
18775 /* POOL16C_0 instruction pool */
18776 enum {
18777 NM_POOL16C_00 = 0x00,
18780 /* P16.JRC instruction pool */
18781 enum {
18782 NM_JRC = 0x00,
18783 NM_JALRC16 = 0x01,
18786 /* P.SYSCALL instruction pool */
18787 enum {
18788 NM_SYSCALL = 0x00,
18789 NM_HYPCALL = 0x01,
18792 /* P.TRAP instruction pool */
18793 enum {
18794 NM_TEQ = 0x00,
18795 NM_TNE = 0x01,
18798 /* P.CMOVE instruction pool */
18799 enum {
18800 NM_MOVZ = 0x00,
18801 NM_MOVN = 0x01,
18804 /* POOL32Axf instruction pool */
18805 enum {
18806 NM_POOL32AXF_1 = 0x01,
18807 NM_POOL32AXF_2 = 0x02,
18808 NM_POOL32AXF_4 = 0x04,
18809 NM_POOL32AXF_5 = 0x05,
18810 NM_POOL32AXF_7 = 0x07,
18813 /* POOL32Axf_1 instruction pool */
18814 enum {
18815 NM_POOL32AXF_1_0 = 0x00,
18816 NM_POOL32AXF_1_1 = 0x01,
18817 NM_POOL32AXF_1_3 = 0x03,
18818 NM_POOL32AXF_1_4 = 0x04,
18819 NM_POOL32AXF_1_5 = 0x05,
18820 NM_POOL32AXF_1_7 = 0x07,
18823 /* POOL32Axf_2 instruction pool */
18824 enum {
18825 NM_POOL32AXF_2_0_7 = 0x00,
18826 NM_POOL32AXF_2_8_15 = 0x01,
18827 NM_POOL32AXF_2_16_23 = 0x02,
18828 NM_POOL32AXF_2_24_31 = 0x03,
18831 /* POOL32Axf_7 instruction pool */
18832 enum {
18833 NM_SHRA_R_QB = 0x0,
18834 NM_SHRL_PH = 0x1,
18835 NM_REPL_QB = 0x2,
18838 /* POOL32Axf_1_0 instruction pool */
18839 enum {
18840 NM_MFHI = 0x0,
18841 NM_MFLO = 0x1,
18842 NM_MTHI = 0x2,
18843 NM_MTLO = 0x3,
18846 /* POOL32Axf_1_1 instruction pool */
18847 enum {
18848 NM_MTHLIP = 0x0,
18849 NM_SHILOV = 0x1,
18852 /* POOL32Axf_1_3 instruction pool */
18853 enum {
18854 NM_RDDSP = 0x0,
18855 NM_WRDSP = 0x1,
18856 NM_EXTP = 0x2,
18857 NM_EXTPDP = 0x3,
18860 /* POOL32Axf_1_4 instruction pool */
18861 enum {
18862 NM_SHLL_QB = 0x0,
18863 NM_SHRL_QB = 0x1,
18866 /* POOL32Axf_1_5 instruction pool */
18867 enum {
18868 NM_MAQ_S_W_PHR = 0x0,
18869 NM_MAQ_S_W_PHL = 0x1,
18870 NM_MAQ_SA_W_PHR = 0x2,
18871 NM_MAQ_SA_W_PHL = 0x3,
18874 /* POOL32Axf_1_7 instruction pool */
18875 enum {
18876 NM_EXTR_W = 0x0,
18877 NM_EXTR_R_W = 0x1,
18878 NM_EXTR_RS_W = 0x2,
18879 NM_EXTR_S_H = 0x3,
18882 /* POOL32Axf_2_0_7 instruction pool */
18883 enum {
18884 NM_DPA_W_PH = 0x0,
18885 NM_DPAQ_S_W_PH = 0x1,
18886 NM_DPS_W_PH = 0x2,
18887 NM_DPSQ_S_W_PH = 0x3,
18888 NM_BALIGN = 0x4,
18889 NM_MADD = 0x5,
18890 NM_MULT = 0x6,
18891 NM_EXTRV_W = 0x7,
18894 /* POOL32Axf_2_8_15 instruction pool */
18895 enum {
18896 NM_DPAX_W_PH = 0x0,
18897 NM_DPAQ_SA_L_W = 0x1,
18898 NM_DPSX_W_PH = 0x2,
18899 NM_DPSQ_SA_L_W = 0x3,
18900 NM_MADDU = 0x5,
18901 NM_MULTU = 0x6,
18902 NM_EXTRV_R_W = 0x7,
18905 /* POOL32Axf_2_16_23 instruction pool */
18906 enum {
18907 NM_DPAU_H_QBL = 0x0,
18908 NM_DPAQX_S_W_PH = 0x1,
18909 NM_DPSU_H_QBL = 0x2,
18910 NM_DPSQX_S_W_PH = 0x3,
18911 NM_EXTPV = 0x4,
18912 NM_MSUB = 0x5,
18913 NM_MULSA_W_PH = 0x6,
18914 NM_EXTRV_RS_W = 0x7,
18917 /* POOL32Axf_2_24_31 instruction pool */
18918 enum {
18919 NM_DPAU_H_QBR = 0x0,
18920 NM_DPAQX_SA_W_PH = 0x1,
18921 NM_DPSU_H_QBR = 0x2,
18922 NM_DPSQX_SA_W_PH = 0x3,
18923 NM_EXTPDPV = 0x4,
18924 NM_MSUBU = 0x5,
18925 NM_MULSAQ_S_W_PH = 0x6,
18926 NM_EXTRV_S_H = 0x7,
18929 /* POOL32Axf_{4, 5} instruction pool */
18930 enum {
18931 NM_CLO = 0x25,
18932 NM_CLZ = 0x2d,
18934 NM_TLBP = 0x01,
18935 NM_TLBR = 0x09,
18936 NM_TLBWI = 0x11,
18937 NM_TLBWR = 0x19,
18938 NM_TLBINV = 0x03,
18939 NM_TLBINVF = 0x0b,
18940 NM_DI = 0x23,
18941 NM_EI = 0x2b,
18942 NM_RDPGPR = 0x70,
18943 NM_WRPGPR = 0x78,
18944 NM_WAIT = 0x61,
18945 NM_DERET = 0x71,
18946 NM_ERETX = 0x79,
18948 /* nanoMIPS DSP instructions */
18949 NM_ABSQ_S_QB = 0x00,
18950 NM_ABSQ_S_PH = 0x08,
18951 NM_ABSQ_S_W = 0x10,
18952 NM_PRECEQ_W_PHL = 0x28,
18953 NM_PRECEQ_W_PHR = 0x30,
18954 NM_PRECEQU_PH_QBL = 0x38,
18955 NM_PRECEQU_PH_QBR = 0x48,
18956 NM_PRECEU_PH_QBL = 0x58,
18957 NM_PRECEU_PH_QBR = 0x68,
18958 NM_PRECEQU_PH_QBLA = 0x39,
18959 NM_PRECEQU_PH_QBRA = 0x49,
18960 NM_PRECEU_PH_QBLA = 0x59,
18961 NM_PRECEU_PH_QBRA = 0x69,
18962 NM_REPLV_PH = 0x01,
18963 NM_REPLV_QB = 0x09,
18964 NM_BITREV = 0x18,
18965 NM_INSV = 0x20,
18966 NM_RADDU_W_QB = 0x78,
18968 NM_BITSWAP = 0x05,
18969 NM_WSBH = 0x3d,
18972 /* PP.SR instruction pool */
18973 enum {
18974 NM_SAVE = 0x00,
18975 NM_RESTORE = 0x02,
18976 NM_RESTORE_JRC = 0x03,
18979 /* P.SR.F instruction pool */
18980 enum {
18981 NM_SAVEF = 0x00,
18982 NM_RESTOREF = 0x01,
18985 /* P16.SYSCALL instruction pool */
18986 enum {
18987 NM_SYSCALL16 = 0x00,
18988 NM_HYPCALL16 = 0x01,
18991 /* POOL16C_00 instruction pool */
18992 enum {
18993 NM_NOT16 = 0x00,
18994 NM_XOR16 = 0x01,
18995 NM_AND16 = 0x02,
18996 NM_OR16 = 0x03,
18999 /* PP.LSX and PP.LSXS instruction pool */
19000 enum {
19001 NM_LBX = 0x00,
19002 NM_LHX = 0x04,
19003 NM_LWX = 0x08,
19004 NM_LDX = 0x0c,
19006 NM_SBX = 0x01,
19007 NM_SHX = 0x05,
19008 NM_SWX = 0x09,
19009 NM_SDX = 0x0d,
19011 NM_LBUX = 0x02,
19012 NM_LHUX = 0x06,
19013 NM_LWC1X = 0x0a,
19014 NM_LDC1X = 0x0e,
19016 NM_LWUX = 0x07,
19017 NM_SWC1X = 0x0b,
19018 NM_SDC1X = 0x0f,
19020 NM_LHXS = 0x04,
19021 NM_LWXS = 0x08,
19022 NM_LDXS = 0x0c,
19024 NM_SHXS = 0x05,
19025 NM_SWXS = 0x09,
19026 NM_SDXS = 0x0d,
19028 NM_LHUXS = 0x06,
19029 NM_LWC1XS = 0x0a,
19030 NM_LDC1XS = 0x0e,
19032 NM_LWUXS = 0x07,
19033 NM_SWC1XS = 0x0b,
19034 NM_SDC1XS = 0x0f,
19037 /* ERETx instruction pool */
19038 enum {
19039 NM_ERET = 0x00,
19040 NM_ERETNC = 0x01,
19043 /* POOL32FxF_{0, 1} insturction pool */
19044 enum {
19045 NM_CFC1 = 0x40,
19046 NM_CTC1 = 0x60,
19047 NM_MFC1 = 0x80,
19048 NM_MTC1 = 0xa0,
19049 NM_MFHC1 = 0xc0,
19050 NM_MTHC1 = 0xe0,
19052 NM_CVT_S_PL = 0x84,
19053 NM_CVT_S_PU = 0xa4,
19055 NM_CVT_L_S = 0x004,
19056 NM_CVT_L_D = 0x104,
19057 NM_CVT_W_S = 0x024,
19058 NM_CVT_W_D = 0x124,
19060 NM_RSQRT_S = 0x008,
19061 NM_RSQRT_D = 0x108,
19063 NM_SQRT_S = 0x028,
19064 NM_SQRT_D = 0x128,
19066 NM_RECIP_S = 0x048,
19067 NM_RECIP_D = 0x148,
19069 NM_FLOOR_L_S = 0x00c,
19070 NM_FLOOR_L_D = 0x10c,
19072 NM_FLOOR_W_S = 0x02c,
19073 NM_FLOOR_W_D = 0x12c,
19075 NM_CEIL_L_S = 0x04c,
19076 NM_CEIL_L_D = 0x14c,
19077 NM_CEIL_W_S = 0x06c,
19078 NM_CEIL_W_D = 0x16c,
19079 NM_TRUNC_L_S = 0x08c,
19080 NM_TRUNC_L_D = 0x18c,
19081 NM_TRUNC_W_S = 0x0ac,
19082 NM_TRUNC_W_D = 0x1ac,
19083 NM_ROUND_L_S = 0x0cc,
19084 NM_ROUND_L_D = 0x1cc,
19085 NM_ROUND_W_S = 0x0ec,
19086 NM_ROUND_W_D = 0x1ec,
19088 NM_MOV_S = 0x01,
19089 NM_MOV_D = 0x81,
19090 NM_ABS_S = 0x0d,
19091 NM_ABS_D = 0x8d,
19092 NM_NEG_S = 0x2d,
19093 NM_NEG_D = 0xad,
19094 NM_CVT_D_S = 0x04d,
19095 NM_CVT_D_W = 0x0cd,
19096 NM_CVT_D_L = 0x14d,
19097 NM_CVT_S_D = 0x06d,
19098 NM_CVT_S_W = 0x0ed,
19099 NM_CVT_S_L = 0x16d,
19102 /* P.LL instruction pool */
19103 enum {
19104 NM_LL = 0x00,
19105 NM_LLWP = 0x01,
19108 /* P.SC instruction pool */
19109 enum {
19110 NM_SC = 0x00,
19111 NM_SCWP = 0x01,
19114 /* P.DVP instruction pool */
19115 enum {
19116 NM_DVP = 0x00,
19117 NM_EVP = 0x01,
19123 * nanoMIPS decoding engine
19128 /* extraction utilities */
19130 #define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7)
19131 #define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7)
19132 #define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7)
19133 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
19134 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
19136 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
19137 static inline int decode_gpr_gpr3(int r)
19139 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
19141 return map[r & 0x7];
19144 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
19145 static inline int decode_gpr_gpr3_src_store(int r)
19147 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
19149 return map[r & 0x7];
19152 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
19153 static inline int decode_gpr_gpr4(int r)
19155 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
19156 16, 17, 18, 19, 20, 21, 22, 23 };
19158 return map[r & 0xf];
19161 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
19162 static inline int decode_gpr_gpr4_zero(int r)
19164 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
19165 16, 17, 18, 19, 20, 21, 22, 23 };
19167 return map[r & 0xf];
19171 static void gen_adjust_sp(DisasContext *ctx, int u)
19173 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
19176 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
19177 uint8_t gp, uint16_t u)
19179 int counter = 0;
19180 TCGv va = tcg_temp_new();
19181 TCGv t0 = tcg_temp_new();
19183 while (counter != count) {
19184 bool use_gp = gp && (counter == count - 1);
19185 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
19186 int this_offset = -((counter + 1) << 2);
19187 gen_base_offset_addr(ctx, va, 29, this_offset);
19188 gen_load_gpr(t0, this_rt);
19189 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
19190 (MO_TEUL | ctx->default_tcg_memop_mask));
19191 counter++;
19194 /* adjust stack pointer */
19195 gen_adjust_sp(ctx, -u);
19197 tcg_temp_free(t0);
19198 tcg_temp_free(va);
19201 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
19202 uint8_t gp, uint16_t u)
19204 int counter = 0;
19205 TCGv va = tcg_temp_new();
19206 TCGv t0 = tcg_temp_new();
19208 while (counter != count) {
19209 bool use_gp = gp && (counter == count - 1);
19210 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
19211 int this_offset = u - ((counter + 1) << 2);
19212 gen_base_offset_addr(ctx, va, 29, this_offset);
19213 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
19214 ctx->default_tcg_memop_mask);
19215 tcg_gen_ext32s_tl(t0, t0);
19216 gen_store_gpr(t0, this_rt);
19217 counter++;
19220 /* adjust stack pointer */
19221 gen_adjust_sp(ctx, u);
19223 tcg_temp_free(t0);
19224 tcg_temp_free(va);
19227 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
19229 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
19230 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
19232 switch (extract32(ctx->opcode, 2, 2)) {
19233 case NM_NOT16:
19234 gen_logic(ctx, OPC_NOR, rt, rs, 0);
19235 break;
19236 case NM_AND16:
19237 gen_logic(ctx, OPC_AND, rt, rt, rs);
19238 break;
19239 case NM_XOR16:
19240 gen_logic(ctx, OPC_XOR, rt, rt, rs);
19241 break;
19242 case NM_OR16:
19243 gen_logic(ctx, OPC_OR, rt, rt, rs);
19244 break;
19248 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19250 int rt = extract32(ctx->opcode, 21, 5);
19251 int rs = extract32(ctx->opcode, 16, 5);
19252 int rd = extract32(ctx->opcode, 11, 5);
19254 switch (extract32(ctx->opcode, 3, 7)) {
19255 case NM_P_TRAP:
19256 switch (extract32(ctx->opcode, 10, 1)) {
19257 case NM_TEQ:
19258 check_nms(ctx);
19259 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
19260 break;
19261 case NM_TNE:
19262 check_nms(ctx);
19263 gen_trap(ctx, OPC_TNE, rs, rt, -1);
19264 break;
19266 break;
19267 case NM_RDHWR:
19268 check_nms(ctx);
19269 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
19270 break;
19271 case NM_SEB:
19272 check_nms(ctx);
19273 gen_bshfl(ctx, OPC_SEB, rs, rt);
19274 break;
19275 case NM_SEH:
19276 gen_bshfl(ctx, OPC_SEH, rs, rt);
19277 break;
19278 case NM_SLLV:
19279 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
19280 break;
19281 case NM_SRLV:
19282 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
19283 break;
19284 case NM_SRAV:
19285 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
19286 break;
19287 case NM_ROTRV:
19288 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
19289 break;
19290 case NM_ADD:
19291 gen_arith(ctx, OPC_ADD, rd, rs, rt);
19292 break;
19293 case NM_ADDU:
19294 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
19295 break;
19296 case NM_SUB:
19297 check_nms(ctx);
19298 gen_arith(ctx, OPC_SUB, rd, rs, rt);
19299 break;
19300 case NM_SUBU:
19301 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
19302 break;
19303 case NM_P_CMOVE:
19304 switch (extract32(ctx->opcode, 10, 1)) {
19305 case NM_MOVZ:
19306 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
19307 break;
19308 case NM_MOVN:
19309 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
19310 break;
19312 break;
19313 case NM_AND:
19314 gen_logic(ctx, OPC_AND, rd, rs, rt);
19315 break;
19316 case NM_OR:
19317 gen_logic(ctx, OPC_OR, rd, rs, rt);
19318 break;
19319 case NM_NOR:
19320 gen_logic(ctx, OPC_NOR, rd, rs, rt);
19321 break;
19322 case NM_XOR:
19323 gen_logic(ctx, OPC_XOR, rd, rs, rt);
19324 break;
19325 case NM_SLT:
19326 gen_slt(ctx, OPC_SLT, rd, rs, rt);
19327 break;
19328 case NM_P_SLTU:
19329 if (rd == 0) {
19330 /* P_DVP */
19331 #ifndef CONFIG_USER_ONLY
19332 TCGv t0 = tcg_temp_new();
19333 switch (extract32(ctx->opcode, 10, 1)) {
19334 case NM_DVP:
19335 if (ctx->vp) {
19336 check_cp0_enabled(ctx);
19337 gen_helper_dvp(t0, cpu_env);
19338 gen_store_gpr(t0, rt);
19340 break;
19341 case NM_EVP:
19342 if (ctx->vp) {
19343 check_cp0_enabled(ctx);
19344 gen_helper_evp(t0, cpu_env);
19345 gen_store_gpr(t0, rt);
19347 break;
19349 tcg_temp_free(t0);
19350 #endif
19351 } else {
19352 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
19354 break;
19355 case NM_SOV:
19357 TCGv t0 = tcg_temp_new();
19358 TCGv t1 = tcg_temp_new();
19359 TCGv t2 = tcg_temp_new();
19361 gen_load_gpr(t1, rs);
19362 gen_load_gpr(t2, rt);
19363 tcg_gen_add_tl(t0, t1, t2);
19364 tcg_gen_ext32s_tl(t0, t0);
19365 tcg_gen_xor_tl(t1, t1, t2);
19366 tcg_gen_xor_tl(t2, t0, t2);
19367 tcg_gen_andc_tl(t1, t2, t1);
19369 /* operands of same sign, result different sign */
19370 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
19371 gen_store_gpr(t0, rd);
19373 tcg_temp_free(t0);
19374 tcg_temp_free(t1);
19375 tcg_temp_free(t2);
19377 break;
19378 case NM_MUL:
19379 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
19380 break;
19381 case NM_MUH:
19382 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
19383 break;
19384 case NM_MULU:
19385 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
19386 break;
19387 case NM_MUHU:
19388 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
19389 break;
19390 case NM_DIV:
19391 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
19392 break;
19393 case NM_MOD:
19394 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
19395 break;
19396 case NM_DIVU:
19397 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
19398 break;
19399 case NM_MODU:
19400 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
19401 break;
19402 #ifndef CONFIG_USER_ONLY
19403 case NM_MFC0:
19404 check_cp0_enabled(ctx);
19405 if (rt == 0) {
19406 /* Treat as NOP. */
19407 break;
19409 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
19410 break;
19411 case NM_MTC0:
19412 check_cp0_enabled(ctx);
19414 TCGv t0 = tcg_temp_new();
19416 gen_load_gpr(t0, rt);
19417 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
19418 tcg_temp_free(t0);
19420 break;
19421 case NM_D_E_MT_VPE:
19423 uint8_t sc = extract32(ctx->opcode, 10, 1);
19424 TCGv t0 = tcg_temp_new();
19426 switch (sc) {
19427 case 0:
19428 if (rs == 1) {
19429 /* DMT */
19430 check_cp0_mt(ctx);
19431 gen_helper_dmt(t0);
19432 gen_store_gpr(t0, rt);
19433 } else if (rs == 0) {
19434 /* DVPE */
19435 check_cp0_mt(ctx);
19436 gen_helper_dvpe(t0, cpu_env);
19437 gen_store_gpr(t0, rt);
19438 } else {
19439 gen_reserved_instruction(ctx);
19441 break;
19442 case 1:
19443 if (rs == 1) {
19444 /* EMT */
19445 check_cp0_mt(ctx);
19446 gen_helper_emt(t0);
19447 gen_store_gpr(t0, rt);
19448 } else if (rs == 0) {
19449 /* EVPE */
19450 check_cp0_mt(ctx);
19451 gen_helper_evpe(t0, cpu_env);
19452 gen_store_gpr(t0, rt);
19453 } else {
19454 gen_reserved_instruction(ctx);
19456 break;
19459 tcg_temp_free(t0);
19461 break;
19462 case NM_FORK:
19463 check_mt(ctx);
19465 TCGv t0 = tcg_temp_new();
19466 TCGv t1 = tcg_temp_new();
19468 gen_load_gpr(t0, rt);
19469 gen_load_gpr(t1, rs);
19470 gen_helper_fork(t0, t1);
19471 tcg_temp_free(t0);
19472 tcg_temp_free(t1);
19474 break;
19475 case NM_MFTR:
19476 case NM_MFHTR:
19477 check_cp0_enabled(ctx);
19478 if (rd == 0) {
19479 /* Treat as NOP. */
19480 return;
19482 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
19483 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
19484 break;
19485 case NM_MTTR:
19486 case NM_MTHTR:
19487 check_cp0_enabled(ctx);
19488 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
19489 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
19490 break;
19491 case NM_YIELD:
19492 check_mt(ctx);
19494 TCGv t0 = tcg_temp_new();
19496 gen_load_gpr(t0, rs);
19497 gen_helper_yield(t0, cpu_env, t0);
19498 gen_store_gpr(t0, rt);
19499 tcg_temp_free(t0);
19501 break;
19502 #endif
19503 default:
19504 gen_reserved_instruction(ctx);
19505 break;
19509 /* dsp */
19510 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
19511 int ret, int v1, int v2)
19513 TCGv_i32 t0;
19514 TCGv v0_t;
19515 TCGv v1_t;
19517 t0 = tcg_temp_new_i32();
19519 v0_t = tcg_temp_new();
19520 v1_t = tcg_temp_new();
19522 tcg_gen_movi_i32(t0, v2 >> 3);
19524 gen_load_gpr(v0_t, ret);
19525 gen_load_gpr(v1_t, v1);
19527 switch (opc) {
19528 case NM_MAQ_S_W_PHR:
19529 check_dsp(ctx);
19530 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
19531 break;
19532 case NM_MAQ_S_W_PHL:
19533 check_dsp(ctx);
19534 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
19535 break;
19536 case NM_MAQ_SA_W_PHR:
19537 check_dsp(ctx);
19538 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
19539 break;
19540 case NM_MAQ_SA_W_PHL:
19541 check_dsp(ctx);
19542 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
19543 break;
19544 default:
19545 gen_reserved_instruction(ctx);
19546 break;
19549 tcg_temp_free_i32(t0);
19551 tcg_temp_free(v0_t);
19552 tcg_temp_free(v1_t);
19556 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
19557 int ret, int v1, int v2)
19559 int16_t imm;
19560 TCGv t0 = tcg_temp_new();
19561 TCGv t1 = tcg_temp_new();
19562 TCGv v0_t = tcg_temp_new();
19564 gen_load_gpr(v0_t, v1);
19566 switch (opc) {
19567 case NM_POOL32AXF_1_0:
19568 check_dsp(ctx);
19569 switch (extract32(ctx->opcode, 12, 2)) {
19570 case NM_MFHI:
19571 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
19572 break;
19573 case NM_MFLO:
19574 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
19575 break;
19576 case NM_MTHI:
19577 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
19578 break;
19579 case NM_MTLO:
19580 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
19581 break;
19583 break;
19584 case NM_POOL32AXF_1_1:
19585 check_dsp(ctx);
19586 switch (extract32(ctx->opcode, 12, 2)) {
19587 case NM_MTHLIP:
19588 tcg_gen_movi_tl(t0, v2);
19589 gen_helper_mthlip(t0, v0_t, cpu_env);
19590 break;
19591 case NM_SHILOV:
19592 tcg_gen_movi_tl(t0, v2 >> 3);
19593 gen_helper_shilo(t0, v0_t, cpu_env);
19594 break;
19595 default:
19596 gen_reserved_instruction(ctx);
19597 break;
19599 break;
19600 case NM_POOL32AXF_1_3:
19601 check_dsp(ctx);
19602 imm = extract32(ctx->opcode, 14, 7);
19603 switch (extract32(ctx->opcode, 12, 2)) {
19604 case NM_RDDSP:
19605 tcg_gen_movi_tl(t0, imm);
19606 gen_helper_rddsp(t0, t0, cpu_env);
19607 gen_store_gpr(t0, ret);
19608 break;
19609 case NM_WRDSP:
19610 gen_load_gpr(t0, ret);
19611 tcg_gen_movi_tl(t1, imm);
19612 gen_helper_wrdsp(t0, t1, cpu_env);
19613 break;
19614 case NM_EXTP:
19615 tcg_gen_movi_tl(t0, v2 >> 3);
19616 tcg_gen_movi_tl(t1, v1);
19617 gen_helper_extp(t0, t0, t1, cpu_env);
19618 gen_store_gpr(t0, ret);
19619 break;
19620 case NM_EXTPDP:
19621 tcg_gen_movi_tl(t0, v2 >> 3);
19622 tcg_gen_movi_tl(t1, v1);
19623 gen_helper_extpdp(t0, t0, t1, cpu_env);
19624 gen_store_gpr(t0, ret);
19625 break;
19627 break;
19628 case NM_POOL32AXF_1_4:
19629 check_dsp(ctx);
19630 tcg_gen_movi_tl(t0, v2 >> 2);
19631 switch (extract32(ctx->opcode, 12, 1)) {
19632 case NM_SHLL_QB:
19633 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
19634 gen_store_gpr(t0, ret);
19635 break;
19636 case NM_SHRL_QB:
19637 gen_helper_shrl_qb(t0, t0, v0_t);
19638 gen_store_gpr(t0, ret);
19639 break;
19641 break;
19642 case NM_POOL32AXF_1_5:
19643 opc = extract32(ctx->opcode, 12, 2);
19644 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
19645 break;
19646 case NM_POOL32AXF_1_7:
19647 check_dsp(ctx);
19648 tcg_gen_movi_tl(t0, v2 >> 3);
19649 tcg_gen_movi_tl(t1, v1);
19650 switch (extract32(ctx->opcode, 12, 2)) {
19651 case NM_EXTR_W:
19652 gen_helper_extr_w(t0, t0, t1, cpu_env);
19653 gen_store_gpr(t0, ret);
19654 break;
19655 case NM_EXTR_R_W:
19656 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
19657 gen_store_gpr(t0, ret);
19658 break;
19659 case NM_EXTR_RS_W:
19660 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
19661 gen_store_gpr(t0, ret);
19662 break;
19663 case NM_EXTR_S_H:
19664 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
19665 gen_store_gpr(t0, ret);
19666 break;
19668 break;
19669 default:
19670 gen_reserved_instruction(ctx);
19671 break;
19674 tcg_temp_free(t0);
19675 tcg_temp_free(t1);
19676 tcg_temp_free(v0_t);
19679 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
19680 TCGv v0, TCGv v1, int rd)
19682 TCGv_i32 t0;
19684 t0 = tcg_temp_new_i32();
19686 tcg_gen_movi_i32(t0, rd >> 3);
19688 switch (opc) {
19689 case NM_POOL32AXF_2_0_7:
19690 switch (extract32(ctx->opcode, 9, 3)) {
19691 case NM_DPA_W_PH:
19692 check_dsp_r2(ctx);
19693 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
19694 break;
19695 case NM_DPAQ_S_W_PH:
19696 check_dsp(ctx);
19697 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
19698 break;
19699 case NM_DPS_W_PH:
19700 check_dsp_r2(ctx);
19701 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
19702 break;
19703 case NM_DPSQ_S_W_PH:
19704 check_dsp(ctx);
19705 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
19706 break;
19707 default:
19708 gen_reserved_instruction(ctx);
19709 break;
19711 break;
19712 case NM_POOL32AXF_2_8_15:
19713 switch (extract32(ctx->opcode, 9, 3)) {
19714 case NM_DPAX_W_PH:
19715 check_dsp_r2(ctx);
19716 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
19717 break;
19718 case NM_DPAQ_SA_L_W:
19719 check_dsp(ctx);
19720 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
19721 break;
19722 case NM_DPSX_W_PH:
19723 check_dsp_r2(ctx);
19724 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
19725 break;
19726 case NM_DPSQ_SA_L_W:
19727 check_dsp(ctx);
19728 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
19729 break;
19730 default:
19731 gen_reserved_instruction(ctx);
19732 break;
19734 break;
19735 case NM_POOL32AXF_2_16_23:
19736 switch (extract32(ctx->opcode, 9, 3)) {
19737 case NM_DPAU_H_QBL:
19738 check_dsp(ctx);
19739 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
19740 break;
19741 case NM_DPAQX_S_W_PH:
19742 check_dsp_r2(ctx);
19743 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
19744 break;
19745 case NM_DPSU_H_QBL:
19746 check_dsp(ctx);
19747 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
19748 break;
19749 case NM_DPSQX_S_W_PH:
19750 check_dsp_r2(ctx);
19751 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
19752 break;
19753 case NM_MULSA_W_PH:
19754 check_dsp_r2(ctx);
19755 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
19756 break;
19757 default:
19758 gen_reserved_instruction(ctx);
19759 break;
19761 break;
19762 case NM_POOL32AXF_2_24_31:
19763 switch (extract32(ctx->opcode, 9, 3)) {
19764 case NM_DPAU_H_QBR:
19765 check_dsp(ctx);
19766 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
19767 break;
19768 case NM_DPAQX_SA_W_PH:
19769 check_dsp_r2(ctx);
19770 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
19771 break;
19772 case NM_DPSU_H_QBR:
19773 check_dsp(ctx);
19774 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
19775 break;
19776 case NM_DPSQX_SA_W_PH:
19777 check_dsp_r2(ctx);
19778 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
19779 break;
19780 case NM_MULSAQ_S_W_PH:
19781 check_dsp(ctx);
19782 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
19783 break;
19784 default:
19785 gen_reserved_instruction(ctx);
19786 break;
19788 break;
19789 default:
19790 gen_reserved_instruction(ctx);
19791 break;
19794 tcg_temp_free_i32(t0);
19797 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
19798 int rt, int rs, int rd)
19800 int ret = rt;
19801 TCGv t0 = tcg_temp_new();
19802 TCGv t1 = tcg_temp_new();
19803 TCGv v0_t = tcg_temp_new();
19804 TCGv v1_t = tcg_temp_new();
19806 gen_load_gpr(v0_t, rt);
19807 gen_load_gpr(v1_t, rs);
19809 switch (opc) {
19810 case NM_POOL32AXF_2_0_7:
19811 switch (extract32(ctx->opcode, 9, 3)) {
19812 case NM_DPA_W_PH:
19813 case NM_DPAQ_S_W_PH:
19814 case NM_DPS_W_PH:
19815 case NM_DPSQ_S_W_PH:
19816 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19817 break;
19818 case NM_BALIGN:
19819 check_dsp_r2(ctx);
19820 if (rt != 0) {
19821 gen_load_gpr(t0, rs);
19822 rd &= 3;
19823 if (rd != 0 && rd != 2) {
19824 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
19825 tcg_gen_ext32u_tl(t0, t0);
19826 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
19827 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19829 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
19831 break;
19832 case NM_MADD:
19833 check_dsp(ctx);
19835 int acc = extract32(ctx->opcode, 14, 2);
19836 TCGv_i64 t2 = tcg_temp_new_i64();
19837 TCGv_i64 t3 = tcg_temp_new_i64();
19839 gen_load_gpr(t0, rt);
19840 gen_load_gpr(t1, rs);
19841 tcg_gen_ext_tl_i64(t2, t0);
19842 tcg_gen_ext_tl_i64(t3, t1);
19843 tcg_gen_mul_i64(t2, t2, t3);
19844 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19845 tcg_gen_add_i64(t2, t2, t3);
19846 tcg_temp_free_i64(t3);
19847 gen_move_low32(cpu_LO[acc], t2);
19848 gen_move_high32(cpu_HI[acc], t2);
19849 tcg_temp_free_i64(t2);
19851 break;
19852 case NM_MULT:
19853 check_dsp(ctx);
19855 int acc = extract32(ctx->opcode, 14, 2);
19856 TCGv_i32 t2 = tcg_temp_new_i32();
19857 TCGv_i32 t3 = tcg_temp_new_i32();
19859 gen_load_gpr(t0, rs);
19860 gen_load_gpr(t1, rt);
19861 tcg_gen_trunc_tl_i32(t2, t0);
19862 tcg_gen_trunc_tl_i32(t3, t1);
19863 tcg_gen_muls2_i32(t2, t3, t2, t3);
19864 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19865 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19866 tcg_temp_free_i32(t2);
19867 tcg_temp_free_i32(t3);
19869 break;
19870 case NM_EXTRV_W:
19871 check_dsp(ctx);
19872 gen_load_gpr(v1_t, rs);
19873 tcg_gen_movi_tl(t0, rd >> 3);
19874 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
19875 gen_store_gpr(t0, ret);
19876 break;
19878 break;
19879 case NM_POOL32AXF_2_8_15:
19880 switch (extract32(ctx->opcode, 9, 3)) {
19881 case NM_DPAX_W_PH:
19882 case NM_DPAQ_SA_L_W:
19883 case NM_DPSX_W_PH:
19884 case NM_DPSQ_SA_L_W:
19885 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19886 break;
19887 case NM_MADDU:
19888 check_dsp(ctx);
19890 int acc = extract32(ctx->opcode, 14, 2);
19891 TCGv_i64 t2 = tcg_temp_new_i64();
19892 TCGv_i64 t3 = tcg_temp_new_i64();
19894 gen_load_gpr(t0, rs);
19895 gen_load_gpr(t1, rt);
19896 tcg_gen_ext32u_tl(t0, t0);
19897 tcg_gen_ext32u_tl(t1, t1);
19898 tcg_gen_extu_tl_i64(t2, t0);
19899 tcg_gen_extu_tl_i64(t3, t1);
19900 tcg_gen_mul_i64(t2, t2, t3);
19901 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19902 tcg_gen_add_i64(t2, t2, t3);
19903 tcg_temp_free_i64(t3);
19904 gen_move_low32(cpu_LO[acc], t2);
19905 gen_move_high32(cpu_HI[acc], t2);
19906 tcg_temp_free_i64(t2);
19908 break;
19909 case NM_MULTU:
19910 check_dsp(ctx);
19912 int acc = extract32(ctx->opcode, 14, 2);
19913 TCGv_i32 t2 = tcg_temp_new_i32();
19914 TCGv_i32 t3 = tcg_temp_new_i32();
19916 gen_load_gpr(t0, rs);
19917 gen_load_gpr(t1, rt);
19918 tcg_gen_trunc_tl_i32(t2, t0);
19919 tcg_gen_trunc_tl_i32(t3, t1);
19920 tcg_gen_mulu2_i32(t2, t3, t2, t3);
19921 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19922 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19923 tcg_temp_free_i32(t2);
19924 tcg_temp_free_i32(t3);
19926 break;
19927 case NM_EXTRV_R_W:
19928 check_dsp(ctx);
19929 tcg_gen_movi_tl(t0, rd >> 3);
19930 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
19931 gen_store_gpr(t0, ret);
19932 break;
19933 default:
19934 gen_reserved_instruction(ctx);
19935 break;
19937 break;
19938 case NM_POOL32AXF_2_16_23:
19939 switch (extract32(ctx->opcode, 9, 3)) {
19940 case NM_DPAU_H_QBL:
19941 case NM_DPAQX_S_W_PH:
19942 case NM_DPSU_H_QBL:
19943 case NM_DPSQX_S_W_PH:
19944 case NM_MULSA_W_PH:
19945 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19946 break;
19947 case NM_EXTPV:
19948 check_dsp(ctx);
19949 tcg_gen_movi_tl(t0, rd >> 3);
19950 gen_helper_extp(t0, t0, v1_t, cpu_env);
19951 gen_store_gpr(t0, ret);
19952 break;
19953 case NM_MSUB:
19954 check_dsp(ctx);
19956 int acc = extract32(ctx->opcode, 14, 2);
19957 TCGv_i64 t2 = tcg_temp_new_i64();
19958 TCGv_i64 t3 = tcg_temp_new_i64();
19960 gen_load_gpr(t0, rs);
19961 gen_load_gpr(t1, rt);
19962 tcg_gen_ext_tl_i64(t2, t0);
19963 tcg_gen_ext_tl_i64(t3, t1);
19964 tcg_gen_mul_i64(t2, t2, t3);
19965 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19966 tcg_gen_sub_i64(t2, t3, t2);
19967 tcg_temp_free_i64(t3);
19968 gen_move_low32(cpu_LO[acc], t2);
19969 gen_move_high32(cpu_HI[acc], t2);
19970 tcg_temp_free_i64(t2);
19972 break;
19973 case NM_EXTRV_RS_W:
19974 check_dsp(ctx);
19975 tcg_gen_movi_tl(t0, rd >> 3);
19976 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
19977 gen_store_gpr(t0, ret);
19978 break;
19980 break;
19981 case NM_POOL32AXF_2_24_31:
19982 switch (extract32(ctx->opcode, 9, 3)) {
19983 case NM_DPAU_H_QBR:
19984 case NM_DPAQX_SA_W_PH:
19985 case NM_DPSU_H_QBR:
19986 case NM_DPSQX_SA_W_PH:
19987 case NM_MULSAQ_S_W_PH:
19988 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19989 break;
19990 case NM_EXTPDPV:
19991 check_dsp(ctx);
19992 tcg_gen_movi_tl(t0, rd >> 3);
19993 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
19994 gen_store_gpr(t0, ret);
19995 break;
19996 case NM_MSUBU:
19997 check_dsp(ctx);
19999 int acc = extract32(ctx->opcode, 14, 2);
20000 TCGv_i64 t2 = tcg_temp_new_i64();
20001 TCGv_i64 t3 = tcg_temp_new_i64();
20003 gen_load_gpr(t0, rs);
20004 gen_load_gpr(t1, rt);
20005 tcg_gen_ext32u_tl(t0, t0);
20006 tcg_gen_ext32u_tl(t1, t1);
20007 tcg_gen_extu_tl_i64(t2, t0);
20008 tcg_gen_extu_tl_i64(t3, t1);
20009 tcg_gen_mul_i64(t2, t2, t3);
20010 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
20011 tcg_gen_sub_i64(t2, t3, t2);
20012 tcg_temp_free_i64(t3);
20013 gen_move_low32(cpu_LO[acc], t2);
20014 gen_move_high32(cpu_HI[acc], t2);
20015 tcg_temp_free_i64(t2);
20017 break;
20018 case NM_EXTRV_S_H:
20019 check_dsp(ctx);
20020 tcg_gen_movi_tl(t0, rd >> 3);
20021 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
20022 gen_store_gpr(t0, ret);
20023 break;
20025 break;
20026 default:
20027 gen_reserved_instruction(ctx);
20028 break;
20031 tcg_temp_free(t0);
20032 tcg_temp_free(t1);
20034 tcg_temp_free(v0_t);
20035 tcg_temp_free(v1_t);
20038 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
20039 int rt, int rs)
20041 int ret = rt;
20042 TCGv t0 = tcg_temp_new();
20043 TCGv v0_t = tcg_temp_new();
20045 gen_load_gpr(v0_t, rs);
20047 switch (opc) {
20048 case NM_ABSQ_S_QB:
20049 check_dsp_r2(ctx);
20050 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
20051 gen_store_gpr(v0_t, ret);
20052 break;
20053 case NM_ABSQ_S_PH:
20054 check_dsp(ctx);
20055 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
20056 gen_store_gpr(v0_t, ret);
20057 break;
20058 case NM_ABSQ_S_W:
20059 check_dsp(ctx);
20060 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
20061 gen_store_gpr(v0_t, ret);
20062 break;
20063 case NM_PRECEQ_W_PHL:
20064 check_dsp(ctx);
20065 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
20066 tcg_gen_ext32s_tl(v0_t, v0_t);
20067 gen_store_gpr(v0_t, ret);
20068 break;
20069 case NM_PRECEQ_W_PHR:
20070 check_dsp(ctx);
20071 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
20072 tcg_gen_shli_tl(v0_t, v0_t, 16);
20073 tcg_gen_ext32s_tl(v0_t, v0_t);
20074 gen_store_gpr(v0_t, ret);
20075 break;
20076 case NM_PRECEQU_PH_QBL:
20077 check_dsp(ctx);
20078 gen_helper_precequ_ph_qbl(v0_t, v0_t);
20079 gen_store_gpr(v0_t, ret);
20080 break;
20081 case NM_PRECEQU_PH_QBR:
20082 check_dsp(ctx);
20083 gen_helper_precequ_ph_qbr(v0_t, v0_t);
20084 gen_store_gpr(v0_t, ret);
20085 break;
20086 case NM_PRECEQU_PH_QBLA:
20087 check_dsp(ctx);
20088 gen_helper_precequ_ph_qbla(v0_t, v0_t);
20089 gen_store_gpr(v0_t, ret);
20090 break;
20091 case NM_PRECEQU_PH_QBRA:
20092 check_dsp(ctx);
20093 gen_helper_precequ_ph_qbra(v0_t, v0_t);
20094 gen_store_gpr(v0_t, ret);
20095 break;
20096 case NM_PRECEU_PH_QBL:
20097 check_dsp(ctx);
20098 gen_helper_preceu_ph_qbl(v0_t, v0_t);
20099 gen_store_gpr(v0_t, ret);
20100 break;
20101 case NM_PRECEU_PH_QBR:
20102 check_dsp(ctx);
20103 gen_helper_preceu_ph_qbr(v0_t, v0_t);
20104 gen_store_gpr(v0_t, ret);
20105 break;
20106 case NM_PRECEU_PH_QBLA:
20107 check_dsp(ctx);
20108 gen_helper_preceu_ph_qbla(v0_t, v0_t);
20109 gen_store_gpr(v0_t, ret);
20110 break;
20111 case NM_PRECEU_PH_QBRA:
20112 check_dsp(ctx);
20113 gen_helper_preceu_ph_qbra(v0_t, v0_t);
20114 gen_store_gpr(v0_t, ret);
20115 break;
20116 case NM_REPLV_PH:
20117 check_dsp(ctx);
20118 tcg_gen_ext16u_tl(v0_t, v0_t);
20119 tcg_gen_shli_tl(t0, v0_t, 16);
20120 tcg_gen_or_tl(v0_t, v0_t, t0);
20121 tcg_gen_ext32s_tl(v0_t, v0_t);
20122 gen_store_gpr(v0_t, ret);
20123 break;
20124 case NM_REPLV_QB:
20125 check_dsp(ctx);
20126 tcg_gen_ext8u_tl(v0_t, v0_t);
20127 tcg_gen_shli_tl(t0, v0_t, 8);
20128 tcg_gen_or_tl(v0_t, v0_t, t0);
20129 tcg_gen_shli_tl(t0, v0_t, 16);
20130 tcg_gen_or_tl(v0_t, v0_t, t0);
20131 tcg_gen_ext32s_tl(v0_t, v0_t);
20132 gen_store_gpr(v0_t, ret);
20133 break;
20134 case NM_BITREV:
20135 check_dsp(ctx);
20136 gen_helper_bitrev(v0_t, v0_t);
20137 gen_store_gpr(v0_t, ret);
20138 break;
20139 case NM_INSV:
20140 check_dsp(ctx);
20142 TCGv tv0 = tcg_temp_new();
20144 gen_load_gpr(tv0, rt);
20145 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
20146 gen_store_gpr(v0_t, ret);
20147 tcg_temp_free(tv0);
20149 break;
20150 case NM_RADDU_W_QB:
20151 check_dsp(ctx);
20152 gen_helper_raddu_w_qb(v0_t, v0_t);
20153 gen_store_gpr(v0_t, ret);
20154 break;
20155 case NM_BITSWAP:
20156 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
20157 break;
20158 case NM_CLO:
20159 check_nms(ctx);
20160 gen_cl(ctx, OPC_CLO, ret, rs);
20161 break;
20162 case NM_CLZ:
20163 check_nms(ctx);
20164 gen_cl(ctx, OPC_CLZ, ret, rs);
20165 break;
20166 case NM_WSBH:
20167 gen_bshfl(ctx, OPC_WSBH, ret, rs);
20168 break;
20169 default:
20170 gen_reserved_instruction(ctx);
20171 break;
20174 tcg_temp_free(v0_t);
20175 tcg_temp_free(t0);
20178 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
20179 int rt, int rs, int rd)
20181 TCGv t0 = tcg_temp_new();
20182 TCGv rs_t = tcg_temp_new();
20184 gen_load_gpr(rs_t, rs);
20186 switch (opc) {
20187 case NM_SHRA_R_QB:
20188 check_dsp_r2(ctx);
20189 tcg_gen_movi_tl(t0, rd >> 2);
20190 switch (extract32(ctx->opcode, 12, 1)) {
20191 case 0:
20192 /* NM_SHRA_QB */
20193 gen_helper_shra_qb(t0, t0, rs_t);
20194 gen_store_gpr(t0, rt);
20195 break;
20196 case 1:
20197 /* NM_SHRA_R_QB */
20198 gen_helper_shra_r_qb(t0, t0, rs_t);
20199 gen_store_gpr(t0, rt);
20200 break;
20202 break;
20203 case NM_SHRL_PH:
20204 check_dsp_r2(ctx);
20205 tcg_gen_movi_tl(t0, rd >> 1);
20206 gen_helper_shrl_ph(t0, t0, rs_t);
20207 gen_store_gpr(t0, rt);
20208 break;
20209 case NM_REPL_QB:
20210 check_dsp(ctx);
20212 int16_t imm;
20213 target_long result;
20214 imm = extract32(ctx->opcode, 13, 8);
20215 result = (uint32_t)imm << 24 |
20216 (uint32_t)imm << 16 |
20217 (uint32_t)imm << 8 |
20218 (uint32_t)imm;
20219 result = (int32_t)result;
20220 tcg_gen_movi_tl(t0, result);
20221 gen_store_gpr(t0, rt);
20223 break;
20224 default:
20225 gen_reserved_instruction(ctx);
20226 break;
20228 tcg_temp_free(t0);
20229 tcg_temp_free(rs_t);
20233 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
20235 int rt = extract32(ctx->opcode, 21, 5);
20236 int rs = extract32(ctx->opcode, 16, 5);
20237 int rd = extract32(ctx->opcode, 11, 5);
20239 switch (extract32(ctx->opcode, 6, 3)) {
20240 case NM_POOL32AXF_1:
20242 int32_t op1 = extract32(ctx->opcode, 9, 3);
20243 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
20245 break;
20246 case NM_POOL32AXF_2:
20248 int32_t op1 = extract32(ctx->opcode, 12, 2);
20249 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
20251 break;
20252 case NM_POOL32AXF_4:
20254 int32_t op1 = extract32(ctx->opcode, 9, 7);
20255 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
20257 break;
20258 case NM_POOL32AXF_5:
20259 switch (extract32(ctx->opcode, 9, 7)) {
20260 #ifndef CONFIG_USER_ONLY
20261 case NM_TLBP:
20262 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
20263 break;
20264 case NM_TLBR:
20265 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
20266 break;
20267 case NM_TLBWI:
20268 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
20269 break;
20270 case NM_TLBWR:
20271 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
20272 break;
20273 case NM_TLBINV:
20274 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
20275 break;
20276 case NM_TLBINVF:
20277 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
20278 break;
20279 case NM_DI:
20280 check_cp0_enabled(ctx);
20282 TCGv t0 = tcg_temp_new();
20284 save_cpu_state(ctx, 1);
20285 gen_helper_di(t0, cpu_env);
20286 gen_store_gpr(t0, rt);
20287 /* Stop translation as we may have switched the execution mode */
20288 ctx->base.is_jmp = DISAS_STOP;
20289 tcg_temp_free(t0);
20291 break;
20292 case NM_EI:
20293 check_cp0_enabled(ctx);
20295 TCGv t0 = tcg_temp_new();
20297 save_cpu_state(ctx, 1);
20298 gen_helper_ei(t0, cpu_env);
20299 gen_store_gpr(t0, rt);
20300 /* Stop translation as we may have switched the execution mode */
20301 ctx->base.is_jmp = DISAS_STOP;
20302 tcg_temp_free(t0);
20304 break;
20305 case NM_RDPGPR:
20306 gen_load_srsgpr(rs, rt);
20307 break;
20308 case NM_WRPGPR:
20309 gen_store_srsgpr(rs, rt);
20310 break;
20311 case NM_WAIT:
20312 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
20313 break;
20314 case NM_DERET:
20315 gen_cp0(env, ctx, OPC_DERET, 0, 0);
20316 break;
20317 case NM_ERETX:
20318 gen_cp0(env, ctx, OPC_ERET, 0, 0);
20319 break;
20320 #endif
20321 default:
20322 gen_reserved_instruction(ctx);
20323 break;
20325 break;
20326 case NM_POOL32AXF_7:
20328 int32_t op1 = extract32(ctx->opcode, 9, 3);
20329 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
20331 break;
20332 default:
20333 gen_reserved_instruction(ctx);
20334 break;
20338 /* Immediate Value Compact Branches */
20339 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
20340 int rt, int32_t imm, int32_t offset)
20342 TCGCond cond = TCG_COND_ALWAYS;
20343 TCGv t0 = tcg_temp_new();
20344 TCGv t1 = tcg_temp_new();
20346 gen_load_gpr(t0, rt);
20347 tcg_gen_movi_tl(t1, imm);
20348 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20350 /* Load needed operands and calculate btarget */
20351 switch (opc) {
20352 case NM_BEQIC:
20353 if (rt == 0 && imm == 0) {
20354 /* Unconditional branch */
20355 } else if (rt == 0 && imm != 0) {
20356 /* Treat as NOP */
20357 goto out;
20358 } else {
20359 cond = TCG_COND_EQ;
20361 break;
20362 case NM_BBEQZC:
20363 case NM_BBNEZC:
20364 check_nms(ctx);
20365 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
20366 gen_reserved_instruction(ctx);
20367 goto out;
20368 } else if (rt == 0 && opc == NM_BBEQZC) {
20369 /* Unconditional branch */
20370 } else if (rt == 0 && opc == NM_BBNEZC) {
20371 /* Treat as NOP */
20372 goto out;
20373 } else {
20374 tcg_gen_shri_tl(t0, t0, imm);
20375 tcg_gen_andi_tl(t0, t0, 1);
20376 tcg_gen_movi_tl(t1, 0);
20377 if (opc == NM_BBEQZC) {
20378 cond = TCG_COND_EQ;
20379 } else {
20380 cond = TCG_COND_NE;
20383 break;
20384 case NM_BNEIC:
20385 if (rt == 0 && imm == 0) {
20386 /* Treat as NOP */
20387 goto out;
20388 } else if (rt == 0 && imm != 0) {
20389 /* Unconditional branch */
20390 } else {
20391 cond = TCG_COND_NE;
20393 break;
20394 case NM_BGEIC:
20395 if (rt == 0 && imm == 0) {
20396 /* Unconditional branch */
20397 } else {
20398 cond = TCG_COND_GE;
20400 break;
20401 case NM_BLTIC:
20402 cond = TCG_COND_LT;
20403 break;
20404 case NM_BGEIUC:
20405 if (rt == 0 && imm == 0) {
20406 /* Unconditional branch */
20407 } else {
20408 cond = TCG_COND_GEU;
20410 break;
20411 case NM_BLTIUC:
20412 cond = TCG_COND_LTU;
20413 break;
20414 default:
20415 MIPS_INVAL("Immediate Value Compact branch");
20416 gen_reserved_instruction(ctx);
20417 goto out;
20420 /* branch completion */
20421 clear_branch_hflags(ctx);
20422 ctx->base.is_jmp = DISAS_NORETURN;
20424 if (cond == TCG_COND_ALWAYS) {
20425 /* Uncoditional compact branch */
20426 gen_goto_tb(ctx, 0, ctx->btarget);
20427 } else {
20428 /* Conditional compact branch */
20429 TCGLabel *fs = gen_new_label();
20431 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
20433 gen_goto_tb(ctx, 1, ctx->btarget);
20434 gen_set_label(fs);
20436 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20439 out:
20440 tcg_temp_free(t0);
20441 tcg_temp_free(t1);
20444 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
20445 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
20446 int rt)
20448 TCGv t0 = tcg_temp_new();
20449 TCGv t1 = tcg_temp_new();
20451 /* load rs */
20452 gen_load_gpr(t0, rs);
20454 /* link */
20455 if (rt != 0) {
20456 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
20459 /* calculate btarget */
20460 tcg_gen_shli_tl(t0, t0, 1);
20461 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
20462 gen_op_addr_add(ctx, btarget, t1, t0);
20464 /* branch completion */
20465 clear_branch_hflags(ctx);
20466 ctx->base.is_jmp = DISAS_NORETURN;
20468 /* unconditional branch to register */
20469 tcg_gen_mov_tl(cpu_PC, btarget);
20470 tcg_gen_lookup_and_goto_ptr();
20472 tcg_temp_free(t0);
20473 tcg_temp_free(t1);
20476 /* nanoMIPS Branches */
20477 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
20478 int rs, int rt, int32_t offset)
20480 int bcond_compute = 0;
20481 TCGv t0 = tcg_temp_new();
20482 TCGv t1 = tcg_temp_new();
20484 /* Load needed operands and calculate btarget */
20485 switch (opc) {
20486 /* compact branch */
20487 case OPC_BGEC:
20488 case OPC_BLTC:
20489 gen_load_gpr(t0, rs);
20490 gen_load_gpr(t1, rt);
20491 bcond_compute = 1;
20492 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20493 break;
20494 case OPC_BGEUC:
20495 case OPC_BLTUC:
20496 if (rs == 0 || rs == rt) {
20497 /* OPC_BLEZALC, OPC_BGEZALC */
20498 /* OPC_BGTZALC, OPC_BLTZALC */
20499 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
20501 gen_load_gpr(t0, rs);
20502 gen_load_gpr(t1, rt);
20503 bcond_compute = 1;
20504 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20505 break;
20506 case OPC_BC:
20507 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20508 break;
20509 case OPC_BEQZC:
20510 if (rs != 0) {
20511 /* OPC_BEQZC, OPC_BNEZC */
20512 gen_load_gpr(t0, rs);
20513 bcond_compute = 1;
20514 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20515 } else {
20516 /* OPC_JIC, OPC_JIALC */
20517 TCGv tbase = tcg_temp_new();
20518 TCGv toffset = tcg_temp_new();
20520 gen_load_gpr(tbase, rt);
20521 tcg_gen_movi_tl(toffset, offset);
20522 gen_op_addr_add(ctx, btarget, tbase, toffset);
20523 tcg_temp_free(tbase);
20524 tcg_temp_free(toffset);
20526 break;
20527 default:
20528 MIPS_INVAL("Compact branch/jump");
20529 gen_reserved_instruction(ctx);
20530 goto out;
20533 if (bcond_compute == 0) {
20534 /* Uncoditional compact branch */
20535 switch (opc) {
20536 case OPC_BC:
20537 gen_goto_tb(ctx, 0, ctx->btarget);
20538 break;
20539 default:
20540 MIPS_INVAL("Compact branch/jump");
20541 gen_reserved_instruction(ctx);
20542 goto out;
20544 } else {
20545 /* Conditional compact branch */
20546 TCGLabel *fs = gen_new_label();
20548 switch (opc) {
20549 case OPC_BGEUC:
20550 if (rs == 0 && rt != 0) {
20551 /* OPC_BLEZALC */
20552 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20553 } else if (rs != 0 && rt != 0 && rs == rt) {
20554 /* OPC_BGEZALC */
20555 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20556 } else {
20557 /* OPC_BGEUC */
20558 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
20560 break;
20561 case OPC_BLTUC:
20562 if (rs == 0 && rt != 0) {
20563 /* OPC_BGTZALC */
20564 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20565 } else if (rs != 0 && rt != 0 && rs == rt) {
20566 /* OPC_BLTZALC */
20567 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20568 } else {
20569 /* OPC_BLTUC */
20570 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
20572 break;
20573 case OPC_BGEC:
20574 if (rs == 0 && rt != 0) {
20575 /* OPC_BLEZC */
20576 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20577 } else if (rs != 0 && rt != 0 && rs == rt) {
20578 /* OPC_BGEZC */
20579 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20580 } else {
20581 /* OPC_BGEC */
20582 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
20584 break;
20585 case OPC_BLTC:
20586 if (rs == 0 && rt != 0) {
20587 /* OPC_BGTZC */
20588 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20589 } else if (rs != 0 && rt != 0 && rs == rt) {
20590 /* OPC_BLTZC */
20591 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20592 } else {
20593 /* OPC_BLTC */
20594 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
20596 break;
20597 case OPC_BEQZC:
20598 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
20599 break;
20600 default:
20601 MIPS_INVAL("Compact conditional branch/jump");
20602 gen_reserved_instruction(ctx);
20603 goto out;
20606 /* branch completion */
20607 clear_branch_hflags(ctx);
20608 ctx->base.is_jmp = DISAS_NORETURN;
20610 /* Generating branch here as compact branches don't have delay slot */
20611 gen_goto_tb(ctx, 1, ctx->btarget);
20612 gen_set_label(fs);
20614 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20617 out:
20618 tcg_temp_free(t0);
20619 tcg_temp_free(t1);
20623 /* nanoMIPS CP1 Branches */
20624 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
20625 int32_t ft, int32_t offset)
20627 target_ulong btarget;
20628 TCGv_i64 t0 = tcg_temp_new_i64();
20630 gen_load_fpr64(ctx, t0, ft);
20631 tcg_gen_andi_i64(t0, t0, 1);
20633 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20635 switch (op) {
20636 case NM_BC1EQZC:
20637 tcg_gen_xori_i64(t0, t0, 1);
20638 ctx->hflags |= MIPS_HFLAG_BC;
20639 break;
20640 case NM_BC1NEZC:
20641 /* t0 already set */
20642 ctx->hflags |= MIPS_HFLAG_BC;
20643 break;
20644 default:
20645 MIPS_INVAL("cp1 cond branch");
20646 gen_reserved_instruction(ctx);
20647 goto out;
20650 tcg_gen_trunc_i64_tl(bcond, t0);
20652 ctx->btarget = btarget;
20654 out:
20655 tcg_temp_free_i64(t0);
20659 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
20661 TCGv t0, t1;
20662 t0 = tcg_temp_new();
20663 t1 = tcg_temp_new();
20665 gen_load_gpr(t0, rs);
20666 gen_load_gpr(t1, rt);
20668 if ((extract32(ctx->opcode, 6, 1)) == 1) {
20669 /* PP.LSXS instructions require shifting */
20670 switch (extract32(ctx->opcode, 7, 4)) {
20671 case NM_SHXS:
20672 check_nms(ctx);
20673 /* fall through */
20674 case NM_LHXS:
20675 case NM_LHUXS:
20676 tcg_gen_shli_tl(t0, t0, 1);
20677 break;
20678 case NM_SWXS:
20679 check_nms(ctx);
20680 /* fall through */
20681 case NM_LWXS:
20682 case NM_LWC1XS:
20683 case NM_SWC1XS:
20684 tcg_gen_shli_tl(t0, t0, 2);
20685 break;
20686 case NM_LDC1XS:
20687 case NM_SDC1XS:
20688 tcg_gen_shli_tl(t0, t0, 3);
20689 break;
20692 gen_op_addr_add(ctx, t0, t0, t1);
20694 switch (extract32(ctx->opcode, 7, 4)) {
20695 case NM_LBX:
20696 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20697 MO_SB);
20698 gen_store_gpr(t0, rd);
20699 break;
20700 case NM_LHX:
20701 /*case NM_LHXS:*/
20702 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20703 MO_TESW);
20704 gen_store_gpr(t0, rd);
20705 break;
20706 case NM_LWX:
20707 /*case NM_LWXS:*/
20708 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20709 MO_TESL);
20710 gen_store_gpr(t0, rd);
20711 break;
20712 case NM_LBUX:
20713 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20714 MO_UB);
20715 gen_store_gpr(t0, rd);
20716 break;
20717 case NM_LHUX:
20718 /*case NM_LHUXS:*/
20719 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20720 MO_TEUW);
20721 gen_store_gpr(t0, rd);
20722 break;
20723 case NM_SBX:
20724 check_nms(ctx);
20725 gen_load_gpr(t1, rd);
20726 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20727 MO_8);
20728 break;
20729 case NM_SHX:
20730 /*case NM_SHXS:*/
20731 check_nms(ctx);
20732 gen_load_gpr(t1, rd);
20733 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20734 MO_TEUW);
20735 break;
20736 case NM_SWX:
20737 /*case NM_SWXS:*/
20738 check_nms(ctx);
20739 gen_load_gpr(t1, rd);
20740 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20741 MO_TEUL);
20742 break;
20743 case NM_LWC1X:
20744 /*case NM_LWC1XS:*/
20745 case NM_LDC1X:
20746 /*case NM_LDC1XS:*/
20747 case NM_SWC1X:
20748 /*case NM_SWC1XS:*/
20749 case NM_SDC1X:
20750 /*case NM_SDC1XS:*/
20751 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
20752 check_cp1_enabled(ctx);
20753 switch (extract32(ctx->opcode, 7, 4)) {
20754 case NM_LWC1X:
20755 /*case NM_LWC1XS:*/
20756 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
20757 break;
20758 case NM_LDC1X:
20759 /*case NM_LDC1XS:*/
20760 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
20761 break;
20762 case NM_SWC1X:
20763 /*case NM_SWC1XS:*/
20764 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
20765 break;
20766 case NM_SDC1X:
20767 /*case NM_SDC1XS:*/
20768 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
20769 break;
20771 } else {
20772 generate_exception_err(ctx, EXCP_CpU, 1);
20774 break;
20775 default:
20776 gen_reserved_instruction(ctx);
20777 break;
20780 tcg_temp_free(t0);
20781 tcg_temp_free(t1);
20784 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
20786 int rt, rs, rd;
20788 rt = extract32(ctx->opcode, 21, 5);
20789 rs = extract32(ctx->opcode, 16, 5);
20790 rd = extract32(ctx->opcode, 11, 5);
20792 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
20793 gen_reserved_instruction(ctx);
20794 return;
20796 check_cp1_enabled(ctx);
20797 switch (extract32(ctx->opcode, 0, 3)) {
20798 case NM_POOL32F_0:
20799 switch (extract32(ctx->opcode, 3, 7)) {
20800 case NM_RINT_S:
20801 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
20802 break;
20803 case NM_RINT_D:
20804 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
20805 break;
20806 case NM_CLASS_S:
20807 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
20808 break;
20809 case NM_CLASS_D:
20810 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
20811 break;
20812 case NM_ADD_S:
20813 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
20814 break;
20815 case NM_ADD_D:
20816 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
20817 break;
20818 case NM_SUB_S:
20819 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
20820 break;
20821 case NM_SUB_D:
20822 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
20823 break;
20824 case NM_MUL_S:
20825 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
20826 break;
20827 case NM_MUL_D:
20828 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
20829 break;
20830 case NM_DIV_S:
20831 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
20832 break;
20833 case NM_DIV_D:
20834 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
20835 break;
20836 case NM_SELEQZ_S:
20837 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
20838 break;
20839 case NM_SELEQZ_D:
20840 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
20841 break;
20842 case NM_SELNEZ_S:
20843 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
20844 break;
20845 case NM_SELNEZ_D:
20846 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
20847 break;
20848 case NM_SEL_S:
20849 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
20850 break;
20851 case NM_SEL_D:
20852 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
20853 break;
20854 case NM_MADDF_S:
20855 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
20856 break;
20857 case NM_MADDF_D:
20858 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
20859 break;
20860 case NM_MSUBF_S:
20861 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
20862 break;
20863 case NM_MSUBF_D:
20864 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
20865 break;
20866 default:
20867 gen_reserved_instruction(ctx);
20868 break;
20870 break;
20871 case NM_POOL32F_3:
20872 switch (extract32(ctx->opcode, 3, 3)) {
20873 case NM_MIN_FMT:
20874 switch (extract32(ctx->opcode, 9, 1)) {
20875 case FMT_SDPS_S:
20876 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
20877 break;
20878 case FMT_SDPS_D:
20879 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
20880 break;
20882 break;
20883 case NM_MAX_FMT:
20884 switch (extract32(ctx->opcode, 9, 1)) {
20885 case FMT_SDPS_S:
20886 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
20887 break;
20888 case FMT_SDPS_D:
20889 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
20890 break;
20892 break;
20893 case NM_MINA_FMT:
20894 switch (extract32(ctx->opcode, 9, 1)) {
20895 case FMT_SDPS_S:
20896 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
20897 break;
20898 case FMT_SDPS_D:
20899 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
20900 break;
20902 break;
20903 case NM_MAXA_FMT:
20904 switch (extract32(ctx->opcode, 9, 1)) {
20905 case FMT_SDPS_S:
20906 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
20907 break;
20908 case FMT_SDPS_D:
20909 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
20910 break;
20912 break;
20913 case NM_POOL32FXF:
20914 switch (extract32(ctx->opcode, 6, 8)) {
20915 case NM_CFC1:
20916 gen_cp1(ctx, OPC_CFC1, rt, rs);
20917 break;
20918 case NM_CTC1:
20919 gen_cp1(ctx, OPC_CTC1, rt, rs);
20920 break;
20921 case NM_MFC1:
20922 gen_cp1(ctx, OPC_MFC1, rt, rs);
20923 break;
20924 case NM_MTC1:
20925 gen_cp1(ctx, OPC_MTC1, rt, rs);
20926 break;
20927 case NM_MFHC1:
20928 gen_cp1(ctx, OPC_MFHC1, rt, rs);
20929 break;
20930 case NM_MTHC1:
20931 gen_cp1(ctx, OPC_MTHC1, rt, rs);
20932 break;
20933 case NM_CVT_S_PL:
20934 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
20935 break;
20936 case NM_CVT_S_PU:
20937 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
20938 break;
20939 default:
20940 switch (extract32(ctx->opcode, 6, 9)) {
20941 case NM_CVT_L_S:
20942 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
20943 break;
20944 case NM_CVT_L_D:
20945 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
20946 break;
20947 case NM_CVT_W_S:
20948 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
20949 break;
20950 case NM_CVT_W_D:
20951 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
20952 break;
20953 case NM_RSQRT_S:
20954 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
20955 break;
20956 case NM_RSQRT_D:
20957 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
20958 break;
20959 case NM_SQRT_S:
20960 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
20961 break;
20962 case NM_SQRT_D:
20963 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
20964 break;
20965 case NM_RECIP_S:
20966 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
20967 break;
20968 case NM_RECIP_D:
20969 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
20970 break;
20971 case NM_FLOOR_L_S:
20972 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
20973 break;
20974 case NM_FLOOR_L_D:
20975 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
20976 break;
20977 case NM_FLOOR_W_S:
20978 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
20979 break;
20980 case NM_FLOOR_W_D:
20981 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
20982 break;
20983 case NM_CEIL_L_S:
20984 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
20985 break;
20986 case NM_CEIL_L_D:
20987 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
20988 break;
20989 case NM_CEIL_W_S:
20990 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
20991 break;
20992 case NM_CEIL_W_D:
20993 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
20994 break;
20995 case NM_TRUNC_L_S:
20996 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
20997 break;
20998 case NM_TRUNC_L_D:
20999 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
21000 break;
21001 case NM_TRUNC_W_S:
21002 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
21003 break;
21004 case NM_TRUNC_W_D:
21005 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
21006 break;
21007 case NM_ROUND_L_S:
21008 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
21009 break;
21010 case NM_ROUND_L_D:
21011 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
21012 break;
21013 case NM_ROUND_W_S:
21014 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
21015 break;
21016 case NM_ROUND_W_D:
21017 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
21018 break;
21019 case NM_MOV_S:
21020 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
21021 break;
21022 case NM_MOV_D:
21023 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
21024 break;
21025 case NM_ABS_S:
21026 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
21027 break;
21028 case NM_ABS_D:
21029 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
21030 break;
21031 case NM_NEG_S:
21032 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
21033 break;
21034 case NM_NEG_D:
21035 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
21036 break;
21037 case NM_CVT_D_S:
21038 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
21039 break;
21040 case NM_CVT_D_W:
21041 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
21042 break;
21043 case NM_CVT_D_L:
21044 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
21045 break;
21046 case NM_CVT_S_D:
21047 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
21048 break;
21049 case NM_CVT_S_W:
21050 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
21051 break;
21052 case NM_CVT_S_L:
21053 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
21054 break;
21055 default:
21056 gen_reserved_instruction(ctx);
21057 break;
21059 break;
21061 break;
21063 break;
21064 case NM_POOL32F_5:
21065 switch (extract32(ctx->opcode, 3, 3)) {
21066 case NM_CMP_CONDN_S:
21067 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
21068 break;
21069 case NM_CMP_CONDN_D:
21070 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
21071 break;
21072 default:
21073 gen_reserved_instruction(ctx);
21074 break;
21076 break;
21077 default:
21078 gen_reserved_instruction(ctx);
21079 break;
21083 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
21084 int rd, int rs, int rt)
21086 int ret = rd;
21087 TCGv t0 = tcg_temp_new();
21088 TCGv v1_t = tcg_temp_new();
21089 TCGv v2_t = tcg_temp_new();
21091 gen_load_gpr(v1_t, rs);
21092 gen_load_gpr(v2_t, rt);
21094 switch (opc) {
21095 case NM_CMP_EQ_PH:
21096 check_dsp(ctx);
21097 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
21098 break;
21099 case NM_CMP_LT_PH:
21100 check_dsp(ctx);
21101 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
21102 break;
21103 case NM_CMP_LE_PH:
21104 check_dsp(ctx);
21105 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
21106 break;
21107 case NM_CMPU_EQ_QB:
21108 check_dsp(ctx);
21109 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
21110 break;
21111 case NM_CMPU_LT_QB:
21112 check_dsp(ctx);
21113 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
21114 break;
21115 case NM_CMPU_LE_QB:
21116 check_dsp(ctx);
21117 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
21118 break;
21119 case NM_CMPGU_EQ_QB:
21120 check_dsp(ctx);
21121 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
21122 gen_store_gpr(v1_t, ret);
21123 break;
21124 case NM_CMPGU_LT_QB:
21125 check_dsp(ctx);
21126 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
21127 gen_store_gpr(v1_t, ret);
21128 break;
21129 case NM_CMPGU_LE_QB:
21130 check_dsp(ctx);
21131 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
21132 gen_store_gpr(v1_t, ret);
21133 break;
21134 case NM_CMPGDU_EQ_QB:
21135 check_dsp_r2(ctx);
21136 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
21137 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
21138 gen_store_gpr(v1_t, ret);
21139 break;
21140 case NM_CMPGDU_LT_QB:
21141 check_dsp_r2(ctx);
21142 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
21143 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
21144 gen_store_gpr(v1_t, ret);
21145 break;
21146 case NM_CMPGDU_LE_QB:
21147 check_dsp_r2(ctx);
21148 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
21149 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
21150 gen_store_gpr(v1_t, ret);
21151 break;
21152 case NM_PACKRL_PH:
21153 check_dsp(ctx);
21154 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
21155 gen_store_gpr(v1_t, ret);
21156 break;
21157 case NM_PICK_QB:
21158 check_dsp(ctx);
21159 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
21160 gen_store_gpr(v1_t, ret);
21161 break;
21162 case NM_PICK_PH:
21163 check_dsp(ctx);
21164 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
21165 gen_store_gpr(v1_t, ret);
21166 break;
21167 case NM_ADDQ_S_W:
21168 check_dsp(ctx);
21169 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
21170 gen_store_gpr(v1_t, ret);
21171 break;
21172 case NM_SUBQ_S_W:
21173 check_dsp(ctx);
21174 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
21175 gen_store_gpr(v1_t, ret);
21176 break;
21177 case NM_ADDSC:
21178 check_dsp(ctx);
21179 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
21180 gen_store_gpr(v1_t, ret);
21181 break;
21182 case NM_ADDWC:
21183 check_dsp(ctx);
21184 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
21185 gen_store_gpr(v1_t, ret);
21186 break;
21187 case NM_ADDQ_S_PH:
21188 check_dsp(ctx);
21189 switch (extract32(ctx->opcode, 10, 1)) {
21190 case 0:
21191 /* ADDQ_PH */
21192 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
21193 gen_store_gpr(v1_t, ret);
21194 break;
21195 case 1:
21196 /* ADDQ_S_PH */
21197 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
21198 gen_store_gpr(v1_t, ret);
21199 break;
21201 break;
21202 case NM_ADDQH_R_PH:
21203 check_dsp_r2(ctx);
21204 switch (extract32(ctx->opcode, 10, 1)) {
21205 case 0:
21206 /* ADDQH_PH */
21207 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
21208 gen_store_gpr(v1_t, ret);
21209 break;
21210 case 1:
21211 /* ADDQH_R_PH */
21212 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
21213 gen_store_gpr(v1_t, ret);
21214 break;
21216 break;
21217 case NM_ADDQH_R_W:
21218 check_dsp_r2(ctx);
21219 switch (extract32(ctx->opcode, 10, 1)) {
21220 case 0:
21221 /* ADDQH_W */
21222 gen_helper_addqh_w(v1_t, v1_t, v2_t);
21223 gen_store_gpr(v1_t, ret);
21224 break;
21225 case 1:
21226 /* ADDQH_R_W */
21227 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
21228 gen_store_gpr(v1_t, ret);
21229 break;
21231 break;
21232 case NM_ADDU_S_QB:
21233 check_dsp(ctx);
21234 switch (extract32(ctx->opcode, 10, 1)) {
21235 case 0:
21236 /* ADDU_QB */
21237 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
21238 gen_store_gpr(v1_t, ret);
21239 break;
21240 case 1:
21241 /* ADDU_S_QB */
21242 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
21243 gen_store_gpr(v1_t, ret);
21244 break;
21246 break;
21247 case NM_ADDU_S_PH:
21248 check_dsp_r2(ctx);
21249 switch (extract32(ctx->opcode, 10, 1)) {
21250 case 0:
21251 /* ADDU_PH */
21252 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
21253 gen_store_gpr(v1_t, ret);
21254 break;
21255 case 1:
21256 /* ADDU_S_PH */
21257 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
21258 gen_store_gpr(v1_t, ret);
21259 break;
21261 break;
21262 case NM_ADDUH_R_QB:
21263 check_dsp_r2(ctx);
21264 switch (extract32(ctx->opcode, 10, 1)) {
21265 case 0:
21266 /* ADDUH_QB */
21267 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
21268 gen_store_gpr(v1_t, ret);
21269 break;
21270 case 1:
21271 /* ADDUH_R_QB */
21272 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
21273 gen_store_gpr(v1_t, ret);
21274 break;
21276 break;
21277 case NM_SHRAV_R_PH:
21278 check_dsp(ctx);
21279 switch (extract32(ctx->opcode, 10, 1)) {
21280 case 0:
21281 /* SHRAV_PH */
21282 gen_helper_shra_ph(v1_t, v1_t, v2_t);
21283 gen_store_gpr(v1_t, ret);
21284 break;
21285 case 1:
21286 /* SHRAV_R_PH */
21287 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
21288 gen_store_gpr(v1_t, ret);
21289 break;
21291 break;
21292 case NM_SHRAV_R_QB:
21293 check_dsp_r2(ctx);
21294 switch (extract32(ctx->opcode, 10, 1)) {
21295 case 0:
21296 /* SHRAV_QB */
21297 gen_helper_shra_qb(v1_t, v1_t, v2_t);
21298 gen_store_gpr(v1_t, ret);
21299 break;
21300 case 1:
21301 /* SHRAV_R_QB */
21302 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
21303 gen_store_gpr(v1_t, ret);
21304 break;
21306 break;
21307 case NM_SUBQ_S_PH:
21308 check_dsp(ctx);
21309 switch (extract32(ctx->opcode, 10, 1)) {
21310 case 0:
21311 /* SUBQ_PH */
21312 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
21313 gen_store_gpr(v1_t, ret);
21314 break;
21315 case 1:
21316 /* SUBQ_S_PH */
21317 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
21318 gen_store_gpr(v1_t, ret);
21319 break;
21321 break;
21322 case NM_SUBQH_R_PH:
21323 check_dsp_r2(ctx);
21324 switch (extract32(ctx->opcode, 10, 1)) {
21325 case 0:
21326 /* SUBQH_PH */
21327 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
21328 gen_store_gpr(v1_t, ret);
21329 break;
21330 case 1:
21331 /* SUBQH_R_PH */
21332 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
21333 gen_store_gpr(v1_t, ret);
21334 break;
21336 break;
21337 case NM_SUBQH_R_W:
21338 check_dsp_r2(ctx);
21339 switch (extract32(ctx->opcode, 10, 1)) {
21340 case 0:
21341 /* SUBQH_W */
21342 gen_helper_subqh_w(v1_t, v1_t, v2_t);
21343 gen_store_gpr(v1_t, ret);
21344 break;
21345 case 1:
21346 /* SUBQH_R_W */
21347 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
21348 gen_store_gpr(v1_t, ret);
21349 break;
21351 break;
21352 case NM_SUBU_S_QB:
21353 check_dsp(ctx);
21354 switch (extract32(ctx->opcode, 10, 1)) {
21355 case 0:
21356 /* SUBU_QB */
21357 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
21358 gen_store_gpr(v1_t, ret);
21359 break;
21360 case 1:
21361 /* SUBU_S_QB */
21362 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
21363 gen_store_gpr(v1_t, ret);
21364 break;
21366 break;
21367 case NM_SUBU_S_PH:
21368 check_dsp_r2(ctx);
21369 switch (extract32(ctx->opcode, 10, 1)) {
21370 case 0:
21371 /* SUBU_PH */
21372 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
21373 gen_store_gpr(v1_t, ret);
21374 break;
21375 case 1:
21376 /* SUBU_S_PH */
21377 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
21378 gen_store_gpr(v1_t, ret);
21379 break;
21381 break;
21382 case NM_SUBUH_R_QB:
21383 check_dsp_r2(ctx);
21384 switch (extract32(ctx->opcode, 10, 1)) {
21385 case 0:
21386 /* SUBUH_QB */
21387 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
21388 gen_store_gpr(v1_t, ret);
21389 break;
21390 case 1:
21391 /* SUBUH_R_QB */
21392 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
21393 gen_store_gpr(v1_t, ret);
21394 break;
21396 break;
21397 case NM_SHLLV_S_PH:
21398 check_dsp(ctx);
21399 switch (extract32(ctx->opcode, 10, 1)) {
21400 case 0:
21401 /* SHLLV_PH */
21402 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
21403 gen_store_gpr(v1_t, ret);
21404 break;
21405 case 1:
21406 /* SHLLV_S_PH */
21407 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
21408 gen_store_gpr(v1_t, ret);
21409 break;
21411 break;
21412 case NM_PRECR_SRA_R_PH_W:
21413 check_dsp_r2(ctx);
21414 switch (extract32(ctx->opcode, 10, 1)) {
21415 case 0:
21416 /* PRECR_SRA_PH_W */
21418 TCGv_i32 sa_t = tcg_const_i32(rd);
21419 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
21420 cpu_gpr[rt]);
21421 gen_store_gpr(v1_t, rt);
21422 tcg_temp_free_i32(sa_t);
21424 break;
21425 case 1:
21426 /* PRECR_SRA_R_PH_W */
21428 TCGv_i32 sa_t = tcg_const_i32(rd);
21429 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
21430 cpu_gpr[rt]);
21431 gen_store_gpr(v1_t, rt);
21432 tcg_temp_free_i32(sa_t);
21434 break;
21436 break;
21437 case NM_MULEU_S_PH_QBL:
21438 check_dsp(ctx);
21439 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
21440 gen_store_gpr(v1_t, ret);
21441 break;
21442 case NM_MULEU_S_PH_QBR:
21443 check_dsp(ctx);
21444 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
21445 gen_store_gpr(v1_t, ret);
21446 break;
21447 case NM_MULQ_RS_PH:
21448 check_dsp(ctx);
21449 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
21450 gen_store_gpr(v1_t, ret);
21451 break;
21452 case NM_MULQ_S_PH:
21453 check_dsp_r2(ctx);
21454 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
21455 gen_store_gpr(v1_t, ret);
21456 break;
21457 case NM_MULQ_RS_W:
21458 check_dsp_r2(ctx);
21459 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
21460 gen_store_gpr(v1_t, ret);
21461 break;
21462 case NM_MULQ_S_W:
21463 check_dsp_r2(ctx);
21464 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
21465 gen_store_gpr(v1_t, ret);
21466 break;
21467 case NM_APPEND:
21468 check_dsp_r2(ctx);
21469 gen_load_gpr(t0, rs);
21470 if (rd != 0) {
21471 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
21473 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21474 break;
21475 case NM_MODSUB:
21476 check_dsp(ctx);
21477 gen_helper_modsub(v1_t, v1_t, v2_t);
21478 gen_store_gpr(v1_t, ret);
21479 break;
21480 case NM_SHRAV_R_W:
21481 check_dsp(ctx);
21482 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
21483 gen_store_gpr(v1_t, ret);
21484 break;
21485 case NM_SHRLV_PH:
21486 check_dsp_r2(ctx);
21487 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
21488 gen_store_gpr(v1_t, ret);
21489 break;
21490 case NM_SHRLV_QB:
21491 check_dsp(ctx);
21492 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
21493 gen_store_gpr(v1_t, ret);
21494 break;
21495 case NM_SHLLV_QB:
21496 check_dsp(ctx);
21497 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
21498 gen_store_gpr(v1_t, ret);
21499 break;
21500 case NM_SHLLV_S_W:
21501 check_dsp(ctx);
21502 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
21503 gen_store_gpr(v1_t, ret);
21504 break;
21505 case NM_SHILO:
21506 check_dsp(ctx);
21508 TCGv tv0 = tcg_temp_new();
21509 TCGv tv1 = tcg_temp_new();
21510 int16_t imm = extract32(ctx->opcode, 16, 7);
21512 tcg_gen_movi_tl(tv0, rd >> 3);
21513 tcg_gen_movi_tl(tv1, imm);
21514 gen_helper_shilo(tv0, tv1, cpu_env);
21516 break;
21517 case NM_MULEQ_S_W_PHL:
21518 check_dsp(ctx);
21519 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
21520 gen_store_gpr(v1_t, ret);
21521 break;
21522 case NM_MULEQ_S_W_PHR:
21523 check_dsp(ctx);
21524 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
21525 gen_store_gpr(v1_t, ret);
21526 break;
21527 case NM_MUL_S_PH:
21528 check_dsp_r2(ctx);
21529 switch (extract32(ctx->opcode, 10, 1)) {
21530 case 0:
21531 /* MUL_PH */
21532 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
21533 gen_store_gpr(v1_t, ret);
21534 break;
21535 case 1:
21536 /* MUL_S_PH */
21537 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
21538 gen_store_gpr(v1_t, ret);
21539 break;
21541 break;
21542 case NM_PRECR_QB_PH:
21543 check_dsp_r2(ctx);
21544 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
21545 gen_store_gpr(v1_t, ret);
21546 break;
21547 case NM_PRECRQ_QB_PH:
21548 check_dsp(ctx);
21549 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
21550 gen_store_gpr(v1_t, ret);
21551 break;
21552 case NM_PRECRQ_PH_W:
21553 check_dsp(ctx);
21554 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
21555 gen_store_gpr(v1_t, ret);
21556 break;
21557 case NM_PRECRQ_RS_PH_W:
21558 check_dsp(ctx);
21559 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
21560 gen_store_gpr(v1_t, ret);
21561 break;
21562 case NM_PRECRQU_S_QB_PH:
21563 check_dsp(ctx);
21564 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
21565 gen_store_gpr(v1_t, ret);
21566 break;
21567 case NM_SHRA_R_W:
21568 check_dsp(ctx);
21569 tcg_gen_movi_tl(t0, rd);
21570 gen_helper_shra_r_w(v1_t, t0, v1_t);
21571 gen_store_gpr(v1_t, rt);
21572 break;
21573 case NM_SHRA_R_PH:
21574 check_dsp(ctx);
21575 tcg_gen_movi_tl(t0, rd >> 1);
21576 switch (extract32(ctx->opcode, 10, 1)) {
21577 case 0:
21578 /* SHRA_PH */
21579 gen_helper_shra_ph(v1_t, t0, v1_t);
21580 gen_store_gpr(v1_t, rt);
21581 break;
21582 case 1:
21583 /* SHRA_R_PH */
21584 gen_helper_shra_r_ph(v1_t, t0, v1_t);
21585 gen_store_gpr(v1_t, rt);
21586 break;
21588 break;
21589 case NM_SHLL_S_PH:
21590 check_dsp(ctx);
21591 tcg_gen_movi_tl(t0, rd >> 1);
21592 switch (extract32(ctx->opcode, 10, 2)) {
21593 case 0:
21594 /* SHLL_PH */
21595 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
21596 gen_store_gpr(v1_t, rt);
21597 break;
21598 case 2:
21599 /* SHLL_S_PH */
21600 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
21601 gen_store_gpr(v1_t, rt);
21602 break;
21603 default:
21604 gen_reserved_instruction(ctx);
21605 break;
21607 break;
21608 case NM_SHLL_S_W:
21609 check_dsp(ctx);
21610 tcg_gen_movi_tl(t0, rd);
21611 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
21612 gen_store_gpr(v1_t, rt);
21613 break;
21614 case NM_REPL_PH:
21615 check_dsp(ctx);
21617 int16_t imm;
21618 imm = sextract32(ctx->opcode, 11, 11);
21619 imm = (int16_t)(imm << 6) >> 6;
21620 if (rt != 0) {
21621 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
21624 break;
21625 default:
21626 gen_reserved_instruction(ctx);
21627 break;
21631 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
21633 uint16_t insn;
21634 uint32_t op;
21635 int rt, rs, rd;
21636 int offset;
21637 int imm;
21639 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
21640 ctx->opcode = (ctx->opcode << 16) | insn;
21642 rt = extract32(ctx->opcode, 21, 5);
21643 rs = extract32(ctx->opcode, 16, 5);
21644 rd = extract32(ctx->opcode, 11, 5);
21646 op = extract32(ctx->opcode, 26, 6);
21647 switch (op) {
21648 case NM_P_ADDIU:
21649 if (rt == 0) {
21650 /* P.RI */
21651 switch (extract32(ctx->opcode, 19, 2)) {
21652 case NM_SIGRIE:
21653 default:
21654 gen_reserved_instruction(ctx);
21655 break;
21656 case NM_P_SYSCALL:
21657 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
21658 generate_exception_end(ctx, EXCP_SYSCALL);
21659 } else {
21660 gen_reserved_instruction(ctx);
21662 break;
21663 case NM_BREAK:
21664 generate_exception_end(ctx, EXCP_BREAK);
21665 break;
21666 case NM_SDBBP:
21667 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
21668 gen_helper_do_semihosting(cpu_env);
21669 } else {
21670 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21671 gen_reserved_instruction(ctx);
21672 } else {
21673 generate_exception_end(ctx, EXCP_DBp);
21676 break;
21678 } else {
21679 /* NM_ADDIU */
21680 imm = extract32(ctx->opcode, 0, 16);
21681 if (rs != 0) {
21682 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
21683 } else {
21684 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21686 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21688 break;
21689 case NM_ADDIUPC:
21690 if (rt != 0) {
21691 offset = sextract32(ctx->opcode, 0, 1) << 21 |
21692 extract32(ctx->opcode, 1, 20) << 1;
21693 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
21694 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21696 break;
21697 case NM_POOL32A:
21698 switch (ctx->opcode & 0x07) {
21699 case NM_POOL32A0:
21700 gen_pool32a0_nanomips_insn(env, ctx);
21701 break;
21702 case NM_POOL32A5:
21704 int32_t op1 = extract32(ctx->opcode, 3, 7);
21705 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
21707 break;
21708 case NM_POOL32A7:
21709 switch (extract32(ctx->opcode, 3, 3)) {
21710 case NM_P_LSX:
21711 gen_p_lsx(ctx, rd, rs, rt);
21712 break;
21713 case NM_LSA:
21715 * In nanoMIPS, the shift field directly encodes the shift
21716 * amount, meaning that the supported shift values are in
21717 * the range 0 to 3 (instead of 1 to 4 in MIPSR6).
21719 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
21720 extract32(ctx->opcode, 9, 2) - 1);
21721 break;
21722 case NM_EXTW:
21723 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
21724 break;
21725 case NM_POOL32AXF:
21726 gen_pool32axf_nanomips_insn(env, ctx);
21727 break;
21728 default:
21729 gen_reserved_instruction(ctx);
21730 break;
21732 break;
21733 default:
21734 gen_reserved_instruction(ctx);
21735 break;
21737 break;
21738 case NM_P_GP_W:
21739 switch (ctx->opcode & 0x03) {
21740 case NM_ADDIUGP_W:
21741 if (rt != 0) {
21742 offset = extract32(ctx->opcode, 0, 21);
21743 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
21745 break;
21746 case NM_LWGP:
21747 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21748 break;
21749 case NM_SWGP:
21750 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21751 break;
21752 default:
21753 gen_reserved_instruction(ctx);
21754 break;
21756 break;
21757 case NM_P48I:
21759 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
21760 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
21761 switch (extract32(ctx->opcode, 16, 5)) {
21762 case NM_LI48:
21763 check_nms(ctx);
21764 if (rt != 0) {
21765 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
21767 break;
21768 case NM_ADDIU48:
21769 check_nms(ctx);
21770 if (rt != 0) {
21771 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
21772 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21774 break;
21775 case NM_ADDIUGP48:
21776 check_nms(ctx);
21777 if (rt != 0) {
21778 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
21780 break;
21781 case NM_ADDIUPC48:
21782 check_nms(ctx);
21783 if (rt != 0) {
21784 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21785 addr_off);
21787 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21789 break;
21790 case NM_LWPC48:
21791 check_nms(ctx);
21792 if (rt != 0) {
21793 TCGv t0;
21794 t0 = tcg_temp_new();
21796 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21797 addr_off);
21799 tcg_gen_movi_tl(t0, addr);
21800 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
21801 tcg_temp_free(t0);
21803 break;
21804 case NM_SWPC48:
21805 check_nms(ctx);
21807 TCGv t0, t1;
21808 t0 = tcg_temp_new();
21809 t1 = tcg_temp_new();
21811 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21812 addr_off);
21814 tcg_gen_movi_tl(t0, addr);
21815 gen_load_gpr(t1, rt);
21817 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
21819 tcg_temp_free(t0);
21820 tcg_temp_free(t1);
21822 break;
21823 default:
21824 gen_reserved_instruction(ctx);
21825 break;
21827 return 6;
21829 case NM_P_U12:
21830 switch (extract32(ctx->opcode, 12, 4)) {
21831 case NM_ORI:
21832 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
21833 break;
21834 case NM_XORI:
21835 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
21836 break;
21837 case NM_ANDI:
21838 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
21839 break;
21840 case NM_P_SR:
21841 switch (extract32(ctx->opcode, 20, 1)) {
21842 case NM_PP_SR:
21843 switch (ctx->opcode & 3) {
21844 case NM_SAVE:
21845 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
21846 extract32(ctx->opcode, 2, 1),
21847 extract32(ctx->opcode, 3, 9) << 3);
21848 break;
21849 case NM_RESTORE:
21850 case NM_RESTORE_JRC:
21851 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
21852 extract32(ctx->opcode, 2, 1),
21853 extract32(ctx->opcode, 3, 9) << 3);
21854 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
21855 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21857 break;
21858 default:
21859 gen_reserved_instruction(ctx);
21860 break;
21862 break;
21863 case NM_P_SR_F:
21864 gen_reserved_instruction(ctx);
21865 break;
21867 break;
21868 case NM_SLTI:
21869 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
21870 break;
21871 case NM_SLTIU:
21872 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
21873 break;
21874 case NM_SEQI:
21876 TCGv t0 = tcg_temp_new();
21878 imm = extract32(ctx->opcode, 0, 12);
21879 gen_load_gpr(t0, rs);
21880 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
21881 gen_store_gpr(t0, rt);
21883 tcg_temp_free(t0);
21885 break;
21886 case NM_ADDIUNEG:
21887 imm = (int16_t) extract32(ctx->opcode, 0, 12);
21888 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
21889 break;
21890 case NM_P_SHIFT:
21892 int shift = extract32(ctx->opcode, 0, 5);
21893 switch (extract32(ctx->opcode, 5, 4)) {
21894 case NM_P_SLL:
21895 if (rt == 0 && shift == 0) {
21896 /* NOP */
21897 } else if (rt == 0 && shift == 3) {
21898 /* EHB - treat as NOP */
21899 } else if (rt == 0 && shift == 5) {
21900 /* PAUSE - treat as NOP */
21901 } else if (rt == 0 && shift == 6) {
21902 /* SYNC */
21903 gen_sync(extract32(ctx->opcode, 16, 5));
21904 } else {
21905 /* SLL */
21906 gen_shift_imm(ctx, OPC_SLL, rt, rs,
21907 extract32(ctx->opcode, 0, 5));
21909 break;
21910 case NM_SRL:
21911 gen_shift_imm(ctx, OPC_SRL, rt, rs,
21912 extract32(ctx->opcode, 0, 5));
21913 break;
21914 case NM_SRA:
21915 gen_shift_imm(ctx, OPC_SRA, rt, rs,
21916 extract32(ctx->opcode, 0, 5));
21917 break;
21918 case NM_ROTR:
21919 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
21920 extract32(ctx->opcode, 0, 5));
21921 break;
21924 break;
21925 case NM_P_ROTX:
21926 check_nms(ctx);
21927 if (rt != 0) {
21928 TCGv t0 = tcg_temp_new();
21929 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
21930 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
21931 << 1);
21932 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
21934 gen_load_gpr(t0, rs);
21935 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
21936 tcg_temp_free(t0);
21938 tcg_temp_free_i32(shift);
21939 tcg_temp_free_i32(shiftx);
21940 tcg_temp_free_i32(stripe);
21942 break;
21943 case NM_P_INS:
21944 switch (((ctx->opcode >> 10) & 2) |
21945 (extract32(ctx->opcode, 5, 1))) {
21946 case NM_INS:
21947 check_nms(ctx);
21948 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
21949 extract32(ctx->opcode, 6, 5));
21950 break;
21951 default:
21952 gen_reserved_instruction(ctx);
21953 break;
21955 break;
21956 case NM_P_EXT:
21957 switch (((ctx->opcode >> 10) & 2) |
21958 (extract32(ctx->opcode, 5, 1))) {
21959 case NM_EXT:
21960 check_nms(ctx);
21961 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
21962 extract32(ctx->opcode, 6, 5));
21963 break;
21964 default:
21965 gen_reserved_instruction(ctx);
21966 break;
21968 break;
21969 default:
21970 gen_reserved_instruction(ctx);
21971 break;
21973 break;
21974 case NM_POOL32F:
21975 gen_pool32f_nanomips_insn(ctx);
21976 break;
21977 case NM_POOL32S:
21978 break;
21979 case NM_P_LUI:
21980 switch (extract32(ctx->opcode, 1, 1)) {
21981 case NM_LUI:
21982 if (rt != 0) {
21983 tcg_gen_movi_tl(cpu_gpr[rt],
21984 sextract32(ctx->opcode, 0, 1) << 31 |
21985 extract32(ctx->opcode, 2, 10) << 21 |
21986 extract32(ctx->opcode, 12, 9) << 12);
21988 break;
21989 case NM_ALUIPC:
21990 if (rt != 0) {
21991 offset = sextract32(ctx->opcode, 0, 1) << 31 |
21992 extract32(ctx->opcode, 2, 10) << 21 |
21993 extract32(ctx->opcode, 12, 9) << 12;
21994 target_long addr;
21995 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
21996 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21998 break;
22000 break;
22001 case NM_P_GP_BH:
22003 uint32_t u = extract32(ctx->opcode, 0, 18);
22005 switch (extract32(ctx->opcode, 18, 3)) {
22006 case NM_LBGP:
22007 gen_ld(ctx, OPC_LB, rt, 28, u);
22008 break;
22009 case NM_SBGP:
22010 gen_st(ctx, OPC_SB, rt, 28, u);
22011 break;
22012 case NM_LBUGP:
22013 gen_ld(ctx, OPC_LBU, rt, 28, u);
22014 break;
22015 case NM_ADDIUGP_B:
22016 if (rt != 0) {
22017 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
22019 break;
22020 case NM_P_GP_LH:
22021 u &= ~1;
22022 switch (ctx->opcode & 1) {
22023 case NM_LHGP:
22024 gen_ld(ctx, OPC_LH, rt, 28, u);
22025 break;
22026 case NM_LHUGP:
22027 gen_ld(ctx, OPC_LHU, rt, 28, u);
22028 break;
22030 break;
22031 case NM_P_GP_SH:
22032 u &= ~1;
22033 switch (ctx->opcode & 1) {
22034 case NM_SHGP:
22035 gen_st(ctx, OPC_SH, rt, 28, u);
22036 break;
22037 default:
22038 gen_reserved_instruction(ctx);
22039 break;
22041 break;
22042 case NM_P_GP_CP1:
22043 u &= ~0x3;
22044 switch (ctx->opcode & 0x3) {
22045 case NM_LWC1GP:
22046 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
22047 break;
22048 case NM_LDC1GP:
22049 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
22050 break;
22051 case NM_SWC1GP:
22052 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
22053 break;
22054 case NM_SDC1GP:
22055 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
22056 break;
22058 break;
22059 default:
22060 gen_reserved_instruction(ctx);
22061 break;
22064 break;
22065 case NM_P_LS_U12:
22067 uint32_t u = extract32(ctx->opcode, 0, 12);
22069 switch (extract32(ctx->opcode, 12, 4)) {
22070 case NM_P_PREFU12:
22071 if (rt == 31) {
22072 /* SYNCI */
22074 * Break the TB to be able to sync copied instructions
22075 * immediately.
22077 ctx->base.is_jmp = DISAS_STOP;
22078 } else {
22079 /* PREF */
22080 /* Treat as NOP. */
22082 break;
22083 case NM_LB:
22084 gen_ld(ctx, OPC_LB, rt, rs, u);
22085 break;
22086 case NM_LH:
22087 gen_ld(ctx, OPC_LH, rt, rs, u);
22088 break;
22089 case NM_LW:
22090 gen_ld(ctx, OPC_LW, rt, rs, u);
22091 break;
22092 case NM_LBU:
22093 gen_ld(ctx, OPC_LBU, rt, rs, u);
22094 break;
22095 case NM_LHU:
22096 gen_ld(ctx, OPC_LHU, rt, rs, u);
22097 break;
22098 case NM_SB:
22099 gen_st(ctx, OPC_SB, rt, rs, u);
22100 break;
22101 case NM_SH:
22102 gen_st(ctx, OPC_SH, rt, rs, u);
22103 break;
22104 case NM_SW:
22105 gen_st(ctx, OPC_SW, rt, rs, u);
22106 break;
22107 case NM_LWC1:
22108 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
22109 break;
22110 case NM_LDC1:
22111 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
22112 break;
22113 case NM_SWC1:
22114 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
22115 break;
22116 case NM_SDC1:
22117 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
22118 break;
22119 default:
22120 gen_reserved_instruction(ctx);
22121 break;
22124 break;
22125 case NM_P_LS_S9:
22127 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
22128 extract32(ctx->opcode, 0, 8);
22130 switch (extract32(ctx->opcode, 8, 3)) {
22131 case NM_P_LS_S0:
22132 switch (extract32(ctx->opcode, 11, 4)) {
22133 case NM_LBS9:
22134 gen_ld(ctx, OPC_LB, rt, rs, s);
22135 break;
22136 case NM_LHS9:
22137 gen_ld(ctx, OPC_LH, rt, rs, s);
22138 break;
22139 case NM_LWS9:
22140 gen_ld(ctx, OPC_LW, rt, rs, s);
22141 break;
22142 case NM_LBUS9:
22143 gen_ld(ctx, OPC_LBU, rt, rs, s);
22144 break;
22145 case NM_LHUS9:
22146 gen_ld(ctx, OPC_LHU, rt, rs, s);
22147 break;
22148 case NM_SBS9:
22149 gen_st(ctx, OPC_SB, rt, rs, s);
22150 break;
22151 case NM_SHS9:
22152 gen_st(ctx, OPC_SH, rt, rs, s);
22153 break;
22154 case NM_SWS9:
22155 gen_st(ctx, OPC_SW, rt, rs, s);
22156 break;
22157 case NM_LWC1S9:
22158 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
22159 break;
22160 case NM_LDC1S9:
22161 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
22162 break;
22163 case NM_SWC1S9:
22164 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
22165 break;
22166 case NM_SDC1S9:
22167 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
22168 break;
22169 case NM_P_PREFS9:
22170 if (rt == 31) {
22171 /* SYNCI */
22173 * Break the TB to be able to sync copied instructions
22174 * immediately.
22176 ctx->base.is_jmp = DISAS_STOP;
22177 } else {
22178 /* PREF */
22179 /* Treat as NOP. */
22181 break;
22182 default:
22183 gen_reserved_instruction(ctx);
22184 break;
22186 break;
22187 case NM_P_LS_S1:
22188 switch (extract32(ctx->opcode, 11, 4)) {
22189 case NM_UALH:
22190 case NM_UASH:
22191 check_nms(ctx);
22193 TCGv t0 = tcg_temp_new();
22194 TCGv t1 = tcg_temp_new();
22196 gen_base_offset_addr(ctx, t0, rs, s);
22198 switch (extract32(ctx->opcode, 11, 4)) {
22199 case NM_UALH:
22200 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
22201 MO_UNALN);
22202 gen_store_gpr(t0, rt);
22203 break;
22204 case NM_UASH:
22205 gen_load_gpr(t1, rt);
22206 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
22207 MO_UNALN);
22208 break;
22210 tcg_temp_free(t0);
22211 tcg_temp_free(t1);
22213 break;
22214 case NM_P_LL:
22215 switch (ctx->opcode & 0x03) {
22216 case NM_LL:
22217 gen_ld(ctx, OPC_LL, rt, rs, s);
22218 break;
22219 case NM_LLWP:
22220 check_xnp(ctx);
22221 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
22222 break;
22224 break;
22225 case NM_P_SC:
22226 switch (ctx->opcode & 0x03) {
22227 case NM_SC:
22228 gen_st_cond(ctx, rt, rs, s, MO_TESL, false);
22229 break;
22230 case NM_SCWP:
22231 check_xnp(ctx);
22232 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
22233 false);
22234 break;
22236 break;
22237 case NM_CACHE:
22238 check_cp0_enabled(ctx);
22239 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
22240 gen_cache_operation(ctx, rt, rs, s);
22242 break;
22244 break;
22245 case NM_P_LS_E0:
22246 switch (extract32(ctx->opcode, 11, 4)) {
22247 case NM_LBE:
22248 check_eva(ctx);
22249 check_cp0_enabled(ctx);
22250 gen_ld(ctx, OPC_LBE, rt, rs, s);
22251 break;
22252 case NM_SBE:
22253 check_eva(ctx);
22254 check_cp0_enabled(ctx);
22255 gen_st(ctx, OPC_SBE, rt, rs, s);
22256 break;
22257 case NM_LBUE:
22258 check_eva(ctx);
22259 check_cp0_enabled(ctx);
22260 gen_ld(ctx, OPC_LBUE, rt, rs, s);
22261 break;
22262 case NM_P_PREFE:
22263 if (rt == 31) {
22264 /* case NM_SYNCIE */
22265 check_eva(ctx);
22266 check_cp0_enabled(ctx);
22268 * Break the TB to be able to sync copied instructions
22269 * immediately.
22271 ctx->base.is_jmp = DISAS_STOP;
22272 } else {
22273 /* case NM_PREFE */
22274 check_eva(ctx);
22275 check_cp0_enabled(ctx);
22276 /* Treat as NOP. */
22278 break;
22279 case NM_LHE:
22280 check_eva(ctx);
22281 check_cp0_enabled(ctx);
22282 gen_ld(ctx, OPC_LHE, rt, rs, s);
22283 break;
22284 case NM_SHE:
22285 check_eva(ctx);
22286 check_cp0_enabled(ctx);
22287 gen_st(ctx, OPC_SHE, rt, rs, s);
22288 break;
22289 case NM_LHUE:
22290 check_eva(ctx);
22291 check_cp0_enabled(ctx);
22292 gen_ld(ctx, OPC_LHUE, rt, rs, s);
22293 break;
22294 case NM_CACHEE:
22295 check_nms_dl_il_sl_tl_l2c(ctx);
22296 gen_cache_operation(ctx, rt, rs, s);
22297 break;
22298 case NM_LWE:
22299 check_eva(ctx);
22300 check_cp0_enabled(ctx);
22301 gen_ld(ctx, OPC_LWE, rt, rs, s);
22302 break;
22303 case NM_SWE:
22304 check_eva(ctx);
22305 check_cp0_enabled(ctx);
22306 gen_st(ctx, OPC_SWE, rt, rs, s);
22307 break;
22308 case NM_P_LLE:
22309 switch (extract32(ctx->opcode, 2, 2)) {
22310 case NM_LLE:
22311 check_xnp(ctx);
22312 check_eva(ctx);
22313 check_cp0_enabled(ctx);
22314 gen_ld(ctx, OPC_LLE, rt, rs, s);
22315 break;
22316 case NM_LLWPE:
22317 check_xnp(ctx);
22318 check_eva(ctx);
22319 check_cp0_enabled(ctx);
22320 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
22321 break;
22322 default:
22323 gen_reserved_instruction(ctx);
22324 break;
22326 break;
22327 case NM_P_SCE:
22328 switch (extract32(ctx->opcode, 2, 2)) {
22329 case NM_SCE:
22330 check_xnp(ctx);
22331 check_eva(ctx);
22332 check_cp0_enabled(ctx);
22333 gen_st_cond(ctx, rt, rs, s, MO_TESL, true);
22334 break;
22335 case NM_SCWPE:
22336 check_xnp(ctx);
22337 check_eva(ctx);
22338 check_cp0_enabled(ctx);
22339 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
22340 true);
22341 break;
22342 default:
22343 gen_reserved_instruction(ctx);
22344 break;
22346 break;
22348 break;
22349 case NM_P_LS_WM:
22350 case NM_P_LS_UAWM:
22351 check_nms(ctx);
22353 int count = extract32(ctx->opcode, 12, 3);
22354 int counter = 0;
22356 offset = sextract32(ctx->opcode, 15, 1) << 8 |
22357 extract32(ctx->opcode, 0, 8);
22358 TCGv va = tcg_temp_new();
22359 TCGv t1 = tcg_temp_new();
22360 MemOp memop = (extract32(ctx->opcode, 8, 3)) ==
22361 NM_P_LS_UAWM ? MO_UNALN : 0;
22363 count = (count == 0) ? 8 : count;
22364 while (counter != count) {
22365 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
22366 int this_offset = offset + (counter << 2);
22368 gen_base_offset_addr(ctx, va, rs, this_offset);
22370 switch (extract32(ctx->opcode, 11, 1)) {
22371 case NM_LWM:
22372 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
22373 memop | MO_TESL);
22374 gen_store_gpr(t1, this_rt);
22375 if ((this_rt == rs) &&
22376 (counter != (count - 1))) {
22377 /* UNPREDICTABLE */
22379 break;
22380 case NM_SWM:
22381 this_rt = (rt == 0) ? 0 : this_rt;
22382 gen_load_gpr(t1, this_rt);
22383 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
22384 memop | MO_TEUL);
22385 break;
22387 counter++;
22389 tcg_temp_free(va);
22390 tcg_temp_free(t1);
22392 break;
22393 default:
22394 gen_reserved_instruction(ctx);
22395 break;
22398 break;
22399 case NM_MOVE_BALC:
22400 check_nms(ctx);
22402 TCGv t0 = tcg_temp_new();
22403 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
22404 extract32(ctx->opcode, 1, 20) << 1;
22405 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
22406 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
22407 extract32(ctx->opcode, 21, 3));
22408 gen_load_gpr(t0, rt);
22409 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22410 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
22411 tcg_temp_free(t0);
22413 break;
22414 case NM_P_BAL:
22416 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
22417 extract32(ctx->opcode, 1, 24) << 1;
22419 if ((extract32(ctx->opcode, 25, 1)) == 0) {
22420 /* BC */
22421 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
22422 } else {
22423 /* BALC */
22424 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
22427 break;
22428 case NM_P_J:
22429 switch (extract32(ctx->opcode, 12, 4)) {
22430 case NM_JALRC:
22431 case NM_JALRC_HB:
22432 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
22433 break;
22434 case NM_P_BALRSC:
22435 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
22436 break;
22437 default:
22438 gen_reserved_instruction(ctx);
22439 break;
22441 break;
22442 case NM_P_BR1:
22444 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
22445 extract32(ctx->opcode, 1, 13) << 1;
22446 switch (extract32(ctx->opcode, 14, 2)) {
22447 case NM_BEQC:
22448 check_nms(ctx);
22449 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
22450 break;
22451 case NM_P_BR3A:
22452 s = sextract32(ctx->opcode, 0, 1) << 14 |
22453 extract32(ctx->opcode, 1, 13) << 1;
22454 check_cp1_enabled(ctx);
22455 switch (extract32(ctx->opcode, 16, 5)) {
22456 case NM_BC1EQZC:
22457 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
22458 break;
22459 case NM_BC1NEZC:
22460 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
22461 break;
22462 case NM_BPOSGE32C:
22463 check_dsp_r3(ctx);
22465 int32_t imm = extract32(ctx->opcode, 1, 13) |
22466 extract32(ctx->opcode, 0, 1) << 13;
22468 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
22469 imm);
22471 break;
22472 default:
22473 gen_reserved_instruction(ctx);
22474 break;
22476 break;
22477 case NM_BGEC:
22478 if (rs == rt) {
22479 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
22480 } else {
22481 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
22483 break;
22484 case NM_BGEUC:
22485 if (rs == rt || rt == 0) {
22486 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
22487 } else if (rs == 0) {
22488 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
22489 } else {
22490 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
22492 break;
22495 break;
22496 case NM_P_BR2:
22498 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
22499 extract32(ctx->opcode, 1, 13) << 1;
22500 switch (extract32(ctx->opcode, 14, 2)) {
22501 case NM_BNEC:
22502 check_nms(ctx);
22503 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
22504 break;
22505 case NM_BLTC:
22506 if (rs != 0 && rt != 0 && rs == rt) {
22507 /* NOP */
22508 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22509 } else {
22510 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
22512 break;
22513 case NM_BLTUC:
22514 if (rs == 0 || rs == rt) {
22515 /* NOP */
22516 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22517 } else {
22518 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
22520 break;
22521 default:
22522 gen_reserved_instruction(ctx);
22523 break;
22526 break;
22527 case NM_P_BRI:
22529 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
22530 extract32(ctx->opcode, 1, 10) << 1;
22531 uint32_t u = extract32(ctx->opcode, 11, 7);
22533 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
22534 rt, u, s);
22536 break;
22537 default:
22538 gen_reserved_instruction(ctx);
22539 break;
22541 return 4;
22544 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
22546 uint32_t op;
22547 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
22548 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22549 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode));
22550 int offset;
22551 int imm;
22553 /* make sure instructions are on a halfword boundary */
22554 if (ctx->base.pc_next & 0x1) {
22555 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
22556 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
22557 tcg_temp_free(tmp);
22558 generate_exception_end(ctx, EXCP_AdEL);
22559 return 2;
22562 op = extract32(ctx->opcode, 10, 6);
22563 switch (op) {
22564 case NM_P16_MV:
22565 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22566 if (rt != 0) {
22567 /* MOVE */
22568 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
22569 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
22570 } else {
22571 /* P16.RI */
22572 switch (extract32(ctx->opcode, 3, 2)) {
22573 case NM_P16_SYSCALL:
22574 if (extract32(ctx->opcode, 2, 1) == 0) {
22575 generate_exception_end(ctx, EXCP_SYSCALL);
22576 } else {
22577 gen_reserved_instruction(ctx);
22579 break;
22580 case NM_BREAK16:
22581 generate_exception_end(ctx, EXCP_BREAK);
22582 break;
22583 case NM_SDBBP16:
22584 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
22585 gen_helper_do_semihosting(cpu_env);
22586 } else {
22587 if (ctx->hflags & MIPS_HFLAG_SBRI) {
22588 gen_reserved_instruction(ctx);
22589 } else {
22590 generate_exception_end(ctx, EXCP_DBp);
22593 break;
22594 default:
22595 gen_reserved_instruction(ctx);
22596 break;
22599 break;
22600 case NM_P16_SHIFT:
22602 int shift = extract32(ctx->opcode, 0, 3);
22603 uint32_t opc = 0;
22604 shift = (shift == 0) ? 8 : shift;
22606 switch (extract32(ctx->opcode, 3, 1)) {
22607 case NM_SLL16:
22608 opc = OPC_SLL;
22609 break;
22610 case NM_SRL16:
22611 opc = OPC_SRL;
22612 break;
22614 gen_shift_imm(ctx, opc, rt, rs, shift);
22616 break;
22617 case NM_P16C:
22618 switch (ctx->opcode & 1) {
22619 case NM_POOL16C_0:
22620 gen_pool16c_nanomips_insn(ctx);
22621 break;
22622 case NM_LWXS16:
22623 gen_ldxs(ctx, rt, rs, rd);
22624 break;
22626 break;
22627 case NM_P16_A1:
22628 switch (extract32(ctx->opcode, 6, 1)) {
22629 case NM_ADDIUR1SP:
22630 imm = extract32(ctx->opcode, 0, 6) << 2;
22631 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
22632 break;
22633 default:
22634 gen_reserved_instruction(ctx);
22635 break;
22637 break;
22638 case NM_P16_A2:
22639 switch (extract32(ctx->opcode, 3, 1)) {
22640 case NM_ADDIUR2:
22641 imm = extract32(ctx->opcode, 0, 3) << 2;
22642 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
22643 break;
22644 case NM_P_ADDIURS5:
22645 rt = extract32(ctx->opcode, 5, 5);
22646 if (rt != 0) {
22647 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
22648 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
22649 (extract32(ctx->opcode, 0, 3));
22650 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
22652 break;
22654 break;
22655 case NM_P16_ADDU:
22656 switch (ctx->opcode & 0x1) {
22657 case NM_ADDU16:
22658 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
22659 break;
22660 case NM_SUBU16:
22661 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
22662 break;
22664 break;
22665 case NM_P16_4X4:
22666 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22667 extract32(ctx->opcode, 5, 3);
22668 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22669 extract32(ctx->opcode, 0, 3);
22670 rt = decode_gpr_gpr4(rt);
22671 rs = decode_gpr_gpr4(rs);
22672 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
22673 (extract32(ctx->opcode, 3, 1))) {
22674 case NM_ADDU4X4:
22675 check_nms(ctx);
22676 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
22677 break;
22678 case NM_MUL4X4:
22679 check_nms(ctx);
22680 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
22681 break;
22682 default:
22683 gen_reserved_instruction(ctx);
22684 break;
22686 break;
22687 case NM_LI16:
22689 int imm = extract32(ctx->opcode, 0, 7);
22690 imm = (imm == 0x7f ? -1 : imm);
22691 if (rt != 0) {
22692 tcg_gen_movi_tl(cpu_gpr[rt], imm);
22695 break;
22696 case NM_ANDI16:
22698 uint32_t u = extract32(ctx->opcode, 0, 4);
22699 u = (u == 12) ? 0xff :
22700 (u == 13) ? 0xffff : u;
22701 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
22703 break;
22704 case NM_P16_LB:
22705 offset = extract32(ctx->opcode, 0, 2);
22706 switch (extract32(ctx->opcode, 2, 2)) {
22707 case NM_LB16:
22708 gen_ld(ctx, OPC_LB, rt, rs, offset);
22709 break;
22710 case NM_SB16:
22711 rt = decode_gpr_gpr3_src_store(
22712 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22713 gen_st(ctx, OPC_SB, rt, rs, offset);
22714 break;
22715 case NM_LBU16:
22716 gen_ld(ctx, OPC_LBU, rt, rs, offset);
22717 break;
22718 default:
22719 gen_reserved_instruction(ctx);
22720 break;
22722 break;
22723 case NM_P16_LH:
22724 offset = extract32(ctx->opcode, 1, 2) << 1;
22725 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
22726 case NM_LH16:
22727 gen_ld(ctx, OPC_LH, rt, rs, offset);
22728 break;
22729 case NM_SH16:
22730 rt = decode_gpr_gpr3_src_store(
22731 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22732 gen_st(ctx, OPC_SH, rt, rs, offset);
22733 break;
22734 case NM_LHU16:
22735 gen_ld(ctx, OPC_LHU, rt, rs, offset);
22736 break;
22737 default:
22738 gen_reserved_instruction(ctx);
22739 break;
22741 break;
22742 case NM_LW16:
22743 offset = extract32(ctx->opcode, 0, 4) << 2;
22744 gen_ld(ctx, OPC_LW, rt, rs, offset);
22745 break;
22746 case NM_LWSP16:
22747 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22748 offset = extract32(ctx->opcode, 0, 5) << 2;
22749 gen_ld(ctx, OPC_LW, rt, 29, offset);
22750 break;
22751 case NM_LW4X4:
22752 check_nms(ctx);
22753 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22754 extract32(ctx->opcode, 5, 3);
22755 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22756 extract32(ctx->opcode, 0, 3);
22757 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22758 (extract32(ctx->opcode, 8, 1) << 2);
22759 rt = decode_gpr_gpr4(rt);
22760 rs = decode_gpr_gpr4(rs);
22761 gen_ld(ctx, OPC_LW, rt, rs, offset);
22762 break;
22763 case NM_SW4X4:
22764 check_nms(ctx);
22765 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22766 extract32(ctx->opcode, 5, 3);
22767 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22768 extract32(ctx->opcode, 0, 3);
22769 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22770 (extract32(ctx->opcode, 8, 1) << 2);
22771 rt = decode_gpr_gpr4_zero(rt);
22772 rs = decode_gpr_gpr4(rs);
22773 gen_st(ctx, OPC_SW, rt, rs, offset);
22774 break;
22775 case NM_LWGP16:
22776 offset = extract32(ctx->opcode, 0, 7) << 2;
22777 gen_ld(ctx, OPC_LW, rt, 28, offset);
22778 break;
22779 case NM_SWSP16:
22780 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22781 offset = extract32(ctx->opcode, 0, 5) << 2;
22782 gen_st(ctx, OPC_SW, rt, 29, offset);
22783 break;
22784 case NM_SW16:
22785 rt = decode_gpr_gpr3_src_store(
22786 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22787 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22788 offset = extract32(ctx->opcode, 0, 4) << 2;
22789 gen_st(ctx, OPC_SW, rt, rs, offset);
22790 break;
22791 case NM_SWGP16:
22792 rt = decode_gpr_gpr3_src_store(
22793 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22794 offset = extract32(ctx->opcode, 0, 7) << 2;
22795 gen_st(ctx, OPC_SW, rt, 28, offset);
22796 break;
22797 case NM_BC16:
22798 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
22799 (sextract32(ctx->opcode, 0, 1) << 10) |
22800 (extract32(ctx->opcode, 1, 9) << 1));
22801 break;
22802 case NM_BALC16:
22803 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
22804 (sextract32(ctx->opcode, 0, 1) << 10) |
22805 (extract32(ctx->opcode, 1, 9) << 1));
22806 break;
22807 case NM_BEQZC16:
22808 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
22809 (sextract32(ctx->opcode, 0, 1) << 7) |
22810 (extract32(ctx->opcode, 1, 6) << 1));
22811 break;
22812 case NM_BNEZC16:
22813 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
22814 (sextract32(ctx->opcode, 0, 1) << 7) |
22815 (extract32(ctx->opcode, 1, 6) << 1));
22816 break;
22817 case NM_P16_BR:
22818 switch (ctx->opcode & 0xf) {
22819 case 0:
22820 /* P16.JRC */
22821 switch (extract32(ctx->opcode, 4, 1)) {
22822 case NM_JRC:
22823 gen_compute_branch_nm(ctx, OPC_JR, 2,
22824 extract32(ctx->opcode, 5, 5), 0, 0);
22825 break;
22826 case NM_JALRC16:
22827 gen_compute_branch_nm(ctx, OPC_JALR, 2,
22828 extract32(ctx->opcode, 5, 5), 31, 0);
22829 break;
22831 break;
22832 default:
22834 /* P16.BRI */
22835 uint32_t opc = extract32(ctx->opcode, 4, 3) <
22836 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
22837 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
22838 extract32(ctx->opcode, 0, 4) << 1);
22840 break;
22842 break;
22843 case NM_P16_SR:
22845 int count = extract32(ctx->opcode, 0, 4);
22846 int u = extract32(ctx->opcode, 4, 4) << 4;
22848 rt = 30 + extract32(ctx->opcode, 9, 1);
22849 switch (extract32(ctx->opcode, 8, 1)) {
22850 case NM_SAVE16:
22851 gen_save(ctx, rt, count, 0, u);
22852 break;
22853 case NM_RESTORE_JRC16:
22854 gen_restore(ctx, rt, count, 0, u);
22855 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
22856 break;
22859 break;
22860 case NM_MOVEP:
22861 case NM_MOVEPREV:
22862 check_nms(ctx);
22864 static const int gpr2reg1[] = {4, 5, 6, 7};
22865 static const int gpr2reg2[] = {5, 6, 7, 8};
22866 int re;
22867 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
22868 extract32(ctx->opcode, 8, 1);
22869 int r1 = gpr2reg1[rd2];
22870 int r2 = gpr2reg2[rd2];
22871 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
22872 extract32(ctx->opcode, 0, 3);
22873 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
22874 extract32(ctx->opcode, 5, 3);
22875 TCGv t0 = tcg_temp_new();
22876 TCGv t1 = tcg_temp_new();
22877 if (op == NM_MOVEP) {
22878 rd = r1;
22879 re = r2;
22880 rs = decode_gpr_gpr4_zero(r3);
22881 rt = decode_gpr_gpr4_zero(r4);
22882 } else {
22883 rd = decode_gpr_gpr4(r3);
22884 re = decode_gpr_gpr4(r4);
22885 rs = r1;
22886 rt = r2;
22888 gen_load_gpr(t0, rs);
22889 gen_load_gpr(t1, rt);
22890 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22891 tcg_gen_mov_tl(cpu_gpr[re], t1);
22892 tcg_temp_free(t0);
22893 tcg_temp_free(t1);
22895 break;
22896 default:
22897 return decode_nanomips_32_48_opc(env, ctx);
22900 return 2;
22904 /* SmartMIPS extension to MIPS32 */
22906 #if defined(TARGET_MIPS64)
22908 /* MDMX extension to MIPS64 */
22910 #endif
22912 /* MIPSDSP functions. */
22913 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
22914 int rd, int base, int offset)
22916 TCGv t0;
22918 check_dsp(ctx);
22919 t0 = tcg_temp_new();
22921 if (base == 0) {
22922 gen_load_gpr(t0, offset);
22923 } else if (offset == 0) {
22924 gen_load_gpr(t0, base);
22925 } else {
22926 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
22929 switch (opc) {
22930 case OPC_LBUX:
22931 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
22932 gen_store_gpr(t0, rd);
22933 break;
22934 case OPC_LHX:
22935 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
22936 gen_store_gpr(t0, rd);
22937 break;
22938 case OPC_LWX:
22939 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
22940 gen_store_gpr(t0, rd);
22941 break;
22942 #if defined(TARGET_MIPS64)
22943 case OPC_LDX:
22944 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
22945 gen_store_gpr(t0, rd);
22946 break;
22947 #endif
22949 tcg_temp_free(t0);
22952 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
22953 int ret, int v1, int v2)
22955 TCGv v1_t;
22956 TCGv v2_t;
22958 if (ret == 0) {
22959 /* Treat as NOP. */
22960 return;
22963 v1_t = tcg_temp_new();
22964 v2_t = tcg_temp_new();
22966 gen_load_gpr(v1_t, v1);
22967 gen_load_gpr(v2_t, v2);
22969 switch (op1) {
22970 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
22971 case OPC_MULT_G_2E:
22972 check_dsp_r2(ctx);
22973 switch (op2) {
22974 case OPC_ADDUH_QB:
22975 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
22976 break;
22977 case OPC_ADDUH_R_QB:
22978 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22979 break;
22980 case OPC_ADDQH_PH:
22981 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
22982 break;
22983 case OPC_ADDQH_R_PH:
22984 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22985 break;
22986 case OPC_ADDQH_W:
22987 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
22988 break;
22989 case OPC_ADDQH_R_W:
22990 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22991 break;
22992 case OPC_SUBUH_QB:
22993 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
22994 break;
22995 case OPC_SUBUH_R_QB:
22996 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22997 break;
22998 case OPC_SUBQH_PH:
22999 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
23000 break;
23001 case OPC_SUBQH_R_PH:
23002 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
23003 break;
23004 case OPC_SUBQH_W:
23005 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
23006 break;
23007 case OPC_SUBQH_R_W:
23008 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
23009 break;
23011 break;
23012 case OPC_ABSQ_S_PH_DSP:
23013 switch (op2) {
23014 case OPC_ABSQ_S_QB:
23015 check_dsp_r2(ctx);
23016 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
23017 break;
23018 case OPC_ABSQ_S_PH:
23019 check_dsp(ctx);
23020 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
23021 break;
23022 case OPC_ABSQ_S_W:
23023 check_dsp(ctx);
23024 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
23025 break;
23026 case OPC_PRECEQ_W_PHL:
23027 check_dsp(ctx);
23028 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
23029 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23030 break;
23031 case OPC_PRECEQ_W_PHR:
23032 check_dsp(ctx);
23033 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
23034 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
23035 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23036 break;
23037 case OPC_PRECEQU_PH_QBL:
23038 check_dsp(ctx);
23039 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
23040 break;
23041 case OPC_PRECEQU_PH_QBR:
23042 check_dsp(ctx);
23043 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
23044 break;
23045 case OPC_PRECEQU_PH_QBLA:
23046 check_dsp(ctx);
23047 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
23048 break;
23049 case OPC_PRECEQU_PH_QBRA:
23050 check_dsp(ctx);
23051 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
23052 break;
23053 case OPC_PRECEU_PH_QBL:
23054 check_dsp(ctx);
23055 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
23056 break;
23057 case OPC_PRECEU_PH_QBR:
23058 check_dsp(ctx);
23059 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
23060 break;
23061 case OPC_PRECEU_PH_QBLA:
23062 check_dsp(ctx);
23063 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
23064 break;
23065 case OPC_PRECEU_PH_QBRA:
23066 check_dsp(ctx);
23067 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
23068 break;
23070 break;
23071 case OPC_ADDU_QB_DSP:
23072 switch (op2) {
23073 case OPC_ADDQ_PH:
23074 check_dsp(ctx);
23075 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23076 break;
23077 case OPC_ADDQ_S_PH:
23078 check_dsp(ctx);
23079 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23080 break;
23081 case OPC_ADDQ_S_W:
23082 check_dsp(ctx);
23083 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23084 break;
23085 case OPC_ADDU_QB:
23086 check_dsp(ctx);
23087 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23088 break;
23089 case OPC_ADDU_S_QB:
23090 check_dsp(ctx);
23091 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23092 break;
23093 case OPC_ADDU_PH:
23094 check_dsp_r2(ctx);
23095 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23096 break;
23097 case OPC_ADDU_S_PH:
23098 check_dsp_r2(ctx);
23099 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23100 break;
23101 case OPC_SUBQ_PH:
23102 check_dsp(ctx);
23103 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23104 break;
23105 case OPC_SUBQ_S_PH:
23106 check_dsp(ctx);
23107 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23108 break;
23109 case OPC_SUBQ_S_W:
23110 check_dsp(ctx);
23111 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23112 break;
23113 case OPC_SUBU_QB:
23114 check_dsp(ctx);
23115 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23116 break;
23117 case OPC_SUBU_S_QB:
23118 check_dsp(ctx);
23119 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23120 break;
23121 case OPC_SUBU_PH:
23122 check_dsp_r2(ctx);
23123 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23124 break;
23125 case OPC_SUBU_S_PH:
23126 check_dsp_r2(ctx);
23127 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23128 break;
23129 case OPC_ADDSC:
23130 check_dsp(ctx);
23131 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23132 break;
23133 case OPC_ADDWC:
23134 check_dsp(ctx);
23135 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23136 break;
23137 case OPC_MODSUB:
23138 check_dsp(ctx);
23139 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
23140 break;
23141 case OPC_RADDU_W_QB:
23142 check_dsp(ctx);
23143 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
23144 break;
23146 break;
23147 case OPC_CMPU_EQ_QB_DSP:
23148 switch (op2) {
23149 case OPC_PRECR_QB_PH:
23150 check_dsp_r2(ctx);
23151 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
23152 break;
23153 case OPC_PRECRQ_QB_PH:
23154 check_dsp(ctx);
23155 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
23156 break;
23157 case OPC_PRECR_SRA_PH_W:
23158 check_dsp_r2(ctx);
23160 TCGv_i32 sa_t = tcg_const_i32(v2);
23161 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
23162 cpu_gpr[ret]);
23163 tcg_temp_free_i32(sa_t);
23164 break;
23166 case OPC_PRECR_SRA_R_PH_W:
23167 check_dsp_r2(ctx);
23169 TCGv_i32 sa_t = tcg_const_i32(v2);
23170 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
23171 cpu_gpr[ret]);
23172 tcg_temp_free_i32(sa_t);
23173 break;
23175 case OPC_PRECRQ_PH_W:
23176 check_dsp(ctx);
23177 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
23178 break;
23179 case OPC_PRECRQ_RS_PH_W:
23180 check_dsp(ctx);
23181 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23182 break;
23183 case OPC_PRECRQU_S_QB_PH:
23184 check_dsp(ctx);
23185 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23186 break;
23188 break;
23189 #ifdef TARGET_MIPS64
23190 case OPC_ABSQ_S_QH_DSP:
23191 switch (op2) {
23192 case OPC_PRECEQ_L_PWL:
23193 check_dsp(ctx);
23194 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
23195 break;
23196 case OPC_PRECEQ_L_PWR:
23197 check_dsp(ctx);
23198 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
23199 break;
23200 case OPC_PRECEQ_PW_QHL:
23201 check_dsp(ctx);
23202 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
23203 break;
23204 case OPC_PRECEQ_PW_QHR:
23205 check_dsp(ctx);
23206 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
23207 break;
23208 case OPC_PRECEQ_PW_QHLA:
23209 check_dsp(ctx);
23210 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
23211 break;
23212 case OPC_PRECEQ_PW_QHRA:
23213 check_dsp(ctx);
23214 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
23215 break;
23216 case OPC_PRECEQU_QH_OBL:
23217 check_dsp(ctx);
23218 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
23219 break;
23220 case OPC_PRECEQU_QH_OBR:
23221 check_dsp(ctx);
23222 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
23223 break;
23224 case OPC_PRECEQU_QH_OBLA:
23225 check_dsp(ctx);
23226 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
23227 break;
23228 case OPC_PRECEQU_QH_OBRA:
23229 check_dsp(ctx);
23230 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
23231 break;
23232 case OPC_PRECEU_QH_OBL:
23233 check_dsp(ctx);
23234 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
23235 break;
23236 case OPC_PRECEU_QH_OBR:
23237 check_dsp(ctx);
23238 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
23239 break;
23240 case OPC_PRECEU_QH_OBLA:
23241 check_dsp(ctx);
23242 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
23243 break;
23244 case OPC_PRECEU_QH_OBRA:
23245 check_dsp(ctx);
23246 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
23247 break;
23248 case OPC_ABSQ_S_OB:
23249 check_dsp_r2(ctx);
23250 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
23251 break;
23252 case OPC_ABSQ_S_PW:
23253 check_dsp(ctx);
23254 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
23255 break;
23256 case OPC_ABSQ_S_QH:
23257 check_dsp(ctx);
23258 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
23259 break;
23261 break;
23262 case OPC_ADDU_OB_DSP:
23263 switch (op2) {
23264 case OPC_RADDU_L_OB:
23265 check_dsp(ctx);
23266 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
23267 break;
23268 case OPC_SUBQ_PW:
23269 check_dsp(ctx);
23270 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23271 break;
23272 case OPC_SUBQ_S_PW:
23273 check_dsp(ctx);
23274 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23275 break;
23276 case OPC_SUBQ_QH:
23277 check_dsp(ctx);
23278 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23279 break;
23280 case OPC_SUBQ_S_QH:
23281 check_dsp(ctx);
23282 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23283 break;
23284 case OPC_SUBU_OB:
23285 check_dsp(ctx);
23286 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23287 break;
23288 case OPC_SUBU_S_OB:
23289 check_dsp(ctx);
23290 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23291 break;
23292 case OPC_SUBU_QH:
23293 check_dsp_r2(ctx);
23294 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23295 break;
23296 case OPC_SUBU_S_QH:
23297 check_dsp_r2(ctx);
23298 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23299 break;
23300 case OPC_SUBUH_OB:
23301 check_dsp_r2(ctx);
23302 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
23303 break;
23304 case OPC_SUBUH_R_OB:
23305 check_dsp_r2(ctx);
23306 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
23307 break;
23308 case OPC_ADDQ_PW:
23309 check_dsp(ctx);
23310 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23311 break;
23312 case OPC_ADDQ_S_PW:
23313 check_dsp(ctx);
23314 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23315 break;
23316 case OPC_ADDQ_QH:
23317 check_dsp(ctx);
23318 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23319 break;
23320 case OPC_ADDQ_S_QH:
23321 check_dsp(ctx);
23322 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23323 break;
23324 case OPC_ADDU_OB:
23325 check_dsp(ctx);
23326 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23327 break;
23328 case OPC_ADDU_S_OB:
23329 check_dsp(ctx);
23330 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23331 break;
23332 case OPC_ADDU_QH:
23333 check_dsp_r2(ctx);
23334 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23335 break;
23336 case OPC_ADDU_S_QH:
23337 check_dsp_r2(ctx);
23338 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23339 break;
23340 case OPC_ADDUH_OB:
23341 check_dsp_r2(ctx);
23342 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
23343 break;
23344 case OPC_ADDUH_R_OB:
23345 check_dsp_r2(ctx);
23346 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
23347 break;
23349 break;
23350 case OPC_CMPU_EQ_OB_DSP:
23351 switch (op2) {
23352 case OPC_PRECR_OB_QH:
23353 check_dsp_r2(ctx);
23354 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
23355 break;
23356 case OPC_PRECR_SRA_QH_PW:
23357 check_dsp_r2(ctx);
23359 TCGv_i32 ret_t = tcg_const_i32(ret);
23360 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
23361 tcg_temp_free_i32(ret_t);
23362 break;
23364 case OPC_PRECR_SRA_R_QH_PW:
23365 check_dsp_r2(ctx);
23367 TCGv_i32 sa_v = tcg_const_i32(ret);
23368 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
23369 tcg_temp_free_i32(sa_v);
23370 break;
23372 case OPC_PRECRQ_OB_QH:
23373 check_dsp(ctx);
23374 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
23375 break;
23376 case OPC_PRECRQ_PW_L:
23377 check_dsp(ctx);
23378 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
23379 break;
23380 case OPC_PRECRQ_QH_PW:
23381 check_dsp(ctx);
23382 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
23383 break;
23384 case OPC_PRECRQ_RS_QH_PW:
23385 check_dsp(ctx);
23386 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23387 break;
23388 case OPC_PRECRQU_S_OB_QH:
23389 check_dsp(ctx);
23390 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23391 break;
23393 break;
23394 #endif
23397 tcg_temp_free(v1_t);
23398 tcg_temp_free(v2_t);
23401 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
23402 int ret, int v1, int v2)
23404 uint32_t op2;
23405 TCGv t0;
23406 TCGv v1_t;
23407 TCGv v2_t;
23409 if (ret == 0) {
23410 /* Treat as NOP. */
23411 return;
23414 t0 = tcg_temp_new();
23415 v1_t = tcg_temp_new();
23416 v2_t = tcg_temp_new();
23418 tcg_gen_movi_tl(t0, v1);
23419 gen_load_gpr(v1_t, v1);
23420 gen_load_gpr(v2_t, v2);
23422 switch (opc) {
23423 case OPC_SHLL_QB_DSP:
23425 op2 = MASK_SHLL_QB(ctx->opcode);
23426 switch (op2) {
23427 case OPC_SHLL_QB:
23428 check_dsp(ctx);
23429 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
23430 break;
23431 case OPC_SHLLV_QB:
23432 check_dsp(ctx);
23433 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23434 break;
23435 case OPC_SHLL_PH:
23436 check_dsp(ctx);
23437 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
23438 break;
23439 case OPC_SHLLV_PH:
23440 check_dsp(ctx);
23441 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23442 break;
23443 case OPC_SHLL_S_PH:
23444 check_dsp(ctx);
23445 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
23446 break;
23447 case OPC_SHLLV_S_PH:
23448 check_dsp(ctx);
23449 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23450 break;
23451 case OPC_SHLL_S_W:
23452 check_dsp(ctx);
23453 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
23454 break;
23455 case OPC_SHLLV_S_W:
23456 check_dsp(ctx);
23457 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23458 break;
23459 case OPC_SHRL_QB:
23460 check_dsp(ctx);
23461 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
23462 break;
23463 case OPC_SHRLV_QB:
23464 check_dsp(ctx);
23465 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
23466 break;
23467 case OPC_SHRL_PH:
23468 check_dsp_r2(ctx);
23469 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
23470 break;
23471 case OPC_SHRLV_PH:
23472 check_dsp_r2(ctx);
23473 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
23474 break;
23475 case OPC_SHRA_QB:
23476 check_dsp_r2(ctx);
23477 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
23478 break;
23479 case OPC_SHRA_R_QB:
23480 check_dsp_r2(ctx);
23481 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
23482 break;
23483 case OPC_SHRAV_QB:
23484 check_dsp_r2(ctx);
23485 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
23486 break;
23487 case OPC_SHRAV_R_QB:
23488 check_dsp_r2(ctx);
23489 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
23490 break;
23491 case OPC_SHRA_PH:
23492 check_dsp(ctx);
23493 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
23494 break;
23495 case OPC_SHRA_R_PH:
23496 check_dsp(ctx);
23497 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
23498 break;
23499 case OPC_SHRAV_PH:
23500 check_dsp(ctx);
23501 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
23502 break;
23503 case OPC_SHRAV_R_PH:
23504 check_dsp(ctx);
23505 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
23506 break;
23507 case OPC_SHRA_R_W:
23508 check_dsp(ctx);
23509 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
23510 break;
23511 case OPC_SHRAV_R_W:
23512 check_dsp(ctx);
23513 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
23514 break;
23515 default: /* Invalid */
23516 MIPS_INVAL("MASK SHLL.QB");
23517 gen_reserved_instruction(ctx);
23518 break;
23520 break;
23522 #ifdef TARGET_MIPS64
23523 case OPC_SHLL_OB_DSP:
23524 op2 = MASK_SHLL_OB(ctx->opcode);
23525 switch (op2) {
23526 case OPC_SHLL_PW:
23527 check_dsp(ctx);
23528 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23529 break;
23530 case OPC_SHLLV_PW:
23531 check_dsp(ctx);
23532 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23533 break;
23534 case OPC_SHLL_S_PW:
23535 check_dsp(ctx);
23536 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23537 break;
23538 case OPC_SHLLV_S_PW:
23539 check_dsp(ctx);
23540 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23541 break;
23542 case OPC_SHLL_OB:
23543 check_dsp(ctx);
23544 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
23545 break;
23546 case OPC_SHLLV_OB:
23547 check_dsp(ctx);
23548 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23549 break;
23550 case OPC_SHLL_QH:
23551 check_dsp(ctx);
23552 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23553 break;
23554 case OPC_SHLLV_QH:
23555 check_dsp(ctx);
23556 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23557 break;
23558 case OPC_SHLL_S_QH:
23559 check_dsp(ctx);
23560 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23561 break;
23562 case OPC_SHLLV_S_QH:
23563 check_dsp(ctx);
23564 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23565 break;
23566 case OPC_SHRA_OB:
23567 check_dsp_r2(ctx);
23568 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
23569 break;
23570 case OPC_SHRAV_OB:
23571 check_dsp_r2(ctx);
23572 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
23573 break;
23574 case OPC_SHRA_R_OB:
23575 check_dsp_r2(ctx);
23576 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
23577 break;
23578 case OPC_SHRAV_R_OB:
23579 check_dsp_r2(ctx);
23580 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
23581 break;
23582 case OPC_SHRA_PW:
23583 check_dsp(ctx);
23584 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
23585 break;
23586 case OPC_SHRAV_PW:
23587 check_dsp(ctx);
23588 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
23589 break;
23590 case OPC_SHRA_R_PW:
23591 check_dsp(ctx);
23592 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
23593 break;
23594 case OPC_SHRAV_R_PW:
23595 check_dsp(ctx);
23596 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
23597 break;
23598 case OPC_SHRA_QH:
23599 check_dsp(ctx);
23600 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
23601 break;
23602 case OPC_SHRAV_QH:
23603 check_dsp(ctx);
23604 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
23605 break;
23606 case OPC_SHRA_R_QH:
23607 check_dsp(ctx);
23608 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
23609 break;
23610 case OPC_SHRAV_R_QH:
23611 check_dsp(ctx);
23612 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
23613 break;
23614 case OPC_SHRL_OB:
23615 check_dsp(ctx);
23616 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
23617 break;
23618 case OPC_SHRLV_OB:
23619 check_dsp(ctx);
23620 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
23621 break;
23622 case OPC_SHRL_QH:
23623 check_dsp_r2(ctx);
23624 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
23625 break;
23626 case OPC_SHRLV_QH:
23627 check_dsp_r2(ctx);
23628 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
23629 break;
23630 default: /* Invalid */
23631 MIPS_INVAL("MASK SHLL.OB");
23632 gen_reserved_instruction(ctx);
23633 break;
23635 break;
23636 #endif
23639 tcg_temp_free(t0);
23640 tcg_temp_free(v1_t);
23641 tcg_temp_free(v2_t);
23644 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
23645 int ret, int v1, int v2, int check_ret)
23647 TCGv_i32 t0;
23648 TCGv v1_t;
23649 TCGv v2_t;
23651 if ((ret == 0) && (check_ret == 1)) {
23652 /* Treat as NOP. */
23653 return;
23656 t0 = tcg_temp_new_i32();
23657 v1_t = tcg_temp_new();
23658 v2_t = tcg_temp_new();
23660 tcg_gen_movi_i32(t0, ret);
23661 gen_load_gpr(v1_t, v1);
23662 gen_load_gpr(v2_t, v2);
23664 switch (op1) {
23666 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
23667 * the same mask and op1.
23669 case OPC_MULT_G_2E:
23670 check_dsp_r2(ctx);
23671 switch (op2) {
23672 case OPC_MUL_PH:
23673 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23674 break;
23675 case OPC_MUL_S_PH:
23676 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23677 break;
23678 case OPC_MULQ_S_W:
23679 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23680 break;
23681 case OPC_MULQ_RS_W:
23682 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23683 break;
23685 break;
23686 case OPC_DPA_W_PH_DSP:
23687 switch (op2) {
23688 case OPC_DPAU_H_QBL:
23689 check_dsp(ctx);
23690 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
23691 break;
23692 case OPC_DPAU_H_QBR:
23693 check_dsp(ctx);
23694 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
23695 break;
23696 case OPC_DPSU_H_QBL:
23697 check_dsp(ctx);
23698 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
23699 break;
23700 case OPC_DPSU_H_QBR:
23701 check_dsp(ctx);
23702 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
23703 break;
23704 case OPC_DPA_W_PH:
23705 check_dsp_r2(ctx);
23706 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
23707 break;
23708 case OPC_DPAX_W_PH:
23709 check_dsp_r2(ctx);
23710 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
23711 break;
23712 case OPC_DPAQ_S_W_PH:
23713 check_dsp(ctx);
23714 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23715 break;
23716 case OPC_DPAQX_S_W_PH:
23717 check_dsp_r2(ctx);
23718 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23719 break;
23720 case OPC_DPAQX_SA_W_PH:
23721 check_dsp_r2(ctx);
23722 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23723 break;
23724 case OPC_DPS_W_PH:
23725 check_dsp_r2(ctx);
23726 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
23727 break;
23728 case OPC_DPSX_W_PH:
23729 check_dsp_r2(ctx);
23730 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
23731 break;
23732 case OPC_DPSQ_S_W_PH:
23733 check_dsp(ctx);
23734 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23735 break;
23736 case OPC_DPSQX_S_W_PH:
23737 check_dsp_r2(ctx);
23738 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23739 break;
23740 case OPC_DPSQX_SA_W_PH:
23741 check_dsp_r2(ctx);
23742 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23743 break;
23744 case OPC_MULSAQ_S_W_PH:
23745 check_dsp(ctx);
23746 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23747 break;
23748 case OPC_DPAQ_SA_L_W:
23749 check_dsp(ctx);
23750 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23751 break;
23752 case OPC_DPSQ_SA_L_W:
23753 check_dsp(ctx);
23754 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23755 break;
23756 case OPC_MAQ_S_W_PHL:
23757 check_dsp(ctx);
23758 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
23759 break;
23760 case OPC_MAQ_S_W_PHR:
23761 check_dsp(ctx);
23762 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
23763 break;
23764 case OPC_MAQ_SA_W_PHL:
23765 check_dsp(ctx);
23766 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
23767 break;
23768 case OPC_MAQ_SA_W_PHR:
23769 check_dsp(ctx);
23770 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
23771 break;
23772 case OPC_MULSA_W_PH:
23773 check_dsp_r2(ctx);
23774 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
23775 break;
23777 break;
23778 #ifdef TARGET_MIPS64
23779 case OPC_DPAQ_W_QH_DSP:
23781 int ac = ret & 0x03;
23782 tcg_gen_movi_i32(t0, ac);
23784 switch (op2) {
23785 case OPC_DMADD:
23786 check_dsp(ctx);
23787 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
23788 break;
23789 case OPC_DMADDU:
23790 check_dsp(ctx);
23791 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
23792 break;
23793 case OPC_DMSUB:
23794 check_dsp(ctx);
23795 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
23796 break;
23797 case OPC_DMSUBU:
23798 check_dsp(ctx);
23799 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
23800 break;
23801 case OPC_DPA_W_QH:
23802 check_dsp_r2(ctx);
23803 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
23804 break;
23805 case OPC_DPAQ_S_W_QH:
23806 check_dsp(ctx);
23807 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23808 break;
23809 case OPC_DPAQ_SA_L_PW:
23810 check_dsp(ctx);
23811 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23812 break;
23813 case OPC_DPAU_H_OBL:
23814 check_dsp(ctx);
23815 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
23816 break;
23817 case OPC_DPAU_H_OBR:
23818 check_dsp(ctx);
23819 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
23820 break;
23821 case OPC_DPS_W_QH:
23822 check_dsp_r2(ctx);
23823 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
23824 break;
23825 case OPC_DPSQ_S_W_QH:
23826 check_dsp(ctx);
23827 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23828 break;
23829 case OPC_DPSQ_SA_L_PW:
23830 check_dsp(ctx);
23831 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23832 break;
23833 case OPC_DPSU_H_OBL:
23834 check_dsp(ctx);
23835 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
23836 break;
23837 case OPC_DPSU_H_OBR:
23838 check_dsp(ctx);
23839 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
23840 break;
23841 case OPC_MAQ_S_L_PWL:
23842 check_dsp(ctx);
23843 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
23844 break;
23845 case OPC_MAQ_S_L_PWR:
23846 check_dsp(ctx);
23847 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
23848 break;
23849 case OPC_MAQ_S_W_QHLL:
23850 check_dsp(ctx);
23851 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
23852 break;
23853 case OPC_MAQ_SA_W_QHLL:
23854 check_dsp(ctx);
23855 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
23856 break;
23857 case OPC_MAQ_S_W_QHLR:
23858 check_dsp(ctx);
23859 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
23860 break;
23861 case OPC_MAQ_SA_W_QHLR:
23862 check_dsp(ctx);
23863 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
23864 break;
23865 case OPC_MAQ_S_W_QHRL:
23866 check_dsp(ctx);
23867 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
23868 break;
23869 case OPC_MAQ_SA_W_QHRL:
23870 check_dsp(ctx);
23871 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
23872 break;
23873 case OPC_MAQ_S_W_QHRR:
23874 check_dsp(ctx);
23875 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
23876 break;
23877 case OPC_MAQ_SA_W_QHRR:
23878 check_dsp(ctx);
23879 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
23880 break;
23881 case OPC_MULSAQ_S_L_PW:
23882 check_dsp(ctx);
23883 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
23884 break;
23885 case OPC_MULSAQ_S_W_QH:
23886 check_dsp(ctx);
23887 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23888 break;
23891 break;
23892 #endif
23893 case OPC_ADDU_QB_DSP:
23894 switch (op2) {
23895 case OPC_MULEU_S_PH_QBL:
23896 check_dsp(ctx);
23897 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23898 break;
23899 case OPC_MULEU_S_PH_QBR:
23900 check_dsp(ctx);
23901 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23902 break;
23903 case OPC_MULQ_RS_PH:
23904 check_dsp(ctx);
23905 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23906 break;
23907 case OPC_MULEQ_S_W_PHL:
23908 check_dsp(ctx);
23909 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23910 break;
23911 case OPC_MULEQ_S_W_PHR:
23912 check_dsp(ctx);
23913 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23914 break;
23915 case OPC_MULQ_S_PH:
23916 check_dsp_r2(ctx);
23917 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23918 break;
23920 break;
23921 #ifdef TARGET_MIPS64
23922 case OPC_ADDU_OB_DSP:
23923 switch (op2) {
23924 case OPC_MULEQ_S_PW_QHL:
23925 check_dsp(ctx);
23926 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23927 break;
23928 case OPC_MULEQ_S_PW_QHR:
23929 check_dsp(ctx);
23930 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23931 break;
23932 case OPC_MULEU_S_QH_OBL:
23933 check_dsp(ctx);
23934 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23935 break;
23936 case OPC_MULEU_S_QH_OBR:
23937 check_dsp(ctx);
23938 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23939 break;
23940 case OPC_MULQ_RS_QH:
23941 check_dsp(ctx);
23942 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23943 break;
23945 break;
23946 #endif
23949 tcg_temp_free_i32(t0);
23950 tcg_temp_free(v1_t);
23951 tcg_temp_free(v2_t);
23954 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23955 int ret, int val)
23957 int16_t imm;
23958 TCGv t0;
23959 TCGv val_t;
23961 if (ret == 0) {
23962 /* Treat as NOP. */
23963 return;
23966 t0 = tcg_temp_new();
23967 val_t = tcg_temp_new();
23968 gen_load_gpr(val_t, val);
23970 switch (op1) {
23971 case OPC_ABSQ_S_PH_DSP:
23972 switch (op2) {
23973 case OPC_BITREV:
23974 check_dsp(ctx);
23975 gen_helper_bitrev(cpu_gpr[ret], val_t);
23976 break;
23977 case OPC_REPL_QB:
23978 check_dsp(ctx);
23980 target_long result;
23981 imm = (ctx->opcode >> 16) & 0xFF;
23982 result = (uint32_t)imm << 24 |
23983 (uint32_t)imm << 16 |
23984 (uint32_t)imm << 8 |
23985 (uint32_t)imm;
23986 result = (int32_t)result;
23987 tcg_gen_movi_tl(cpu_gpr[ret], result);
23989 break;
23990 case OPC_REPLV_QB:
23991 check_dsp(ctx);
23992 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23993 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23994 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23995 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23996 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23997 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23998 break;
23999 case OPC_REPL_PH:
24000 check_dsp(ctx);
24002 imm = (ctx->opcode >> 16) & 0x03FF;
24003 imm = (int16_t)(imm << 6) >> 6;
24004 tcg_gen_movi_tl(cpu_gpr[ret], \
24005 (target_long)((int32_t)imm << 16 | \
24006 (uint16_t)imm));
24008 break;
24009 case OPC_REPLV_PH:
24010 check_dsp(ctx);
24011 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
24012 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
24013 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24014 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
24015 break;
24017 break;
24018 #ifdef TARGET_MIPS64
24019 case OPC_ABSQ_S_QH_DSP:
24020 switch (op2) {
24021 case OPC_REPL_OB:
24022 check_dsp(ctx);
24024 target_long temp;
24026 imm = (ctx->opcode >> 16) & 0xFF;
24027 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
24028 temp = (temp << 16) | temp;
24029 temp = (temp << 32) | temp;
24030 tcg_gen_movi_tl(cpu_gpr[ret], temp);
24031 break;
24033 case OPC_REPL_PW:
24034 check_dsp(ctx);
24036 target_long temp;
24038 imm = (ctx->opcode >> 16) & 0x03FF;
24039 imm = (int16_t)(imm << 6) >> 6;
24040 temp = ((target_long)imm << 32) \
24041 | ((target_long)imm & 0xFFFFFFFF);
24042 tcg_gen_movi_tl(cpu_gpr[ret], temp);
24043 break;
24045 case OPC_REPL_QH:
24046 check_dsp(ctx);
24048 target_long temp;
24050 imm = (ctx->opcode >> 16) & 0x03FF;
24051 imm = (int16_t)(imm << 6) >> 6;
24053 temp = ((uint64_t)(uint16_t)imm << 48) |
24054 ((uint64_t)(uint16_t)imm << 32) |
24055 ((uint64_t)(uint16_t)imm << 16) |
24056 (uint64_t)(uint16_t)imm;
24057 tcg_gen_movi_tl(cpu_gpr[ret], temp);
24058 break;
24060 case OPC_REPLV_OB:
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_shli_tl(t0, cpu_gpr[ret], 32);
24068 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24069 break;
24070 case OPC_REPLV_PW:
24071 check_dsp(ctx);
24072 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
24073 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
24074 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24075 break;
24076 case OPC_REPLV_QH:
24077 check_dsp(ctx);
24078 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
24079 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
24080 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24081 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
24082 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24083 break;
24085 break;
24086 #endif
24088 tcg_temp_free(t0);
24089 tcg_temp_free(val_t);
24092 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
24093 uint32_t op1, uint32_t op2,
24094 int ret, int v1, int v2, int check_ret)
24096 TCGv t1;
24097 TCGv v1_t;
24098 TCGv v2_t;
24100 if ((ret == 0) && (check_ret == 1)) {
24101 /* Treat as NOP. */
24102 return;
24105 t1 = tcg_temp_new();
24106 v1_t = tcg_temp_new();
24107 v2_t = tcg_temp_new();
24109 gen_load_gpr(v1_t, v1);
24110 gen_load_gpr(v2_t, v2);
24112 switch (op1) {
24113 case OPC_CMPU_EQ_QB_DSP:
24114 switch (op2) {
24115 case OPC_CMPU_EQ_QB:
24116 check_dsp(ctx);
24117 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
24118 break;
24119 case OPC_CMPU_LT_QB:
24120 check_dsp(ctx);
24121 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
24122 break;
24123 case OPC_CMPU_LE_QB:
24124 check_dsp(ctx);
24125 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
24126 break;
24127 case OPC_CMPGU_EQ_QB:
24128 check_dsp(ctx);
24129 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
24130 break;
24131 case OPC_CMPGU_LT_QB:
24132 check_dsp(ctx);
24133 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
24134 break;
24135 case OPC_CMPGU_LE_QB:
24136 check_dsp(ctx);
24137 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
24138 break;
24139 case OPC_CMPGDU_EQ_QB:
24140 check_dsp_r2(ctx);
24141 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
24142 tcg_gen_mov_tl(cpu_gpr[ret], t1);
24143 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
24144 tcg_gen_shli_tl(t1, t1, 24);
24145 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
24146 break;
24147 case OPC_CMPGDU_LT_QB:
24148 check_dsp_r2(ctx);
24149 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
24150 tcg_gen_mov_tl(cpu_gpr[ret], t1);
24151 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
24152 tcg_gen_shli_tl(t1, t1, 24);
24153 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
24154 break;
24155 case OPC_CMPGDU_LE_QB:
24156 check_dsp_r2(ctx);
24157 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
24158 tcg_gen_mov_tl(cpu_gpr[ret], t1);
24159 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
24160 tcg_gen_shli_tl(t1, t1, 24);
24161 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
24162 break;
24163 case OPC_CMP_EQ_PH:
24164 check_dsp(ctx);
24165 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
24166 break;
24167 case OPC_CMP_LT_PH:
24168 check_dsp(ctx);
24169 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
24170 break;
24171 case OPC_CMP_LE_PH:
24172 check_dsp(ctx);
24173 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
24174 break;
24175 case OPC_PICK_QB:
24176 check_dsp(ctx);
24177 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24178 break;
24179 case OPC_PICK_PH:
24180 check_dsp(ctx);
24181 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24182 break;
24183 case OPC_PACKRL_PH:
24184 check_dsp(ctx);
24185 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
24186 break;
24188 break;
24189 #ifdef TARGET_MIPS64
24190 case OPC_CMPU_EQ_OB_DSP:
24191 switch (op2) {
24192 case OPC_CMP_EQ_PW:
24193 check_dsp(ctx);
24194 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
24195 break;
24196 case OPC_CMP_LT_PW:
24197 check_dsp(ctx);
24198 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
24199 break;
24200 case OPC_CMP_LE_PW:
24201 check_dsp(ctx);
24202 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
24203 break;
24204 case OPC_CMP_EQ_QH:
24205 check_dsp(ctx);
24206 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
24207 break;
24208 case OPC_CMP_LT_QH:
24209 check_dsp(ctx);
24210 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
24211 break;
24212 case OPC_CMP_LE_QH:
24213 check_dsp(ctx);
24214 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
24215 break;
24216 case OPC_CMPGDU_EQ_OB:
24217 check_dsp_r2(ctx);
24218 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24219 break;
24220 case OPC_CMPGDU_LT_OB:
24221 check_dsp_r2(ctx);
24222 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24223 break;
24224 case OPC_CMPGDU_LE_OB:
24225 check_dsp_r2(ctx);
24226 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24227 break;
24228 case OPC_CMPGU_EQ_OB:
24229 check_dsp(ctx);
24230 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
24231 break;
24232 case OPC_CMPGU_LT_OB:
24233 check_dsp(ctx);
24234 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
24235 break;
24236 case OPC_CMPGU_LE_OB:
24237 check_dsp(ctx);
24238 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
24239 break;
24240 case OPC_CMPU_EQ_OB:
24241 check_dsp(ctx);
24242 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
24243 break;
24244 case OPC_CMPU_LT_OB:
24245 check_dsp(ctx);
24246 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
24247 break;
24248 case OPC_CMPU_LE_OB:
24249 check_dsp(ctx);
24250 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
24251 break;
24252 case OPC_PACKRL_PW:
24253 check_dsp(ctx);
24254 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
24255 break;
24256 case OPC_PICK_OB:
24257 check_dsp(ctx);
24258 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24259 break;
24260 case OPC_PICK_PW:
24261 check_dsp(ctx);
24262 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24263 break;
24264 case OPC_PICK_QH:
24265 check_dsp(ctx);
24266 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24267 break;
24269 break;
24270 #endif
24273 tcg_temp_free(t1);
24274 tcg_temp_free(v1_t);
24275 tcg_temp_free(v2_t);
24278 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
24279 uint32_t op1, int rt, int rs, int sa)
24281 TCGv t0;
24283 check_dsp_r2(ctx);
24285 if (rt == 0) {
24286 /* Treat as NOP. */
24287 return;
24290 t0 = tcg_temp_new();
24291 gen_load_gpr(t0, rs);
24293 switch (op1) {
24294 case OPC_APPEND_DSP:
24295 switch (MASK_APPEND(ctx->opcode)) {
24296 case OPC_APPEND:
24297 if (sa != 0) {
24298 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
24300 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
24301 break;
24302 case OPC_PREPEND:
24303 if (sa != 0) {
24304 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
24305 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
24306 tcg_gen_shli_tl(t0, t0, 32 - sa);
24307 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24309 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
24310 break;
24311 case OPC_BALIGN:
24312 sa &= 3;
24313 if (sa != 0 && sa != 2) {
24314 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
24315 tcg_gen_ext32u_tl(t0, t0);
24316 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
24317 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24319 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
24320 break;
24321 default: /* Invalid */
24322 MIPS_INVAL("MASK APPEND");
24323 gen_reserved_instruction(ctx);
24324 break;
24326 break;
24327 #ifdef TARGET_MIPS64
24328 case OPC_DAPPEND_DSP:
24329 switch (MASK_DAPPEND(ctx->opcode)) {
24330 case OPC_DAPPEND:
24331 if (sa != 0) {
24332 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
24334 break;
24335 case OPC_PREPENDD:
24336 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
24337 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
24338 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
24339 break;
24340 case OPC_PREPENDW:
24341 if (sa != 0) {
24342 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
24343 tcg_gen_shli_tl(t0, t0, 64 - sa);
24344 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24346 break;
24347 case OPC_DBALIGN:
24348 sa &= 7;
24349 if (sa != 0 && sa != 2 && sa != 4) {
24350 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
24351 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
24352 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24354 break;
24355 default: /* Invalid */
24356 MIPS_INVAL("MASK DAPPEND");
24357 gen_reserved_instruction(ctx);
24358 break;
24360 break;
24361 #endif
24363 tcg_temp_free(t0);
24366 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
24367 int ret, int v1, int v2, int check_ret)
24370 TCGv t0;
24371 TCGv t1;
24372 TCGv v1_t;
24373 TCGv v2_t;
24374 int16_t imm;
24376 if ((ret == 0) && (check_ret == 1)) {
24377 /* Treat as NOP. */
24378 return;
24381 t0 = tcg_temp_new();
24382 t1 = tcg_temp_new();
24383 v1_t = tcg_temp_new();
24384 v2_t = tcg_temp_new();
24386 gen_load_gpr(v1_t, v1);
24387 gen_load_gpr(v2_t, v2);
24389 switch (op1) {
24390 case OPC_EXTR_W_DSP:
24391 check_dsp(ctx);
24392 switch (op2) {
24393 case OPC_EXTR_W:
24394 tcg_gen_movi_tl(t0, v2);
24395 tcg_gen_movi_tl(t1, v1);
24396 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
24397 break;
24398 case OPC_EXTR_R_W:
24399 tcg_gen_movi_tl(t0, v2);
24400 tcg_gen_movi_tl(t1, v1);
24401 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24402 break;
24403 case OPC_EXTR_RS_W:
24404 tcg_gen_movi_tl(t0, v2);
24405 tcg_gen_movi_tl(t1, v1);
24406 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24407 break;
24408 case OPC_EXTR_S_H:
24409 tcg_gen_movi_tl(t0, v2);
24410 tcg_gen_movi_tl(t1, v1);
24411 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24412 break;
24413 case OPC_EXTRV_S_H:
24414 tcg_gen_movi_tl(t0, v2);
24415 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
24416 break;
24417 case OPC_EXTRV_W:
24418 tcg_gen_movi_tl(t0, v2);
24419 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24420 break;
24421 case OPC_EXTRV_R_W:
24422 tcg_gen_movi_tl(t0, v2);
24423 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24424 break;
24425 case OPC_EXTRV_RS_W:
24426 tcg_gen_movi_tl(t0, v2);
24427 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24428 break;
24429 case OPC_EXTP:
24430 tcg_gen_movi_tl(t0, v2);
24431 tcg_gen_movi_tl(t1, v1);
24432 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
24433 break;
24434 case OPC_EXTPV:
24435 tcg_gen_movi_tl(t0, v2);
24436 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
24437 break;
24438 case OPC_EXTPDP:
24439 tcg_gen_movi_tl(t0, v2);
24440 tcg_gen_movi_tl(t1, v1);
24441 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
24442 break;
24443 case OPC_EXTPDPV:
24444 tcg_gen_movi_tl(t0, v2);
24445 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
24446 break;
24447 case OPC_SHILO:
24448 imm = (ctx->opcode >> 20) & 0x3F;
24449 tcg_gen_movi_tl(t0, ret);
24450 tcg_gen_movi_tl(t1, imm);
24451 gen_helper_shilo(t0, t1, cpu_env);
24452 break;
24453 case OPC_SHILOV:
24454 tcg_gen_movi_tl(t0, ret);
24455 gen_helper_shilo(t0, v1_t, cpu_env);
24456 break;
24457 case OPC_MTHLIP:
24458 tcg_gen_movi_tl(t0, ret);
24459 gen_helper_mthlip(t0, v1_t, cpu_env);
24460 break;
24461 case OPC_WRDSP:
24462 imm = (ctx->opcode >> 11) & 0x3FF;
24463 tcg_gen_movi_tl(t0, imm);
24464 gen_helper_wrdsp(v1_t, t0, cpu_env);
24465 break;
24466 case OPC_RDDSP:
24467 imm = (ctx->opcode >> 16) & 0x03FF;
24468 tcg_gen_movi_tl(t0, imm);
24469 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
24470 break;
24472 break;
24473 #ifdef TARGET_MIPS64
24474 case OPC_DEXTR_W_DSP:
24475 check_dsp(ctx);
24476 switch (op2) {
24477 case OPC_DMTHLIP:
24478 tcg_gen_movi_tl(t0, ret);
24479 gen_helper_dmthlip(v1_t, t0, cpu_env);
24480 break;
24481 case OPC_DSHILO:
24483 int shift = (ctx->opcode >> 19) & 0x7F;
24484 int ac = (ctx->opcode >> 11) & 0x03;
24485 tcg_gen_movi_tl(t0, shift);
24486 tcg_gen_movi_tl(t1, ac);
24487 gen_helper_dshilo(t0, t1, cpu_env);
24488 break;
24490 case OPC_DSHILOV:
24492 int ac = (ctx->opcode >> 11) & 0x03;
24493 tcg_gen_movi_tl(t0, ac);
24494 gen_helper_dshilo(v1_t, t0, cpu_env);
24495 break;
24497 case OPC_DEXTP:
24498 tcg_gen_movi_tl(t0, v2);
24499 tcg_gen_movi_tl(t1, v1);
24501 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
24502 break;
24503 case OPC_DEXTPV:
24504 tcg_gen_movi_tl(t0, v2);
24505 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
24506 break;
24507 case OPC_DEXTPDP:
24508 tcg_gen_movi_tl(t0, v2);
24509 tcg_gen_movi_tl(t1, v1);
24510 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
24511 break;
24512 case OPC_DEXTPDPV:
24513 tcg_gen_movi_tl(t0, v2);
24514 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
24515 break;
24516 case OPC_DEXTR_L:
24517 tcg_gen_movi_tl(t0, v2);
24518 tcg_gen_movi_tl(t1, v1);
24519 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
24520 break;
24521 case OPC_DEXTR_R_L:
24522 tcg_gen_movi_tl(t0, v2);
24523 tcg_gen_movi_tl(t1, v1);
24524 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
24525 break;
24526 case OPC_DEXTR_RS_L:
24527 tcg_gen_movi_tl(t0, v2);
24528 tcg_gen_movi_tl(t1, v1);
24529 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
24530 break;
24531 case OPC_DEXTR_W:
24532 tcg_gen_movi_tl(t0, v2);
24533 tcg_gen_movi_tl(t1, v1);
24534 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
24535 break;
24536 case OPC_DEXTR_R_W:
24537 tcg_gen_movi_tl(t0, v2);
24538 tcg_gen_movi_tl(t1, v1);
24539 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24540 break;
24541 case OPC_DEXTR_RS_W:
24542 tcg_gen_movi_tl(t0, v2);
24543 tcg_gen_movi_tl(t1, v1);
24544 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24545 break;
24546 case OPC_DEXTR_S_H:
24547 tcg_gen_movi_tl(t0, v2);
24548 tcg_gen_movi_tl(t1, v1);
24549 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24550 break;
24551 case OPC_DEXTRV_S_H:
24552 tcg_gen_movi_tl(t0, v2);
24553 tcg_gen_movi_tl(t1, v1);
24554 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24555 break;
24556 case OPC_DEXTRV_L:
24557 tcg_gen_movi_tl(t0, v2);
24558 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24559 break;
24560 case OPC_DEXTRV_R_L:
24561 tcg_gen_movi_tl(t0, v2);
24562 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24563 break;
24564 case OPC_DEXTRV_RS_L:
24565 tcg_gen_movi_tl(t0, v2);
24566 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24567 break;
24568 case OPC_DEXTRV_W:
24569 tcg_gen_movi_tl(t0, v2);
24570 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24571 break;
24572 case OPC_DEXTRV_R_W:
24573 tcg_gen_movi_tl(t0, v2);
24574 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24575 break;
24576 case OPC_DEXTRV_RS_W:
24577 tcg_gen_movi_tl(t0, v2);
24578 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24579 break;
24581 break;
24582 #endif
24585 tcg_temp_free(t0);
24586 tcg_temp_free(t1);
24587 tcg_temp_free(v1_t);
24588 tcg_temp_free(v2_t);
24591 /* End MIPSDSP functions. */
24593 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
24595 int rs, rt, rd, sa;
24596 uint32_t op1, op2;
24598 rs = (ctx->opcode >> 21) & 0x1f;
24599 rt = (ctx->opcode >> 16) & 0x1f;
24600 rd = (ctx->opcode >> 11) & 0x1f;
24601 sa = (ctx->opcode >> 6) & 0x1f;
24603 op1 = MASK_SPECIAL(ctx->opcode);
24604 switch (op1) {
24605 case OPC_LSA:
24606 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
24607 break;
24608 case OPC_MULT:
24609 case OPC_MULTU:
24610 case OPC_DIV:
24611 case OPC_DIVU:
24612 op2 = MASK_R6_MULDIV(ctx->opcode);
24613 switch (op2) {
24614 case R6_OPC_MUL:
24615 case R6_OPC_MUH:
24616 case R6_OPC_MULU:
24617 case R6_OPC_MUHU:
24618 case R6_OPC_DIV:
24619 case R6_OPC_MOD:
24620 case R6_OPC_DIVU:
24621 case R6_OPC_MODU:
24622 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24623 break;
24624 default:
24625 MIPS_INVAL("special_r6 muldiv");
24626 gen_reserved_instruction(ctx);
24627 break;
24629 break;
24630 case OPC_SELEQZ:
24631 case OPC_SELNEZ:
24632 gen_cond_move(ctx, op1, rd, rs, rt);
24633 break;
24634 case R6_OPC_CLO:
24635 case R6_OPC_CLZ:
24636 if (rt == 0 && sa == 1) {
24638 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24639 * We need additionally to check other fields.
24641 gen_cl(ctx, op1, rd, rs);
24642 } else {
24643 gen_reserved_instruction(ctx);
24645 break;
24646 case R6_OPC_SDBBP:
24647 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
24648 gen_helper_do_semihosting(cpu_env);
24649 } else {
24650 if (ctx->hflags & MIPS_HFLAG_SBRI) {
24651 gen_reserved_instruction(ctx);
24652 } else {
24653 generate_exception_end(ctx, EXCP_DBp);
24656 break;
24657 #if defined(TARGET_MIPS64)
24658 case OPC_DLSA:
24659 check_mips_64(ctx);
24660 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
24661 break;
24662 case R6_OPC_DCLO:
24663 case R6_OPC_DCLZ:
24664 if (rt == 0 && sa == 1) {
24666 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24667 * We need additionally to check other fields.
24669 check_mips_64(ctx);
24670 gen_cl(ctx, op1, rd, rs);
24671 } else {
24672 gen_reserved_instruction(ctx);
24674 break;
24675 case OPC_DMULT:
24676 case OPC_DMULTU:
24677 case OPC_DDIV:
24678 case OPC_DDIVU:
24680 op2 = MASK_R6_MULDIV(ctx->opcode);
24681 switch (op2) {
24682 case R6_OPC_DMUL:
24683 case R6_OPC_DMUH:
24684 case R6_OPC_DMULU:
24685 case R6_OPC_DMUHU:
24686 case R6_OPC_DDIV:
24687 case R6_OPC_DMOD:
24688 case R6_OPC_DDIVU:
24689 case R6_OPC_DMODU:
24690 check_mips_64(ctx);
24691 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24692 break;
24693 default:
24694 MIPS_INVAL("special_r6 muldiv");
24695 gen_reserved_instruction(ctx);
24696 break;
24698 break;
24699 #endif
24700 default: /* Invalid */
24701 MIPS_INVAL("special_r6");
24702 gen_reserved_instruction(ctx);
24703 break;
24707 static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
24709 int rs = extract32(ctx->opcode, 21, 5);
24710 int rt = extract32(ctx->opcode, 16, 5);
24711 int rd = extract32(ctx->opcode, 11, 5);
24712 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
24714 switch (op1) {
24715 case OPC_MOVN: /* Conditional move */
24716 case OPC_MOVZ:
24717 gen_cond_move(ctx, op1, rd, rs, rt);
24718 break;
24719 case OPC_MFHI: /* Move from HI/LO */
24720 case OPC_MFLO:
24721 gen_HILO(ctx, op1, 0, rd);
24722 break;
24723 case OPC_MTHI:
24724 case OPC_MTLO: /* Move to HI/LO */
24725 gen_HILO(ctx, op1, 0, rs);
24726 break;
24727 case OPC_MULT:
24728 case OPC_MULTU:
24729 gen_mul_txx9(ctx, op1, rd, rs, rt);
24730 break;
24731 case OPC_DIV:
24732 case OPC_DIVU:
24733 gen_muldiv(ctx, op1, 0, rs, rt);
24734 break;
24735 #if defined(TARGET_MIPS64)
24736 case OPC_DMULT:
24737 case OPC_DMULTU:
24738 case OPC_DDIV:
24739 case OPC_DDIVU:
24740 check_insn_opc_user_only(ctx, INSN_R5900);
24741 gen_muldiv(ctx, op1, 0, rs, rt);
24742 break;
24743 #endif
24744 case OPC_JR:
24745 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
24746 break;
24747 default: /* Invalid */
24748 MIPS_INVAL("special_tx79");
24749 gen_reserved_instruction(ctx);
24750 break;
24754 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
24756 int rs, rt, rd, sa;
24757 uint32_t op1;
24759 rs = (ctx->opcode >> 21) & 0x1f;
24760 rt = (ctx->opcode >> 16) & 0x1f;
24761 rd = (ctx->opcode >> 11) & 0x1f;
24762 sa = (ctx->opcode >> 6) & 0x1f;
24764 op1 = MASK_SPECIAL(ctx->opcode);
24765 switch (op1) {
24766 case OPC_MOVN: /* Conditional move */
24767 case OPC_MOVZ:
24768 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1 |
24769 INSN_LOONGSON2E | INSN_LOONGSON2F);
24770 gen_cond_move(ctx, op1, rd, rs, rt);
24771 break;
24772 case OPC_MFHI: /* Move from HI/LO */
24773 case OPC_MFLO:
24774 gen_HILO(ctx, op1, rs & 3, rd);
24775 break;
24776 case OPC_MTHI:
24777 case OPC_MTLO: /* Move to HI/LO */
24778 gen_HILO(ctx, op1, rd & 3, rs);
24779 break;
24780 case OPC_MOVCI:
24781 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
24782 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
24783 check_cp1_enabled(ctx);
24784 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
24785 (ctx->opcode >> 16) & 1);
24786 } else {
24787 generate_exception_err(ctx, EXCP_CpU, 1);
24789 break;
24790 case OPC_MULT:
24791 case OPC_MULTU:
24792 if (sa) {
24793 check_insn(ctx, INSN_VR54XX);
24794 op1 = MASK_MUL_VR54XX(ctx->opcode);
24795 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
24796 } else {
24797 gen_muldiv(ctx, op1, rd & 3, rs, rt);
24799 break;
24800 case OPC_DIV:
24801 case OPC_DIVU:
24802 gen_muldiv(ctx, op1, 0, rs, rt);
24803 break;
24804 #if defined(TARGET_MIPS64)
24805 case OPC_DMULT:
24806 case OPC_DMULTU:
24807 case OPC_DDIV:
24808 case OPC_DDIVU:
24809 check_insn(ctx, ISA_MIPS3);
24810 check_mips_64(ctx);
24811 gen_muldiv(ctx, op1, 0, rs, rt);
24812 break;
24813 #endif
24814 case OPC_JR:
24815 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24816 break;
24817 case OPC_SPIM:
24818 #ifdef MIPS_STRICT_STANDARD
24819 MIPS_INVAL("SPIM");
24820 gen_reserved_instruction(ctx);
24821 #else
24822 /* Implemented as RI exception for now. */
24823 MIPS_INVAL("spim (unofficial)");
24824 gen_reserved_instruction(ctx);
24825 #endif
24826 break;
24827 default: /* Invalid */
24828 MIPS_INVAL("special_legacy");
24829 gen_reserved_instruction(ctx);
24830 break;
24834 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
24836 int rs, rt, rd, sa;
24837 uint32_t op1;
24839 rs = (ctx->opcode >> 21) & 0x1f;
24840 rt = (ctx->opcode >> 16) & 0x1f;
24841 rd = (ctx->opcode >> 11) & 0x1f;
24842 sa = (ctx->opcode >> 6) & 0x1f;
24844 op1 = MASK_SPECIAL(ctx->opcode);
24845 switch (op1) {
24846 case OPC_SLL: /* Shift with immediate */
24847 if (sa == 5 && rd == 0 &&
24848 rs == 0 && rt == 0) { /* PAUSE */
24849 if ((ctx->insn_flags & ISA_MIPS_R6) &&
24850 (ctx->hflags & MIPS_HFLAG_BMASK)) {
24851 gen_reserved_instruction(ctx);
24852 break;
24855 /* Fallthrough */
24856 case OPC_SRA:
24857 gen_shift_imm(ctx, op1, rd, rt, sa);
24858 break;
24859 case OPC_SRL:
24860 switch ((ctx->opcode >> 21) & 0x1f) {
24861 case 1:
24862 /* rotr is decoded as srl on non-R2 CPUs */
24863 if (ctx->insn_flags & ISA_MIPS_R2) {
24864 op1 = OPC_ROTR;
24866 /* Fallthrough */
24867 case 0:
24868 gen_shift_imm(ctx, op1, rd, rt, sa);
24869 break;
24870 default:
24871 gen_reserved_instruction(ctx);
24872 break;
24874 break;
24875 case OPC_ADD:
24876 case OPC_ADDU:
24877 case OPC_SUB:
24878 case OPC_SUBU:
24879 gen_arith(ctx, op1, rd, rs, rt);
24880 break;
24881 case OPC_SLLV: /* Shifts */
24882 case OPC_SRAV:
24883 gen_shift(ctx, op1, rd, rs, rt);
24884 break;
24885 case OPC_SRLV:
24886 switch ((ctx->opcode >> 6) & 0x1f) {
24887 case 1:
24888 /* rotrv is decoded as srlv on non-R2 CPUs */
24889 if (ctx->insn_flags & ISA_MIPS_R2) {
24890 op1 = OPC_ROTRV;
24892 /* Fallthrough */
24893 case 0:
24894 gen_shift(ctx, op1, rd, rs, rt);
24895 break;
24896 default:
24897 gen_reserved_instruction(ctx);
24898 break;
24900 break;
24901 case OPC_SLT: /* Set on less than */
24902 case OPC_SLTU:
24903 gen_slt(ctx, op1, rd, rs, rt);
24904 break;
24905 case OPC_AND: /* Logic*/
24906 case OPC_OR:
24907 case OPC_NOR:
24908 case OPC_XOR:
24909 gen_logic(ctx, op1, rd, rs, rt);
24910 break;
24911 case OPC_JALR:
24912 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24913 break;
24914 case OPC_TGE: /* Traps */
24915 case OPC_TGEU:
24916 case OPC_TLT:
24917 case OPC_TLTU:
24918 case OPC_TEQ:
24919 case OPC_TNE:
24920 check_insn(ctx, ISA_MIPS2);
24921 gen_trap(ctx, op1, rs, rt, -1);
24922 break;
24923 case OPC_LSA: /* OPC_PMON */
24924 if ((ctx->insn_flags & ISA_MIPS_R6) ||
24925 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
24926 decode_opc_special_r6(env, ctx);
24927 } else {
24928 /* Pmon entry point, also R4010 selsl */
24929 #ifdef MIPS_STRICT_STANDARD
24930 MIPS_INVAL("PMON / selsl");
24931 gen_reserved_instruction(ctx);
24932 #else
24933 gen_helper_0e0i(pmon, sa);
24934 #endif
24936 break;
24937 case OPC_SYSCALL:
24938 generate_exception_end(ctx, EXCP_SYSCALL);
24939 break;
24940 case OPC_BREAK:
24941 generate_exception_end(ctx, EXCP_BREAK);
24942 break;
24943 case OPC_SYNC:
24944 check_insn(ctx, ISA_MIPS2);
24945 gen_sync(extract32(ctx->opcode, 6, 5));
24946 break;
24948 #if defined(TARGET_MIPS64)
24949 /* MIPS64 specific opcodes */
24950 case OPC_DSLL:
24951 case OPC_DSRA:
24952 case OPC_DSLL32:
24953 case OPC_DSRA32:
24954 check_insn(ctx, ISA_MIPS3);
24955 check_mips_64(ctx);
24956 gen_shift_imm(ctx, op1, rd, rt, sa);
24957 break;
24958 case OPC_DSRL:
24959 switch ((ctx->opcode >> 21) & 0x1f) {
24960 case 1:
24961 /* drotr is decoded as dsrl on non-R2 CPUs */
24962 if (ctx->insn_flags & ISA_MIPS_R2) {
24963 op1 = OPC_DROTR;
24965 /* Fallthrough */
24966 case 0:
24967 check_insn(ctx, ISA_MIPS3);
24968 check_mips_64(ctx);
24969 gen_shift_imm(ctx, op1, rd, rt, sa);
24970 break;
24971 default:
24972 gen_reserved_instruction(ctx);
24973 break;
24975 break;
24976 case OPC_DSRL32:
24977 switch ((ctx->opcode >> 21) & 0x1f) {
24978 case 1:
24979 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
24980 if (ctx->insn_flags & ISA_MIPS_R2) {
24981 op1 = OPC_DROTR32;
24983 /* Fallthrough */
24984 case 0:
24985 check_insn(ctx, ISA_MIPS3);
24986 check_mips_64(ctx);
24987 gen_shift_imm(ctx, op1, rd, rt, sa);
24988 break;
24989 default:
24990 gen_reserved_instruction(ctx);
24991 break;
24993 break;
24994 case OPC_DADD:
24995 case OPC_DADDU:
24996 case OPC_DSUB:
24997 case OPC_DSUBU:
24998 check_insn(ctx, ISA_MIPS3);
24999 check_mips_64(ctx);
25000 gen_arith(ctx, op1, rd, rs, rt);
25001 break;
25002 case OPC_DSLLV:
25003 case OPC_DSRAV:
25004 check_insn(ctx, ISA_MIPS3);
25005 check_mips_64(ctx);
25006 gen_shift(ctx, op1, rd, rs, rt);
25007 break;
25008 case OPC_DSRLV:
25009 switch ((ctx->opcode >> 6) & 0x1f) {
25010 case 1:
25011 /* drotrv is decoded as dsrlv on non-R2 CPUs */
25012 if (ctx->insn_flags & ISA_MIPS_R2) {
25013 op1 = OPC_DROTRV;
25015 /* Fallthrough */
25016 case 0:
25017 check_insn(ctx, ISA_MIPS3);
25018 check_mips_64(ctx);
25019 gen_shift(ctx, op1, rd, rs, rt);
25020 break;
25021 default:
25022 gen_reserved_instruction(ctx);
25023 break;
25025 break;
25026 case OPC_DLSA:
25027 if ((ctx->insn_flags & ISA_MIPS_R6) ||
25028 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
25029 decode_opc_special_r6(env, ctx);
25031 break;
25032 #endif
25033 default:
25034 if (ctx->insn_flags & ISA_MIPS_R6) {
25035 decode_opc_special_r6(env, ctx);
25036 } else if (ctx->insn_flags & INSN_R5900) {
25037 decode_opc_special_tx79(env, ctx);
25038 } else {
25039 decode_opc_special_legacy(env, ctx);
25045 #if defined(TARGET_MIPS64)
25049 * MMI (MultiMedia Interface) ASE instructions
25050 * ===========================================
25054 * MMI instructions category: data communication
25055 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25057 * PCPYH PEXCH PEXTLB PINTH PPACB PEXT5 PREVH
25058 * PCPYLD PEXCW PEXTLH PINTEH PPACH PPAC5 PROT3W
25059 * PCPYUD PEXEH PEXTLW PPACW
25060 * PEXEW PEXTUB
25061 * PEXTUH
25062 * PEXTUW
25066 * PCPYH rd, rt
25068 * Parallel Copy Halfword
25070 * 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
25071 * +-----------+---------+---------+---------+---------+-----------+
25072 * | MMI |0 0 0 0 0| rt | rd | PCPYH | MMI3 |
25073 * +-----------+---------+---------+---------+---------+-----------+
25075 static void gen_mmi_pcpyh(DisasContext *ctx)
25077 uint32_t pd, rt, rd;
25078 uint32_t opcode;
25080 opcode = ctx->opcode;
25082 pd = extract32(opcode, 21, 5);
25083 rt = extract32(opcode, 16, 5);
25084 rd = extract32(opcode, 11, 5);
25086 if (unlikely(pd != 0)) {
25087 gen_reserved_instruction(ctx);
25088 } else if (rd == 0) {
25089 /* nop */
25090 } else if (rt == 0) {
25091 tcg_gen_movi_i64(cpu_gpr[rd], 0);
25092 tcg_gen_movi_i64(cpu_mmr[rd], 0);
25093 } else {
25094 TCGv_i64 t0 = tcg_temp_new();
25095 TCGv_i64 t1 = tcg_temp_new();
25096 uint64_t mask = (1ULL << 16) - 1;
25098 tcg_gen_andi_i64(t0, cpu_gpr[rt], mask);
25099 tcg_gen_movi_i64(t1, 0);
25100 tcg_gen_or_i64(t1, t0, t1);
25101 tcg_gen_shli_i64(t0, t0, 16);
25102 tcg_gen_or_i64(t1, t0, t1);
25103 tcg_gen_shli_i64(t0, t0, 16);
25104 tcg_gen_or_i64(t1, t0, t1);
25105 tcg_gen_shli_i64(t0, t0, 16);
25106 tcg_gen_or_i64(t1, t0, t1);
25108 tcg_gen_mov_i64(cpu_gpr[rd], t1);
25110 tcg_gen_andi_i64(t0, cpu_mmr[rt], mask);
25111 tcg_gen_movi_i64(t1, 0);
25112 tcg_gen_or_i64(t1, t0, t1);
25113 tcg_gen_shli_i64(t0, t0, 16);
25114 tcg_gen_or_i64(t1, t0, t1);
25115 tcg_gen_shli_i64(t0, t0, 16);
25116 tcg_gen_or_i64(t1, t0, t1);
25117 tcg_gen_shli_i64(t0, t0, 16);
25118 tcg_gen_or_i64(t1, t0, t1);
25120 tcg_gen_mov_i64(cpu_mmr[rd], t1);
25122 tcg_temp_free(t0);
25123 tcg_temp_free(t1);
25128 * PCPYLD rd, rs, rt
25130 * Parallel Copy Lower Doubleword
25132 * 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
25133 * +-----------+---------+---------+---------+---------+-----------+
25134 * | MMI | rs | rt | rd | PCPYLD | MMI2 |
25135 * +-----------+---------+---------+---------+---------+-----------+
25137 static void gen_mmi_pcpyld(DisasContext *ctx)
25139 uint32_t rs, rt, rd;
25140 uint32_t opcode;
25142 opcode = ctx->opcode;
25144 rs = extract32(opcode, 21, 5);
25145 rt = extract32(opcode, 16, 5);
25146 rd = extract32(opcode, 11, 5);
25148 if (rd == 0) {
25149 /* nop */
25150 } else {
25151 if (rs == 0) {
25152 tcg_gen_movi_i64(cpu_mmr[rd], 0);
25153 } else {
25154 tcg_gen_mov_i64(cpu_mmr[rd], cpu_gpr[rs]);
25156 if (rt == 0) {
25157 tcg_gen_movi_i64(cpu_gpr[rd], 0);
25158 } else {
25159 if (rd != rt) {
25160 tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr[rt]);
25167 * PCPYUD rd, rs, rt
25169 * Parallel Copy Upper Doubleword
25171 * 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
25172 * +-----------+---------+---------+---------+---------+-----------+
25173 * | MMI | rs | rt | rd | PCPYUD | MMI3 |
25174 * +-----------+---------+---------+---------+---------+-----------+
25176 static void gen_mmi_pcpyud(DisasContext *ctx)
25178 uint32_t rs, rt, rd;
25179 uint32_t opcode;
25181 opcode = ctx->opcode;
25183 rs = extract32(opcode, 21, 5);
25184 rt = extract32(opcode, 16, 5);
25185 rd = extract32(opcode, 11, 5);
25187 if (rd == 0) {
25188 /* nop */
25189 } else {
25190 if (rs == 0) {
25191 tcg_gen_movi_i64(cpu_gpr[rd], 0);
25192 } else {
25193 tcg_gen_mov_i64(cpu_gpr[rd], cpu_mmr[rs]);
25195 if (rt == 0) {
25196 tcg_gen_movi_i64(cpu_mmr[rd], 0);
25197 } else {
25198 if (rd != rt) {
25199 tcg_gen_mov_i64(cpu_mmr[rd], cpu_mmr[rt]);
25205 #endif
25208 #if !defined(TARGET_MIPS64)
25210 /* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
25211 #define MXU_APTN1_A 0
25212 #define MXU_APTN1_S 1
25214 /* MXU accumulate add/subtract 2-bit pattern 'aptn2' */
25215 #define MXU_APTN2_AA 0
25216 #define MXU_APTN2_AS 1
25217 #define MXU_APTN2_SA 2
25218 #define MXU_APTN2_SS 3
25220 /* MXU execute add/subtract 2-bit pattern 'eptn2' */
25221 #define MXU_EPTN2_AA 0
25222 #define MXU_EPTN2_AS 1
25223 #define MXU_EPTN2_SA 2
25224 #define MXU_EPTN2_SS 3
25226 /* MXU operand getting pattern 'optn2' */
25227 #define MXU_OPTN2_PTN0 0
25228 #define MXU_OPTN2_PTN1 1
25229 #define MXU_OPTN2_PTN2 2
25230 #define MXU_OPTN2_PTN3 3
25231 /* alternative naming scheme for 'optn2' */
25232 #define MXU_OPTN2_WW 0
25233 #define MXU_OPTN2_LW 1
25234 #define MXU_OPTN2_HW 2
25235 #define MXU_OPTN2_XW 3
25237 /* MXU operand getting pattern 'optn3' */
25238 #define MXU_OPTN3_PTN0 0
25239 #define MXU_OPTN3_PTN1 1
25240 #define MXU_OPTN3_PTN2 2
25241 #define MXU_OPTN3_PTN3 3
25242 #define MXU_OPTN3_PTN4 4
25243 #define MXU_OPTN3_PTN5 5
25244 #define MXU_OPTN3_PTN6 6
25245 #define MXU_OPTN3_PTN7 7
25249 * S32I2M XRa, rb - Register move from GRF to XRF
25251 static void gen_mxu_s32i2m(DisasContext *ctx)
25253 TCGv t0;
25254 uint32_t XRa, Rb;
25256 t0 = tcg_temp_new();
25258 XRa = extract32(ctx->opcode, 6, 5);
25259 Rb = extract32(ctx->opcode, 16, 5);
25261 gen_load_gpr(t0, Rb);
25262 if (XRa <= 15) {
25263 gen_store_mxu_gpr(t0, XRa);
25264 } else if (XRa == 16) {
25265 gen_store_mxu_cr(t0);
25268 tcg_temp_free(t0);
25272 * S32M2I XRa, rb - Register move from XRF to GRF
25274 static void gen_mxu_s32m2i(DisasContext *ctx)
25276 TCGv t0;
25277 uint32_t XRa, Rb;
25279 t0 = tcg_temp_new();
25281 XRa = extract32(ctx->opcode, 6, 5);
25282 Rb = extract32(ctx->opcode, 16, 5);
25284 if (XRa <= 15) {
25285 gen_load_mxu_gpr(t0, XRa);
25286 } else if (XRa == 16) {
25287 gen_load_mxu_cr(t0);
25290 gen_store_gpr(t0, Rb);
25292 tcg_temp_free(t0);
25296 * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF
25298 static void gen_mxu_s8ldd(DisasContext *ctx)
25300 TCGv t0, t1;
25301 uint32_t XRa, Rb, s8, optn3;
25303 t0 = tcg_temp_new();
25304 t1 = tcg_temp_new();
25306 XRa = extract32(ctx->opcode, 6, 4);
25307 s8 = extract32(ctx->opcode, 10, 8);
25308 optn3 = extract32(ctx->opcode, 18, 3);
25309 Rb = extract32(ctx->opcode, 21, 5);
25311 gen_load_gpr(t0, Rb);
25312 tcg_gen_addi_tl(t0, t0, (int8_t)s8);
25314 switch (optn3) {
25315 /* XRa[7:0] = tmp8 */
25316 case MXU_OPTN3_PTN0:
25317 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25318 gen_load_mxu_gpr(t0, XRa);
25319 tcg_gen_deposit_tl(t0, t0, t1, 0, 8);
25320 break;
25321 /* XRa[15:8] = tmp8 */
25322 case MXU_OPTN3_PTN1:
25323 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25324 gen_load_mxu_gpr(t0, XRa);
25325 tcg_gen_deposit_tl(t0, t0, t1, 8, 8);
25326 break;
25327 /* XRa[23:16] = tmp8 */
25328 case MXU_OPTN3_PTN2:
25329 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25330 gen_load_mxu_gpr(t0, XRa);
25331 tcg_gen_deposit_tl(t0, t0, t1, 16, 8);
25332 break;
25333 /* XRa[31:24] = tmp8 */
25334 case MXU_OPTN3_PTN3:
25335 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25336 gen_load_mxu_gpr(t0, XRa);
25337 tcg_gen_deposit_tl(t0, t0, t1, 24, 8);
25338 break;
25339 /* XRa = {8'b0, tmp8, 8'b0, tmp8} */
25340 case MXU_OPTN3_PTN4:
25341 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25342 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25343 break;
25344 /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */
25345 case MXU_OPTN3_PTN5:
25346 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25347 tcg_gen_shli_tl(t1, t1, 8);
25348 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25349 break;
25350 /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */
25351 case MXU_OPTN3_PTN6:
25352 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB);
25353 tcg_gen_mov_tl(t0, t1);
25354 tcg_gen_andi_tl(t0, t0, 0xFF00FFFF);
25355 tcg_gen_shli_tl(t1, t1, 16);
25356 tcg_gen_or_tl(t0, t0, t1);
25357 break;
25358 /* XRa = {tmp8, tmp8, tmp8, tmp8} */
25359 case MXU_OPTN3_PTN7:
25360 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25361 tcg_gen_deposit_tl(t1, t1, t1, 8, 8);
25362 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25363 break;
25366 gen_store_mxu_gpr(t0, XRa);
25368 tcg_temp_free(t0);
25369 tcg_temp_free(t1);
25373 * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication
25375 static void gen_mxu_d16mul(DisasContext *ctx)
25377 TCGv t0, t1, t2, t3;
25378 uint32_t XRa, XRb, XRc, XRd, optn2;
25380 t0 = tcg_temp_new();
25381 t1 = tcg_temp_new();
25382 t2 = tcg_temp_new();
25383 t3 = tcg_temp_new();
25385 XRa = extract32(ctx->opcode, 6, 4);
25386 XRb = extract32(ctx->opcode, 10, 4);
25387 XRc = extract32(ctx->opcode, 14, 4);
25388 XRd = extract32(ctx->opcode, 18, 4);
25389 optn2 = extract32(ctx->opcode, 22, 2);
25391 gen_load_mxu_gpr(t1, XRb);
25392 tcg_gen_sextract_tl(t0, t1, 0, 16);
25393 tcg_gen_sextract_tl(t1, t1, 16, 16);
25394 gen_load_mxu_gpr(t3, XRc);
25395 tcg_gen_sextract_tl(t2, t3, 0, 16);
25396 tcg_gen_sextract_tl(t3, t3, 16, 16);
25398 switch (optn2) {
25399 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
25400 tcg_gen_mul_tl(t3, t1, t3);
25401 tcg_gen_mul_tl(t2, t0, t2);
25402 break;
25403 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
25404 tcg_gen_mul_tl(t3, t0, t3);
25405 tcg_gen_mul_tl(t2, t0, t2);
25406 break;
25407 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
25408 tcg_gen_mul_tl(t3, t1, t3);
25409 tcg_gen_mul_tl(t2, t1, t2);
25410 break;
25411 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
25412 tcg_gen_mul_tl(t3, t0, t3);
25413 tcg_gen_mul_tl(t2, t1, t2);
25414 break;
25416 gen_store_mxu_gpr(t3, XRa);
25417 gen_store_mxu_gpr(t2, XRd);
25419 tcg_temp_free(t0);
25420 tcg_temp_free(t1);
25421 tcg_temp_free(t2);
25422 tcg_temp_free(t3);
25426 * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply
25427 * and accumulate
25429 static void gen_mxu_d16mac(DisasContext *ctx)
25431 TCGv t0, t1, t2, t3;
25432 uint32_t XRa, XRb, XRc, XRd, optn2, aptn2;
25434 t0 = tcg_temp_new();
25435 t1 = tcg_temp_new();
25436 t2 = tcg_temp_new();
25437 t3 = tcg_temp_new();
25439 XRa = extract32(ctx->opcode, 6, 4);
25440 XRb = extract32(ctx->opcode, 10, 4);
25441 XRc = extract32(ctx->opcode, 14, 4);
25442 XRd = extract32(ctx->opcode, 18, 4);
25443 optn2 = extract32(ctx->opcode, 22, 2);
25444 aptn2 = extract32(ctx->opcode, 24, 2);
25446 gen_load_mxu_gpr(t1, XRb);
25447 tcg_gen_sextract_tl(t0, t1, 0, 16);
25448 tcg_gen_sextract_tl(t1, t1, 16, 16);
25450 gen_load_mxu_gpr(t3, XRc);
25451 tcg_gen_sextract_tl(t2, t3, 0, 16);
25452 tcg_gen_sextract_tl(t3, t3, 16, 16);
25454 switch (optn2) {
25455 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
25456 tcg_gen_mul_tl(t3, t1, t3);
25457 tcg_gen_mul_tl(t2, t0, t2);
25458 break;
25459 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
25460 tcg_gen_mul_tl(t3, t0, t3);
25461 tcg_gen_mul_tl(t2, t0, t2);
25462 break;
25463 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
25464 tcg_gen_mul_tl(t3, t1, t3);
25465 tcg_gen_mul_tl(t2, t1, t2);
25466 break;
25467 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
25468 tcg_gen_mul_tl(t3, t0, t3);
25469 tcg_gen_mul_tl(t2, t1, t2);
25470 break;
25472 gen_load_mxu_gpr(t0, XRa);
25473 gen_load_mxu_gpr(t1, XRd);
25475 switch (aptn2) {
25476 case MXU_APTN2_AA:
25477 tcg_gen_add_tl(t3, t0, t3);
25478 tcg_gen_add_tl(t2, t1, t2);
25479 break;
25480 case MXU_APTN2_AS:
25481 tcg_gen_add_tl(t3, t0, t3);
25482 tcg_gen_sub_tl(t2, t1, t2);
25483 break;
25484 case MXU_APTN2_SA:
25485 tcg_gen_sub_tl(t3, t0, t3);
25486 tcg_gen_add_tl(t2, t1, t2);
25487 break;
25488 case MXU_APTN2_SS:
25489 tcg_gen_sub_tl(t3, t0, t3);
25490 tcg_gen_sub_tl(t2, t1, t2);
25491 break;
25493 gen_store_mxu_gpr(t3, XRa);
25494 gen_store_mxu_gpr(t2, XRd);
25496 tcg_temp_free(t0);
25497 tcg_temp_free(t1);
25498 tcg_temp_free(t2);
25499 tcg_temp_free(t3);
25503 * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply
25504 * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply
25506 static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx)
25508 TCGv t0, t1, t2, t3, t4, t5, t6, t7;
25509 uint32_t XRa, XRb, XRc, XRd, sel;
25511 t0 = tcg_temp_new();
25512 t1 = tcg_temp_new();
25513 t2 = tcg_temp_new();
25514 t3 = tcg_temp_new();
25515 t4 = tcg_temp_new();
25516 t5 = tcg_temp_new();
25517 t6 = tcg_temp_new();
25518 t7 = tcg_temp_new();
25520 XRa = extract32(ctx->opcode, 6, 4);
25521 XRb = extract32(ctx->opcode, 10, 4);
25522 XRc = extract32(ctx->opcode, 14, 4);
25523 XRd = extract32(ctx->opcode, 18, 4);
25524 sel = extract32(ctx->opcode, 22, 2);
25526 gen_load_mxu_gpr(t3, XRb);
25527 gen_load_mxu_gpr(t7, XRc);
25529 if (sel == 0x2) {
25530 /* Q8MULSU */
25531 tcg_gen_ext8s_tl(t0, t3);
25532 tcg_gen_shri_tl(t3, t3, 8);
25533 tcg_gen_ext8s_tl(t1, t3);
25534 tcg_gen_shri_tl(t3, t3, 8);
25535 tcg_gen_ext8s_tl(t2, t3);
25536 tcg_gen_shri_tl(t3, t3, 8);
25537 tcg_gen_ext8s_tl(t3, t3);
25538 } else {
25539 /* Q8MUL */
25540 tcg_gen_ext8u_tl(t0, t3);
25541 tcg_gen_shri_tl(t3, t3, 8);
25542 tcg_gen_ext8u_tl(t1, t3);
25543 tcg_gen_shri_tl(t3, t3, 8);
25544 tcg_gen_ext8u_tl(t2, t3);
25545 tcg_gen_shri_tl(t3, t3, 8);
25546 tcg_gen_ext8u_tl(t3, t3);
25549 tcg_gen_ext8u_tl(t4, t7);
25550 tcg_gen_shri_tl(t7, t7, 8);
25551 tcg_gen_ext8u_tl(t5, t7);
25552 tcg_gen_shri_tl(t7, t7, 8);
25553 tcg_gen_ext8u_tl(t6, t7);
25554 tcg_gen_shri_tl(t7, t7, 8);
25555 tcg_gen_ext8u_tl(t7, t7);
25557 tcg_gen_mul_tl(t0, t0, t4);
25558 tcg_gen_mul_tl(t1, t1, t5);
25559 tcg_gen_mul_tl(t2, t2, t6);
25560 tcg_gen_mul_tl(t3, t3, t7);
25562 tcg_gen_andi_tl(t0, t0, 0xFFFF);
25563 tcg_gen_andi_tl(t1, t1, 0xFFFF);
25564 tcg_gen_andi_tl(t2, t2, 0xFFFF);
25565 tcg_gen_andi_tl(t3, t3, 0xFFFF);
25567 tcg_gen_shli_tl(t1, t1, 16);
25568 tcg_gen_shli_tl(t3, t3, 16);
25570 tcg_gen_or_tl(t0, t0, t1);
25571 tcg_gen_or_tl(t1, t2, t3);
25573 gen_store_mxu_gpr(t0, XRd);
25574 gen_store_mxu_gpr(t1, XRa);
25576 tcg_temp_free(t0);
25577 tcg_temp_free(t1);
25578 tcg_temp_free(t2);
25579 tcg_temp_free(t3);
25580 tcg_temp_free(t4);
25581 tcg_temp_free(t5);
25582 tcg_temp_free(t6);
25583 tcg_temp_free(t7);
25587 * S32LDD XRa, Rb, S12 - Load a word from memory to XRF
25588 * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte seq.
25590 static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx)
25592 TCGv t0, t1;
25593 uint32_t XRa, Rb, s12, sel;
25595 t0 = tcg_temp_new();
25596 t1 = tcg_temp_new();
25598 XRa = extract32(ctx->opcode, 6, 4);
25599 s12 = extract32(ctx->opcode, 10, 10);
25600 sel = extract32(ctx->opcode, 20, 1);
25601 Rb = extract32(ctx->opcode, 21, 5);
25603 gen_load_gpr(t0, Rb);
25605 tcg_gen_movi_tl(t1, s12);
25606 tcg_gen_shli_tl(t1, t1, 2);
25607 if (s12 & 0x200) {
25608 tcg_gen_ori_tl(t1, t1, 0xFFFFF000);
25610 tcg_gen_add_tl(t1, t0, t1);
25611 tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL);
25613 if (sel == 1) {
25614 /* S32LDDR */
25615 tcg_gen_bswap32_tl(t1, t1);
25617 gen_store_mxu_gpr(t1, XRa);
25619 tcg_temp_free(t0);
25620 tcg_temp_free(t1);
25625 * MXU instruction category: logic
25626 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25628 * S32NOR S32AND S32OR S32XOR
25632 * S32NOR XRa, XRb, XRc
25633 * Update XRa with the result of logical bitwise 'nor' operation
25634 * applied to the content of XRb and XRc.
25636 * 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
25637 * +-----------+---------+-----+-------+-------+-------+-----------+
25638 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25639 * +-----------+---------+-----+-------+-------+-------+-----------+
25641 static void gen_mxu_S32NOR(DisasContext *ctx)
25643 uint32_t pad, XRc, XRb, XRa;
25645 pad = extract32(ctx->opcode, 21, 5);
25646 XRc = extract32(ctx->opcode, 14, 4);
25647 XRb = extract32(ctx->opcode, 10, 4);
25648 XRa = extract32(ctx->opcode, 6, 4);
25650 if (unlikely(pad != 0)) {
25651 /* opcode padding incorrect -> do nothing */
25652 } else if (unlikely(XRa == 0)) {
25653 /* destination is zero register -> do nothing */
25654 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25655 /* both operands zero registers -> just set destination to all 1s */
25656 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF);
25657 } else if (unlikely(XRb == 0)) {
25658 /* XRb zero register -> just set destination to the negation of XRc */
25659 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25660 } else if (unlikely(XRc == 0)) {
25661 /* XRa zero register -> just set destination to the negation of XRb */
25662 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25663 } else if (unlikely(XRb == XRc)) {
25664 /* both operands same -> just set destination to the negation of XRb */
25665 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25666 } else {
25667 /* the most general case */
25668 tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25673 * S32AND XRa, XRb, XRc
25674 * Update XRa with the result of logical bitwise 'and' operation
25675 * applied to the content of XRb and XRc.
25677 * 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
25678 * +-----------+---------+-----+-------+-------+-------+-----------+
25679 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25680 * +-----------+---------+-----+-------+-------+-------+-----------+
25682 static void gen_mxu_S32AND(DisasContext *ctx)
25684 uint32_t pad, XRc, XRb, XRa;
25686 pad = extract32(ctx->opcode, 21, 5);
25687 XRc = extract32(ctx->opcode, 14, 4);
25688 XRb = extract32(ctx->opcode, 10, 4);
25689 XRa = extract32(ctx->opcode, 6, 4);
25691 if (unlikely(pad != 0)) {
25692 /* opcode padding incorrect -> do nothing */
25693 } else if (unlikely(XRa == 0)) {
25694 /* destination is zero register -> do nothing */
25695 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25696 /* one of operands zero register -> just set destination to all 0s */
25697 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25698 } else if (unlikely(XRb == XRc)) {
25699 /* both operands same -> just set destination to one of them */
25700 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25701 } else {
25702 /* the most general case */
25703 tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25708 * S32OR XRa, XRb, XRc
25709 * Update XRa with the result of logical bitwise 'or' operation
25710 * applied to the content of XRb and XRc.
25712 * 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
25713 * +-----------+---------+-----+-------+-------+-------+-----------+
25714 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25715 * +-----------+---------+-----+-------+-------+-------+-----------+
25717 static void gen_mxu_S32OR(DisasContext *ctx)
25719 uint32_t pad, XRc, XRb, XRa;
25721 pad = extract32(ctx->opcode, 21, 5);
25722 XRc = extract32(ctx->opcode, 14, 4);
25723 XRb = extract32(ctx->opcode, 10, 4);
25724 XRa = extract32(ctx->opcode, 6, 4);
25726 if (unlikely(pad != 0)) {
25727 /* opcode padding incorrect -> do nothing */
25728 } else if (unlikely(XRa == 0)) {
25729 /* destination is zero register -> do nothing */
25730 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25731 /* both operands zero registers -> just set destination to all 0s */
25732 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25733 } else if (unlikely(XRb == 0)) {
25734 /* XRb zero register -> just set destination to the content of XRc */
25735 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25736 } else if (unlikely(XRc == 0)) {
25737 /* XRc zero register -> just set destination to the content of XRb */
25738 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25739 } else if (unlikely(XRb == XRc)) {
25740 /* both operands same -> just set destination to one of them */
25741 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25742 } else {
25743 /* the most general case */
25744 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25749 * S32XOR XRa, XRb, XRc
25750 * Update XRa with the result of logical bitwise 'xor' operation
25751 * applied to the content of XRb and XRc.
25753 * 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
25754 * +-----------+---------+-----+-------+-------+-------+-----------+
25755 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25756 * +-----------+---------+-----+-------+-------+-------+-----------+
25758 static void gen_mxu_S32XOR(DisasContext *ctx)
25760 uint32_t pad, XRc, XRb, XRa;
25762 pad = extract32(ctx->opcode, 21, 5);
25763 XRc = extract32(ctx->opcode, 14, 4);
25764 XRb = extract32(ctx->opcode, 10, 4);
25765 XRa = extract32(ctx->opcode, 6, 4);
25767 if (unlikely(pad != 0)) {
25768 /* opcode padding incorrect -> do nothing */
25769 } else if (unlikely(XRa == 0)) {
25770 /* destination is zero register -> do nothing */
25771 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25772 /* both operands zero registers -> just set destination to all 0s */
25773 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25774 } else if (unlikely(XRb == 0)) {
25775 /* XRb zero register -> just set destination to the content of XRc */
25776 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25777 } else if (unlikely(XRc == 0)) {
25778 /* XRc zero register -> just set destination to the content of XRb */
25779 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25780 } else if (unlikely(XRb == XRc)) {
25781 /* both operands same -> just set destination to all 0s */
25782 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25783 } else {
25784 /* the most general case */
25785 tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25791 * MXU instruction category max/min
25792 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25794 * S32MAX D16MAX Q8MAX
25795 * S32MIN D16MIN Q8MIN
25799 * S32MAX XRa, XRb, XRc
25800 * Update XRa with the maximum of signed 32-bit integers contained
25801 * in XRb and XRc.
25803 * S32MIN XRa, XRb, XRc
25804 * Update XRa with the minimum of signed 32-bit integers contained
25805 * in XRb and XRc.
25807 * 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
25808 * +-----------+---------+-----+-------+-------+-------+-----------+
25809 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25810 * +-----------+---------+-----+-------+-------+-------+-----------+
25812 static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx)
25814 uint32_t pad, opc, XRc, XRb, XRa;
25816 pad = extract32(ctx->opcode, 21, 5);
25817 opc = extract32(ctx->opcode, 18, 3);
25818 XRc = extract32(ctx->opcode, 14, 4);
25819 XRb = extract32(ctx->opcode, 10, 4);
25820 XRa = extract32(ctx->opcode, 6, 4);
25822 if (unlikely(pad != 0)) {
25823 /* opcode padding incorrect -> do nothing */
25824 } else if (unlikely(XRa == 0)) {
25825 /* destination is zero register -> do nothing */
25826 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25827 /* both operands zero registers -> just set destination to zero */
25828 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25829 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25830 /* exactly one operand is zero register - find which one is not...*/
25831 uint32_t XRx = XRb ? XRb : XRc;
25832 /* ...and do max/min operation with one operand 0 */
25833 if (opc == OPC_MXU_S32MAX) {
25834 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25835 } else {
25836 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25838 } else if (unlikely(XRb == XRc)) {
25839 /* both operands same -> just set destination to one of them */
25840 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25841 } else {
25842 /* the most general case */
25843 if (opc == OPC_MXU_S32MAX) {
25844 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25845 mxu_gpr[XRc - 1]);
25846 } else {
25847 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25848 mxu_gpr[XRc - 1]);
25854 * D16MAX
25855 * Update XRa with the 16-bit-wise maximums of signed integers
25856 * contained in XRb and XRc.
25858 * D16MIN
25859 * Update XRa with the 16-bit-wise minimums of signed integers
25860 * contained in XRb and XRc.
25862 * 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
25863 * +-----------+---------+-----+-------+-------+-------+-----------+
25864 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25865 * +-----------+---------+-----+-------+-------+-------+-----------+
25867 static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx)
25869 uint32_t pad, opc, XRc, XRb, XRa;
25871 pad = extract32(ctx->opcode, 21, 5);
25872 opc = extract32(ctx->opcode, 18, 3);
25873 XRc = extract32(ctx->opcode, 14, 4);
25874 XRb = extract32(ctx->opcode, 10, 4);
25875 XRa = extract32(ctx->opcode, 6, 4);
25877 if (unlikely(pad != 0)) {
25878 /* opcode padding incorrect -> do nothing */
25879 } else if (unlikely(XRc == 0)) {
25880 /* destination is zero register -> do nothing */
25881 } else if (unlikely((XRb == 0) && (XRa == 0))) {
25882 /* both operands zero registers -> just set destination to zero */
25883 tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0);
25884 } else if (unlikely((XRb == 0) || (XRa == 0))) {
25885 /* exactly one operand is zero register - find which one is not...*/
25886 uint32_t XRx = XRb ? XRb : XRc;
25887 /* ...and do half-word-wise max/min with one operand 0 */
25888 TCGv_i32 t0 = tcg_temp_new();
25889 TCGv_i32 t1 = tcg_const_i32(0);
25891 /* the left half-word first */
25892 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000);
25893 if (opc == OPC_MXU_D16MAX) {
25894 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25895 } else {
25896 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25899 /* the right half-word */
25900 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF);
25901 /* move half-words to the leftmost position */
25902 tcg_gen_shli_i32(t0, t0, 16);
25903 /* t0 will be max/min of t0 and t1 */
25904 if (opc == OPC_MXU_D16MAX) {
25905 tcg_gen_smax_i32(t0, t0, t1);
25906 } else {
25907 tcg_gen_smin_i32(t0, t0, t1);
25909 /* return resulting half-words to its original position */
25910 tcg_gen_shri_i32(t0, t0, 16);
25911 /* finally update the destination */
25912 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25914 tcg_temp_free(t1);
25915 tcg_temp_free(t0);
25916 } else if (unlikely(XRb == XRc)) {
25917 /* both operands same -> just set destination to one of them */
25918 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25919 } else {
25920 /* the most general case */
25921 TCGv_i32 t0 = tcg_temp_new();
25922 TCGv_i32 t1 = tcg_temp_new();
25924 /* the left half-word first */
25925 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000);
25926 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25927 if (opc == OPC_MXU_D16MAX) {
25928 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25929 } else {
25930 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25933 /* the right half-word */
25934 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25935 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF);
25936 /* move half-words to the leftmost position */
25937 tcg_gen_shli_i32(t0, t0, 16);
25938 tcg_gen_shli_i32(t1, t1, 16);
25939 /* t0 will be max/min of t0 and t1 */
25940 if (opc == OPC_MXU_D16MAX) {
25941 tcg_gen_smax_i32(t0, t0, t1);
25942 } else {
25943 tcg_gen_smin_i32(t0, t0, t1);
25945 /* return resulting half-words to its original position */
25946 tcg_gen_shri_i32(t0, t0, 16);
25947 /* finally update the destination */
25948 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25950 tcg_temp_free(t1);
25951 tcg_temp_free(t0);
25956 * Q8MAX
25957 * Update XRa with the 8-bit-wise maximums of signed integers
25958 * contained in XRb and XRc.
25960 * Q8MIN
25961 * Update XRa with the 8-bit-wise minimums of signed integers
25962 * contained in XRb and XRc.
25964 * 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
25965 * +-----------+---------+-----+-------+-------+-------+-----------+
25966 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25967 * +-----------+---------+-----+-------+-------+-------+-----------+
25969 static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx)
25971 uint32_t pad, opc, XRc, XRb, XRa;
25973 pad = extract32(ctx->opcode, 21, 5);
25974 opc = extract32(ctx->opcode, 18, 3);
25975 XRc = extract32(ctx->opcode, 14, 4);
25976 XRb = extract32(ctx->opcode, 10, 4);
25977 XRa = extract32(ctx->opcode, 6, 4);
25979 if (unlikely(pad != 0)) {
25980 /* opcode padding incorrect -> do nothing */
25981 } else if (unlikely(XRa == 0)) {
25982 /* destination is zero register -> do nothing */
25983 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25984 /* both operands zero registers -> just set destination to zero */
25985 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25986 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25987 /* exactly one operand is zero register - make it be the first...*/
25988 uint32_t XRx = XRb ? XRb : XRc;
25989 /* ...and do byte-wise max/min with one operand 0 */
25990 TCGv_i32 t0 = tcg_temp_new();
25991 TCGv_i32 t1 = tcg_const_i32(0);
25992 int32_t i;
25994 /* the leftmost byte (byte 3) first */
25995 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000);
25996 if (opc == OPC_MXU_Q8MAX) {
25997 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25998 } else {
25999 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
26002 /* bytes 2, 1, 0 */
26003 for (i = 2; i >= 0; i--) {
26004 /* extract the byte */
26005 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i));
26006 /* move the byte to the leftmost position */
26007 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
26008 /* t0 will be max/min of t0 and t1 */
26009 if (opc == OPC_MXU_Q8MAX) {
26010 tcg_gen_smax_i32(t0, t0, t1);
26011 } else {
26012 tcg_gen_smin_i32(t0, t0, t1);
26014 /* return resulting byte to its original position */
26015 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
26016 /* finally update the destination */
26017 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
26020 tcg_temp_free(t1);
26021 tcg_temp_free(t0);
26022 } else if (unlikely(XRb == XRc)) {
26023 /* both operands same -> just set destination to one of them */
26024 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
26025 } else {
26026 /* the most general case */
26027 TCGv_i32 t0 = tcg_temp_new();
26028 TCGv_i32 t1 = tcg_temp_new();
26029 int32_t i;
26031 /* the leftmost bytes (bytes 3) first */
26032 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000);
26033 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
26034 if (opc == OPC_MXU_Q8MAX) {
26035 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
26036 } else {
26037 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
26040 /* bytes 2, 1, 0 */
26041 for (i = 2; i >= 0; i--) {
26042 /* extract corresponding bytes */
26043 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i));
26044 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i));
26045 /* move the bytes to the leftmost position */
26046 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
26047 tcg_gen_shli_i32(t1, t1, 8 * (3 - i));
26048 /* t0 will be max/min of t0 and t1 */
26049 if (opc == OPC_MXU_Q8MAX) {
26050 tcg_gen_smax_i32(t0, t0, t1);
26051 } else {
26052 tcg_gen_smin_i32(t0, t0, t1);
26054 /* return resulting byte to its original position */
26055 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
26056 /* finally update the destination */
26057 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
26060 tcg_temp_free(t1);
26061 tcg_temp_free(t0);
26067 * MXU instruction category: align
26068 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
26070 * S32ALN S32ALNI
26074 * S32ALNI XRc, XRb, XRa, optn3
26075 * Arrange bytes from XRb and XRc according to one of five sets of
26076 * rules determined by optn3, and place the result in XRa.
26078 * 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
26079 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26080 * | SPECIAL2 |optn3|0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26081 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26084 static void gen_mxu_S32ALNI(DisasContext *ctx)
26086 uint32_t optn3, pad, XRc, XRb, XRa;
26088 optn3 = extract32(ctx->opcode, 23, 3);
26089 pad = extract32(ctx->opcode, 21, 2);
26090 XRc = extract32(ctx->opcode, 14, 4);
26091 XRb = extract32(ctx->opcode, 10, 4);
26092 XRa = extract32(ctx->opcode, 6, 4);
26094 if (unlikely(pad != 0)) {
26095 /* opcode padding incorrect -> do nothing */
26096 } else if (unlikely(XRa == 0)) {
26097 /* destination is zero register -> do nothing */
26098 } else if (unlikely((XRb == 0) && (XRc == 0))) {
26099 /* both operands zero registers -> just set destination to all 0s */
26100 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
26101 } else if (unlikely(XRb == 0)) {
26102 /* XRb zero register -> just appropriatelly shift XRc into XRa */
26103 switch (optn3) {
26104 case MXU_OPTN3_PTN0:
26105 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
26106 break;
26107 case MXU_OPTN3_PTN1:
26108 case MXU_OPTN3_PTN2:
26109 case MXU_OPTN3_PTN3:
26110 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1],
26111 8 * (4 - optn3));
26112 break;
26113 case MXU_OPTN3_PTN4:
26114 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
26115 break;
26117 } else if (unlikely(XRc == 0)) {
26118 /* XRc zero register -> just appropriatelly shift XRb into XRa */
26119 switch (optn3) {
26120 case MXU_OPTN3_PTN0:
26121 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
26122 break;
26123 case MXU_OPTN3_PTN1:
26124 case MXU_OPTN3_PTN2:
26125 case MXU_OPTN3_PTN3:
26126 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
26127 break;
26128 case MXU_OPTN3_PTN4:
26129 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
26130 break;
26132 } else if (unlikely(XRb == XRc)) {
26133 /* both operands same -> just rotation or moving from any of them */
26134 switch (optn3) {
26135 case MXU_OPTN3_PTN0:
26136 case MXU_OPTN3_PTN4:
26137 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
26138 break;
26139 case MXU_OPTN3_PTN1:
26140 case MXU_OPTN3_PTN2:
26141 case MXU_OPTN3_PTN3:
26142 tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
26143 break;
26145 } else {
26146 /* the most general case */
26147 switch (optn3) {
26148 case MXU_OPTN3_PTN0:
26150 /* */
26151 /* XRb XRc */
26152 /* +---------------+ */
26153 /* | A B C D | E F G H */
26154 /* +-------+-------+ */
26155 /* | */
26156 /* XRa */
26157 /* */
26159 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
26161 break;
26162 case MXU_OPTN3_PTN1:
26164 /* */
26165 /* XRb XRc */
26166 /* +-------------------+ */
26167 /* A | B C D E | F G H */
26168 /* +---------+---------+ */
26169 /* | */
26170 /* XRa */
26171 /* */
26173 TCGv_i32 t0 = tcg_temp_new();
26174 TCGv_i32 t1 = tcg_temp_new();
26176 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF);
26177 tcg_gen_shli_i32(t0, t0, 8);
26179 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
26180 tcg_gen_shri_i32(t1, t1, 24);
26182 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
26184 tcg_temp_free(t1);
26185 tcg_temp_free(t0);
26187 break;
26188 case MXU_OPTN3_PTN2:
26190 /* */
26191 /* XRb XRc */
26192 /* +-------------------+ */
26193 /* A B | C D E F | G H */
26194 /* +---------+---------+ */
26195 /* | */
26196 /* XRa */
26197 /* */
26199 TCGv_i32 t0 = tcg_temp_new();
26200 TCGv_i32 t1 = tcg_temp_new();
26202 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
26203 tcg_gen_shli_i32(t0, t0, 16);
26205 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
26206 tcg_gen_shri_i32(t1, t1, 16);
26208 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
26210 tcg_temp_free(t1);
26211 tcg_temp_free(t0);
26213 break;
26214 case MXU_OPTN3_PTN3:
26216 /* */
26217 /* XRb XRc */
26218 /* +-------------------+ */
26219 /* A B C | D E F G | H */
26220 /* +---------+---------+ */
26221 /* | */
26222 /* XRa */
26223 /* */
26225 TCGv_i32 t0 = tcg_temp_new();
26226 TCGv_i32 t1 = tcg_temp_new();
26228 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF);
26229 tcg_gen_shli_i32(t0, t0, 24);
26231 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00);
26232 tcg_gen_shri_i32(t1, t1, 8);
26234 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
26236 tcg_temp_free(t1);
26237 tcg_temp_free(t0);
26239 break;
26240 case MXU_OPTN3_PTN4:
26242 /* */
26243 /* XRb XRc */
26244 /* +---------------+ */
26245 /* A B C D | E F G H | */
26246 /* +-------+-------+ */
26247 /* | */
26248 /* XRa */
26249 /* */
26251 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
26253 break;
26260 * Decoding engine for MXU
26261 * =======================
26266 * Decode MXU pool00
26268 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26269 * +-----------+---------+-----+-------+-------+-------+-----------+
26270 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL00|
26271 * +-----------+---------+-----+-------+-------+-------+-----------+
26274 static void decode_opc_mxu__pool00(CPUMIPSState *env, DisasContext *ctx)
26276 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26278 switch (opcode) {
26279 case OPC_MXU_S32MAX:
26280 case OPC_MXU_S32MIN:
26281 gen_mxu_S32MAX_S32MIN(ctx);
26282 break;
26283 case OPC_MXU_D16MAX:
26284 case OPC_MXU_D16MIN:
26285 gen_mxu_D16MAX_D16MIN(ctx);
26286 break;
26287 case OPC_MXU_Q8MAX:
26288 case OPC_MXU_Q8MIN:
26289 gen_mxu_Q8MAX_Q8MIN(ctx);
26290 break;
26291 case OPC_MXU_Q8SLT:
26292 /* TODO: Implement emulation of Q8SLT instruction. */
26293 MIPS_INVAL("OPC_MXU_Q8SLT");
26294 gen_reserved_instruction(ctx);
26295 break;
26296 case OPC_MXU_Q8SLTU:
26297 /* TODO: Implement emulation of Q8SLTU instruction. */
26298 MIPS_INVAL("OPC_MXU_Q8SLTU");
26299 gen_reserved_instruction(ctx);
26300 break;
26301 default:
26302 MIPS_INVAL("decode_opc_mxu");
26303 gen_reserved_instruction(ctx);
26304 break;
26310 * Decode MXU pool01
26312 * S32SLT, D16SLT, D16AVG, D16AVGR, Q8AVG, Q8AVGR:
26313 * 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
26314 * +-----------+---------+-----+-------+-------+-------+-----------+
26315 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
26316 * +-----------+---------+-----+-------+-------+-------+-----------+
26318 * Q8ADD:
26319 * 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
26320 * +-----------+---+-----+-----+-------+-------+-------+-----------+
26321 * | SPECIAL2 |en2|0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
26322 * +-----------+---+-----+-----+-------+-------+-------+-----------+
26325 static void decode_opc_mxu__pool01(CPUMIPSState *env, DisasContext *ctx)
26327 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26329 switch (opcode) {
26330 case OPC_MXU_S32SLT:
26331 /* TODO: Implement emulation of S32SLT instruction. */
26332 MIPS_INVAL("OPC_MXU_S32SLT");
26333 gen_reserved_instruction(ctx);
26334 break;
26335 case OPC_MXU_D16SLT:
26336 /* TODO: Implement emulation of D16SLT instruction. */
26337 MIPS_INVAL("OPC_MXU_D16SLT");
26338 gen_reserved_instruction(ctx);
26339 break;
26340 case OPC_MXU_D16AVG:
26341 /* TODO: Implement emulation of D16AVG instruction. */
26342 MIPS_INVAL("OPC_MXU_D16AVG");
26343 gen_reserved_instruction(ctx);
26344 break;
26345 case OPC_MXU_D16AVGR:
26346 /* TODO: Implement emulation of D16AVGR instruction. */
26347 MIPS_INVAL("OPC_MXU_D16AVGR");
26348 gen_reserved_instruction(ctx);
26349 break;
26350 case OPC_MXU_Q8AVG:
26351 /* TODO: Implement emulation of Q8AVG instruction. */
26352 MIPS_INVAL("OPC_MXU_Q8AVG");
26353 gen_reserved_instruction(ctx);
26354 break;
26355 case OPC_MXU_Q8AVGR:
26356 /* TODO: Implement emulation of Q8AVGR instruction. */
26357 MIPS_INVAL("OPC_MXU_Q8AVGR");
26358 gen_reserved_instruction(ctx);
26359 break;
26360 case OPC_MXU_Q8ADD:
26361 /* TODO: Implement emulation of Q8ADD instruction. */
26362 MIPS_INVAL("OPC_MXU_Q8ADD");
26363 gen_reserved_instruction(ctx);
26364 break;
26365 default:
26366 MIPS_INVAL("decode_opc_mxu");
26367 gen_reserved_instruction(ctx);
26368 break;
26374 * Decode MXU pool02
26376 * 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
26377 * +-----------+---------+-----+-------+-------+-------+-----------+
26378 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL02|
26379 * +-----------+---------+-----+-------+-------+-------+-----------+
26382 static void decode_opc_mxu__pool02(CPUMIPSState *env, DisasContext *ctx)
26384 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26386 switch (opcode) {
26387 case OPC_MXU_S32CPS:
26388 /* TODO: Implement emulation of S32CPS instruction. */
26389 MIPS_INVAL("OPC_MXU_S32CPS");
26390 gen_reserved_instruction(ctx);
26391 break;
26392 case OPC_MXU_D16CPS:
26393 /* TODO: Implement emulation of D16CPS instruction. */
26394 MIPS_INVAL("OPC_MXU_D16CPS");
26395 gen_reserved_instruction(ctx);
26396 break;
26397 case OPC_MXU_Q8ABD:
26398 /* TODO: Implement emulation of Q8ABD instruction. */
26399 MIPS_INVAL("OPC_MXU_Q8ABD");
26400 gen_reserved_instruction(ctx);
26401 break;
26402 case OPC_MXU_Q16SAT:
26403 /* TODO: Implement emulation of Q16SAT instruction. */
26404 MIPS_INVAL("OPC_MXU_Q16SAT");
26405 gen_reserved_instruction(ctx);
26406 break;
26407 default:
26408 MIPS_INVAL("decode_opc_mxu");
26409 gen_reserved_instruction(ctx);
26410 break;
26416 * Decode MXU pool03
26418 * D16MULF:
26419 * 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
26420 * +-----------+---+---+-------+-------+-------+-------+-----------+
26421 * | SPECIAL2 |x x|on2|0 0 0 0| XRc | XRb | XRa |MXU__POOL03|
26422 * +-----------+---+---+-------+-------+-------+-------+-----------+
26424 * D16MULE:
26425 * 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
26426 * +-----------+---+---+-------+-------+-------+-------+-----------+
26427 * | SPECIAL2 |x x|on2| Xd | XRc | XRb | XRa |MXU__POOL03|
26428 * +-----------+---+---+-------+-------+-------+-------+-----------+
26431 static void decode_opc_mxu__pool03(CPUMIPSState *env, DisasContext *ctx)
26433 uint32_t opcode = extract32(ctx->opcode, 24, 2);
26435 switch (opcode) {
26436 case OPC_MXU_D16MULF:
26437 /* TODO: Implement emulation of D16MULF instruction. */
26438 MIPS_INVAL("OPC_MXU_D16MULF");
26439 gen_reserved_instruction(ctx);
26440 break;
26441 case OPC_MXU_D16MULE:
26442 /* TODO: Implement emulation of D16MULE instruction. */
26443 MIPS_INVAL("OPC_MXU_D16MULE");
26444 gen_reserved_instruction(ctx);
26445 break;
26446 default:
26447 MIPS_INVAL("decode_opc_mxu");
26448 gen_reserved_instruction(ctx);
26449 break;
26455 * Decode MXU pool04
26457 * 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
26458 * +-----------+---------+-+-------------------+-------+-----------+
26459 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL04|
26460 * +-----------+---------+-+-------------------+-------+-----------+
26463 static void decode_opc_mxu__pool04(CPUMIPSState *env, DisasContext *ctx)
26465 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26467 switch (opcode) {
26468 case OPC_MXU_S32LDD:
26469 case OPC_MXU_S32LDDR:
26470 gen_mxu_s32ldd_s32lddr(ctx);
26471 break;
26472 default:
26473 MIPS_INVAL("decode_opc_mxu");
26474 gen_reserved_instruction(ctx);
26475 break;
26481 * Decode MXU pool05
26483 * 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
26484 * +-----------+---------+-+-------------------+-------+-----------+
26485 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL05|
26486 * +-----------+---------+-+-------------------+-------+-----------+
26489 static void decode_opc_mxu__pool05(CPUMIPSState *env, DisasContext *ctx)
26491 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26493 switch (opcode) {
26494 case OPC_MXU_S32STD:
26495 /* TODO: Implement emulation of S32STD instruction. */
26496 MIPS_INVAL("OPC_MXU_S32STD");
26497 gen_reserved_instruction(ctx);
26498 break;
26499 case OPC_MXU_S32STDR:
26500 /* TODO: Implement emulation of S32STDR instruction. */
26501 MIPS_INVAL("OPC_MXU_S32STDR");
26502 gen_reserved_instruction(ctx);
26503 break;
26504 default:
26505 MIPS_INVAL("decode_opc_mxu");
26506 gen_reserved_instruction(ctx);
26507 break;
26513 * Decode MXU pool06
26515 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26516 * +-----------+---------+---------+---+-------+-------+-----------+
26517 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL06|
26518 * +-----------+---------+---------+---+-------+-------+-----------+
26521 static void decode_opc_mxu__pool06(CPUMIPSState *env, DisasContext *ctx)
26523 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26525 switch (opcode) {
26526 case OPC_MXU_S32LDDV:
26527 /* TODO: Implement emulation of S32LDDV instruction. */
26528 MIPS_INVAL("OPC_MXU_S32LDDV");
26529 gen_reserved_instruction(ctx);
26530 break;
26531 case OPC_MXU_S32LDDVR:
26532 /* TODO: Implement emulation of S32LDDVR instruction. */
26533 MIPS_INVAL("OPC_MXU_S32LDDVR");
26534 gen_reserved_instruction(ctx);
26535 break;
26536 default:
26537 MIPS_INVAL("decode_opc_mxu");
26538 gen_reserved_instruction(ctx);
26539 break;
26545 * Decode MXU pool07
26547 * 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
26548 * +-----------+---------+---------+---+-------+-------+-----------+
26549 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL07|
26550 * +-----------+---------+---------+---+-------+-------+-----------+
26553 static void decode_opc_mxu__pool07(CPUMIPSState *env, DisasContext *ctx)
26555 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26557 switch (opcode) {
26558 case OPC_MXU_S32STDV:
26559 /* TODO: Implement emulation of S32TDV instruction. */
26560 MIPS_INVAL("OPC_MXU_S32TDV");
26561 gen_reserved_instruction(ctx);
26562 break;
26563 case OPC_MXU_S32STDVR:
26564 /* TODO: Implement emulation of S32TDVR instruction. */
26565 MIPS_INVAL("OPC_MXU_S32TDVR");
26566 gen_reserved_instruction(ctx);
26567 break;
26568 default:
26569 MIPS_INVAL("decode_opc_mxu");
26570 gen_reserved_instruction(ctx);
26571 break;
26577 * Decode MXU pool08
26579 * 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
26580 * +-----------+---------+-+-------------------+-------+-----------+
26581 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL08|
26582 * +-----------+---------+-+-------------------+-------+-----------+
26585 static void decode_opc_mxu__pool08(CPUMIPSState *env, DisasContext *ctx)
26587 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26589 switch (opcode) {
26590 case OPC_MXU_S32LDI:
26591 /* TODO: Implement emulation of S32LDI instruction. */
26592 MIPS_INVAL("OPC_MXU_S32LDI");
26593 gen_reserved_instruction(ctx);
26594 break;
26595 case OPC_MXU_S32LDIR:
26596 /* TODO: Implement emulation of S32LDIR instruction. */
26597 MIPS_INVAL("OPC_MXU_S32LDIR");
26598 gen_reserved_instruction(ctx);
26599 break;
26600 default:
26601 MIPS_INVAL("decode_opc_mxu");
26602 gen_reserved_instruction(ctx);
26603 break;
26609 * Decode MXU pool09
26611 * 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
26612 * +-----------+---------+-+-------------------+-------+-----------+
26613 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL09|
26614 * +-----------+---------+-+-------------------+-------+-----------+
26617 static void decode_opc_mxu__pool09(CPUMIPSState *env, DisasContext *ctx)
26619 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26621 switch (opcode) {
26622 case OPC_MXU_S32SDI:
26623 /* TODO: Implement emulation of S32SDI instruction. */
26624 MIPS_INVAL("OPC_MXU_S32SDI");
26625 gen_reserved_instruction(ctx);
26626 break;
26627 case OPC_MXU_S32SDIR:
26628 /* TODO: Implement emulation of S32SDIR instruction. */
26629 MIPS_INVAL("OPC_MXU_S32SDIR");
26630 gen_reserved_instruction(ctx);
26631 break;
26632 default:
26633 MIPS_INVAL("decode_opc_mxu");
26634 gen_reserved_instruction(ctx);
26635 break;
26641 * Decode MXU pool10
26643 * 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
26644 * +-----------+---------+---------+---+-------+-------+-----------+
26645 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL10|
26646 * +-----------+---------+---------+---+-------+-------+-----------+
26649 static void decode_opc_mxu__pool10(CPUMIPSState *env, DisasContext *ctx)
26651 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26653 switch (opcode) {
26654 case OPC_MXU_S32LDIV:
26655 /* TODO: Implement emulation of S32LDIV instruction. */
26656 MIPS_INVAL("OPC_MXU_S32LDIV");
26657 gen_reserved_instruction(ctx);
26658 break;
26659 case OPC_MXU_S32LDIVR:
26660 /* TODO: Implement emulation of S32LDIVR instruction. */
26661 MIPS_INVAL("OPC_MXU_S32LDIVR");
26662 gen_reserved_instruction(ctx);
26663 break;
26664 default:
26665 MIPS_INVAL("decode_opc_mxu");
26666 gen_reserved_instruction(ctx);
26667 break;
26673 * Decode MXU pool11
26675 * 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
26676 * +-----------+---------+---------+---+-------+-------+-----------+
26677 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL11|
26678 * +-----------+---------+---------+---+-------+-------+-----------+
26681 static void decode_opc_mxu__pool11(CPUMIPSState *env, DisasContext *ctx)
26683 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26685 switch (opcode) {
26686 case OPC_MXU_S32SDIV:
26687 /* TODO: Implement emulation of S32SDIV instruction. */
26688 MIPS_INVAL("OPC_MXU_S32SDIV");
26689 gen_reserved_instruction(ctx);
26690 break;
26691 case OPC_MXU_S32SDIVR:
26692 /* TODO: Implement emulation of S32SDIVR instruction. */
26693 MIPS_INVAL("OPC_MXU_S32SDIVR");
26694 gen_reserved_instruction(ctx);
26695 break;
26696 default:
26697 MIPS_INVAL("decode_opc_mxu");
26698 gen_reserved_instruction(ctx);
26699 break;
26705 * Decode MXU pool12
26707 * 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
26708 * +-----------+---+---+-------+-------+-------+-------+-----------+
26709 * | SPECIAL2 |an2|x x| Xd | XRc | XRb | XRa |MXU__POOL12|
26710 * +-----------+---+---+-------+-------+-------+-------+-----------+
26713 static void decode_opc_mxu__pool12(CPUMIPSState *env, DisasContext *ctx)
26715 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26717 switch (opcode) {
26718 case OPC_MXU_D32ACC:
26719 /* TODO: Implement emulation of D32ACC instruction. */
26720 MIPS_INVAL("OPC_MXU_D32ACC");
26721 gen_reserved_instruction(ctx);
26722 break;
26723 case OPC_MXU_D32ACCM:
26724 /* TODO: Implement emulation of D32ACCM instruction. */
26725 MIPS_INVAL("OPC_MXU_D32ACCM");
26726 gen_reserved_instruction(ctx);
26727 break;
26728 case OPC_MXU_D32ASUM:
26729 /* TODO: Implement emulation of D32ASUM instruction. */
26730 MIPS_INVAL("OPC_MXU_D32ASUM");
26731 gen_reserved_instruction(ctx);
26732 break;
26733 default:
26734 MIPS_INVAL("decode_opc_mxu");
26735 gen_reserved_instruction(ctx);
26736 break;
26742 * Decode MXU pool13
26744 * 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
26745 * +-----------+---+---+-------+-------+-------+-------+-----------+
26746 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL13|
26747 * +-----------+---+---+-------+-------+-------+-------+-----------+
26750 static void decode_opc_mxu__pool13(CPUMIPSState *env, DisasContext *ctx)
26752 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26754 switch (opcode) {
26755 case OPC_MXU_Q16ACC:
26756 /* TODO: Implement emulation of Q16ACC instruction. */
26757 MIPS_INVAL("OPC_MXU_Q16ACC");
26758 gen_reserved_instruction(ctx);
26759 break;
26760 case OPC_MXU_Q16ACCM:
26761 /* TODO: Implement emulation of Q16ACCM instruction. */
26762 MIPS_INVAL("OPC_MXU_Q16ACCM");
26763 gen_reserved_instruction(ctx);
26764 break;
26765 case OPC_MXU_Q16ASUM:
26766 /* TODO: Implement emulation of Q16ASUM instruction. */
26767 MIPS_INVAL("OPC_MXU_Q16ASUM");
26768 gen_reserved_instruction(ctx);
26769 break;
26770 default:
26771 MIPS_INVAL("decode_opc_mxu");
26772 gen_reserved_instruction(ctx);
26773 break;
26779 * Decode MXU pool14
26781 * Q8ADDE, Q8ACCE:
26782 * 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
26783 * +-----------+---+---+-------+-------+-------+-------+-----------+
26784 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL14|
26785 * +-----------+---+---+-------+-------+-------+-------+-----------+
26787 * D8SUM, D8SUMC:
26788 * 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
26789 * +-----------+---+---+-------+-------+-------+-------+-----------+
26790 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL14|
26791 * +-----------+---+---+-------+-------+-------+-------+-----------+
26794 static void decode_opc_mxu__pool14(CPUMIPSState *env, DisasContext *ctx)
26796 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26798 switch (opcode) {
26799 case OPC_MXU_Q8ADDE:
26800 /* TODO: Implement emulation of Q8ADDE instruction. */
26801 MIPS_INVAL("OPC_MXU_Q8ADDE");
26802 gen_reserved_instruction(ctx);
26803 break;
26804 case OPC_MXU_D8SUM:
26805 /* TODO: Implement emulation of D8SUM instruction. */
26806 MIPS_INVAL("OPC_MXU_D8SUM");
26807 gen_reserved_instruction(ctx);
26808 break;
26809 case OPC_MXU_D8SUMC:
26810 /* TODO: Implement emulation of D8SUMC instruction. */
26811 MIPS_INVAL("OPC_MXU_D8SUMC");
26812 gen_reserved_instruction(ctx);
26813 break;
26814 default:
26815 MIPS_INVAL("decode_opc_mxu");
26816 gen_reserved_instruction(ctx);
26817 break;
26823 * Decode MXU pool15
26825 * S32MUL, S32MULU, S32EXTRV:
26826 * 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
26827 * +-----------+---------+---------+---+-------+-------+-----------+
26828 * | SPECIAL2 | rs | rt |x x| XRd | XRa |MXU__POOL15|
26829 * +-----------+---------+---------+---+-------+-------+-----------+
26831 * S32EXTR:
26832 * 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
26833 * +-----------+---------+---------+---+-------+-------+-----------+
26834 * | SPECIAL2 | rb | sft5 |x x| XRd | XRa |MXU__POOL15|
26835 * +-----------+---------+---------+---+-------+-------+-----------+
26838 static void decode_opc_mxu__pool15(CPUMIPSState *env, DisasContext *ctx)
26840 uint32_t opcode = extract32(ctx->opcode, 14, 2);
26842 switch (opcode) {
26843 case OPC_MXU_S32MUL:
26844 /* TODO: Implement emulation of S32MUL instruction. */
26845 MIPS_INVAL("OPC_MXU_S32MUL");
26846 gen_reserved_instruction(ctx);
26847 break;
26848 case OPC_MXU_S32MULU:
26849 /* TODO: Implement emulation of S32MULU instruction. */
26850 MIPS_INVAL("OPC_MXU_S32MULU");
26851 gen_reserved_instruction(ctx);
26852 break;
26853 case OPC_MXU_S32EXTR:
26854 /* TODO: Implement emulation of S32EXTR instruction. */
26855 MIPS_INVAL("OPC_MXU_S32EXTR");
26856 gen_reserved_instruction(ctx);
26857 break;
26858 case OPC_MXU_S32EXTRV:
26859 /* TODO: Implement emulation of S32EXTRV instruction. */
26860 MIPS_INVAL("OPC_MXU_S32EXTRV");
26861 gen_reserved_instruction(ctx);
26862 break;
26863 default:
26864 MIPS_INVAL("decode_opc_mxu");
26865 gen_reserved_instruction(ctx);
26866 break;
26872 * Decode MXU pool16
26874 * D32SARW:
26875 * 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
26876 * +-----------+---------+-----+-------+-------+-------+-----------+
26877 * | SPECIAL2 | rb |x x x| XRc | XRb | XRa |MXU__POOL16|
26878 * +-----------+---------+-----+-------+-------+-------+-----------+
26880 * S32ALN:
26881 * 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
26882 * +-----------+---------+-----+-------+-------+-------+-----------+
26883 * | SPECIAL2 | rs |x x x| XRc | XRb | XRa |MXU__POOL16|
26884 * +-----------+---------+-----+-------+-------+-------+-----------+
26886 * S32ALNI:
26887 * 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
26888 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26889 * | SPECIAL2 | s3 |0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26890 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26892 * S32LUI:
26893 * 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
26894 * +-----------+-----+---+-----+-------+---------------+-----------+
26895 * | SPECIAL2 |optn3|0 0|x x x| XRc | s8 |MXU__POOL16|
26896 * +-----------+-----+---+-----+-------+---------------+-----------+
26898 * S32NOR, S32AND, S32OR, S32XOR:
26899 * 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
26900 * +-----------+---------+-----+-------+-------+-------+-----------+
26901 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26902 * +-----------+---------+-----+-------+-------+-------+-----------+
26905 static void decode_opc_mxu__pool16(CPUMIPSState *env, DisasContext *ctx)
26907 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26909 switch (opcode) {
26910 case OPC_MXU_D32SARW:
26911 /* TODO: Implement emulation of D32SARW instruction. */
26912 MIPS_INVAL("OPC_MXU_D32SARW");
26913 gen_reserved_instruction(ctx);
26914 break;
26915 case OPC_MXU_S32ALN:
26916 /* TODO: Implement emulation of S32ALN instruction. */
26917 MIPS_INVAL("OPC_MXU_S32ALN");
26918 gen_reserved_instruction(ctx);
26919 break;
26920 case OPC_MXU_S32ALNI:
26921 gen_mxu_S32ALNI(ctx);
26922 break;
26923 case OPC_MXU_S32LUI:
26924 /* TODO: Implement emulation of S32LUI instruction. */
26925 MIPS_INVAL("OPC_MXU_S32LUI");
26926 gen_reserved_instruction(ctx);
26927 break;
26928 case OPC_MXU_S32NOR:
26929 gen_mxu_S32NOR(ctx);
26930 break;
26931 case OPC_MXU_S32AND:
26932 gen_mxu_S32AND(ctx);
26933 break;
26934 case OPC_MXU_S32OR:
26935 gen_mxu_S32OR(ctx);
26936 break;
26937 case OPC_MXU_S32XOR:
26938 gen_mxu_S32XOR(ctx);
26939 break;
26940 default:
26941 MIPS_INVAL("decode_opc_mxu");
26942 gen_reserved_instruction(ctx);
26943 break;
26949 * Decode MXU pool17
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 | rt |0 0| rd |x x x|MXU__POOL15|
26954 * +-----------+---------+---------+---+---------+-----+-----------+
26957 static void decode_opc_mxu__pool17(CPUMIPSState *env, DisasContext *ctx)
26959 uint32_t opcode = extract32(ctx->opcode, 6, 2);
26961 switch (opcode) {
26962 case OPC_MXU_LXW:
26963 /* TODO: Implement emulation of LXW instruction. */
26964 MIPS_INVAL("OPC_MXU_LXW");
26965 gen_reserved_instruction(ctx);
26966 break;
26967 case OPC_MXU_LXH:
26968 /* TODO: Implement emulation of LXH instruction. */
26969 MIPS_INVAL("OPC_MXU_LXH");
26970 gen_reserved_instruction(ctx);
26971 break;
26972 case OPC_MXU_LXHU:
26973 /* TODO: Implement emulation of LXHU instruction. */
26974 MIPS_INVAL("OPC_MXU_LXHU");
26975 gen_reserved_instruction(ctx);
26976 break;
26977 case OPC_MXU_LXB:
26978 /* TODO: Implement emulation of LXB instruction. */
26979 MIPS_INVAL("OPC_MXU_LXB");
26980 gen_reserved_instruction(ctx);
26981 break;
26982 case OPC_MXU_LXBU:
26983 /* TODO: Implement emulation of LXBU instruction. */
26984 MIPS_INVAL("OPC_MXU_LXBU");
26985 gen_reserved_instruction(ctx);
26986 break;
26987 default:
26988 MIPS_INVAL("decode_opc_mxu");
26989 gen_reserved_instruction(ctx);
26990 break;
26995 * Decode MXU pool18
26997 * 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
26998 * +-----------+---------+-----+-------+-------+-------+-----------+
26999 * | SPECIAL2 | rb |x x x| XRd | XRa |0 0 0 0|MXU__POOL18|
27000 * +-----------+---------+-----+-------+-------+-------+-----------+
27003 static void decode_opc_mxu__pool18(CPUMIPSState *env, DisasContext *ctx)
27005 uint32_t opcode = extract32(ctx->opcode, 18, 3);
27007 switch (opcode) {
27008 case OPC_MXU_D32SLLV:
27009 /* TODO: Implement emulation of D32SLLV instruction. */
27010 MIPS_INVAL("OPC_MXU_D32SLLV");
27011 gen_reserved_instruction(ctx);
27012 break;
27013 case OPC_MXU_D32SLRV:
27014 /* TODO: Implement emulation of D32SLRV instruction. */
27015 MIPS_INVAL("OPC_MXU_D32SLRV");
27016 gen_reserved_instruction(ctx);
27017 break;
27018 case OPC_MXU_D32SARV:
27019 /* TODO: Implement emulation of D32SARV instruction. */
27020 MIPS_INVAL("OPC_MXU_D32SARV");
27021 gen_reserved_instruction(ctx);
27022 break;
27023 case OPC_MXU_Q16SLLV:
27024 /* TODO: Implement emulation of Q16SLLV instruction. */
27025 MIPS_INVAL("OPC_MXU_Q16SLLV");
27026 gen_reserved_instruction(ctx);
27027 break;
27028 case OPC_MXU_Q16SLRV:
27029 /* TODO: Implement emulation of Q16SLRV instruction. */
27030 MIPS_INVAL("OPC_MXU_Q16SLRV");
27031 gen_reserved_instruction(ctx);
27032 break;
27033 case OPC_MXU_Q16SARV:
27034 /* TODO: Implement emulation of Q16SARV instruction. */
27035 MIPS_INVAL("OPC_MXU_Q16SARV");
27036 gen_reserved_instruction(ctx);
27037 break;
27038 default:
27039 MIPS_INVAL("decode_opc_mxu");
27040 gen_reserved_instruction(ctx);
27041 break;
27047 * Decode MXU pool19
27049 * 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
27050 * +-----------+---+---+-------+-------+-------+-------+-----------+
27051 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL19|
27052 * +-----------+---+---+-------+-------+-------+-------+-----------+
27055 static void decode_opc_mxu__pool19(CPUMIPSState *env, DisasContext *ctx)
27057 uint32_t opcode = extract32(ctx->opcode, 22, 2);
27059 switch (opcode) {
27060 case OPC_MXU_Q8MUL:
27061 case OPC_MXU_Q8MULSU:
27062 gen_mxu_q8mul_q8mulsu(ctx);
27063 break;
27064 default:
27065 MIPS_INVAL("decode_opc_mxu");
27066 gen_reserved_instruction(ctx);
27067 break;
27073 * Decode MXU pool20
27075 * 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
27076 * +-----------+---------+-----+-------+-------+-------+-----------+
27077 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL20|
27078 * +-----------+---------+-----+-------+-------+-------+-----------+
27081 static void decode_opc_mxu__pool20(CPUMIPSState *env, DisasContext *ctx)
27083 uint32_t opcode = extract32(ctx->opcode, 18, 3);
27085 switch (opcode) {
27086 case OPC_MXU_Q8MOVZ:
27087 /* TODO: Implement emulation of Q8MOVZ instruction. */
27088 MIPS_INVAL("OPC_MXU_Q8MOVZ");
27089 gen_reserved_instruction(ctx);
27090 break;
27091 case OPC_MXU_Q8MOVN:
27092 /* TODO: Implement emulation of Q8MOVN instruction. */
27093 MIPS_INVAL("OPC_MXU_Q8MOVN");
27094 gen_reserved_instruction(ctx);
27095 break;
27096 case OPC_MXU_D16MOVZ:
27097 /* TODO: Implement emulation of D16MOVZ instruction. */
27098 MIPS_INVAL("OPC_MXU_D16MOVZ");
27099 gen_reserved_instruction(ctx);
27100 break;
27101 case OPC_MXU_D16MOVN:
27102 /* TODO: Implement emulation of D16MOVN instruction. */
27103 MIPS_INVAL("OPC_MXU_D16MOVN");
27104 gen_reserved_instruction(ctx);
27105 break;
27106 case OPC_MXU_S32MOVZ:
27107 /* TODO: Implement emulation of S32MOVZ instruction. */
27108 MIPS_INVAL("OPC_MXU_S32MOVZ");
27109 gen_reserved_instruction(ctx);
27110 break;
27111 case OPC_MXU_S32MOVN:
27112 /* TODO: Implement emulation of S32MOVN instruction. */
27113 MIPS_INVAL("OPC_MXU_S32MOVN");
27114 gen_reserved_instruction(ctx);
27115 break;
27116 default:
27117 MIPS_INVAL("decode_opc_mxu");
27118 gen_reserved_instruction(ctx);
27119 break;
27125 * Decode MXU pool21
27127 * 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
27128 * +-----------+---+---+-------+-------+-------+-------+-----------+
27129 * | SPECIAL2 |an2|x x| XRd | XRc | XRb | XRa |MXU__POOL21|
27130 * +-----------+---+---+-------+-------+-------+-------+-----------+
27133 static void decode_opc_mxu__pool21(CPUMIPSState *env, DisasContext *ctx)
27135 uint32_t opcode = extract32(ctx->opcode, 22, 2);
27137 switch (opcode) {
27138 case OPC_MXU_Q8MAC:
27139 /* TODO: Implement emulation of Q8MAC instruction. */
27140 MIPS_INVAL("OPC_MXU_Q8MAC");
27141 gen_reserved_instruction(ctx);
27142 break;
27143 case OPC_MXU_Q8MACSU:
27144 /* TODO: Implement emulation of Q8MACSU instruction. */
27145 MIPS_INVAL("OPC_MXU_Q8MACSU");
27146 gen_reserved_instruction(ctx);
27147 break;
27148 default:
27149 MIPS_INVAL("decode_opc_mxu");
27150 gen_reserved_instruction(ctx);
27151 break;
27157 * Main MXU decoding function
27159 * 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
27160 * +-----------+---------------------------------------+-----------+
27161 * | SPECIAL2 | |x x x x x x|
27162 * +-----------+---------------------------------------+-----------+
27165 static void decode_opc_mxu(CPUMIPSState *env, DisasContext *ctx)
27168 * TODO: Investigate necessity of including handling of
27169 * CLZ, CLO, SDBB in this function, as they belong to
27170 * SPECIAL2 opcode space for regular pre-R6 MIPS ISAs.
27172 uint32_t opcode = extract32(ctx->opcode, 0, 6);
27174 if (opcode == OPC__MXU_MUL) {
27175 uint32_t rs, rt, rd, op1;
27177 rs = extract32(ctx->opcode, 21, 5);
27178 rt = extract32(ctx->opcode, 16, 5);
27179 rd = extract32(ctx->opcode, 11, 5);
27180 op1 = MASK_SPECIAL2(ctx->opcode);
27182 gen_arith(ctx, op1, rd, rs, rt);
27184 return;
27187 if (opcode == OPC_MXU_S32M2I) {
27188 gen_mxu_s32m2i(ctx);
27189 return;
27192 if (opcode == OPC_MXU_S32I2M) {
27193 gen_mxu_s32i2m(ctx);
27194 return;
27198 TCGv t_mxu_cr = tcg_temp_new();
27199 TCGLabel *l_exit = gen_new_label();
27201 gen_load_mxu_cr(t_mxu_cr);
27202 tcg_gen_andi_tl(t_mxu_cr, t_mxu_cr, MXU_CR_MXU_EN);
27203 tcg_gen_brcondi_tl(TCG_COND_NE, t_mxu_cr, MXU_CR_MXU_EN, l_exit);
27205 switch (opcode) {
27206 case OPC_MXU_S32MADD:
27207 /* TODO: Implement emulation of S32MADD instruction. */
27208 MIPS_INVAL("OPC_MXU_S32MADD");
27209 gen_reserved_instruction(ctx);
27210 break;
27211 case OPC_MXU_S32MADDU:
27212 /* TODO: Implement emulation of S32MADDU instruction. */
27213 MIPS_INVAL("OPC_MXU_S32MADDU");
27214 gen_reserved_instruction(ctx);
27215 break;
27216 case OPC_MXU__POOL00:
27217 decode_opc_mxu__pool00(env, ctx);
27218 break;
27219 case OPC_MXU_S32MSUB:
27220 /* TODO: Implement emulation of S32MSUB instruction. */
27221 MIPS_INVAL("OPC_MXU_S32MSUB");
27222 gen_reserved_instruction(ctx);
27223 break;
27224 case OPC_MXU_S32MSUBU:
27225 /* TODO: Implement emulation of S32MSUBU instruction. */
27226 MIPS_INVAL("OPC_MXU_S32MSUBU");
27227 gen_reserved_instruction(ctx);
27228 break;
27229 case OPC_MXU__POOL01:
27230 decode_opc_mxu__pool01(env, ctx);
27231 break;
27232 case OPC_MXU__POOL02:
27233 decode_opc_mxu__pool02(env, ctx);
27234 break;
27235 case OPC_MXU_D16MUL:
27236 gen_mxu_d16mul(ctx);
27237 break;
27238 case OPC_MXU__POOL03:
27239 decode_opc_mxu__pool03(env, ctx);
27240 break;
27241 case OPC_MXU_D16MAC:
27242 gen_mxu_d16mac(ctx);
27243 break;
27244 case OPC_MXU_D16MACF:
27245 /* TODO: Implement emulation of D16MACF instruction. */
27246 MIPS_INVAL("OPC_MXU_D16MACF");
27247 gen_reserved_instruction(ctx);
27248 break;
27249 case OPC_MXU_D16MADL:
27250 /* TODO: Implement emulation of D16MADL instruction. */
27251 MIPS_INVAL("OPC_MXU_D16MADL");
27252 gen_reserved_instruction(ctx);
27253 break;
27254 case OPC_MXU_S16MAD:
27255 /* TODO: Implement emulation of S16MAD instruction. */
27256 MIPS_INVAL("OPC_MXU_S16MAD");
27257 gen_reserved_instruction(ctx);
27258 break;
27259 case OPC_MXU_Q16ADD:
27260 /* TODO: Implement emulation of Q16ADD instruction. */
27261 MIPS_INVAL("OPC_MXU_Q16ADD");
27262 gen_reserved_instruction(ctx);
27263 break;
27264 case OPC_MXU_D16MACE:
27265 /* TODO: Implement emulation of D16MACE instruction. */
27266 MIPS_INVAL("OPC_MXU_D16MACE");
27267 gen_reserved_instruction(ctx);
27268 break;
27269 case OPC_MXU__POOL04:
27270 decode_opc_mxu__pool04(env, ctx);
27271 break;
27272 case OPC_MXU__POOL05:
27273 decode_opc_mxu__pool05(env, ctx);
27274 break;
27275 case OPC_MXU__POOL06:
27276 decode_opc_mxu__pool06(env, ctx);
27277 break;
27278 case OPC_MXU__POOL07:
27279 decode_opc_mxu__pool07(env, ctx);
27280 break;
27281 case OPC_MXU__POOL08:
27282 decode_opc_mxu__pool08(env, ctx);
27283 break;
27284 case OPC_MXU__POOL09:
27285 decode_opc_mxu__pool09(env, ctx);
27286 break;
27287 case OPC_MXU__POOL10:
27288 decode_opc_mxu__pool10(env, ctx);
27289 break;
27290 case OPC_MXU__POOL11:
27291 decode_opc_mxu__pool11(env, ctx);
27292 break;
27293 case OPC_MXU_D32ADD:
27294 /* TODO: Implement emulation of D32ADD instruction. */
27295 MIPS_INVAL("OPC_MXU_D32ADD");
27296 gen_reserved_instruction(ctx);
27297 break;
27298 case OPC_MXU__POOL12:
27299 decode_opc_mxu__pool12(env, ctx);
27300 break;
27301 case OPC_MXU__POOL13:
27302 decode_opc_mxu__pool13(env, ctx);
27303 break;
27304 case OPC_MXU__POOL14:
27305 decode_opc_mxu__pool14(env, ctx);
27306 break;
27307 case OPC_MXU_Q8ACCE:
27308 /* TODO: Implement emulation of Q8ACCE instruction. */
27309 MIPS_INVAL("OPC_MXU_Q8ACCE");
27310 gen_reserved_instruction(ctx);
27311 break;
27312 case OPC_MXU_S8LDD:
27313 gen_mxu_s8ldd(ctx);
27314 break;
27315 case OPC_MXU_S8STD:
27316 /* TODO: Implement emulation of S8STD instruction. */
27317 MIPS_INVAL("OPC_MXU_S8STD");
27318 gen_reserved_instruction(ctx);
27319 break;
27320 case OPC_MXU_S8LDI:
27321 /* TODO: Implement emulation of S8LDI instruction. */
27322 MIPS_INVAL("OPC_MXU_S8LDI");
27323 gen_reserved_instruction(ctx);
27324 break;
27325 case OPC_MXU_S8SDI:
27326 /* TODO: Implement emulation of S8SDI instruction. */
27327 MIPS_INVAL("OPC_MXU_S8SDI");
27328 gen_reserved_instruction(ctx);
27329 break;
27330 case OPC_MXU__POOL15:
27331 decode_opc_mxu__pool15(env, ctx);
27332 break;
27333 case OPC_MXU__POOL16:
27334 decode_opc_mxu__pool16(env, ctx);
27335 break;
27336 case OPC_MXU__POOL17:
27337 decode_opc_mxu__pool17(env, ctx);
27338 break;
27339 case OPC_MXU_S16LDD:
27340 /* TODO: Implement emulation of S16LDD instruction. */
27341 MIPS_INVAL("OPC_MXU_S16LDD");
27342 gen_reserved_instruction(ctx);
27343 break;
27344 case OPC_MXU_S16STD:
27345 /* TODO: Implement emulation of S16STD instruction. */
27346 MIPS_INVAL("OPC_MXU_S16STD");
27347 gen_reserved_instruction(ctx);
27348 break;
27349 case OPC_MXU_S16LDI:
27350 /* TODO: Implement emulation of S16LDI instruction. */
27351 MIPS_INVAL("OPC_MXU_S16LDI");
27352 gen_reserved_instruction(ctx);
27353 break;
27354 case OPC_MXU_S16SDI:
27355 /* TODO: Implement emulation of S16SDI instruction. */
27356 MIPS_INVAL("OPC_MXU_S16SDI");
27357 gen_reserved_instruction(ctx);
27358 break;
27359 case OPC_MXU_D32SLL:
27360 /* TODO: Implement emulation of D32SLL instruction. */
27361 MIPS_INVAL("OPC_MXU_D32SLL");
27362 gen_reserved_instruction(ctx);
27363 break;
27364 case OPC_MXU_D32SLR:
27365 /* TODO: Implement emulation of D32SLR instruction. */
27366 MIPS_INVAL("OPC_MXU_D32SLR");
27367 gen_reserved_instruction(ctx);
27368 break;
27369 case OPC_MXU_D32SARL:
27370 /* TODO: Implement emulation of D32SARL instruction. */
27371 MIPS_INVAL("OPC_MXU_D32SARL");
27372 gen_reserved_instruction(ctx);
27373 break;
27374 case OPC_MXU_D32SAR:
27375 /* TODO: Implement emulation of D32SAR instruction. */
27376 MIPS_INVAL("OPC_MXU_D32SAR");
27377 gen_reserved_instruction(ctx);
27378 break;
27379 case OPC_MXU_Q16SLL:
27380 /* TODO: Implement emulation of Q16SLL instruction. */
27381 MIPS_INVAL("OPC_MXU_Q16SLL");
27382 gen_reserved_instruction(ctx);
27383 break;
27384 case OPC_MXU_Q16SLR:
27385 /* TODO: Implement emulation of Q16SLR instruction. */
27386 MIPS_INVAL("OPC_MXU_Q16SLR");
27387 gen_reserved_instruction(ctx);
27388 break;
27389 case OPC_MXU__POOL18:
27390 decode_opc_mxu__pool18(env, ctx);
27391 break;
27392 case OPC_MXU_Q16SAR:
27393 /* TODO: Implement emulation of Q16SAR instruction. */
27394 MIPS_INVAL("OPC_MXU_Q16SAR");
27395 gen_reserved_instruction(ctx);
27396 break;
27397 case OPC_MXU__POOL19:
27398 decode_opc_mxu__pool19(env, ctx);
27399 break;
27400 case OPC_MXU__POOL20:
27401 decode_opc_mxu__pool20(env, ctx);
27402 break;
27403 case OPC_MXU__POOL21:
27404 decode_opc_mxu__pool21(env, ctx);
27405 break;
27406 case OPC_MXU_Q16SCOP:
27407 /* TODO: Implement emulation of Q16SCOP instruction. */
27408 MIPS_INVAL("OPC_MXU_Q16SCOP");
27409 gen_reserved_instruction(ctx);
27410 break;
27411 case OPC_MXU_Q8MADL:
27412 /* TODO: Implement emulation of Q8MADL instruction. */
27413 MIPS_INVAL("OPC_MXU_Q8MADL");
27414 gen_reserved_instruction(ctx);
27415 break;
27416 case OPC_MXU_S32SFL:
27417 /* TODO: Implement emulation of S32SFL instruction. */
27418 MIPS_INVAL("OPC_MXU_S32SFL");
27419 gen_reserved_instruction(ctx);
27420 break;
27421 case OPC_MXU_Q8SAD:
27422 /* TODO: Implement emulation of Q8SAD instruction. */
27423 MIPS_INVAL("OPC_MXU_Q8SAD");
27424 gen_reserved_instruction(ctx);
27425 break;
27426 default:
27427 MIPS_INVAL("decode_opc_mxu");
27428 gen_reserved_instruction(ctx);
27431 gen_set_label(l_exit);
27432 tcg_temp_free(t_mxu_cr);
27436 #endif /* !defined(TARGET_MIPS64) */
27439 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
27441 int rs, rt, rd;
27442 uint32_t op1;
27444 check_insn_opc_removed(ctx, ISA_MIPS_R6);
27446 rs = (ctx->opcode >> 21) & 0x1f;
27447 rt = (ctx->opcode >> 16) & 0x1f;
27448 rd = (ctx->opcode >> 11) & 0x1f;
27450 op1 = MASK_SPECIAL2(ctx->opcode);
27451 switch (op1) {
27452 case OPC_MADD: /* Multiply and add/sub */
27453 case OPC_MADDU:
27454 case OPC_MSUB:
27455 case OPC_MSUBU:
27456 check_insn(ctx, ISA_MIPS_R1);
27457 gen_muldiv(ctx, op1, rd & 3, rs, rt);
27458 break;
27459 case OPC_MUL:
27460 gen_arith(ctx, op1, rd, rs, rt);
27461 break;
27462 case OPC_DIV_G_2F:
27463 case OPC_DIVU_G_2F:
27464 case OPC_MULT_G_2F:
27465 case OPC_MULTU_G_2F:
27466 case OPC_MOD_G_2F:
27467 case OPC_MODU_G_2F:
27468 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
27469 gen_loongson_integer(ctx, op1, rd, rs, rt);
27470 break;
27471 case OPC_CLO:
27472 case OPC_CLZ:
27473 check_insn(ctx, ISA_MIPS_R1);
27474 gen_cl(ctx, op1, rd, rs);
27475 break;
27476 case OPC_SDBBP:
27477 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
27478 gen_helper_do_semihosting(cpu_env);
27479 } else {
27481 * XXX: not clear which exception should be raised
27482 * when in debug mode...
27484 check_insn(ctx, ISA_MIPS_R1);
27485 generate_exception_end(ctx, EXCP_DBp);
27487 break;
27488 #if defined(TARGET_MIPS64)
27489 case OPC_DCLO:
27490 case OPC_DCLZ:
27491 check_insn(ctx, ISA_MIPS_R1);
27492 check_mips_64(ctx);
27493 gen_cl(ctx, op1, rd, rs);
27494 break;
27495 case OPC_DMULT_G_2F:
27496 case OPC_DMULTU_G_2F:
27497 case OPC_DDIV_G_2F:
27498 case OPC_DDIVU_G_2F:
27499 case OPC_DMOD_G_2F:
27500 case OPC_DMODU_G_2F:
27501 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
27502 gen_loongson_integer(ctx, op1, rd, rs, rt);
27503 break;
27504 #endif
27505 default: /* Invalid */
27506 MIPS_INVAL("special2_legacy");
27507 gen_reserved_instruction(ctx);
27508 break;
27512 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
27514 int rs, rt, rd, sa;
27515 uint32_t op1, op2;
27516 int16_t imm;
27518 rs = (ctx->opcode >> 21) & 0x1f;
27519 rt = (ctx->opcode >> 16) & 0x1f;
27520 rd = (ctx->opcode >> 11) & 0x1f;
27521 sa = (ctx->opcode >> 6) & 0x1f;
27522 imm = (int16_t)ctx->opcode >> 7;
27524 op1 = MASK_SPECIAL3(ctx->opcode);
27525 switch (op1) {
27526 case R6_OPC_PREF:
27527 if (rt >= 24) {
27528 /* hint codes 24-31 are reserved and signal RI */
27529 gen_reserved_instruction(ctx);
27531 /* Treat as NOP. */
27532 break;
27533 case R6_OPC_CACHE:
27534 check_cp0_enabled(ctx);
27535 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
27536 gen_cache_operation(ctx, rt, rs, imm);
27538 break;
27539 case R6_OPC_SC:
27540 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
27541 break;
27542 case R6_OPC_LL:
27543 gen_ld(ctx, op1, rt, rs, imm);
27544 break;
27545 case OPC_BSHFL:
27547 if (rd == 0) {
27548 /* Treat as NOP. */
27549 break;
27551 op2 = MASK_BSHFL(ctx->opcode);
27552 switch (op2) {
27553 case OPC_ALIGN:
27554 case OPC_ALIGN_1:
27555 case OPC_ALIGN_2:
27556 case OPC_ALIGN_3:
27557 gen_align(ctx, 32, rd, rs, rt, sa & 3);
27558 break;
27559 case OPC_BITSWAP:
27560 gen_bitswap(ctx, op2, rd, rt);
27561 break;
27564 break;
27565 #ifndef CONFIG_USER_ONLY
27566 case OPC_GINV:
27567 if (unlikely(ctx->gi <= 1)) {
27568 gen_reserved_instruction(ctx);
27570 check_cp0_enabled(ctx);
27571 switch ((ctx->opcode >> 6) & 3) {
27572 case 0: /* GINVI */
27573 /* Treat as NOP. */
27574 break;
27575 case 2: /* GINVT */
27576 gen_helper_0e1i(ginvt, cpu_gpr[rs], extract32(ctx->opcode, 8, 2));
27577 break;
27578 default:
27579 gen_reserved_instruction(ctx);
27580 break;
27582 break;
27583 #endif
27584 #if defined(TARGET_MIPS64)
27585 case R6_OPC_SCD:
27586 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
27587 break;
27588 case R6_OPC_LLD:
27589 gen_ld(ctx, op1, rt, rs, imm);
27590 break;
27591 case OPC_DBSHFL:
27592 check_mips_64(ctx);
27594 if (rd == 0) {
27595 /* Treat as NOP. */
27596 break;
27598 op2 = MASK_DBSHFL(ctx->opcode);
27599 switch (op2) {
27600 case OPC_DALIGN:
27601 case OPC_DALIGN_1:
27602 case OPC_DALIGN_2:
27603 case OPC_DALIGN_3:
27604 case OPC_DALIGN_4:
27605 case OPC_DALIGN_5:
27606 case OPC_DALIGN_6:
27607 case OPC_DALIGN_7:
27608 gen_align(ctx, 64, rd, rs, rt, sa & 7);
27609 break;
27610 case OPC_DBITSWAP:
27611 gen_bitswap(ctx, op2, rd, rt);
27612 break;
27616 break;
27617 #endif
27618 default: /* Invalid */
27619 MIPS_INVAL("special3_r6");
27620 gen_reserved_instruction(ctx);
27621 break;
27625 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
27627 int rs, rt, rd;
27628 uint32_t op1, op2;
27630 rs = (ctx->opcode >> 21) & 0x1f;
27631 rt = (ctx->opcode >> 16) & 0x1f;
27632 rd = (ctx->opcode >> 11) & 0x1f;
27634 op1 = MASK_SPECIAL3(ctx->opcode);
27635 switch (op1) {
27636 case OPC_DIV_G_2E:
27637 case OPC_DIVU_G_2E:
27638 case OPC_MOD_G_2E:
27639 case OPC_MODU_G_2E:
27640 case OPC_MULT_G_2E:
27641 case OPC_MULTU_G_2E:
27643 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
27644 * the same mask and op1.
27646 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
27647 op2 = MASK_ADDUH_QB(ctx->opcode);
27648 switch (op2) {
27649 case OPC_ADDUH_QB:
27650 case OPC_ADDUH_R_QB:
27651 case OPC_ADDQH_PH:
27652 case OPC_ADDQH_R_PH:
27653 case OPC_ADDQH_W:
27654 case OPC_ADDQH_R_W:
27655 case OPC_SUBUH_QB:
27656 case OPC_SUBUH_R_QB:
27657 case OPC_SUBQH_PH:
27658 case OPC_SUBQH_R_PH:
27659 case OPC_SUBQH_W:
27660 case OPC_SUBQH_R_W:
27661 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27662 break;
27663 case OPC_MUL_PH:
27664 case OPC_MUL_S_PH:
27665 case OPC_MULQ_S_W:
27666 case OPC_MULQ_RS_W:
27667 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27668 break;
27669 default:
27670 MIPS_INVAL("MASK ADDUH.QB");
27671 gen_reserved_instruction(ctx);
27672 break;
27674 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
27675 gen_loongson_integer(ctx, op1, rd, rs, rt);
27676 } else {
27677 gen_reserved_instruction(ctx);
27679 break;
27680 case OPC_LX_DSP:
27681 op2 = MASK_LX(ctx->opcode);
27682 switch (op2) {
27683 #if defined(TARGET_MIPS64)
27684 case OPC_LDX:
27685 #endif
27686 case OPC_LBUX:
27687 case OPC_LHX:
27688 case OPC_LWX:
27689 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
27690 break;
27691 default: /* Invalid */
27692 MIPS_INVAL("MASK LX");
27693 gen_reserved_instruction(ctx);
27694 break;
27696 break;
27697 case OPC_ABSQ_S_PH_DSP:
27698 op2 = MASK_ABSQ_S_PH(ctx->opcode);
27699 switch (op2) {
27700 case OPC_ABSQ_S_QB:
27701 case OPC_ABSQ_S_PH:
27702 case OPC_ABSQ_S_W:
27703 case OPC_PRECEQ_W_PHL:
27704 case OPC_PRECEQ_W_PHR:
27705 case OPC_PRECEQU_PH_QBL:
27706 case OPC_PRECEQU_PH_QBR:
27707 case OPC_PRECEQU_PH_QBLA:
27708 case OPC_PRECEQU_PH_QBRA:
27709 case OPC_PRECEU_PH_QBL:
27710 case OPC_PRECEU_PH_QBR:
27711 case OPC_PRECEU_PH_QBLA:
27712 case OPC_PRECEU_PH_QBRA:
27713 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27714 break;
27715 case OPC_BITREV:
27716 case OPC_REPL_QB:
27717 case OPC_REPLV_QB:
27718 case OPC_REPL_PH:
27719 case OPC_REPLV_PH:
27720 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27721 break;
27722 default:
27723 MIPS_INVAL("MASK ABSQ_S.PH");
27724 gen_reserved_instruction(ctx);
27725 break;
27727 break;
27728 case OPC_ADDU_QB_DSP:
27729 op2 = MASK_ADDU_QB(ctx->opcode);
27730 switch (op2) {
27731 case OPC_ADDQ_PH:
27732 case OPC_ADDQ_S_PH:
27733 case OPC_ADDQ_S_W:
27734 case OPC_ADDU_QB:
27735 case OPC_ADDU_S_QB:
27736 case OPC_ADDU_PH:
27737 case OPC_ADDU_S_PH:
27738 case OPC_SUBQ_PH:
27739 case OPC_SUBQ_S_PH:
27740 case OPC_SUBQ_S_W:
27741 case OPC_SUBU_QB:
27742 case OPC_SUBU_S_QB:
27743 case OPC_SUBU_PH:
27744 case OPC_SUBU_S_PH:
27745 case OPC_ADDSC:
27746 case OPC_ADDWC:
27747 case OPC_MODSUB:
27748 case OPC_RADDU_W_QB:
27749 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27750 break;
27751 case OPC_MULEU_S_PH_QBL:
27752 case OPC_MULEU_S_PH_QBR:
27753 case OPC_MULQ_RS_PH:
27754 case OPC_MULEQ_S_W_PHL:
27755 case OPC_MULEQ_S_W_PHR:
27756 case OPC_MULQ_S_PH:
27757 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27758 break;
27759 default: /* Invalid */
27760 MIPS_INVAL("MASK ADDU.QB");
27761 gen_reserved_instruction(ctx);
27762 break;
27765 break;
27766 case OPC_CMPU_EQ_QB_DSP:
27767 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
27768 switch (op2) {
27769 case OPC_PRECR_SRA_PH_W:
27770 case OPC_PRECR_SRA_R_PH_W:
27771 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
27772 break;
27773 case OPC_PRECR_QB_PH:
27774 case OPC_PRECRQ_QB_PH:
27775 case OPC_PRECRQ_PH_W:
27776 case OPC_PRECRQ_RS_PH_W:
27777 case OPC_PRECRQU_S_QB_PH:
27778 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27779 break;
27780 case OPC_CMPU_EQ_QB:
27781 case OPC_CMPU_LT_QB:
27782 case OPC_CMPU_LE_QB:
27783 case OPC_CMP_EQ_PH:
27784 case OPC_CMP_LT_PH:
27785 case OPC_CMP_LE_PH:
27786 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
27787 break;
27788 case OPC_CMPGU_EQ_QB:
27789 case OPC_CMPGU_LT_QB:
27790 case OPC_CMPGU_LE_QB:
27791 case OPC_CMPGDU_EQ_QB:
27792 case OPC_CMPGDU_LT_QB:
27793 case OPC_CMPGDU_LE_QB:
27794 case OPC_PICK_QB:
27795 case OPC_PICK_PH:
27796 case OPC_PACKRL_PH:
27797 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27798 break;
27799 default: /* Invalid */
27800 MIPS_INVAL("MASK CMPU.EQ.QB");
27801 gen_reserved_instruction(ctx);
27802 break;
27804 break;
27805 case OPC_SHLL_QB_DSP:
27806 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27807 break;
27808 case OPC_DPA_W_PH_DSP:
27809 op2 = MASK_DPA_W_PH(ctx->opcode);
27810 switch (op2) {
27811 case OPC_DPAU_H_QBL:
27812 case OPC_DPAU_H_QBR:
27813 case OPC_DPSU_H_QBL:
27814 case OPC_DPSU_H_QBR:
27815 case OPC_DPA_W_PH:
27816 case OPC_DPAX_W_PH:
27817 case OPC_DPAQ_S_W_PH:
27818 case OPC_DPAQX_S_W_PH:
27819 case OPC_DPAQX_SA_W_PH:
27820 case OPC_DPS_W_PH:
27821 case OPC_DPSX_W_PH:
27822 case OPC_DPSQ_S_W_PH:
27823 case OPC_DPSQX_S_W_PH:
27824 case OPC_DPSQX_SA_W_PH:
27825 case OPC_MULSAQ_S_W_PH:
27826 case OPC_DPAQ_SA_L_W:
27827 case OPC_DPSQ_SA_L_W:
27828 case OPC_MAQ_S_W_PHL:
27829 case OPC_MAQ_S_W_PHR:
27830 case OPC_MAQ_SA_W_PHL:
27831 case OPC_MAQ_SA_W_PHR:
27832 case OPC_MULSA_W_PH:
27833 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27834 break;
27835 default: /* Invalid */
27836 MIPS_INVAL("MASK DPAW.PH");
27837 gen_reserved_instruction(ctx);
27838 break;
27840 break;
27841 case OPC_INSV_DSP:
27842 op2 = MASK_INSV(ctx->opcode);
27843 switch (op2) {
27844 case OPC_INSV:
27845 check_dsp(ctx);
27847 TCGv t0, t1;
27849 if (rt == 0) {
27850 break;
27853 t0 = tcg_temp_new();
27854 t1 = tcg_temp_new();
27856 gen_load_gpr(t0, rt);
27857 gen_load_gpr(t1, rs);
27859 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
27861 tcg_temp_free(t0);
27862 tcg_temp_free(t1);
27863 break;
27865 default: /* Invalid */
27866 MIPS_INVAL("MASK INSV");
27867 gen_reserved_instruction(ctx);
27868 break;
27870 break;
27871 case OPC_APPEND_DSP:
27872 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27873 break;
27874 case OPC_EXTR_W_DSP:
27875 op2 = MASK_EXTR_W(ctx->opcode);
27876 switch (op2) {
27877 case OPC_EXTR_W:
27878 case OPC_EXTR_R_W:
27879 case OPC_EXTR_RS_W:
27880 case OPC_EXTR_S_H:
27881 case OPC_EXTRV_S_H:
27882 case OPC_EXTRV_W:
27883 case OPC_EXTRV_R_W:
27884 case OPC_EXTRV_RS_W:
27885 case OPC_EXTP:
27886 case OPC_EXTPV:
27887 case OPC_EXTPDP:
27888 case OPC_EXTPDPV:
27889 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27890 break;
27891 case OPC_RDDSP:
27892 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
27893 break;
27894 case OPC_SHILO:
27895 case OPC_SHILOV:
27896 case OPC_MTHLIP:
27897 case OPC_WRDSP:
27898 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27899 break;
27900 default: /* Invalid */
27901 MIPS_INVAL("MASK EXTR.W");
27902 gen_reserved_instruction(ctx);
27903 break;
27905 break;
27906 #if defined(TARGET_MIPS64)
27907 case OPC_DDIV_G_2E:
27908 case OPC_DDIVU_G_2E:
27909 case OPC_DMULT_G_2E:
27910 case OPC_DMULTU_G_2E:
27911 case OPC_DMOD_G_2E:
27912 case OPC_DMODU_G_2E:
27913 check_insn(ctx, INSN_LOONGSON2E);
27914 gen_loongson_integer(ctx, op1, rd, rs, rt);
27915 break;
27916 case OPC_ABSQ_S_QH_DSP:
27917 op2 = MASK_ABSQ_S_QH(ctx->opcode);
27918 switch (op2) {
27919 case OPC_PRECEQ_L_PWL:
27920 case OPC_PRECEQ_L_PWR:
27921 case OPC_PRECEQ_PW_QHL:
27922 case OPC_PRECEQ_PW_QHR:
27923 case OPC_PRECEQ_PW_QHLA:
27924 case OPC_PRECEQ_PW_QHRA:
27925 case OPC_PRECEQU_QH_OBL:
27926 case OPC_PRECEQU_QH_OBR:
27927 case OPC_PRECEQU_QH_OBLA:
27928 case OPC_PRECEQU_QH_OBRA:
27929 case OPC_PRECEU_QH_OBL:
27930 case OPC_PRECEU_QH_OBR:
27931 case OPC_PRECEU_QH_OBLA:
27932 case OPC_PRECEU_QH_OBRA:
27933 case OPC_ABSQ_S_OB:
27934 case OPC_ABSQ_S_PW:
27935 case OPC_ABSQ_S_QH:
27936 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27937 break;
27938 case OPC_REPL_OB:
27939 case OPC_REPL_PW:
27940 case OPC_REPL_QH:
27941 case OPC_REPLV_OB:
27942 case OPC_REPLV_PW:
27943 case OPC_REPLV_QH:
27944 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27945 break;
27946 default: /* Invalid */
27947 MIPS_INVAL("MASK ABSQ_S.QH");
27948 gen_reserved_instruction(ctx);
27949 break;
27951 break;
27952 case OPC_ADDU_OB_DSP:
27953 op2 = MASK_ADDU_OB(ctx->opcode);
27954 switch (op2) {
27955 case OPC_RADDU_L_OB:
27956 case OPC_SUBQ_PW:
27957 case OPC_SUBQ_S_PW:
27958 case OPC_SUBQ_QH:
27959 case OPC_SUBQ_S_QH:
27960 case OPC_SUBU_OB:
27961 case OPC_SUBU_S_OB:
27962 case OPC_SUBU_QH:
27963 case OPC_SUBU_S_QH:
27964 case OPC_SUBUH_OB:
27965 case OPC_SUBUH_R_OB:
27966 case OPC_ADDQ_PW:
27967 case OPC_ADDQ_S_PW:
27968 case OPC_ADDQ_QH:
27969 case OPC_ADDQ_S_QH:
27970 case OPC_ADDU_OB:
27971 case OPC_ADDU_S_OB:
27972 case OPC_ADDU_QH:
27973 case OPC_ADDU_S_QH:
27974 case OPC_ADDUH_OB:
27975 case OPC_ADDUH_R_OB:
27976 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27977 break;
27978 case OPC_MULEQ_S_PW_QHL:
27979 case OPC_MULEQ_S_PW_QHR:
27980 case OPC_MULEU_S_QH_OBL:
27981 case OPC_MULEU_S_QH_OBR:
27982 case OPC_MULQ_RS_QH:
27983 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27984 break;
27985 default: /* Invalid */
27986 MIPS_INVAL("MASK ADDU.OB");
27987 gen_reserved_instruction(ctx);
27988 break;
27990 break;
27991 case OPC_CMPU_EQ_OB_DSP:
27992 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
27993 switch (op2) {
27994 case OPC_PRECR_SRA_QH_PW:
27995 case OPC_PRECR_SRA_R_QH_PW:
27996 /* Return value is rt. */
27997 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
27998 break;
27999 case OPC_PRECR_OB_QH:
28000 case OPC_PRECRQ_OB_QH:
28001 case OPC_PRECRQ_PW_L:
28002 case OPC_PRECRQ_QH_PW:
28003 case OPC_PRECRQ_RS_QH_PW:
28004 case OPC_PRECRQU_S_OB_QH:
28005 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
28006 break;
28007 case OPC_CMPU_EQ_OB:
28008 case OPC_CMPU_LT_OB:
28009 case OPC_CMPU_LE_OB:
28010 case OPC_CMP_EQ_QH:
28011 case OPC_CMP_LT_QH:
28012 case OPC_CMP_LE_QH:
28013 case OPC_CMP_EQ_PW:
28014 case OPC_CMP_LT_PW:
28015 case OPC_CMP_LE_PW:
28016 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
28017 break;
28018 case OPC_CMPGDU_EQ_OB:
28019 case OPC_CMPGDU_LT_OB:
28020 case OPC_CMPGDU_LE_OB:
28021 case OPC_CMPGU_EQ_OB:
28022 case OPC_CMPGU_LT_OB:
28023 case OPC_CMPGU_LE_OB:
28024 case OPC_PACKRL_PW:
28025 case OPC_PICK_OB:
28026 case OPC_PICK_PW:
28027 case OPC_PICK_QH:
28028 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
28029 break;
28030 default: /* Invalid */
28031 MIPS_INVAL("MASK CMPU_EQ.OB");
28032 gen_reserved_instruction(ctx);
28033 break;
28035 break;
28036 case OPC_DAPPEND_DSP:
28037 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
28038 break;
28039 case OPC_DEXTR_W_DSP:
28040 op2 = MASK_DEXTR_W(ctx->opcode);
28041 switch (op2) {
28042 case OPC_DEXTP:
28043 case OPC_DEXTPDP:
28044 case OPC_DEXTPDPV:
28045 case OPC_DEXTPV:
28046 case OPC_DEXTR_L:
28047 case OPC_DEXTR_R_L:
28048 case OPC_DEXTR_RS_L:
28049 case OPC_DEXTR_W:
28050 case OPC_DEXTR_R_W:
28051 case OPC_DEXTR_RS_W:
28052 case OPC_DEXTR_S_H:
28053 case OPC_DEXTRV_L:
28054 case OPC_DEXTRV_R_L:
28055 case OPC_DEXTRV_RS_L:
28056 case OPC_DEXTRV_S_H:
28057 case OPC_DEXTRV_W:
28058 case OPC_DEXTRV_R_W:
28059 case OPC_DEXTRV_RS_W:
28060 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
28061 break;
28062 case OPC_DMTHLIP:
28063 case OPC_DSHILO:
28064 case OPC_DSHILOV:
28065 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
28066 break;
28067 default: /* Invalid */
28068 MIPS_INVAL("MASK EXTR.W");
28069 gen_reserved_instruction(ctx);
28070 break;
28072 break;
28073 case OPC_DPAQ_W_QH_DSP:
28074 op2 = MASK_DPAQ_W_QH(ctx->opcode);
28075 switch (op2) {
28076 case OPC_DPAU_H_OBL:
28077 case OPC_DPAU_H_OBR:
28078 case OPC_DPSU_H_OBL:
28079 case OPC_DPSU_H_OBR:
28080 case OPC_DPA_W_QH:
28081 case OPC_DPAQ_S_W_QH:
28082 case OPC_DPS_W_QH:
28083 case OPC_DPSQ_S_W_QH:
28084 case OPC_MULSAQ_S_W_QH:
28085 case OPC_DPAQ_SA_L_PW:
28086 case OPC_DPSQ_SA_L_PW:
28087 case OPC_MULSAQ_S_L_PW:
28088 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
28089 break;
28090 case OPC_MAQ_S_W_QHLL:
28091 case OPC_MAQ_S_W_QHLR:
28092 case OPC_MAQ_S_W_QHRL:
28093 case OPC_MAQ_S_W_QHRR:
28094 case OPC_MAQ_SA_W_QHLL:
28095 case OPC_MAQ_SA_W_QHLR:
28096 case OPC_MAQ_SA_W_QHRL:
28097 case OPC_MAQ_SA_W_QHRR:
28098 case OPC_MAQ_S_L_PWL:
28099 case OPC_MAQ_S_L_PWR:
28100 case OPC_DMADD:
28101 case OPC_DMADDU:
28102 case OPC_DMSUB:
28103 case OPC_DMSUBU:
28104 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
28105 break;
28106 default: /* Invalid */
28107 MIPS_INVAL("MASK DPAQ.W.QH");
28108 gen_reserved_instruction(ctx);
28109 break;
28111 break;
28112 case OPC_DINSV_DSP:
28113 op2 = MASK_INSV(ctx->opcode);
28114 switch (op2) {
28115 case OPC_DINSV:
28117 TCGv t0, t1;
28119 if (rt == 0) {
28120 break;
28122 check_dsp(ctx);
28124 t0 = tcg_temp_new();
28125 t1 = tcg_temp_new();
28127 gen_load_gpr(t0, rt);
28128 gen_load_gpr(t1, rs);
28130 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
28132 tcg_temp_free(t0);
28133 tcg_temp_free(t1);
28134 break;
28136 default: /* Invalid */
28137 MIPS_INVAL("MASK DINSV");
28138 gen_reserved_instruction(ctx);
28139 break;
28141 break;
28142 case OPC_SHLL_OB_DSP:
28143 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
28144 break;
28145 #endif
28146 default: /* Invalid */
28147 MIPS_INVAL("special3_legacy");
28148 gen_reserved_instruction(ctx);
28149 break;
28154 #if defined(TARGET_MIPS64)
28156 static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx)
28158 uint32_t opc = MASK_MMI0(ctx->opcode);
28160 switch (opc) {
28161 case MMI_OPC_0_PADDW: /* TODO: MMI_OPC_0_PADDW */
28162 case MMI_OPC_0_PSUBW: /* TODO: MMI_OPC_0_PSUBW */
28163 case MMI_OPC_0_PCGTW: /* TODO: MMI_OPC_0_PCGTW */
28164 case MMI_OPC_0_PMAXW: /* TODO: MMI_OPC_0_PMAXW */
28165 case MMI_OPC_0_PADDH: /* TODO: MMI_OPC_0_PADDH */
28166 case MMI_OPC_0_PSUBH: /* TODO: MMI_OPC_0_PSUBH */
28167 case MMI_OPC_0_PCGTH: /* TODO: MMI_OPC_0_PCGTH */
28168 case MMI_OPC_0_PMAXH: /* TODO: MMI_OPC_0_PMAXH */
28169 case MMI_OPC_0_PADDB: /* TODO: MMI_OPC_0_PADDB */
28170 case MMI_OPC_0_PSUBB: /* TODO: MMI_OPC_0_PSUBB */
28171 case MMI_OPC_0_PCGTB: /* TODO: MMI_OPC_0_PCGTB */
28172 case MMI_OPC_0_PADDSW: /* TODO: MMI_OPC_0_PADDSW */
28173 case MMI_OPC_0_PSUBSW: /* TODO: MMI_OPC_0_PSUBSW */
28174 case MMI_OPC_0_PEXTLW: /* TODO: MMI_OPC_0_PEXTLW */
28175 case MMI_OPC_0_PPACW: /* TODO: MMI_OPC_0_PPACW */
28176 case MMI_OPC_0_PADDSH: /* TODO: MMI_OPC_0_PADDSH */
28177 case MMI_OPC_0_PSUBSH: /* TODO: MMI_OPC_0_PSUBSH */
28178 case MMI_OPC_0_PEXTLH: /* TODO: MMI_OPC_0_PEXTLH */
28179 case MMI_OPC_0_PPACH: /* TODO: MMI_OPC_0_PPACH */
28180 case MMI_OPC_0_PADDSB: /* TODO: MMI_OPC_0_PADDSB */
28181 case MMI_OPC_0_PSUBSB: /* TODO: MMI_OPC_0_PSUBSB */
28182 case MMI_OPC_0_PEXTLB: /* TODO: MMI_OPC_0_PEXTLB */
28183 case MMI_OPC_0_PPACB: /* TODO: MMI_OPC_0_PPACB */
28184 case MMI_OPC_0_PEXT5: /* TODO: MMI_OPC_0_PEXT5 */
28185 case MMI_OPC_0_PPAC5: /* TODO: MMI_OPC_0_PPAC5 */
28186 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI0 */
28187 break;
28188 default:
28189 MIPS_INVAL("TX79 MMI class MMI0");
28190 gen_reserved_instruction(ctx);
28191 break;
28195 static void decode_mmi1(CPUMIPSState *env, DisasContext *ctx)
28197 uint32_t opc = MASK_MMI1(ctx->opcode);
28199 switch (opc) {
28200 case MMI_OPC_1_PABSW: /* TODO: MMI_OPC_1_PABSW */
28201 case MMI_OPC_1_PCEQW: /* TODO: MMI_OPC_1_PCEQW */
28202 case MMI_OPC_1_PMINW: /* TODO: MMI_OPC_1_PMINW */
28203 case MMI_OPC_1_PADSBH: /* TODO: MMI_OPC_1_PADSBH */
28204 case MMI_OPC_1_PABSH: /* TODO: MMI_OPC_1_PABSH */
28205 case MMI_OPC_1_PCEQH: /* TODO: MMI_OPC_1_PCEQH */
28206 case MMI_OPC_1_PMINH: /* TODO: MMI_OPC_1_PMINH */
28207 case MMI_OPC_1_PCEQB: /* TODO: MMI_OPC_1_PCEQB */
28208 case MMI_OPC_1_PADDUW: /* TODO: MMI_OPC_1_PADDUW */
28209 case MMI_OPC_1_PSUBUW: /* TODO: MMI_OPC_1_PSUBUW */
28210 case MMI_OPC_1_PEXTUW: /* TODO: MMI_OPC_1_PEXTUW */
28211 case MMI_OPC_1_PADDUH: /* TODO: MMI_OPC_1_PADDUH */
28212 case MMI_OPC_1_PSUBUH: /* TODO: MMI_OPC_1_PSUBUH */
28213 case MMI_OPC_1_PEXTUH: /* TODO: MMI_OPC_1_PEXTUH */
28214 case MMI_OPC_1_PADDUB: /* TODO: MMI_OPC_1_PADDUB */
28215 case MMI_OPC_1_PSUBUB: /* TODO: MMI_OPC_1_PSUBUB */
28216 case MMI_OPC_1_PEXTUB: /* TODO: MMI_OPC_1_PEXTUB */
28217 case MMI_OPC_1_QFSRV: /* TODO: MMI_OPC_1_QFSRV */
28218 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI1 */
28219 break;
28220 default:
28221 MIPS_INVAL("TX79 MMI class MMI1");
28222 gen_reserved_instruction(ctx);
28223 break;
28227 static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx)
28229 uint32_t opc = MASK_MMI2(ctx->opcode);
28231 switch (opc) {
28232 case MMI_OPC_2_PMADDW: /* TODO: MMI_OPC_2_PMADDW */
28233 case MMI_OPC_2_PSLLVW: /* TODO: MMI_OPC_2_PSLLVW */
28234 case MMI_OPC_2_PSRLVW: /* TODO: MMI_OPC_2_PSRLVW */
28235 case MMI_OPC_2_PMSUBW: /* TODO: MMI_OPC_2_PMSUBW */
28236 case MMI_OPC_2_PMFHI: /* TODO: MMI_OPC_2_PMFHI */
28237 case MMI_OPC_2_PMFLO: /* TODO: MMI_OPC_2_PMFLO */
28238 case MMI_OPC_2_PINTH: /* TODO: MMI_OPC_2_PINTH */
28239 case MMI_OPC_2_PMULTW: /* TODO: MMI_OPC_2_PMULTW */
28240 case MMI_OPC_2_PDIVW: /* TODO: MMI_OPC_2_PDIVW */
28241 case MMI_OPC_2_PMADDH: /* TODO: MMI_OPC_2_PMADDH */
28242 case MMI_OPC_2_PHMADH: /* TODO: MMI_OPC_2_PHMADH */
28243 case MMI_OPC_2_PAND: /* TODO: MMI_OPC_2_PAND */
28244 case MMI_OPC_2_PXOR: /* TODO: MMI_OPC_2_PXOR */
28245 case MMI_OPC_2_PMSUBH: /* TODO: MMI_OPC_2_PMSUBH */
28246 case MMI_OPC_2_PHMSBH: /* TODO: MMI_OPC_2_PHMSBH */
28247 case MMI_OPC_2_PEXEH: /* TODO: MMI_OPC_2_PEXEH */
28248 case MMI_OPC_2_PREVH: /* TODO: MMI_OPC_2_PREVH */
28249 case MMI_OPC_2_PMULTH: /* TODO: MMI_OPC_2_PMULTH */
28250 case MMI_OPC_2_PDIVBW: /* TODO: MMI_OPC_2_PDIVBW */
28251 case MMI_OPC_2_PEXEW: /* TODO: MMI_OPC_2_PEXEW */
28252 case MMI_OPC_2_PROT3W: /* TODO: MMI_OPC_2_PROT3W */
28253 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI2 */
28254 break;
28255 case MMI_OPC_2_PCPYLD:
28256 gen_mmi_pcpyld(ctx);
28257 break;
28258 default:
28259 MIPS_INVAL("TX79 MMI class MMI2");
28260 gen_reserved_instruction(ctx);
28261 break;
28265 static void decode_mmi3(CPUMIPSState *env, DisasContext *ctx)
28267 uint32_t opc = MASK_MMI3(ctx->opcode);
28269 switch (opc) {
28270 case MMI_OPC_3_PMADDUW: /* TODO: MMI_OPC_3_PMADDUW */
28271 case MMI_OPC_3_PSRAVW: /* TODO: MMI_OPC_3_PSRAVW */
28272 case MMI_OPC_3_PMTHI: /* TODO: MMI_OPC_3_PMTHI */
28273 case MMI_OPC_3_PMTLO: /* TODO: MMI_OPC_3_PMTLO */
28274 case MMI_OPC_3_PINTEH: /* TODO: MMI_OPC_3_PINTEH */
28275 case MMI_OPC_3_PMULTUW: /* TODO: MMI_OPC_3_PMULTUW */
28276 case MMI_OPC_3_PDIVUW: /* TODO: MMI_OPC_3_PDIVUW */
28277 case MMI_OPC_3_POR: /* TODO: MMI_OPC_3_POR */
28278 case MMI_OPC_3_PNOR: /* TODO: MMI_OPC_3_PNOR */
28279 case MMI_OPC_3_PEXCH: /* TODO: MMI_OPC_3_PEXCH */
28280 case MMI_OPC_3_PEXCW: /* TODO: MMI_OPC_3_PEXCW */
28281 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI3 */
28282 break;
28283 case MMI_OPC_3_PCPYH:
28284 gen_mmi_pcpyh(ctx);
28285 break;
28286 case MMI_OPC_3_PCPYUD:
28287 gen_mmi_pcpyud(ctx);
28288 break;
28289 default:
28290 MIPS_INVAL("TX79 MMI class MMI3");
28291 gen_reserved_instruction(ctx);
28292 break;
28296 static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
28298 uint32_t opc = MASK_MMI(ctx->opcode);
28299 int rs = extract32(ctx->opcode, 21, 5);
28300 int rt = extract32(ctx->opcode, 16, 5);
28301 int rd = extract32(ctx->opcode, 11, 5);
28303 switch (opc) {
28304 case MMI_OPC_CLASS_MMI0:
28305 decode_mmi0(env, ctx);
28306 break;
28307 case MMI_OPC_CLASS_MMI1:
28308 decode_mmi1(env, ctx);
28309 break;
28310 case MMI_OPC_CLASS_MMI2:
28311 decode_mmi2(env, ctx);
28312 break;
28313 case MMI_OPC_CLASS_MMI3:
28314 decode_mmi3(env, ctx);
28315 break;
28316 case MMI_OPC_MULT1:
28317 case MMI_OPC_MULTU1:
28318 case MMI_OPC_MADD:
28319 case MMI_OPC_MADDU:
28320 case MMI_OPC_MADD1:
28321 case MMI_OPC_MADDU1:
28322 gen_mul_txx9(ctx, opc, rd, rs, rt);
28323 break;
28324 case MMI_OPC_DIV1:
28325 case MMI_OPC_DIVU1:
28326 gen_div1_tx79(ctx, opc, rs, rt);
28327 break;
28328 case MMI_OPC_MTLO1:
28329 case MMI_OPC_MTHI1:
28330 gen_HILO1_tx79(ctx, opc, rs);
28331 break;
28332 case MMI_OPC_MFLO1:
28333 case MMI_OPC_MFHI1:
28334 gen_HILO1_tx79(ctx, opc, rd);
28335 break;
28336 case MMI_OPC_PLZCW: /* TODO: MMI_OPC_PLZCW */
28337 case MMI_OPC_PMFHL: /* TODO: MMI_OPC_PMFHL */
28338 case MMI_OPC_PMTHL: /* TODO: MMI_OPC_PMTHL */
28339 case MMI_OPC_PSLLH: /* TODO: MMI_OPC_PSLLH */
28340 case MMI_OPC_PSRLH: /* TODO: MMI_OPC_PSRLH */
28341 case MMI_OPC_PSRAH: /* TODO: MMI_OPC_PSRAH */
28342 case MMI_OPC_PSLLW: /* TODO: MMI_OPC_PSLLW */
28343 case MMI_OPC_PSRLW: /* TODO: MMI_OPC_PSRLW */
28344 case MMI_OPC_PSRAW: /* TODO: MMI_OPC_PSRAW */
28345 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI */
28346 break;
28347 default:
28348 MIPS_INVAL("TX79 MMI class");
28349 gen_reserved_instruction(ctx);
28350 break;
28354 static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
28356 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_LQ */
28359 static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
28361 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_SQ */
28365 * The TX79-specific instruction Store Quadword
28367 * +--------+-------+-------+------------------------+
28368 * | 011111 | base | rt | offset | SQ
28369 * +--------+-------+-------+------------------------+
28370 * 6 5 5 16
28372 * has the same opcode as the Read Hardware Register instruction
28374 * +--------+-------+-------+-------+-------+--------+
28375 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
28376 * +--------+-------+-------+-------+-------+--------+
28377 * 6 5 5 5 5 6
28379 * that is required, trapped and emulated by the Linux kernel. However, all
28380 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
28381 * offset is odd. Therefore all valid SQ instructions can execute normally.
28382 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
28383 * between SQ and RDHWR, as the Linux kernel does.
28385 static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
28387 int base = extract32(ctx->opcode, 21, 5);
28388 int rt = extract32(ctx->opcode, 16, 5);
28389 int offset = extract32(ctx->opcode, 0, 16);
28391 #ifdef CONFIG_USER_ONLY
28392 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
28393 uint32_t op2 = extract32(ctx->opcode, 6, 5);
28395 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
28396 int rd = extract32(ctx->opcode, 11, 5);
28398 gen_rdhwr(ctx, rt, rd, 0);
28399 return;
28401 #endif
28403 gen_mmi_sq(ctx, base, rt, offset);
28406 #endif
28408 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
28410 int rs, rt, rd, sa;
28411 uint32_t op1, op2;
28412 int16_t imm;
28414 rs = (ctx->opcode >> 21) & 0x1f;
28415 rt = (ctx->opcode >> 16) & 0x1f;
28416 rd = (ctx->opcode >> 11) & 0x1f;
28417 sa = (ctx->opcode >> 6) & 0x1f;
28418 imm = sextract32(ctx->opcode, 7, 9);
28420 op1 = MASK_SPECIAL3(ctx->opcode);
28423 * EVA loads and stores overlap Loongson 2E instructions decoded by
28424 * decode_opc_special3_legacy(), so be careful to allow their decoding when
28425 * EVA is absent.
28427 if (ctx->eva) {
28428 switch (op1) {
28429 case OPC_LWLE:
28430 case OPC_LWRE:
28431 check_insn_opc_removed(ctx, ISA_MIPS_R6);
28432 /* fall through */
28433 case OPC_LBUE:
28434 case OPC_LHUE:
28435 case OPC_LBE:
28436 case OPC_LHE:
28437 case OPC_LLE:
28438 case OPC_LWE:
28439 check_cp0_enabled(ctx);
28440 gen_ld(ctx, op1, rt, rs, imm);
28441 return;
28442 case OPC_SWLE:
28443 case OPC_SWRE:
28444 check_insn_opc_removed(ctx, ISA_MIPS_R6);
28445 /* fall through */
28446 case OPC_SBE:
28447 case OPC_SHE:
28448 case OPC_SWE:
28449 check_cp0_enabled(ctx);
28450 gen_st(ctx, op1, rt, rs, imm);
28451 return;
28452 case OPC_SCE:
28453 check_cp0_enabled(ctx);
28454 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
28455 return;
28456 case OPC_CACHEE:
28457 check_cp0_enabled(ctx);
28458 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
28459 gen_cache_operation(ctx, rt, rs, imm);
28461 /* Treat as NOP. */
28462 return;
28463 case OPC_PREFE:
28464 check_cp0_enabled(ctx);
28465 /* Treat as NOP. */
28466 return;
28470 switch (op1) {
28471 case OPC_EXT:
28472 case OPC_INS:
28473 check_insn(ctx, ISA_MIPS_R2);
28474 gen_bitops(ctx, op1, rt, rs, sa, rd);
28475 break;
28476 case OPC_BSHFL:
28477 op2 = MASK_BSHFL(ctx->opcode);
28478 switch (op2) {
28479 case OPC_ALIGN:
28480 case OPC_ALIGN_1:
28481 case OPC_ALIGN_2:
28482 case OPC_ALIGN_3:
28483 case OPC_BITSWAP:
28484 check_insn(ctx, ISA_MIPS_R6);
28485 decode_opc_special3_r6(env, ctx);
28486 break;
28487 default:
28488 check_insn(ctx, ISA_MIPS_R2);
28489 gen_bshfl(ctx, op2, rt, rd);
28490 break;
28492 break;
28493 #if defined(TARGET_MIPS64)
28494 case OPC_DEXTM:
28495 case OPC_DEXTU:
28496 case OPC_DEXT:
28497 case OPC_DINSM:
28498 case OPC_DINSU:
28499 case OPC_DINS:
28500 check_insn(ctx, ISA_MIPS_R2);
28501 check_mips_64(ctx);
28502 gen_bitops(ctx, op1, rt, rs, sa, rd);
28503 break;
28504 case OPC_DBSHFL:
28505 op2 = MASK_DBSHFL(ctx->opcode);
28506 switch (op2) {
28507 case OPC_DALIGN:
28508 case OPC_DALIGN_1:
28509 case OPC_DALIGN_2:
28510 case OPC_DALIGN_3:
28511 case OPC_DALIGN_4:
28512 case OPC_DALIGN_5:
28513 case OPC_DALIGN_6:
28514 case OPC_DALIGN_7:
28515 case OPC_DBITSWAP:
28516 check_insn(ctx, ISA_MIPS_R6);
28517 decode_opc_special3_r6(env, ctx);
28518 break;
28519 default:
28520 check_insn(ctx, ISA_MIPS_R2);
28521 check_mips_64(ctx);
28522 op2 = MASK_DBSHFL(ctx->opcode);
28523 gen_bshfl(ctx, op2, rt, rd);
28524 break;
28526 break;
28527 #endif
28528 case OPC_RDHWR:
28529 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
28530 break;
28531 case OPC_FORK:
28532 check_mt(ctx);
28534 TCGv t0 = tcg_temp_new();
28535 TCGv t1 = tcg_temp_new();
28537 gen_load_gpr(t0, rt);
28538 gen_load_gpr(t1, rs);
28539 gen_helper_fork(t0, t1);
28540 tcg_temp_free(t0);
28541 tcg_temp_free(t1);
28543 break;
28544 case OPC_YIELD:
28545 check_mt(ctx);
28547 TCGv t0 = tcg_temp_new();
28549 gen_load_gpr(t0, rs);
28550 gen_helper_yield(t0, cpu_env, t0);
28551 gen_store_gpr(t0, rd);
28552 tcg_temp_free(t0);
28554 break;
28555 default:
28556 if (ctx->insn_flags & ISA_MIPS_R6) {
28557 decode_opc_special3_r6(env, ctx);
28558 } else {
28559 decode_opc_special3_legacy(env, ctx);
28564 /* MIPS SIMD Architecture (MSA) */
28565 static inline int check_msa_access(DisasContext *ctx)
28567 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
28568 !(ctx->hflags & MIPS_HFLAG_F64))) {
28569 gen_reserved_instruction(ctx);
28570 return 0;
28573 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
28574 if (ctx->insn_flags & ASE_MSA) {
28575 generate_exception_end(ctx, EXCP_MSADIS);
28576 return 0;
28577 } else {
28578 gen_reserved_instruction(ctx);
28579 return 0;
28582 return 1;
28585 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
28587 /* generates tcg ops to check if any element is 0 */
28588 /* Note this function only works with MSA_WRLEN = 128 */
28589 uint64_t eval_zero_or_big = 0;
28590 uint64_t eval_big = 0;
28591 TCGv_i64 t0 = tcg_temp_new_i64();
28592 TCGv_i64 t1 = tcg_temp_new_i64();
28593 switch (df) {
28594 case DF_BYTE:
28595 eval_zero_or_big = 0x0101010101010101ULL;
28596 eval_big = 0x8080808080808080ULL;
28597 break;
28598 case DF_HALF:
28599 eval_zero_or_big = 0x0001000100010001ULL;
28600 eval_big = 0x8000800080008000ULL;
28601 break;
28602 case DF_WORD:
28603 eval_zero_or_big = 0x0000000100000001ULL;
28604 eval_big = 0x8000000080000000ULL;
28605 break;
28606 case DF_DOUBLE:
28607 eval_zero_or_big = 0x0000000000000001ULL;
28608 eval_big = 0x8000000000000000ULL;
28609 break;
28611 tcg_gen_subi_i64(t0, msa_wr_d[wt << 1], eval_zero_or_big);
28612 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt << 1]);
28613 tcg_gen_andi_i64(t0, t0, eval_big);
28614 tcg_gen_subi_i64(t1, msa_wr_d[(wt << 1) + 1], eval_zero_or_big);
28615 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt << 1) + 1]);
28616 tcg_gen_andi_i64(t1, t1, eval_big);
28617 tcg_gen_or_i64(t0, t0, t1);
28618 /* if all bits are zero then all elements are not zero */
28619 /* if some bit is non-zero then some element is zero */
28620 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
28621 tcg_gen_trunc_i64_tl(tresult, t0);
28622 tcg_temp_free_i64(t0);
28623 tcg_temp_free_i64(t1);
28626 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
28628 uint8_t df = (ctx->opcode >> 21) & 0x3;
28629 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28630 int64_t s16 = (int16_t)ctx->opcode;
28632 check_msa_access(ctx);
28634 if (ctx->hflags & MIPS_HFLAG_BMASK) {
28635 gen_reserved_instruction(ctx);
28636 return;
28638 switch (op1) {
28639 case OPC_BZ_V:
28640 case OPC_BNZ_V:
28642 TCGv_i64 t0 = tcg_temp_new_i64();
28643 tcg_gen_or_i64(t0, msa_wr_d[wt << 1], msa_wr_d[(wt << 1) + 1]);
28644 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
28645 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
28646 tcg_gen_trunc_i64_tl(bcond, t0);
28647 tcg_temp_free_i64(t0);
28649 break;
28650 case OPC_BZ_B:
28651 case OPC_BZ_H:
28652 case OPC_BZ_W:
28653 case OPC_BZ_D:
28654 gen_check_zero_element(bcond, df, wt);
28655 break;
28656 case OPC_BNZ_B:
28657 case OPC_BNZ_H:
28658 case OPC_BNZ_W:
28659 case OPC_BNZ_D:
28660 gen_check_zero_element(bcond, df, wt);
28661 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
28662 break;
28665 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
28667 ctx->hflags |= MIPS_HFLAG_BC;
28668 ctx->hflags |= MIPS_HFLAG_BDS32;
28671 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
28673 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
28674 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
28675 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28676 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28678 TCGv_i32 twd = tcg_const_i32(wd);
28679 TCGv_i32 tws = tcg_const_i32(ws);
28680 TCGv_i32 ti8 = tcg_const_i32(i8);
28682 switch (MASK_MSA_I8(ctx->opcode)) {
28683 case OPC_ANDI_B:
28684 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
28685 break;
28686 case OPC_ORI_B:
28687 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
28688 break;
28689 case OPC_NORI_B:
28690 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
28691 break;
28692 case OPC_XORI_B:
28693 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
28694 break;
28695 case OPC_BMNZI_B:
28696 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
28697 break;
28698 case OPC_BMZI_B:
28699 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
28700 break;
28701 case OPC_BSELI_B:
28702 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
28703 break;
28704 case OPC_SHF_B:
28705 case OPC_SHF_H:
28706 case OPC_SHF_W:
28708 uint8_t df = (ctx->opcode >> 24) & 0x3;
28709 if (df == DF_DOUBLE) {
28710 gen_reserved_instruction(ctx);
28711 } else {
28712 TCGv_i32 tdf = tcg_const_i32(df);
28713 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
28714 tcg_temp_free_i32(tdf);
28717 break;
28718 default:
28719 MIPS_INVAL("MSA instruction");
28720 gen_reserved_instruction(ctx);
28721 break;
28724 tcg_temp_free_i32(twd);
28725 tcg_temp_free_i32(tws);
28726 tcg_temp_free_i32(ti8);
28729 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
28731 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28732 uint8_t df = (ctx->opcode >> 21) & 0x3;
28733 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
28734 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
28735 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28736 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28738 TCGv_i32 tdf = tcg_const_i32(df);
28739 TCGv_i32 twd = tcg_const_i32(wd);
28740 TCGv_i32 tws = tcg_const_i32(ws);
28741 TCGv_i32 timm = tcg_temp_new_i32();
28742 tcg_gen_movi_i32(timm, u5);
28744 switch (MASK_MSA_I5(ctx->opcode)) {
28745 case OPC_ADDVI_df:
28746 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
28747 break;
28748 case OPC_SUBVI_df:
28749 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
28750 break;
28751 case OPC_MAXI_S_df:
28752 tcg_gen_movi_i32(timm, s5);
28753 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
28754 break;
28755 case OPC_MAXI_U_df:
28756 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
28757 break;
28758 case OPC_MINI_S_df:
28759 tcg_gen_movi_i32(timm, s5);
28760 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
28761 break;
28762 case OPC_MINI_U_df:
28763 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
28764 break;
28765 case OPC_CEQI_df:
28766 tcg_gen_movi_i32(timm, s5);
28767 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
28768 break;
28769 case OPC_CLTI_S_df:
28770 tcg_gen_movi_i32(timm, s5);
28771 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
28772 break;
28773 case OPC_CLTI_U_df:
28774 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
28775 break;
28776 case OPC_CLEI_S_df:
28777 tcg_gen_movi_i32(timm, s5);
28778 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
28779 break;
28780 case OPC_CLEI_U_df:
28781 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
28782 break;
28783 case OPC_LDI_df:
28785 int32_t s10 = sextract32(ctx->opcode, 11, 10);
28786 tcg_gen_movi_i32(timm, s10);
28787 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
28789 break;
28790 default:
28791 MIPS_INVAL("MSA instruction");
28792 gen_reserved_instruction(ctx);
28793 break;
28796 tcg_temp_free_i32(tdf);
28797 tcg_temp_free_i32(twd);
28798 tcg_temp_free_i32(tws);
28799 tcg_temp_free_i32(timm);
28802 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
28804 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28805 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
28806 uint32_t df = 0, m = 0;
28807 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28808 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28810 TCGv_i32 tdf;
28811 TCGv_i32 tm;
28812 TCGv_i32 twd;
28813 TCGv_i32 tws;
28815 if ((dfm & 0x40) == 0x00) {
28816 m = dfm & 0x3f;
28817 df = DF_DOUBLE;
28818 } else if ((dfm & 0x60) == 0x40) {
28819 m = dfm & 0x1f;
28820 df = DF_WORD;
28821 } else if ((dfm & 0x70) == 0x60) {
28822 m = dfm & 0x0f;
28823 df = DF_HALF;
28824 } else if ((dfm & 0x78) == 0x70) {
28825 m = dfm & 0x7;
28826 df = DF_BYTE;
28827 } else {
28828 gen_reserved_instruction(ctx);
28829 return;
28832 tdf = tcg_const_i32(df);
28833 tm = tcg_const_i32(m);
28834 twd = tcg_const_i32(wd);
28835 tws = tcg_const_i32(ws);
28837 switch (MASK_MSA_BIT(ctx->opcode)) {
28838 case OPC_SLLI_df:
28839 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
28840 break;
28841 case OPC_SRAI_df:
28842 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
28843 break;
28844 case OPC_SRLI_df:
28845 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
28846 break;
28847 case OPC_BCLRI_df:
28848 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
28849 break;
28850 case OPC_BSETI_df:
28851 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
28852 break;
28853 case OPC_BNEGI_df:
28854 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
28855 break;
28856 case OPC_BINSLI_df:
28857 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
28858 break;
28859 case OPC_BINSRI_df:
28860 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
28861 break;
28862 case OPC_SAT_S_df:
28863 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
28864 break;
28865 case OPC_SAT_U_df:
28866 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
28867 break;
28868 case OPC_SRARI_df:
28869 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
28870 break;
28871 case OPC_SRLRI_df:
28872 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
28873 break;
28874 default:
28875 MIPS_INVAL("MSA instruction");
28876 gen_reserved_instruction(ctx);
28877 break;
28880 tcg_temp_free_i32(tdf);
28881 tcg_temp_free_i32(tm);
28882 tcg_temp_free_i32(twd);
28883 tcg_temp_free_i32(tws);
28886 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
28888 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28889 uint8_t df = (ctx->opcode >> 21) & 0x3;
28890 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28891 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28892 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28894 TCGv_i32 tdf = tcg_const_i32(df);
28895 TCGv_i32 twd = tcg_const_i32(wd);
28896 TCGv_i32 tws = tcg_const_i32(ws);
28897 TCGv_i32 twt = tcg_const_i32(wt);
28899 switch (MASK_MSA_3R(ctx->opcode)) {
28900 case OPC_BINSL_df:
28901 switch (df) {
28902 case DF_BYTE:
28903 gen_helper_msa_binsl_b(cpu_env, twd, tws, twt);
28904 break;
28905 case DF_HALF:
28906 gen_helper_msa_binsl_h(cpu_env, twd, tws, twt);
28907 break;
28908 case DF_WORD:
28909 gen_helper_msa_binsl_w(cpu_env, twd, tws, twt);
28910 break;
28911 case DF_DOUBLE:
28912 gen_helper_msa_binsl_d(cpu_env, twd, tws, twt);
28913 break;
28915 break;
28916 case OPC_BINSR_df:
28917 switch (df) {
28918 case DF_BYTE:
28919 gen_helper_msa_binsr_b(cpu_env, twd, tws, twt);
28920 break;
28921 case DF_HALF:
28922 gen_helper_msa_binsr_h(cpu_env, twd, tws, twt);
28923 break;
28924 case DF_WORD:
28925 gen_helper_msa_binsr_w(cpu_env, twd, tws, twt);
28926 break;
28927 case DF_DOUBLE:
28928 gen_helper_msa_binsr_d(cpu_env, twd, tws, twt);
28929 break;
28931 break;
28932 case OPC_BCLR_df:
28933 switch (df) {
28934 case DF_BYTE:
28935 gen_helper_msa_bclr_b(cpu_env, twd, tws, twt);
28936 break;
28937 case DF_HALF:
28938 gen_helper_msa_bclr_h(cpu_env, twd, tws, twt);
28939 break;
28940 case DF_WORD:
28941 gen_helper_msa_bclr_w(cpu_env, twd, tws, twt);
28942 break;
28943 case DF_DOUBLE:
28944 gen_helper_msa_bclr_d(cpu_env, twd, tws, twt);
28945 break;
28947 break;
28948 case OPC_BNEG_df:
28949 switch (df) {
28950 case DF_BYTE:
28951 gen_helper_msa_bneg_b(cpu_env, twd, tws, twt);
28952 break;
28953 case DF_HALF:
28954 gen_helper_msa_bneg_h(cpu_env, twd, tws, twt);
28955 break;
28956 case DF_WORD:
28957 gen_helper_msa_bneg_w(cpu_env, twd, tws, twt);
28958 break;
28959 case DF_DOUBLE:
28960 gen_helper_msa_bneg_d(cpu_env, twd, tws, twt);
28961 break;
28963 break;
28964 case OPC_BSET_df:
28965 switch (df) {
28966 case DF_BYTE:
28967 gen_helper_msa_bset_b(cpu_env, twd, tws, twt);
28968 break;
28969 case DF_HALF:
28970 gen_helper_msa_bset_h(cpu_env, twd, tws, twt);
28971 break;
28972 case DF_WORD:
28973 gen_helper_msa_bset_w(cpu_env, twd, tws, twt);
28974 break;
28975 case DF_DOUBLE:
28976 gen_helper_msa_bset_d(cpu_env, twd, tws, twt);
28977 break;
28979 break;
28980 case OPC_ADD_A_df:
28981 switch (df) {
28982 case DF_BYTE:
28983 gen_helper_msa_add_a_b(cpu_env, twd, tws, twt);
28984 break;
28985 case DF_HALF:
28986 gen_helper_msa_add_a_h(cpu_env, twd, tws, twt);
28987 break;
28988 case DF_WORD:
28989 gen_helper_msa_add_a_w(cpu_env, twd, tws, twt);
28990 break;
28991 case DF_DOUBLE:
28992 gen_helper_msa_add_a_d(cpu_env, twd, tws, twt);
28993 break;
28995 break;
28996 case OPC_ADDS_A_df:
28997 switch (df) {
28998 case DF_BYTE:
28999 gen_helper_msa_adds_a_b(cpu_env, twd, tws, twt);
29000 break;
29001 case DF_HALF:
29002 gen_helper_msa_adds_a_h(cpu_env, twd, tws, twt);
29003 break;
29004 case DF_WORD:
29005 gen_helper_msa_adds_a_w(cpu_env, twd, tws, twt);
29006 break;
29007 case DF_DOUBLE:
29008 gen_helper_msa_adds_a_d(cpu_env, twd, tws, twt);
29009 break;
29011 break;
29012 case OPC_ADDS_S_df:
29013 switch (df) {
29014 case DF_BYTE:
29015 gen_helper_msa_adds_s_b(cpu_env, twd, tws, twt);
29016 break;
29017 case DF_HALF:
29018 gen_helper_msa_adds_s_h(cpu_env, twd, tws, twt);
29019 break;
29020 case DF_WORD:
29021 gen_helper_msa_adds_s_w(cpu_env, twd, tws, twt);
29022 break;
29023 case DF_DOUBLE:
29024 gen_helper_msa_adds_s_d(cpu_env, twd, tws, twt);
29025 break;
29027 break;
29028 case OPC_ADDS_U_df:
29029 switch (df) {
29030 case DF_BYTE:
29031 gen_helper_msa_adds_u_b(cpu_env, twd, tws, twt);
29032 break;
29033 case DF_HALF:
29034 gen_helper_msa_adds_u_h(cpu_env, twd, tws, twt);
29035 break;
29036 case DF_WORD:
29037 gen_helper_msa_adds_u_w(cpu_env, twd, tws, twt);
29038 break;
29039 case DF_DOUBLE:
29040 gen_helper_msa_adds_u_d(cpu_env, twd, tws, twt);
29041 break;
29043 break;
29044 case OPC_ADDV_df:
29045 switch (df) {
29046 case DF_BYTE:
29047 gen_helper_msa_addv_b(cpu_env, twd, tws, twt);
29048 break;
29049 case DF_HALF:
29050 gen_helper_msa_addv_h(cpu_env, twd, tws, twt);
29051 break;
29052 case DF_WORD:
29053 gen_helper_msa_addv_w(cpu_env, twd, tws, twt);
29054 break;
29055 case DF_DOUBLE:
29056 gen_helper_msa_addv_d(cpu_env, twd, tws, twt);
29057 break;
29059 break;
29060 case OPC_AVE_S_df:
29061 switch (df) {
29062 case DF_BYTE:
29063 gen_helper_msa_ave_s_b(cpu_env, twd, tws, twt);
29064 break;
29065 case DF_HALF:
29066 gen_helper_msa_ave_s_h(cpu_env, twd, tws, twt);
29067 break;
29068 case DF_WORD:
29069 gen_helper_msa_ave_s_w(cpu_env, twd, tws, twt);
29070 break;
29071 case DF_DOUBLE:
29072 gen_helper_msa_ave_s_d(cpu_env, twd, tws, twt);
29073 break;
29075 break;
29076 case OPC_AVE_U_df:
29077 switch (df) {
29078 case DF_BYTE:
29079 gen_helper_msa_ave_u_b(cpu_env, twd, tws, twt);
29080 break;
29081 case DF_HALF:
29082 gen_helper_msa_ave_u_h(cpu_env, twd, tws, twt);
29083 break;
29084 case DF_WORD:
29085 gen_helper_msa_ave_u_w(cpu_env, twd, tws, twt);
29086 break;
29087 case DF_DOUBLE:
29088 gen_helper_msa_ave_u_d(cpu_env, twd, tws, twt);
29089 break;
29091 break;
29092 case OPC_AVER_S_df:
29093 switch (df) {
29094 case DF_BYTE:
29095 gen_helper_msa_aver_s_b(cpu_env, twd, tws, twt);
29096 break;
29097 case DF_HALF:
29098 gen_helper_msa_aver_s_h(cpu_env, twd, tws, twt);
29099 break;
29100 case DF_WORD:
29101 gen_helper_msa_aver_s_w(cpu_env, twd, tws, twt);
29102 break;
29103 case DF_DOUBLE:
29104 gen_helper_msa_aver_s_d(cpu_env, twd, tws, twt);
29105 break;
29107 break;
29108 case OPC_AVER_U_df:
29109 switch (df) {
29110 case DF_BYTE:
29111 gen_helper_msa_aver_u_b(cpu_env, twd, tws, twt);
29112 break;
29113 case DF_HALF:
29114 gen_helper_msa_aver_u_h(cpu_env, twd, tws, twt);
29115 break;
29116 case DF_WORD:
29117 gen_helper_msa_aver_u_w(cpu_env, twd, tws, twt);
29118 break;
29119 case DF_DOUBLE:
29120 gen_helper_msa_aver_u_d(cpu_env, twd, tws, twt);
29121 break;
29123 break;
29124 case OPC_CEQ_df:
29125 switch (df) {
29126 case DF_BYTE:
29127 gen_helper_msa_ceq_b(cpu_env, twd, tws, twt);
29128 break;
29129 case DF_HALF:
29130 gen_helper_msa_ceq_h(cpu_env, twd, tws, twt);
29131 break;
29132 case DF_WORD:
29133 gen_helper_msa_ceq_w(cpu_env, twd, tws, twt);
29134 break;
29135 case DF_DOUBLE:
29136 gen_helper_msa_ceq_d(cpu_env, twd, tws, twt);
29137 break;
29139 break;
29140 case OPC_CLE_S_df:
29141 switch (df) {
29142 case DF_BYTE:
29143 gen_helper_msa_cle_s_b(cpu_env, twd, tws, twt);
29144 break;
29145 case DF_HALF:
29146 gen_helper_msa_cle_s_h(cpu_env, twd, tws, twt);
29147 break;
29148 case DF_WORD:
29149 gen_helper_msa_cle_s_w(cpu_env, twd, tws, twt);
29150 break;
29151 case DF_DOUBLE:
29152 gen_helper_msa_cle_s_d(cpu_env, twd, tws, twt);
29153 break;
29155 break;
29156 case OPC_CLE_U_df:
29157 switch (df) {
29158 case DF_BYTE:
29159 gen_helper_msa_cle_u_b(cpu_env, twd, tws, twt);
29160 break;
29161 case DF_HALF:
29162 gen_helper_msa_cle_u_h(cpu_env, twd, tws, twt);
29163 break;
29164 case DF_WORD:
29165 gen_helper_msa_cle_u_w(cpu_env, twd, tws, twt);
29166 break;
29167 case DF_DOUBLE:
29168 gen_helper_msa_cle_u_d(cpu_env, twd, tws, twt);
29169 break;
29171 break;
29172 case OPC_CLT_S_df:
29173 switch (df) {
29174 case DF_BYTE:
29175 gen_helper_msa_clt_s_b(cpu_env, twd, tws, twt);
29176 break;
29177 case DF_HALF:
29178 gen_helper_msa_clt_s_h(cpu_env, twd, tws, twt);
29179 break;
29180 case DF_WORD:
29181 gen_helper_msa_clt_s_w(cpu_env, twd, tws, twt);
29182 break;
29183 case DF_DOUBLE:
29184 gen_helper_msa_clt_s_d(cpu_env, twd, tws, twt);
29185 break;
29187 break;
29188 case OPC_CLT_U_df:
29189 switch (df) {
29190 case DF_BYTE:
29191 gen_helper_msa_clt_u_b(cpu_env, twd, tws, twt);
29192 break;
29193 case DF_HALF:
29194 gen_helper_msa_clt_u_h(cpu_env, twd, tws, twt);
29195 break;
29196 case DF_WORD:
29197 gen_helper_msa_clt_u_w(cpu_env, twd, tws, twt);
29198 break;
29199 case DF_DOUBLE:
29200 gen_helper_msa_clt_u_d(cpu_env, twd, tws, twt);
29201 break;
29203 break;
29204 case OPC_DIV_S_df:
29205 switch (df) {
29206 case DF_BYTE:
29207 gen_helper_msa_div_s_b(cpu_env, twd, tws, twt);
29208 break;
29209 case DF_HALF:
29210 gen_helper_msa_div_s_h(cpu_env, twd, tws, twt);
29211 break;
29212 case DF_WORD:
29213 gen_helper_msa_div_s_w(cpu_env, twd, tws, twt);
29214 break;
29215 case DF_DOUBLE:
29216 gen_helper_msa_div_s_d(cpu_env, twd, tws, twt);
29217 break;
29219 break;
29220 case OPC_DIV_U_df:
29221 switch (df) {
29222 case DF_BYTE:
29223 gen_helper_msa_div_u_b(cpu_env, twd, tws, twt);
29224 break;
29225 case DF_HALF:
29226 gen_helper_msa_div_u_h(cpu_env, twd, tws, twt);
29227 break;
29228 case DF_WORD:
29229 gen_helper_msa_div_u_w(cpu_env, twd, tws, twt);
29230 break;
29231 case DF_DOUBLE:
29232 gen_helper_msa_div_u_d(cpu_env, twd, tws, twt);
29233 break;
29235 break;
29236 case OPC_MAX_A_df:
29237 switch (df) {
29238 case DF_BYTE:
29239 gen_helper_msa_max_a_b(cpu_env, twd, tws, twt);
29240 break;
29241 case DF_HALF:
29242 gen_helper_msa_max_a_h(cpu_env, twd, tws, twt);
29243 break;
29244 case DF_WORD:
29245 gen_helper_msa_max_a_w(cpu_env, twd, tws, twt);
29246 break;
29247 case DF_DOUBLE:
29248 gen_helper_msa_max_a_d(cpu_env, twd, tws, twt);
29249 break;
29251 break;
29252 case OPC_MAX_S_df:
29253 switch (df) {
29254 case DF_BYTE:
29255 gen_helper_msa_max_s_b(cpu_env, twd, tws, twt);
29256 break;
29257 case DF_HALF:
29258 gen_helper_msa_max_s_h(cpu_env, twd, tws, twt);
29259 break;
29260 case DF_WORD:
29261 gen_helper_msa_max_s_w(cpu_env, twd, tws, twt);
29262 break;
29263 case DF_DOUBLE:
29264 gen_helper_msa_max_s_d(cpu_env, twd, tws, twt);
29265 break;
29267 break;
29268 case OPC_MAX_U_df:
29269 switch (df) {
29270 case DF_BYTE:
29271 gen_helper_msa_max_u_b(cpu_env, twd, tws, twt);
29272 break;
29273 case DF_HALF:
29274 gen_helper_msa_max_u_h(cpu_env, twd, tws, twt);
29275 break;
29276 case DF_WORD:
29277 gen_helper_msa_max_u_w(cpu_env, twd, tws, twt);
29278 break;
29279 case DF_DOUBLE:
29280 gen_helper_msa_max_u_d(cpu_env, twd, tws, twt);
29281 break;
29283 break;
29284 case OPC_MIN_A_df:
29285 switch (df) {
29286 case DF_BYTE:
29287 gen_helper_msa_min_a_b(cpu_env, twd, tws, twt);
29288 break;
29289 case DF_HALF:
29290 gen_helper_msa_min_a_h(cpu_env, twd, tws, twt);
29291 break;
29292 case DF_WORD:
29293 gen_helper_msa_min_a_w(cpu_env, twd, tws, twt);
29294 break;
29295 case DF_DOUBLE:
29296 gen_helper_msa_min_a_d(cpu_env, twd, tws, twt);
29297 break;
29299 break;
29300 case OPC_MIN_S_df:
29301 switch (df) {
29302 case DF_BYTE:
29303 gen_helper_msa_min_s_b(cpu_env, twd, tws, twt);
29304 break;
29305 case DF_HALF:
29306 gen_helper_msa_min_s_h(cpu_env, twd, tws, twt);
29307 break;
29308 case DF_WORD:
29309 gen_helper_msa_min_s_w(cpu_env, twd, tws, twt);
29310 break;
29311 case DF_DOUBLE:
29312 gen_helper_msa_min_s_d(cpu_env, twd, tws, twt);
29313 break;
29315 break;
29316 case OPC_MIN_U_df:
29317 switch (df) {
29318 case DF_BYTE:
29319 gen_helper_msa_min_u_b(cpu_env, twd, tws, twt);
29320 break;
29321 case DF_HALF:
29322 gen_helper_msa_min_u_h(cpu_env, twd, tws, twt);
29323 break;
29324 case DF_WORD:
29325 gen_helper_msa_min_u_w(cpu_env, twd, tws, twt);
29326 break;
29327 case DF_DOUBLE:
29328 gen_helper_msa_min_u_d(cpu_env, twd, tws, twt);
29329 break;
29331 break;
29332 case OPC_MOD_S_df:
29333 switch (df) {
29334 case DF_BYTE:
29335 gen_helper_msa_mod_s_b(cpu_env, twd, tws, twt);
29336 break;
29337 case DF_HALF:
29338 gen_helper_msa_mod_s_h(cpu_env, twd, tws, twt);
29339 break;
29340 case DF_WORD:
29341 gen_helper_msa_mod_s_w(cpu_env, twd, tws, twt);
29342 break;
29343 case DF_DOUBLE:
29344 gen_helper_msa_mod_s_d(cpu_env, twd, tws, twt);
29345 break;
29347 break;
29348 case OPC_MOD_U_df:
29349 switch (df) {
29350 case DF_BYTE:
29351 gen_helper_msa_mod_u_b(cpu_env, twd, tws, twt);
29352 break;
29353 case DF_HALF:
29354 gen_helper_msa_mod_u_h(cpu_env, twd, tws, twt);
29355 break;
29356 case DF_WORD:
29357 gen_helper_msa_mod_u_w(cpu_env, twd, tws, twt);
29358 break;
29359 case DF_DOUBLE:
29360 gen_helper_msa_mod_u_d(cpu_env, twd, tws, twt);
29361 break;
29363 break;
29364 case OPC_MADDV_df:
29365 switch (df) {
29366 case DF_BYTE:
29367 gen_helper_msa_maddv_b(cpu_env, twd, tws, twt);
29368 break;
29369 case DF_HALF:
29370 gen_helper_msa_maddv_h(cpu_env, twd, tws, twt);
29371 break;
29372 case DF_WORD:
29373 gen_helper_msa_maddv_w(cpu_env, twd, tws, twt);
29374 break;
29375 case DF_DOUBLE:
29376 gen_helper_msa_maddv_d(cpu_env, twd, tws, twt);
29377 break;
29379 break;
29380 case OPC_MSUBV_df:
29381 switch (df) {
29382 case DF_BYTE:
29383 gen_helper_msa_msubv_b(cpu_env, twd, tws, twt);
29384 break;
29385 case DF_HALF:
29386 gen_helper_msa_msubv_h(cpu_env, twd, tws, twt);
29387 break;
29388 case DF_WORD:
29389 gen_helper_msa_msubv_w(cpu_env, twd, tws, twt);
29390 break;
29391 case DF_DOUBLE:
29392 gen_helper_msa_msubv_d(cpu_env, twd, tws, twt);
29393 break;
29395 break;
29396 case OPC_ASUB_S_df:
29397 switch (df) {
29398 case DF_BYTE:
29399 gen_helper_msa_asub_s_b(cpu_env, twd, tws, twt);
29400 break;
29401 case DF_HALF:
29402 gen_helper_msa_asub_s_h(cpu_env, twd, tws, twt);
29403 break;
29404 case DF_WORD:
29405 gen_helper_msa_asub_s_w(cpu_env, twd, tws, twt);
29406 break;
29407 case DF_DOUBLE:
29408 gen_helper_msa_asub_s_d(cpu_env, twd, tws, twt);
29409 break;
29411 break;
29412 case OPC_ASUB_U_df:
29413 switch (df) {
29414 case DF_BYTE:
29415 gen_helper_msa_asub_u_b(cpu_env, twd, tws, twt);
29416 break;
29417 case DF_HALF:
29418 gen_helper_msa_asub_u_h(cpu_env, twd, tws, twt);
29419 break;
29420 case DF_WORD:
29421 gen_helper_msa_asub_u_w(cpu_env, twd, tws, twt);
29422 break;
29423 case DF_DOUBLE:
29424 gen_helper_msa_asub_u_d(cpu_env, twd, tws, twt);
29425 break;
29427 break;
29428 case OPC_ILVEV_df:
29429 switch (df) {
29430 case DF_BYTE:
29431 gen_helper_msa_ilvev_b(cpu_env, twd, tws, twt);
29432 break;
29433 case DF_HALF:
29434 gen_helper_msa_ilvev_h(cpu_env, twd, tws, twt);
29435 break;
29436 case DF_WORD:
29437 gen_helper_msa_ilvev_w(cpu_env, twd, tws, twt);
29438 break;
29439 case DF_DOUBLE:
29440 gen_helper_msa_ilvev_d(cpu_env, twd, tws, twt);
29441 break;
29443 break;
29444 case OPC_ILVOD_df:
29445 switch (df) {
29446 case DF_BYTE:
29447 gen_helper_msa_ilvod_b(cpu_env, twd, tws, twt);
29448 break;
29449 case DF_HALF:
29450 gen_helper_msa_ilvod_h(cpu_env, twd, tws, twt);
29451 break;
29452 case DF_WORD:
29453 gen_helper_msa_ilvod_w(cpu_env, twd, tws, twt);
29454 break;
29455 case DF_DOUBLE:
29456 gen_helper_msa_ilvod_d(cpu_env, twd, tws, twt);
29457 break;
29459 break;
29460 case OPC_ILVL_df:
29461 switch (df) {
29462 case DF_BYTE:
29463 gen_helper_msa_ilvl_b(cpu_env, twd, tws, twt);
29464 break;
29465 case DF_HALF:
29466 gen_helper_msa_ilvl_h(cpu_env, twd, tws, twt);
29467 break;
29468 case DF_WORD:
29469 gen_helper_msa_ilvl_w(cpu_env, twd, tws, twt);
29470 break;
29471 case DF_DOUBLE:
29472 gen_helper_msa_ilvl_d(cpu_env, twd, tws, twt);
29473 break;
29475 break;
29476 case OPC_ILVR_df:
29477 switch (df) {
29478 case DF_BYTE:
29479 gen_helper_msa_ilvr_b(cpu_env, twd, tws, twt);
29480 break;
29481 case DF_HALF:
29482 gen_helper_msa_ilvr_h(cpu_env, twd, tws, twt);
29483 break;
29484 case DF_WORD:
29485 gen_helper_msa_ilvr_w(cpu_env, twd, tws, twt);
29486 break;
29487 case DF_DOUBLE:
29488 gen_helper_msa_ilvr_d(cpu_env, twd, tws, twt);
29489 break;
29491 break;
29492 case OPC_PCKEV_df:
29493 switch (df) {
29494 case DF_BYTE:
29495 gen_helper_msa_pckev_b(cpu_env, twd, tws, twt);
29496 break;
29497 case DF_HALF:
29498 gen_helper_msa_pckev_h(cpu_env, twd, tws, twt);
29499 break;
29500 case DF_WORD:
29501 gen_helper_msa_pckev_w(cpu_env, twd, tws, twt);
29502 break;
29503 case DF_DOUBLE:
29504 gen_helper_msa_pckev_d(cpu_env, twd, tws, twt);
29505 break;
29507 break;
29508 case OPC_PCKOD_df:
29509 switch (df) {
29510 case DF_BYTE:
29511 gen_helper_msa_pckod_b(cpu_env, twd, tws, twt);
29512 break;
29513 case DF_HALF:
29514 gen_helper_msa_pckod_h(cpu_env, twd, tws, twt);
29515 break;
29516 case DF_WORD:
29517 gen_helper_msa_pckod_w(cpu_env, twd, tws, twt);
29518 break;
29519 case DF_DOUBLE:
29520 gen_helper_msa_pckod_d(cpu_env, twd, tws, twt);
29521 break;
29523 break;
29524 case OPC_SLL_df:
29525 switch (df) {
29526 case DF_BYTE:
29527 gen_helper_msa_sll_b(cpu_env, twd, tws, twt);
29528 break;
29529 case DF_HALF:
29530 gen_helper_msa_sll_h(cpu_env, twd, tws, twt);
29531 break;
29532 case DF_WORD:
29533 gen_helper_msa_sll_w(cpu_env, twd, tws, twt);
29534 break;
29535 case DF_DOUBLE:
29536 gen_helper_msa_sll_d(cpu_env, twd, tws, twt);
29537 break;
29539 break;
29540 case OPC_SRA_df:
29541 switch (df) {
29542 case DF_BYTE:
29543 gen_helper_msa_sra_b(cpu_env, twd, tws, twt);
29544 break;
29545 case DF_HALF:
29546 gen_helper_msa_sra_h(cpu_env, twd, tws, twt);
29547 break;
29548 case DF_WORD:
29549 gen_helper_msa_sra_w(cpu_env, twd, tws, twt);
29550 break;
29551 case DF_DOUBLE:
29552 gen_helper_msa_sra_d(cpu_env, twd, tws, twt);
29553 break;
29555 break;
29556 case OPC_SRAR_df:
29557 switch (df) {
29558 case DF_BYTE:
29559 gen_helper_msa_srar_b(cpu_env, twd, tws, twt);
29560 break;
29561 case DF_HALF:
29562 gen_helper_msa_srar_h(cpu_env, twd, tws, twt);
29563 break;
29564 case DF_WORD:
29565 gen_helper_msa_srar_w(cpu_env, twd, tws, twt);
29566 break;
29567 case DF_DOUBLE:
29568 gen_helper_msa_srar_d(cpu_env, twd, tws, twt);
29569 break;
29571 break;
29572 case OPC_SRL_df:
29573 switch (df) {
29574 case DF_BYTE:
29575 gen_helper_msa_srl_b(cpu_env, twd, tws, twt);
29576 break;
29577 case DF_HALF:
29578 gen_helper_msa_srl_h(cpu_env, twd, tws, twt);
29579 break;
29580 case DF_WORD:
29581 gen_helper_msa_srl_w(cpu_env, twd, tws, twt);
29582 break;
29583 case DF_DOUBLE:
29584 gen_helper_msa_srl_d(cpu_env, twd, tws, twt);
29585 break;
29587 break;
29588 case OPC_SRLR_df:
29589 switch (df) {
29590 case DF_BYTE:
29591 gen_helper_msa_srlr_b(cpu_env, twd, tws, twt);
29592 break;
29593 case DF_HALF:
29594 gen_helper_msa_srlr_h(cpu_env, twd, tws, twt);
29595 break;
29596 case DF_WORD:
29597 gen_helper_msa_srlr_w(cpu_env, twd, tws, twt);
29598 break;
29599 case DF_DOUBLE:
29600 gen_helper_msa_srlr_d(cpu_env, twd, tws, twt);
29601 break;
29603 break;
29604 case OPC_SUBS_S_df:
29605 switch (df) {
29606 case DF_BYTE:
29607 gen_helper_msa_subs_s_b(cpu_env, twd, tws, twt);
29608 break;
29609 case DF_HALF:
29610 gen_helper_msa_subs_s_h(cpu_env, twd, tws, twt);
29611 break;
29612 case DF_WORD:
29613 gen_helper_msa_subs_s_w(cpu_env, twd, tws, twt);
29614 break;
29615 case DF_DOUBLE:
29616 gen_helper_msa_subs_s_d(cpu_env, twd, tws, twt);
29617 break;
29619 break;
29620 case OPC_MULV_df:
29621 switch (df) {
29622 case DF_BYTE:
29623 gen_helper_msa_mulv_b(cpu_env, twd, tws, twt);
29624 break;
29625 case DF_HALF:
29626 gen_helper_msa_mulv_h(cpu_env, twd, tws, twt);
29627 break;
29628 case DF_WORD:
29629 gen_helper_msa_mulv_w(cpu_env, twd, tws, twt);
29630 break;
29631 case DF_DOUBLE:
29632 gen_helper_msa_mulv_d(cpu_env, twd, tws, twt);
29633 break;
29635 break;
29636 case OPC_SLD_df:
29637 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
29638 break;
29639 case OPC_VSHF_df:
29640 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
29641 break;
29642 case OPC_SUBV_df:
29643 switch (df) {
29644 case DF_BYTE:
29645 gen_helper_msa_subv_b(cpu_env, twd, tws, twt);
29646 break;
29647 case DF_HALF:
29648 gen_helper_msa_subv_h(cpu_env, twd, tws, twt);
29649 break;
29650 case DF_WORD:
29651 gen_helper_msa_subv_w(cpu_env, twd, tws, twt);
29652 break;
29653 case DF_DOUBLE:
29654 gen_helper_msa_subv_d(cpu_env, twd, tws, twt);
29655 break;
29657 break;
29658 case OPC_SUBS_U_df:
29659 switch (df) {
29660 case DF_BYTE:
29661 gen_helper_msa_subs_u_b(cpu_env, twd, tws, twt);
29662 break;
29663 case DF_HALF:
29664 gen_helper_msa_subs_u_h(cpu_env, twd, tws, twt);
29665 break;
29666 case DF_WORD:
29667 gen_helper_msa_subs_u_w(cpu_env, twd, tws, twt);
29668 break;
29669 case DF_DOUBLE:
29670 gen_helper_msa_subs_u_d(cpu_env, twd, tws, twt);
29671 break;
29673 break;
29674 case OPC_SPLAT_df:
29675 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
29676 break;
29677 case OPC_SUBSUS_U_df:
29678 switch (df) {
29679 case DF_BYTE:
29680 gen_helper_msa_subsus_u_b(cpu_env, twd, tws, twt);
29681 break;
29682 case DF_HALF:
29683 gen_helper_msa_subsus_u_h(cpu_env, twd, tws, twt);
29684 break;
29685 case DF_WORD:
29686 gen_helper_msa_subsus_u_w(cpu_env, twd, tws, twt);
29687 break;
29688 case DF_DOUBLE:
29689 gen_helper_msa_subsus_u_d(cpu_env, twd, tws, twt);
29690 break;
29692 break;
29693 case OPC_SUBSUU_S_df:
29694 switch (df) {
29695 case DF_BYTE:
29696 gen_helper_msa_subsuu_s_b(cpu_env, twd, tws, twt);
29697 break;
29698 case DF_HALF:
29699 gen_helper_msa_subsuu_s_h(cpu_env, twd, tws, twt);
29700 break;
29701 case DF_WORD:
29702 gen_helper_msa_subsuu_s_w(cpu_env, twd, tws, twt);
29703 break;
29704 case DF_DOUBLE:
29705 gen_helper_msa_subsuu_s_d(cpu_env, twd, tws, twt);
29706 break;
29708 break;
29710 case OPC_DOTP_S_df:
29711 case OPC_DOTP_U_df:
29712 case OPC_DPADD_S_df:
29713 case OPC_DPADD_U_df:
29714 case OPC_DPSUB_S_df:
29715 case OPC_HADD_S_df:
29716 case OPC_DPSUB_U_df:
29717 case OPC_HADD_U_df:
29718 case OPC_HSUB_S_df:
29719 case OPC_HSUB_U_df:
29720 if (df == DF_BYTE) {
29721 gen_reserved_instruction(ctx);
29722 break;
29724 switch (MASK_MSA_3R(ctx->opcode)) {
29725 case OPC_HADD_S_df:
29726 switch (df) {
29727 case DF_HALF:
29728 gen_helper_msa_hadd_s_h(cpu_env, twd, tws, twt);
29729 break;
29730 case DF_WORD:
29731 gen_helper_msa_hadd_s_w(cpu_env, twd, tws, twt);
29732 break;
29733 case DF_DOUBLE:
29734 gen_helper_msa_hadd_s_d(cpu_env, twd, tws, twt);
29735 break;
29737 break;
29738 case OPC_HADD_U_df:
29739 switch (df) {
29740 case DF_HALF:
29741 gen_helper_msa_hadd_u_h(cpu_env, twd, tws, twt);
29742 break;
29743 case DF_WORD:
29744 gen_helper_msa_hadd_u_w(cpu_env, twd, tws, twt);
29745 break;
29746 case DF_DOUBLE:
29747 gen_helper_msa_hadd_u_d(cpu_env, twd, tws, twt);
29748 break;
29750 break;
29751 case OPC_HSUB_S_df:
29752 switch (df) {
29753 case DF_HALF:
29754 gen_helper_msa_hsub_s_h(cpu_env, twd, tws, twt);
29755 break;
29756 case DF_WORD:
29757 gen_helper_msa_hsub_s_w(cpu_env, twd, tws, twt);
29758 break;
29759 case DF_DOUBLE:
29760 gen_helper_msa_hsub_s_d(cpu_env, twd, tws, twt);
29761 break;
29763 break;
29764 case OPC_HSUB_U_df:
29765 switch (df) {
29766 case DF_HALF:
29767 gen_helper_msa_hsub_u_h(cpu_env, twd, tws, twt);
29768 break;
29769 case DF_WORD:
29770 gen_helper_msa_hsub_u_w(cpu_env, twd, tws, twt);
29771 break;
29772 case DF_DOUBLE:
29773 gen_helper_msa_hsub_u_d(cpu_env, twd, tws, twt);
29774 break;
29776 break;
29777 case OPC_DOTP_S_df:
29778 switch (df) {
29779 case DF_HALF:
29780 gen_helper_msa_dotp_s_h(cpu_env, twd, tws, twt);
29781 break;
29782 case DF_WORD:
29783 gen_helper_msa_dotp_s_w(cpu_env, twd, tws, twt);
29784 break;
29785 case DF_DOUBLE:
29786 gen_helper_msa_dotp_s_d(cpu_env, twd, tws, twt);
29787 break;
29789 break;
29790 case OPC_DOTP_U_df:
29791 switch (df) {
29792 case DF_HALF:
29793 gen_helper_msa_dotp_u_h(cpu_env, twd, tws, twt);
29794 break;
29795 case DF_WORD:
29796 gen_helper_msa_dotp_u_w(cpu_env, twd, tws, twt);
29797 break;
29798 case DF_DOUBLE:
29799 gen_helper_msa_dotp_u_d(cpu_env, twd, tws, twt);
29800 break;
29802 break;
29803 case OPC_DPADD_S_df:
29804 switch (df) {
29805 case DF_HALF:
29806 gen_helper_msa_dpadd_s_h(cpu_env, twd, tws, twt);
29807 break;
29808 case DF_WORD:
29809 gen_helper_msa_dpadd_s_w(cpu_env, twd, tws, twt);
29810 break;
29811 case DF_DOUBLE:
29812 gen_helper_msa_dpadd_s_d(cpu_env, twd, tws, twt);
29813 break;
29815 break;
29816 case OPC_DPADD_U_df:
29817 switch (df) {
29818 case DF_HALF:
29819 gen_helper_msa_dpadd_u_h(cpu_env, twd, tws, twt);
29820 break;
29821 case DF_WORD:
29822 gen_helper_msa_dpadd_u_w(cpu_env, twd, tws, twt);
29823 break;
29824 case DF_DOUBLE:
29825 gen_helper_msa_dpadd_u_d(cpu_env, twd, tws, twt);
29826 break;
29828 break;
29829 case OPC_DPSUB_S_df:
29830 switch (df) {
29831 case DF_HALF:
29832 gen_helper_msa_dpsub_s_h(cpu_env, twd, tws, twt);
29833 break;
29834 case DF_WORD:
29835 gen_helper_msa_dpsub_s_w(cpu_env, twd, tws, twt);
29836 break;
29837 case DF_DOUBLE:
29838 gen_helper_msa_dpsub_s_d(cpu_env, twd, tws, twt);
29839 break;
29841 break;
29842 case OPC_DPSUB_U_df:
29843 switch (df) {
29844 case DF_HALF:
29845 gen_helper_msa_dpsub_u_h(cpu_env, twd, tws, twt);
29846 break;
29847 case DF_WORD:
29848 gen_helper_msa_dpsub_u_w(cpu_env, twd, tws, twt);
29849 break;
29850 case DF_DOUBLE:
29851 gen_helper_msa_dpsub_u_d(cpu_env, twd, tws, twt);
29852 break;
29854 break;
29856 break;
29857 default:
29858 MIPS_INVAL("MSA instruction");
29859 gen_reserved_instruction(ctx);
29860 break;
29862 tcg_temp_free_i32(twd);
29863 tcg_temp_free_i32(tws);
29864 tcg_temp_free_i32(twt);
29865 tcg_temp_free_i32(tdf);
29868 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
29870 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
29871 uint8_t source = (ctx->opcode >> 11) & 0x1f;
29872 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
29873 TCGv telm = tcg_temp_new();
29874 TCGv_i32 tsr = tcg_const_i32(source);
29875 TCGv_i32 tdt = tcg_const_i32(dest);
29877 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
29878 case OPC_CTCMSA:
29879 gen_load_gpr(telm, source);
29880 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
29881 break;
29882 case OPC_CFCMSA:
29883 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
29884 gen_store_gpr(telm, dest);
29885 break;
29886 case OPC_MOVE_V:
29887 gen_helper_msa_move_v(cpu_env, tdt, tsr);
29888 break;
29889 default:
29890 MIPS_INVAL("MSA instruction");
29891 gen_reserved_instruction(ctx);
29892 break;
29895 tcg_temp_free(telm);
29896 tcg_temp_free_i32(tdt);
29897 tcg_temp_free_i32(tsr);
29900 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
29901 uint32_t n)
29903 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
29904 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29905 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29907 TCGv_i32 tws = tcg_const_i32(ws);
29908 TCGv_i32 twd = tcg_const_i32(wd);
29909 TCGv_i32 tn = tcg_const_i32(n);
29910 TCGv_i32 tdf = tcg_const_i32(df);
29912 switch (MASK_MSA_ELM(ctx->opcode)) {
29913 case OPC_SLDI_df:
29914 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
29915 break;
29916 case OPC_SPLATI_df:
29917 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
29918 break;
29919 case OPC_INSVE_df:
29920 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
29921 break;
29922 case OPC_COPY_S_df:
29923 case OPC_COPY_U_df:
29924 case OPC_INSERT_df:
29925 #if !defined(TARGET_MIPS64)
29926 /* Double format valid only for MIPS64 */
29927 if (df == DF_DOUBLE) {
29928 gen_reserved_instruction(ctx);
29929 break;
29931 if ((MASK_MSA_ELM(ctx->opcode) == OPC_COPY_U_df) &&
29932 (df == DF_WORD)) {
29933 gen_reserved_instruction(ctx);
29934 break;
29936 #endif
29937 switch (MASK_MSA_ELM(ctx->opcode)) {
29938 case OPC_COPY_S_df:
29939 if (likely(wd != 0)) {
29940 switch (df) {
29941 case DF_BYTE:
29942 gen_helper_msa_copy_s_b(cpu_env, twd, tws, tn);
29943 break;
29944 case DF_HALF:
29945 gen_helper_msa_copy_s_h(cpu_env, twd, tws, tn);
29946 break;
29947 case DF_WORD:
29948 gen_helper_msa_copy_s_w(cpu_env, twd, tws, tn);
29949 break;
29950 #if defined(TARGET_MIPS64)
29951 case DF_DOUBLE:
29952 gen_helper_msa_copy_s_d(cpu_env, twd, tws, tn);
29953 break;
29954 #endif
29955 default:
29956 assert(0);
29959 break;
29960 case OPC_COPY_U_df:
29961 if (likely(wd != 0)) {
29962 switch (df) {
29963 case DF_BYTE:
29964 gen_helper_msa_copy_u_b(cpu_env, twd, tws, tn);
29965 break;
29966 case DF_HALF:
29967 gen_helper_msa_copy_u_h(cpu_env, twd, tws, tn);
29968 break;
29969 #if defined(TARGET_MIPS64)
29970 case DF_WORD:
29971 gen_helper_msa_copy_u_w(cpu_env, twd, tws, tn);
29972 break;
29973 #endif
29974 default:
29975 assert(0);
29978 break;
29979 case OPC_INSERT_df:
29980 switch (df) {
29981 case DF_BYTE:
29982 gen_helper_msa_insert_b(cpu_env, twd, tws, tn);
29983 break;
29984 case DF_HALF:
29985 gen_helper_msa_insert_h(cpu_env, twd, tws, tn);
29986 break;
29987 case DF_WORD:
29988 gen_helper_msa_insert_w(cpu_env, twd, tws, tn);
29989 break;
29990 #if defined(TARGET_MIPS64)
29991 case DF_DOUBLE:
29992 gen_helper_msa_insert_d(cpu_env, twd, tws, tn);
29993 break;
29994 #endif
29995 default:
29996 assert(0);
29998 break;
30000 break;
30001 default:
30002 MIPS_INVAL("MSA instruction");
30003 gen_reserved_instruction(ctx);
30005 tcg_temp_free_i32(twd);
30006 tcg_temp_free_i32(tws);
30007 tcg_temp_free_i32(tn);
30008 tcg_temp_free_i32(tdf);
30011 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
30013 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
30014 uint32_t df = 0, n = 0;
30016 if ((dfn & 0x30) == 0x00) {
30017 n = dfn & 0x0f;
30018 df = DF_BYTE;
30019 } else if ((dfn & 0x38) == 0x20) {
30020 n = dfn & 0x07;
30021 df = DF_HALF;
30022 } else if ((dfn & 0x3c) == 0x30) {
30023 n = dfn & 0x03;
30024 df = DF_WORD;
30025 } else if ((dfn & 0x3e) == 0x38) {
30026 n = dfn & 0x01;
30027 df = DF_DOUBLE;
30028 } else if (dfn == 0x3E) {
30029 /* CTCMSA, CFCMSA, MOVE.V */
30030 gen_msa_elm_3e(env, ctx);
30031 return;
30032 } else {
30033 gen_reserved_instruction(ctx);
30034 return;
30037 gen_msa_elm_df(env, ctx, df, n);
30040 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
30042 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
30043 uint8_t df = (ctx->opcode >> 21) & 0x1;
30044 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
30045 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
30046 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30048 TCGv_i32 twd = tcg_const_i32(wd);
30049 TCGv_i32 tws = tcg_const_i32(ws);
30050 TCGv_i32 twt = tcg_const_i32(wt);
30051 TCGv_i32 tdf = tcg_temp_new_i32();
30053 /* adjust df value for floating-point instruction */
30054 tcg_gen_movi_i32(tdf, df + 2);
30056 switch (MASK_MSA_3RF(ctx->opcode)) {
30057 case OPC_FCAF_df:
30058 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
30059 break;
30060 case OPC_FADD_df:
30061 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
30062 break;
30063 case OPC_FCUN_df:
30064 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
30065 break;
30066 case OPC_FSUB_df:
30067 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
30068 break;
30069 case OPC_FCOR_df:
30070 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
30071 break;
30072 case OPC_FCEQ_df:
30073 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
30074 break;
30075 case OPC_FMUL_df:
30076 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
30077 break;
30078 case OPC_FCUNE_df:
30079 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
30080 break;
30081 case OPC_FCUEQ_df:
30082 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
30083 break;
30084 case OPC_FDIV_df:
30085 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
30086 break;
30087 case OPC_FCNE_df:
30088 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
30089 break;
30090 case OPC_FCLT_df:
30091 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
30092 break;
30093 case OPC_FMADD_df:
30094 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
30095 break;
30096 case OPC_MUL_Q_df:
30097 tcg_gen_movi_i32(tdf, df + 1);
30098 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
30099 break;
30100 case OPC_FCULT_df:
30101 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
30102 break;
30103 case OPC_FMSUB_df:
30104 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
30105 break;
30106 case OPC_MADD_Q_df:
30107 tcg_gen_movi_i32(tdf, df + 1);
30108 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
30109 break;
30110 case OPC_FCLE_df:
30111 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
30112 break;
30113 case OPC_MSUB_Q_df:
30114 tcg_gen_movi_i32(tdf, df + 1);
30115 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
30116 break;
30117 case OPC_FCULE_df:
30118 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
30119 break;
30120 case OPC_FEXP2_df:
30121 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
30122 break;
30123 case OPC_FSAF_df:
30124 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
30125 break;
30126 case OPC_FEXDO_df:
30127 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
30128 break;
30129 case OPC_FSUN_df:
30130 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
30131 break;
30132 case OPC_FSOR_df:
30133 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
30134 break;
30135 case OPC_FSEQ_df:
30136 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
30137 break;
30138 case OPC_FTQ_df:
30139 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
30140 break;
30141 case OPC_FSUNE_df:
30142 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
30143 break;
30144 case OPC_FSUEQ_df:
30145 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
30146 break;
30147 case OPC_FSNE_df:
30148 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
30149 break;
30150 case OPC_FSLT_df:
30151 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
30152 break;
30153 case OPC_FMIN_df:
30154 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
30155 break;
30156 case OPC_MULR_Q_df:
30157 tcg_gen_movi_i32(tdf, df + 1);
30158 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
30159 break;
30160 case OPC_FSULT_df:
30161 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
30162 break;
30163 case OPC_FMIN_A_df:
30164 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
30165 break;
30166 case OPC_MADDR_Q_df:
30167 tcg_gen_movi_i32(tdf, df + 1);
30168 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
30169 break;
30170 case OPC_FSLE_df:
30171 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
30172 break;
30173 case OPC_FMAX_df:
30174 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
30175 break;
30176 case OPC_MSUBR_Q_df:
30177 tcg_gen_movi_i32(tdf, df + 1);
30178 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
30179 break;
30180 case OPC_FSULE_df:
30181 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
30182 break;
30183 case OPC_FMAX_A_df:
30184 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
30185 break;
30186 default:
30187 MIPS_INVAL("MSA instruction");
30188 gen_reserved_instruction(ctx);
30189 break;
30192 tcg_temp_free_i32(twd);
30193 tcg_temp_free_i32(tws);
30194 tcg_temp_free_i32(twt);
30195 tcg_temp_free_i32(tdf);
30198 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
30200 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
30201 (op & (0x7 << 18)))
30202 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
30203 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
30204 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30205 uint8_t df = (ctx->opcode >> 16) & 0x3;
30206 TCGv_i32 twd = tcg_const_i32(wd);
30207 TCGv_i32 tws = tcg_const_i32(ws);
30208 TCGv_i32 twt = tcg_const_i32(wt);
30209 TCGv_i32 tdf = tcg_const_i32(df);
30211 switch (MASK_MSA_2R(ctx->opcode)) {
30212 case OPC_FILL_df:
30213 #if !defined(TARGET_MIPS64)
30214 /* Double format valid only for MIPS64 */
30215 if (df == DF_DOUBLE) {
30216 gen_reserved_instruction(ctx);
30217 break;
30219 #endif
30220 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
30221 break;
30222 case OPC_NLOC_df:
30223 switch (df) {
30224 case DF_BYTE:
30225 gen_helper_msa_nloc_b(cpu_env, twd, tws);
30226 break;
30227 case DF_HALF:
30228 gen_helper_msa_nloc_h(cpu_env, twd, tws);
30229 break;
30230 case DF_WORD:
30231 gen_helper_msa_nloc_w(cpu_env, twd, tws);
30232 break;
30233 case DF_DOUBLE:
30234 gen_helper_msa_nloc_d(cpu_env, twd, tws);
30235 break;
30237 break;
30238 case OPC_NLZC_df:
30239 switch (df) {
30240 case DF_BYTE:
30241 gen_helper_msa_nlzc_b(cpu_env, twd, tws);
30242 break;
30243 case DF_HALF:
30244 gen_helper_msa_nlzc_h(cpu_env, twd, tws);
30245 break;
30246 case DF_WORD:
30247 gen_helper_msa_nlzc_w(cpu_env, twd, tws);
30248 break;
30249 case DF_DOUBLE:
30250 gen_helper_msa_nlzc_d(cpu_env, twd, tws);
30251 break;
30253 break;
30254 case OPC_PCNT_df:
30255 switch (df) {
30256 case DF_BYTE:
30257 gen_helper_msa_pcnt_b(cpu_env, twd, tws);
30258 break;
30259 case DF_HALF:
30260 gen_helper_msa_pcnt_h(cpu_env, twd, tws);
30261 break;
30262 case DF_WORD:
30263 gen_helper_msa_pcnt_w(cpu_env, twd, tws);
30264 break;
30265 case DF_DOUBLE:
30266 gen_helper_msa_pcnt_d(cpu_env, twd, tws);
30267 break;
30269 break;
30270 default:
30271 MIPS_INVAL("MSA instruction");
30272 gen_reserved_instruction(ctx);
30273 break;
30276 tcg_temp_free_i32(twd);
30277 tcg_temp_free_i32(tws);
30278 tcg_temp_free_i32(twt);
30279 tcg_temp_free_i32(tdf);
30282 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
30284 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
30285 (op & (0xf << 17)))
30286 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
30287 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
30288 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30289 uint8_t df = (ctx->opcode >> 16) & 0x1;
30290 TCGv_i32 twd = tcg_const_i32(wd);
30291 TCGv_i32 tws = tcg_const_i32(ws);
30292 TCGv_i32 twt = tcg_const_i32(wt);
30293 /* adjust df value for floating-point instruction */
30294 TCGv_i32 tdf = tcg_const_i32(df + 2);
30296 switch (MASK_MSA_2RF(ctx->opcode)) {
30297 case OPC_FCLASS_df:
30298 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
30299 break;
30300 case OPC_FTRUNC_S_df:
30301 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
30302 break;
30303 case OPC_FTRUNC_U_df:
30304 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
30305 break;
30306 case OPC_FSQRT_df:
30307 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
30308 break;
30309 case OPC_FRSQRT_df:
30310 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
30311 break;
30312 case OPC_FRCP_df:
30313 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
30314 break;
30315 case OPC_FRINT_df:
30316 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
30317 break;
30318 case OPC_FLOG2_df:
30319 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
30320 break;
30321 case OPC_FEXUPL_df:
30322 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
30323 break;
30324 case OPC_FEXUPR_df:
30325 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
30326 break;
30327 case OPC_FFQL_df:
30328 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
30329 break;
30330 case OPC_FFQR_df:
30331 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
30332 break;
30333 case OPC_FTINT_S_df:
30334 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
30335 break;
30336 case OPC_FTINT_U_df:
30337 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
30338 break;
30339 case OPC_FFINT_S_df:
30340 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
30341 break;
30342 case OPC_FFINT_U_df:
30343 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
30344 break;
30347 tcg_temp_free_i32(twd);
30348 tcg_temp_free_i32(tws);
30349 tcg_temp_free_i32(twt);
30350 tcg_temp_free_i32(tdf);
30353 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
30355 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
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 TCGv_i32 twd = tcg_const_i32(wd);
30360 TCGv_i32 tws = tcg_const_i32(ws);
30361 TCGv_i32 twt = tcg_const_i32(wt);
30363 switch (MASK_MSA_VEC(ctx->opcode)) {
30364 case OPC_AND_V:
30365 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
30366 break;
30367 case OPC_OR_V:
30368 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
30369 break;
30370 case OPC_NOR_V:
30371 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
30372 break;
30373 case OPC_XOR_V:
30374 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
30375 break;
30376 case OPC_BMNZ_V:
30377 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
30378 break;
30379 case OPC_BMZ_V:
30380 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
30381 break;
30382 case OPC_BSEL_V:
30383 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
30384 break;
30385 default:
30386 MIPS_INVAL("MSA instruction");
30387 gen_reserved_instruction(ctx);
30388 break;
30391 tcg_temp_free_i32(twd);
30392 tcg_temp_free_i32(tws);
30393 tcg_temp_free_i32(twt);
30396 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
30398 switch (MASK_MSA_VEC(ctx->opcode)) {
30399 case OPC_AND_V:
30400 case OPC_OR_V:
30401 case OPC_NOR_V:
30402 case OPC_XOR_V:
30403 case OPC_BMNZ_V:
30404 case OPC_BMZ_V:
30405 case OPC_BSEL_V:
30406 gen_msa_vec_v(env, ctx);
30407 break;
30408 case OPC_MSA_2R:
30409 gen_msa_2r(env, ctx);
30410 break;
30411 case OPC_MSA_2RF:
30412 gen_msa_2rf(env, ctx);
30413 break;
30414 default:
30415 MIPS_INVAL("MSA instruction");
30416 gen_reserved_instruction(ctx);
30417 break;
30421 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
30423 uint32_t opcode = ctx->opcode;
30424 check_insn(ctx, ASE_MSA);
30425 check_msa_access(ctx);
30427 switch (MASK_MSA_MINOR(opcode)) {
30428 case OPC_MSA_I8_00:
30429 case OPC_MSA_I8_01:
30430 case OPC_MSA_I8_02:
30431 gen_msa_i8(env, ctx);
30432 break;
30433 case OPC_MSA_I5_06:
30434 case OPC_MSA_I5_07:
30435 gen_msa_i5(env, ctx);
30436 break;
30437 case OPC_MSA_BIT_09:
30438 case OPC_MSA_BIT_0A:
30439 gen_msa_bit(env, ctx);
30440 break;
30441 case OPC_MSA_3R_0D:
30442 case OPC_MSA_3R_0E:
30443 case OPC_MSA_3R_0F:
30444 case OPC_MSA_3R_10:
30445 case OPC_MSA_3R_11:
30446 case OPC_MSA_3R_12:
30447 case OPC_MSA_3R_13:
30448 case OPC_MSA_3R_14:
30449 case OPC_MSA_3R_15:
30450 gen_msa_3r(env, ctx);
30451 break;
30452 case OPC_MSA_ELM:
30453 gen_msa_elm(env, ctx);
30454 break;
30455 case OPC_MSA_3RF_1A:
30456 case OPC_MSA_3RF_1B:
30457 case OPC_MSA_3RF_1C:
30458 gen_msa_3rf(env, ctx);
30459 break;
30460 case OPC_MSA_VEC:
30461 gen_msa_vec(env, ctx);
30462 break;
30463 case OPC_LD_B:
30464 case OPC_LD_H:
30465 case OPC_LD_W:
30466 case OPC_LD_D:
30467 case OPC_ST_B:
30468 case OPC_ST_H:
30469 case OPC_ST_W:
30470 case OPC_ST_D:
30472 int32_t s10 = sextract32(ctx->opcode, 16, 10);
30473 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
30474 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30475 uint8_t df = (ctx->opcode >> 0) & 0x3;
30477 TCGv_i32 twd = tcg_const_i32(wd);
30478 TCGv taddr = tcg_temp_new();
30479 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
30481 switch (MASK_MSA_MINOR(opcode)) {
30482 case OPC_LD_B:
30483 gen_helper_msa_ld_b(cpu_env, twd, taddr);
30484 break;
30485 case OPC_LD_H:
30486 gen_helper_msa_ld_h(cpu_env, twd, taddr);
30487 break;
30488 case OPC_LD_W:
30489 gen_helper_msa_ld_w(cpu_env, twd, taddr);
30490 break;
30491 case OPC_LD_D:
30492 gen_helper_msa_ld_d(cpu_env, twd, taddr);
30493 break;
30494 case OPC_ST_B:
30495 gen_helper_msa_st_b(cpu_env, twd, taddr);
30496 break;
30497 case OPC_ST_H:
30498 gen_helper_msa_st_h(cpu_env, twd, taddr);
30499 break;
30500 case OPC_ST_W:
30501 gen_helper_msa_st_w(cpu_env, twd, taddr);
30502 break;
30503 case OPC_ST_D:
30504 gen_helper_msa_st_d(cpu_env, twd, taddr);
30505 break;
30508 tcg_temp_free_i32(twd);
30509 tcg_temp_free(taddr);
30511 break;
30512 default:
30513 MIPS_INVAL("MSA instruction");
30514 gen_reserved_instruction(ctx);
30515 break;
30520 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
30522 int32_t offset;
30523 int rs, rt, rd, sa;
30524 uint32_t op, op1;
30525 int16_t imm;
30527 /* make sure instructions are on a word boundary */
30528 if (ctx->base.pc_next & 0x3) {
30529 env->CP0_BadVAddr = ctx->base.pc_next;
30530 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
30531 return;
30534 /* Handle blikely not taken case */
30535 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
30536 TCGLabel *l1 = gen_new_label();
30538 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
30539 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
30540 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
30541 gen_set_label(l1);
30544 op = MASK_OP_MAJOR(ctx->opcode);
30545 rs = (ctx->opcode >> 21) & 0x1f;
30546 rt = (ctx->opcode >> 16) & 0x1f;
30547 rd = (ctx->opcode >> 11) & 0x1f;
30548 sa = (ctx->opcode >> 6) & 0x1f;
30549 imm = (int16_t)ctx->opcode;
30550 switch (op) {
30551 case OPC_SPECIAL:
30552 decode_opc_special(env, ctx);
30553 break;
30554 case OPC_SPECIAL2:
30555 #if defined(TARGET_MIPS64)
30556 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
30557 decode_mmi(env, ctx);
30558 #else
30559 if (ctx->insn_flags & ASE_MXU) {
30560 decode_opc_mxu(env, ctx);
30561 #endif
30562 } else {
30563 decode_opc_special2_legacy(env, ctx);
30565 break;
30566 case OPC_SPECIAL3:
30567 #if defined(TARGET_MIPS64)
30568 if (ctx->insn_flags & INSN_R5900) {
30569 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
30570 } else {
30571 decode_opc_special3(env, ctx);
30573 #else
30574 decode_opc_special3(env, ctx);
30575 #endif
30576 break;
30577 case OPC_REGIMM:
30578 op1 = MASK_REGIMM(ctx->opcode);
30579 switch (op1) {
30580 case OPC_BLTZL: /* REGIMM branches */
30581 case OPC_BGEZL:
30582 case OPC_BLTZALL:
30583 case OPC_BGEZALL:
30584 check_insn(ctx, ISA_MIPS2);
30585 check_insn_opc_removed(ctx, ISA_MIPS_R6);
30586 /* Fallthrough */
30587 case OPC_BLTZ:
30588 case OPC_BGEZ:
30589 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
30590 break;
30591 case OPC_BLTZAL:
30592 case OPC_BGEZAL:
30593 if (ctx->insn_flags & ISA_MIPS_R6) {
30594 if (rs == 0) {
30595 /* OPC_NAL, OPC_BAL */
30596 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
30597 } else {
30598 gen_reserved_instruction(ctx);
30600 } else {
30601 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
30603 break;
30604 case OPC_TGEI: /* REGIMM traps */
30605 case OPC_TGEIU:
30606 case OPC_TLTI:
30607 case OPC_TLTIU:
30608 case OPC_TEQI:
30610 case OPC_TNEI:
30611 check_insn(ctx, ISA_MIPS2);
30612 check_insn_opc_removed(ctx, ISA_MIPS_R6);
30613 gen_trap(ctx, op1, rs, -1, imm);
30614 break;
30615 case OPC_SIGRIE:
30616 check_insn(ctx, ISA_MIPS_R6);
30617 gen_reserved_instruction(ctx);
30618 break;
30619 case OPC_SYNCI:
30620 check_insn(ctx, ISA_MIPS_R2);
30622 * Break the TB to be able to sync copied instructions
30623 * immediately.
30625 ctx->base.is_jmp = DISAS_STOP;
30626 break;
30627 case OPC_BPOSGE32: /* MIPS DSP branch */
30628 #if defined(TARGET_MIPS64)
30629 case OPC_BPOSGE64:
30630 #endif
30631 check_dsp(ctx);
30632 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
30633 break;
30634 #if defined(TARGET_MIPS64)
30635 case OPC_DAHI:
30636 check_insn(ctx, ISA_MIPS_R6);
30637 check_mips_64(ctx);
30638 if (rs != 0) {
30639 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
30641 break;
30642 case OPC_DATI:
30643 check_insn(ctx, ISA_MIPS_R6);
30644 check_mips_64(ctx);
30645 if (rs != 0) {
30646 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
30648 break;
30649 #endif
30650 default: /* Invalid */
30651 MIPS_INVAL("regimm");
30652 gen_reserved_instruction(ctx);
30653 break;
30655 break;
30656 case OPC_CP0:
30657 check_cp0_enabled(ctx);
30658 op1 = MASK_CP0(ctx->opcode);
30659 switch (op1) {
30660 case OPC_MFC0:
30661 case OPC_MTC0:
30662 case OPC_MFTR:
30663 case OPC_MTTR:
30664 case OPC_MFHC0:
30665 case OPC_MTHC0:
30666 #if defined(TARGET_MIPS64)
30667 case OPC_DMFC0:
30668 case OPC_DMTC0:
30669 #endif
30670 #ifndef CONFIG_USER_ONLY
30671 gen_cp0(env, ctx, op1, rt, rd);
30672 #endif /* !CONFIG_USER_ONLY */
30673 break;
30674 case OPC_C0:
30675 case OPC_C0_1:
30676 case OPC_C0_2:
30677 case OPC_C0_3:
30678 case OPC_C0_4:
30679 case OPC_C0_5:
30680 case OPC_C0_6:
30681 case OPC_C0_7:
30682 case OPC_C0_8:
30683 case OPC_C0_9:
30684 case OPC_C0_A:
30685 case OPC_C0_B:
30686 case OPC_C0_C:
30687 case OPC_C0_D:
30688 case OPC_C0_E:
30689 case OPC_C0_F:
30690 #ifndef CONFIG_USER_ONLY
30691 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
30692 #endif /* !CONFIG_USER_ONLY */
30693 break;
30694 case OPC_MFMC0:
30695 #ifndef CONFIG_USER_ONLY
30697 uint32_t op2;
30698 TCGv t0 = tcg_temp_new();
30700 op2 = MASK_MFMC0(ctx->opcode);
30701 switch (op2) {
30702 case OPC_DMT:
30703 check_cp0_mt(ctx);
30704 gen_helper_dmt(t0);
30705 gen_store_gpr(t0, rt);
30706 break;
30707 case OPC_EMT:
30708 check_cp0_mt(ctx);
30709 gen_helper_emt(t0);
30710 gen_store_gpr(t0, rt);
30711 break;
30712 case OPC_DVPE:
30713 check_cp0_mt(ctx);
30714 gen_helper_dvpe(t0, cpu_env);
30715 gen_store_gpr(t0, rt);
30716 break;
30717 case OPC_EVPE:
30718 check_cp0_mt(ctx);
30719 gen_helper_evpe(t0, cpu_env);
30720 gen_store_gpr(t0, rt);
30721 break;
30722 case OPC_DVP:
30723 check_insn(ctx, ISA_MIPS_R6);
30724 if (ctx->vp) {
30725 gen_helper_dvp(t0, cpu_env);
30726 gen_store_gpr(t0, rt);
30728 break;
30729 case OPC_EVP:
30730 check_insn(ctx, ISA_MIPS_R6);
30731 if (ctx->vp) {
30732 gen_helper_evp(t0, cpu_env);
30733 gen_store_gpr(t0, rt);
30735 break;
30736 case OPC_DI:
30737 check_insn(ctx, ISA_MIPS_R2);
30738 save_cpu_state(ctx, 1);
30739 gen_helper_di(t0, cpu_env);
30740 gen_store_gpr(t0, rt);
30742 * Stop translation as we may have switched
30743 * the execution mode.
30745 ctx->base.is_jmp = DISAS_STOP;
30746 break;
30747 case OPC_EI:
30748 check_insn(ctx, ISA_MIPS_R2);
30749 save_cpu_state(ctx, 1);
30750 gen_helper_ei(t0, cpu_env);
30751 gen_store_gpr(t0, rt);
30753 * DISAS_STOP isn't sufficient, we need to ensure we break
30754 * out of translated code to check for pending interrupts.
30756 gen_save_pc(ctx->base.pc_next + 4);
30757 ctx->base.is_jmp = DISAS_EXIT;
30758 break;
30759 default: /* Invalid */
30760 MIPS_INVAL("mfmc0");
30761 gen_reserved_instruction(ctx);
30762 break;
30764 tcg_temp_free(t0);
30766 #endif /* !CONFIG_USER_ONLY */
30767 break;
30768 case OPC_RDPGPR:
30769 check_insn(ctx, ISA_MIPS_R2);
30770 gen_load_srsgpr(rt, rd);
30771 break;
30772 case OPC_WRPGPR:
30773 check_insn(ctx, ISA_MIPS_R2);
30774 gen_store_srsgpr(rt, rd);
30775 break;
30776 default:
30777 MIPS_INVAL("cp0");
30778 gen_reserved_instruction(ctx);
30779 break;
30781 break;
30782 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
30783 if (ctx->insn_flags & ISA_MIPS_R6) {
30784 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
30785 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30786 } else {
30787 /* OPC_ADDI */
30788 /* Arithmetic with immediate opcode */
30789 gen_arith_imm(ctx, op, rt, rs, imm);
30791 break;
30792 case OPC_ADDIU:
30793 gen_arith_imm(ctx, op, rt, rs, imm);
30794 break;
30795 case OPC_SLTI: /* Set on less than with immediate opcode */
30796 case OPC_SLTIU:
30797 gen_slt_imm(ctx, op, rt, rs, imm);
30798 break;
30799 case OPC_ANDI: /* Arithmetic with immediate opcode */
30800 case OPC_LUI: /* OPC_AUI */
30801 case OPC_ORI:
30802 case OPC_XORI:
30803 gen_logic_imm(ctx, op, rt, rs, imm);
30804 break;
30805 case OPC_J: /* Jump */
30806 case OPC_JAL:
30807 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
30808 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
30809 break;
30810 /* Branch */
30811 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
30812 if (ctx->insn_flags & ISA_MIPS_R6) {
30813 if (rt == 0) {
30814 gen_reserved_instruction(ctx);
30815 break;
30817 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
30818 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30819 } else {
30820 /* OPC_BLEZL */
30821 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30823 break;
30824 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
30825 if (ctx->insn_flags & ISA_MIPS_R6) {
30826 if (rt == 0) {
30827 gen_reserved_instruction(ctx);
30828 break;
30830 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
30831 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30832 } else {
30833 /* OPC_BGTZL */
30834 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30836 break;
30837 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
30838 if (rt == 0) {
30839 /* OPC_BLEZ */
30840 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30841 } else {
30842 check_insn(ctx, ISA_MIPS_R6);
30843 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
30844 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30846 break;
30847 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
30848 if (rt == 0) {
30849 /* OPC_BGTZ */
30850 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30851 } else {
30852 check_insn(ctx, ISA_MIPS_R6);
30853 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
30854 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30856 break;
30857 case OPC_BEQL:
30858 case OPC_BNEL:
30859 check_insn(ctx, ISA_MIPS2);
30860 check_insn_opc_removed(ctx, ISA_MIPS_R6);
30861 /* Fallthrough */
30862 case OPC_BEQ:
30863 case OPC_BNE:
30864 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30865 break;
30866 case OPC_LL: /* Load and stores */
30867 check_insn(ctx, ISA_MIPS2);
30868 if (ctx->insn_flags & INSN_R5900) {
30869 check_insn_opc_user_only(ctx, INSN_R5900);
30871 /* Fallthrough */
30872 case OPC_LWL:
30873 case OPC_LWR:
30874 check_insn_opc_removed(ctx, ISA_MIPS_R6);
30875 /* Fallthrough */
30876 case OPC_LB:
30877 case OPC_LH:
30878 case OPC_LW:
30879 case OPC_LWPC:
30880 case OPC_LBU:
30881 case OPC_LHU:
30882 gen_ld(ctx, op, rt, rs, imm);
30883 break;
30884 case OPC_SWL:
30885 case OPC_SWR:
30886 check_insn_opc_removed(ctx, ISA_MIPS_R6);
30887 /* fall through */
30888 case OPC_SB:
30889 case OPC_SH:
30890 case OPC_SW:
30891 gen_st(ctx, op, rt, rs, imm);
30892 break;
30893 case OPC_SC:
30894 check_insn(ctx, ISA_MIPS2);
30895 check_insn_opc_removed(ctx, ISA_MIPS_R6);
30896 if (ctx->insn_flags & INSN_R5900) {
30897 check_insn_opc_user_only(ctx, INSN_R5900);
30899 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
30900 break;
30901 case OPC_CACHE:
30902 check_insn_opc_removed(ctx, ISA_MIPS_R6);
30903 check_cp0_enabled(ctx);
30904 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
30905 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
30906 gen_cache_operation(ctx, rt, rs, imm);
30908 /* Treat as NOP. */
30909 break;
30910 case OPC_PREF:
30911 check_insn_opc_removed(ctx, ISA_MIPS_R6);
30912 if (ctx->insn_flags & INSN_R5900) {
30913 /* Treat as NOP. */
30914 } else {
30915 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
30916 /* Treat as NOP. */
30918 break;
30920 /* Floating point (COP1). */
30921 case OPC_LWC1:
30922 case OPC_LDC1:
30923 case OPC_SWC1:
30924 case OPC_SDC1:
30925 gen_cop1_ldst(ctx, op, rt, rs, imm);
30926 break;
30928 case OPC_CP1:
30929 op1 = MASK_CP1(ctx->opcode);
30931 switch (op1) {
30932 case OPC_MFHC1:
30933 case OPC_MTHC1:
30934 check_cp1_enabled(ctx);
30935 check_insn(ctx, ISA_MIPS_R2);
30936 /* fall through */
30937 case OPC_MFC1:
30938 case OPC_CFC1:
30939 case OPC_MTC1:
30940 case OPC_CTC1:
30941 check_cp1_enabled(ctx);
30942 gen_cp1(ctx, op1, rt, rd);
30943 break;
30944 #if defined(TARGET_MIPS64)
30945 case OPC_DMFC1:
30946 case OPC_DMTC1:
30947 check_cp1_enabled(ctx);
30948 check_insn(ctx, ISA_MIPS3);
30949 check_mips_64(ctx);
30950 gen_cp1(ctx, op1, rt, rd);
30951 break;
30952 #endif
30953 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
30954 check_cp1_enabled(ctx);
30955 if (ctx->insn_flags & ISA_MIPS_R6) {
30956 /* OPC_BC1EQZ */
30957 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
30958 rt, imm << 2, 4);
30959 } else {
30960 /* OPC_BC1ANY2 */
30961 check_cop1x(ctx);
30962 check_insn(ctx, ASE_MIPS3D);
30963 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
30964 (rt >> 2) & 0x7, imm << 2);
30966 break;
30967 case OPC_BC1NEZ:
30968 check_cp1_enabled(ctx);
30969 check_insn(ctx, ISA_MIPS_R6);
30970 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
30971 rt, imm << 2, 4);
30972 break;
30973 case OPC_BC1ANY4:
30974 check_cp1_enabled(ctx);
30975 check_insn_opc_removed(ctx, ISA_MIPS_R6);
30976 check_cop1x(ctx);
30977 check_insn(ctx, ASE_MIPS3D);
30978 /* fall through */
30979 case OPC_BC1:
30980 check_cp1_enabled(ctx);
30981 check_insn_opc_removed(ctx, ISA_MIPS_R6);
30982 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
30983 (rt >> 2) & 0x7, imm << 2);
30984 break;
30985 case OPC_PS_FMT:
30986 check_ps(ctx);
30987 /* fall through */
30988 case OPC_S_FMT:
30989 case OPC_D_FMT:
30990 check_cp1_enabled(ctx);
30991 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
30992 (imm >> 8) & 0x7);
30993 break;
30994 case OPC_W_FMT:
30995 case OPC_L_FMT:
30997 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
30998 check_cp1_enabled(ctx);
30999 if (ctx->insn_flags & ISA_MIPS_R6) {
31000 switch (r6_op) {
31001 case R6_OPC_CMP_AF_S:
31002 case R6_OPC_CMP_UN_S:
31003 case R6_OPC_CMP_EQ_S:
31004 case R6_OPC_CMP_UEQ_S:
31005 case R6_OPC_CMP_LT_S:
31006 case R6_OPC_CMP_ULT_S:
31007 case R6_OPC_CMP_LE_S:
31008 case R6_OPC_CMP_ULE_S:
31009 case R6_OPC_CMP_SAF_S:
31010 case R6_OPC_CMP_SUN_S:
31011 case R6_OPC_CMP_SEQ_S:
31012 case R6_OPC_CMP_SEUQ_S:
31013 case R6_OPC_CMP_SLT_S:
31014 case R6_OPC_CMP_SULT_S:
31015 case R6_OPC_CMP_SLE_S:
31016 case R6_OPC_CMP_SULE_S:
31017 case R6_OPC_CMP_OR_S:
31018 case R6_OPC_CMP_UNE_S:
31019 case R6_OPC_CMP_NE_S:
31020 case R6_OPC_CMP_SOR_S:
31021 case R6_OPC_CMP_SUNE_S:
31022 case R6_OPC_CMP_SNE_S:
31023 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
31024 break;
31025 case R6_OPC_CMP_AF_D:
31026 case R6_OPC_CMP_UN_D:
31027 case R6_OPC_CMP_EQ_D:
31028 case R6_OPC_CMP_UEQ_D:
31029 case R6_OPC_CMP_LT_D:
31030 case R6_OPC_CMP_ULT_D:
31031 case R6_OPC_CMP_LE_D:
31032 case R6_OPC_CMP_ULE_D:
31033 case R6_OPC_CMP_SAF_D:
31034 case R6_OPC_CMP_SUN_D:
31035 case R6_OPC_CMP_SEQ_D:
31036 case R6_OPC_CMP_SEUQ_D:
31037 case R6_OPC_CMP_SLT_D:
31038 case R6_OPC_CMP_SULT_D:
31039 case R6_OPC_CMP_SLE_D:
31040 case R6_OPC_CMP_SULE_D:
31041 case R6_OPC_CMP_OR_D:
31042 case R6_OPC_CMP_UNE_D:
31043 case R6_OPC_CMP_NE_D:
31044 case R6_OPC_CMP_SOR_D:
31045 case R6_OPC_CMP_SUNE_D:
31046 case R6_OPC_CMP_SNE_D:
31047 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
31048 break;
31049 default:
31050 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
31051 rt, rd, sa, (imm >> 8) & 0x7);
31053 break;
31055 } else {
31056 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
31057 (imm >> 8) & 0x7);
31059 break;
31061 case OPC_BZ_V:
31062 case OPC_BNZ_V:
31063 case OPC_BZ_B:
31064 case OPC_BZ_H:
31065 case OPC_BZ_W:
31066 case OPC_BZ_D:
31067 case OPC_BNZ_B:
31068 case OPC_BNZ_H:
31069 case OPC_BNZ_W:
31070 case OPC_BNZ_D:
31071 check_insn(ctx, ASE_MSA);
31072 gen_msa_branch(env, ctx, op1);
31073 break;
31074 default:
31075 MIPS_INVAL("cp1");
31076 gen_reserved_instruction(ctx);
31077 break;
31079 break;
31081 /* Compact branches [R6] and COP2 [non-R6] */
31082 case OPC_BC: /* OPC_LWC2 */
31083 case OPC_BALC: /* OPC_SWC2 */
31084 if (ctx->insn_flags & ISA_MIPS_R6) {
31085 /* OPC_BC, OPC_BALC */
31086 gen_compute_compact_branch(ctx, op, 0, 0,
31087 sextract32(ctx->opcode << 2, 0, 28));
31088 } else if (ctx->insn_flags & ASE_LEXT) {
31089 gen_loongson_lswc2(ctx, rt, rs, rd);
31090 } else {
31091 /* OPC_LWC2, OPC_SWC2 */
31092 /* COP2: Not implemented. */
31093 generate_exception_err(ctx, EXCP_CpU, 2);
31095 break;
31096 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
31097 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
31098 if (ctx->insn_flags & ISA_MIPS_R6) {
31099 if (rs != 0) {
31100 /* OPC_BEQZC, OPC_BNEZC */
31101 gen_compute_compact_branch(ctx, op, rs, 0,
31102 sextract32(ctx->opcode << 2, 0, 23));
31103 } else {
31104 /* OPC_JIC, OPC_JIALC */
31105 gen_compute_compact_branch(ctx, op, 0, rt, imm);
31107 } else if (ctx->insn_flags & ASE_LEXT) {
31108 gen_loongson_lsdc2(ctx, rt, rs, rd);
31109 } else {
31110 /* OPC_LWC2, OPC_SWC2 */
31111 /* COP2: Not implemented. */
31112 generate_exception_err(ctx, EXCP_CpU, 2);
31114 break;
31115 case OPC_CP2:
31116 check_insn(ctx, ASE_LMMI);
31117 /* Note that these instructions use different fields. */
31118 gen_loongson_multimedia(ctx, sa, rd, rt);
31119 break;
31121 case OPC_CP3:
31122 check_insn_opc_removed(ctx, ISA_MIPS_R6);
31123 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
31124 check_cp1_enabled(ctx);
31125 op1 = MASK_CP3(ctx->opcode);
31126 switch (op1) {
31127 case OPC_LUXC1:
31128 case OPC_SUXC1:
31129 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
31130 /* Fallthrough */
31131 case OPC_LWXC1:
31132 case OPC_LDXC1:
31133 case OPC_SWXC1:
31134 case OPC_SDXC1:
31135 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
31136 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
31137 break;
31138 case OPC_PREFX:
31139 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
31140 /* Treat as NOP. */
31141 break;
31142 case OPC_ALNV_PS:
31143 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
31144 /* Fallthrough */
31145 case OPC_MADD_S:
31146 case OPC_MADD_D:
31147 case OPC_MADD_PS:
31148 case OPC_MSUB_S:
31149 case OPC_MSUB_D:
31150 case OPC_MSUB_PS:
31151 case OPC_NMADD_S:
31152 case OPC_NMADD_D:
31153 case OPC_NMADD_PS:
31154 case OPC_NMSUB_S:
31155 case OPC_NMSUB_D:
31156 case OPC_NMSUB_PS:
31157 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
31158 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
31159 break;
31160 default:
31161 MIPS_INVAL("cp3");
31162 gen_reserved_instruction(ctx);
31163 break;
31165 } else {
31166 generate_exception_err(ctx, EXCP_CpU, 1);
31168 break;
31170 #if defined(TARGET_MIPS64)
31171 /* MIPS64 opcodes */
31172 case OPC_LLD:
31173 if (ctx->insn_flags & INSN_R5900) {
31174 check_insn_opc_user_only(ctx, INSN_R5900);
31176 /* fall through */
31177 case OPC_LDL:
31178 case OPC_LDR:
31179 check_insn_opc_removed(ctx, ISA_MIPS_R6);
31180 /* fall through */
31181 case OPC_LWU:
31182 case OPC_LD:
31183 check_insn(ctx, ISA_MIPS3);
31184 check_mips_64(ctx);
31185 gen_ld(ctx, op, rt, rs, imm);
31186 break;
31187 case OPC_SDL:
31188 case OPC_SDR:
31189 check_insn_opc_removed(ctx, ISA_MIPS_R6);
31190 /* fall through */
31191 case OPC_SD:
31192 check_insn(ctx, ISA_MIPS3);
31193 check_mips_64(ctx);
31194 gen_st(ctx, op, rt, rs, imm);
31195 break;
31196 case OPC_SCD:
31197 check_insn_opc_removed(ctx, ISA_MIPS_R6);
31198 check_insn(ctx, ISA_MIPS3);
31199 if (ctx->insn_flags & INSN_R5900) {
31200 check_insn_opc_user_only(ctx, INSN_R5900);
31202 check_mips_64(ctx);
31203 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
31204 break;
31205 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
31206 if (ctx->insn_flags & ISA_MIPS_R6) {
31207 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
31208 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
31209 } else {
31210 /* OPC_DADDI */
31211 check_insn(ctx, ISA_MIPS3);
31212 check_mips_64(ctx);
31213 gen_arith_imm(ctx, op, rt, rs, imm);
31215 break;
31216 case OPC_DADDIU:
31217 check_insn(ctx, ISA_MIPS3);
31218 check_mips_64(ctx);
31219 gen_arith_imm(ctx, op, rt, rs, imm);
31220 break;
31221 #else
31222 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
31223 if (ctx->insn_flags & ISA_MIPS_R6) {
31224 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
31225 } else {
31226 MIPS_INVAL("major opcode");
31227 gen_reserved_instruction(ctx);
31229 break;
31230 #endif
31231 case OPC_DAUI: /* OPC_JALX */
31232 if (ctx->insn_flags & ISA_MIPS_R6) {
31233 #if defined(TARGET_MIPS64)
31234 /* OPC_DAUI */
31235 check_mips_64(ctx);
31236 if (rs == 0) {
31237 generate_exception(ctx, EXCP_RI);
31238 } else if (rt != 0) {
31239 TCGv t0 = tcg_temp_new();
31240 gen_load_gpr(t0, rs);
31241 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
31242 tcg_temp_free(t0);
31244 #else
31245 gen_reserved_instruction(ctx);
31246 MIPS_INVAL("major opcode");
31247 #endif
31248 } else {
31249 /* OPC_JALX */
31250 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
31251 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
31252 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
31254 break;
31255 case OPC_MSA: /* OPC_MDMX */
31256 if (ctx->insn_flags & INSN_R5900) {
31257 #if defined(TARGET_MIPS64)
31258 gen_mmi_lq(env, ctx); /* MMI_OPC_LQ */
31259 #endif
31260 } else {
31261 /* MDMX: Not implemented. */
31262 gen_msa(env, ctx);
31264 break;
31265 case OPC_PCREL:
31266 check_insn(ctx, ISA_MIPS_R6);
31267 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
31268 break;
31269 default: /* Invalid */
31270 MIPS_INVAL("major opcode");
31271 gen_reserved_instruction(ctx);
31272 break;
31276 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
31278 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31279 CPUMIPSState *env = cs->env_ptr;
31281 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
31282 ctx->saved_pc = -1;
31283 ctx->insn_flags = env->insn_flags;
31284 ctx->CP0_Config1 = env->CP0_Config1;
31285 ctx->CP0_Config2 = env->CP0_Config2;
31286 ctx->CP0_Config3 = env->CP0_Config3;
31287 ctx->CP0_Config5 = env->CP0_Config5;
31288 ctx->btarget = 0;
31289 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
31290 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
31291 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
31292 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
31293 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
31294 ctx->PAMask = env->PAMask;
31295 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
31296 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
31297 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
31298 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
31299 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
31300 /* Restore delay slot state from the tb context. */
31301 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
31302 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
31303 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
31304 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
31305 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
31306 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
31307 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
31308 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
31309 ctx->mi = (env->CP0_Config5 >> CP0C5_MI) & 1;
31310 ctx->gi = (env->CP0_Config5 >> CP0C5_GI) & 3;
31311 restore_cpu_state(env, ctx);
31312 #ifdef CONFIG_USER_ONLY
31313 ctx->mem_idx = MIPS_HFLAG_UM;
31314 #else
31315 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
31316 #endif
31317 ctx->default_tcg_memop_mask = (ctx->insn_flags & (ISA_MIPS_R6 |
31318 INSN_LOONGSON3A)) ? MO_UNALN : MO_ALIGN;
31320 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
31321 ctx->hflags);
31324 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
31328 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
31330 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31332 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
31333 ctx->btarget);
31336 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
31337 const CPUBreakpoint *bp)
31339 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31341 save_cpu_state(ctx, 1);
31342 ctx->base.is_jmp = DISAS_NORETURN;
31343 gen_helper_raise_exception_debug(cpu_env);
31345 * The address covered by the breakpoint must be included in
31346 * [tb->pc, tb->pc + tb->size) in order to for it to be
31347 * properly cleared -- thus we increment the PC here so that
31348 * the logic setting tb->size below does the right thing.
31350 ctx->base.pc_next += 4;
31351 return true;
31354 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
31356 CPUMIPSState *env = cs->env_ptr;
31357 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31358 int insn_bytes;
31359 int is_slot;
31361 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
31362 if (ctx->insn_flags & ISA_NANOMIPS32) {
31363 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
31364 insn_bytes = decode_nanomips_opc(env, ctx);
31365 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
31366 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
31367 insn_bytes = 4;
31368 decode_opc(env, ctx);
31369 } else if (ctx->insn_flags & ASE_MICROMIPS) {
31370 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
31371 insn_bytes = decode_micromips_opc(env, ctx);
31372 } else if (ctx->insn_flags & ASE_MIPS16) {
31373 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
31374 insn_bytes = decode_mips16_opc(env, ctx);
31375 } else {
31376 gen_reserved_instruction(ctx);
31377 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
31378 return;
31381 if (ctx->hflags & MIPS_HFLAG_BMASK) {
31382 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
31383 MIPS_HFLAG_FBNSLOT))) {
31385 * Force to generate branch as there is neither delay nor
31386 * forbidden slot.
31388 is_slot = 1;
31390 if ((ctx->hflags & MIPS_HFLAG_M16) &&
31391 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
31393 * Force to generate branch as microMIPS R6 doesn't restrict
31394 * branches in the forbidden slot.
31396 is_slot = 1;
31399 if (is_slot) {
31400 gen_branch(ctx, insn_bytes);
31402 ctx->base.pc_next += insn_bytes;
31404 if (ctx->base.is_jmp != DISAS_NEXT) {
31405 return;
31408 * Execute a branch and its delay slot as a single instruction.
31409 * This is what GDB expects and is consistent with what the
31410 * hardware does (e.g. if a delay slot instruction faults, the
31411 * reported PC is the PC of the branch).
31413 if (ctx->base.singlestep_enabled &&
31414 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
31415 ctx->base.is_jmp = DISAS_TOO_MANY;
31417 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
31418 ctx->base.is_jmp = DISAS_TOO_MANY;
31422 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
31424 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31426 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
31427 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
31428 gen_helper_raise_exception_debug(cpu_env);
31429 } else {
31430 switch (ctx->base.is_jmp) {
31431 case DISAS_STOP:
31432 gen_save_pc(ctx->base.pc_next);
31433 tcg_gen_lookup_and_goto_ptr();
31434 break;
31435 case DISAS_NEXT:
31436 case DISAS_TOO_MANY:
31437 save_cpu_state(ctx, 0);
31438 gen_goto_tb(ctx, 0, ctx->base.pc_next);
31439 break;
31440 case DISAS_EXIT:
31441 tcg_gen_exit_tb(NULL, 0);
31442 break;
31443 case DISAS_NORETURN:
31444 break;
31445 default:
31446 g_assert_not_reached();
31451 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
31453 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
31454 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
31457 static const TranslatorOps mips_tr_ops = {
31458 .init_disas_context = mips_tr_init_disas_context,
31459 .tb_start = mips_tr_tb_start,
31460 .insn_start = mips_tr_insn_start,
31461 .breakpoint_check = mips_tr_breakpoint_check,
31462 .translate_insn = mips_tr_translate_insn,
31463 .tb_stop = mips_tr_tb_stop,
31464 .disas_log = mips_tr_disas_log,
31467 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
31469 DisasContext ctx;
31471 translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
31474 static void fpu_dump_state(CPUMIPSState *env, FILE * f, int flags)
31476 int i;
31477 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
31479 #define printfpr(fp) \
31480 do { \
31481 if (is_fpu64) \
31482 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
31483 " fd:%13g fs:%13g psu: %13g\n", \
31484 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
31485 (double)(fp)->fd, \
31486 (double)(fp)->fs[FP_ENDIAN_IDX], \
31487 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
31488 else { \
31489 fpr_t tmp; \
31490 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
31491 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
31492 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
31493 " fd:%13g fs:%13g psu:%13g\n", \
31494 tmp.w[FP_ENDIAN_IDX], tmp.d, \
31495 (double)tmp.fd, \
31496 (double)tmp.fs[FP_ENDIAN_IDX], \
31497 (double)tmp.fs[!FP_ENDIAN_IDX]); \
31499 } while (0)
31502 qemu_fprintf(f,
31503 "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
31504 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
31505 get_float_exception_flags(&env->active_fpu.fp_status));
31506 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
31507 qemu_fprintf(f, "%3s: ", fregnames[i]);
31508 printfpr(&env->active_fpu.fpr[i]);
31511 #undef printfpr
31514 void mips_cpu_dump_state(CPUState *cs, FILE *f, int flags)
31516 MIPSCPU *cpu = MIPS_CPU(cs);
31517 CPUMIPSState *env = &cpu->env;
31518 int i;
31520 qemu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
31521 " LO=0x" TARGET_FMT_lx " ds %04x "
31522 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
31523 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
31524 env->hflags, env->btarget, env->bcond);
31525 for (i = 0; i < 32; i++) {
31526 if ((i & 3) == 0) {
31527 qemu_fprintf(f, "GPR%02d:", i);
31529 qemu_fprintf(f, " %s " TARGET_FMT_lx,
31530 regnames[i], env->active_tc.gpr[i]);
31531 if ((i & 3) == 3) {
31532 qemu_fprintf(f, "\n");
31536 qemu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x"
31537 TARGET_FMT_lx "\n",
31538 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
31539 qemu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
31540 PRIx64 "\n",
31541 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
31542 qemu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
31543 env->CP0_Config2, env->CP0_Config3);
31544 qemu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
31545 env->CP0_Config4, env->CP0_Config5);
31546 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
31547 fpu_dump_state(env, f, flags);
31551 void mips_tcg_init(void)
31553 int i;
31555 cpu_gpr[0] = NULL;
31556 for (i = 1; i < 32; i++)
31557 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
31558 offsetof(CPUMIPSState,
31559 active_tc.gpr[i]),
31560 regnames[i]);
31562 for (i = 0; i < 32; i++) {
31563 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
31564 msa_wr_d[i * 2] =
31565 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
31567 * The scalar floating-point unit (FPU) registers are mapped on
31568 * the MSA vector registers.
31570 fpu_f64[i] = msa_wr_d[i * 2];
31571 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
31572 msa_wr_d[i * 2 + 1] =
31573 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
31576 cpu_PC = tcg_global_mem_new(cpu_env,
31577 offsetof(CPUMIPSState, active_tc.PC), "PC");
31578 for (i = 0; i < MIPS_DSP_ACC; i++) {
31579 cpu_HI[i] = tcg_global_mem_new(cpu_env,
31580 offsetof(CPUMIPSState, active_tc.HI[i]),
31581 regnames_HI[i]);
31582 cpu_LO[i] = tcg_global_mem_new(cpu_env,
31583 offsetof(CPUMIPSState, active_tc.LO[i]),
31584 regnames_LO[i]);
31586 cpu_dspctrl = tcg_global_mem_new(cpu_env,
31587 offsetof(CPUMIPSState,
31588 active_tc.DSPControl),
31589 "DSPControl");
31590 bcond = tcg_global_mem_new(cpu_env,
31591 offsetof(CPUMIPSState, bcond), "bcond");
31592 btarget = tcg_global_mem_new(cpu_env,
31593 offsetof(CPUMIPSState, btarget), "btarget");
31594 hflags = tcg_global_mem_new_i32(cpu_env,
31595 offsetof(CPUMIPSState, hflags), "hflags");
31597 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
31598 offsetof(CPUMIPSState, active_fpu.fcr0),
31599 "fcr0");
31600 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
31601 offsetof(CPUMIPSState, active_fpu.fcr31),
31602 "fcr31");
31603 cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
31604 "lladdr");
31605 cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
31606 "llval");
31608 #if defined(TARGET_MIPS64)
31609 cpu_mmr[0] = NULL;
31610 for (i = 1; i < 32; i++) {
31611 cpu_mmr[i] = tcg_global_mem_new_i64(cpu_env,
31612 offsetof(CPUMIPSState,
31613 active_tc.mmr[i]),
31614 regnames[i]);
31616 #endif
31618 #if !defined(TARGET_MIPS64)
31619 for (i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
31620 mxu_gpr[i] = tcg_global_mem_new(cpu_env,
31621 offsetof(CPUMIPSState,
31622 active_tc.mxu_gpr[i]),
31623 mxuregnames[i]);
31626 mxu_CR = tcg_global_mem_new(cpu_env,
31627 offsetof(CPUMIPSState, active_tc.mxu_cr),
31628 mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
31629 #endif
31632 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
31633 target_ulong *data)
31635 env->active_tc.PC = data[0];
31636 env->hflags &= ~MIPS_HFLAG_BMASK;
31637 env->hflags |= data[1];
31638 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
31639 case MIPS_HFLAG_BR:
31640 break;
31641 case MIPS_HFLAG_BC:
31642 case MIPS_HFLAG_BL:
31643 case MIPS_HFLAG_B:
31644 env->btarget = data[2];
31645 break;