]> git.proxmox.com Git - mirror_qemu.git/blob - target/mips/translate.c
docs/devel/testing: Fix typo in dockerfile path
[mirror_qemu.git] / target / mips / translate.c
1 /*
2 * MIPS emulation for QEMU - main translation routines
3 *
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)
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
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.
19 *
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/>.
22 */
23
24 #include "qemu/osdep.h"
25 #include "cpu.h"
26 #include "internal.h"
27 #include "disas/disas.h"
28 #include "exec/exec-all.h"
29 #include "tcg-op.h"
30 #include "exec/cpu_ldst.h"
31 #include "hw/mips/cpudevs.h"
32
33 #include "exec/helper-proto.h"
34 #include "exec/helper-gen.h"
35 #include "hw/semihosting/semihost.h"
36
37 #include "target/mips/trace.h"
38 #include "trace-tcg.h"
39 #include "exec/translator.h"
40 #include "exec/log.h"
41 #include "qemu/qemu-print.h"
42
43 #define MIPS_DEBUG_DISAS 0
44
45 /* MIPS major opcodes */
46 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
47
48 enum {
49 /* indirect opcode tables */
50 OPC_SPECIAL = (0x00 << 26),
51 OPC_REGIMM = (0x01 << 26),
52 OPC_CP0 = (0x10 << 26),
53 OPC_CP1 = (0x11 << 26),
54 OPC_CP2 = (0x12 << 26),
55 OPC_CP3 = (0x13 << 26),
56 OPC_SPECIAL2 = (0x1C << 26),
57 OPC_SPECIAL3 = (0x1F << 26),
58 /* arithmetic with immediate */
59 OPC_ADDI = (0x08 << 26),
60 OPC_ADDIU = (0x09 << 26),
61 OPC_SLTI = (0x0A << 26),
62 OPC_SLTIU = (0x0B << 26),
63 /* logic with immediate */
64 OPC_ANDI = (0x0C << 26),
65 OPC_ORI = (0x0D << 26),
66 OPC_XORI = (0x0E << 26),
67 OPC_LUI = (0x0F << 26),
68 /* arithmetic with immediate */
69 OPC_DADDI = (0x18 << 26),
70 OPC_DADDIU = (0x19 << 26),
71 /* Jump and branches */
72 OPC_J = (0x02 << 26),
73 OPC_JAL = (0x03 << 26),
74 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
75 OPC_BEQL = (0x14 << 26),
76 OPC_BNE = (0x05 << 26),
77 OPC_BNEL = (0x15 << 26),
78 OPC_BLEZ = (0x06 << 26),
79 OPC_BLEZL = (0x16 << 26),
80 OPC_BGTZ = (0x07 << 26),
81 OPC_BGTZL = (0x17 << 26),
82 OPC_JALX = (0x1D << 26),
83 OPC_DAUI = (0x1D << 26),
84 /* Load and stores */
85 OPC_LDL = (0x1A << 26),
86 OPC_LDR = (0x1B << 26),
87 OPC_LB = (0x20 << 26),
88 OPC_LH = (0x21 << 26),
89 OPC_LWL = (0x22 << 26),
90 OPC_LW = (0x23 << 26),
91 OPC_LWPC = OPC_LW | 0x5,
92 OPC_LBU = (0x24 << 26),
93 OPC_LHU = (0x25 << 26),
94 OPC_LWR = (0x26 << 26),
95 OPC_LWU = (0x27 << 26),
96 OPC_SB = (0x28 << 26),
97 OPC_SH = (0x29 << 26),
98 OPC_SWL = (0x2A << 26),
99 OPC_SW = (0x2B << 26),
100 OPC_SDL = (0x2C << 26),
101 OPC_SDR = (0x2D << 26),
102 OPC_SWR = (0x2E << 26),
103 OPC_LL = (0x30 << 26),
104 OPC_LLD = (0x34 << 26),
105 OPC_LD = (0x37 << 26),
106 OPC_LDPC = OPC_LD | 0x5,
107 OPC_SC = (0x38 << 26),
108 OPC_SCD = (0x3C << 26),
109 OPC_SD = (0x3F << 26),
110 /* Floating point load/store */
111 OPC_LWC1 = (0x31 << 26),
112 OPC_LWC2 = (0x32 << 26),
113 OPC_LDC1 = (0x35 << 26),
114 OPC_LDC2 = (0x36 << 26),
115 OPC_SWC1 = (0x39 << 26),
116 OPC_SWC2 = (0x3A << 26),
117 OPC_SDC1 = (0x3D << 26),
118 OPC_SDC2 = (0x3E << 26),
119 /* Compact Branches */
120 OPC_BLEZALC = (0x06 << 26),
121 OPC_BGEZALC = (0x06 << 26),
122 OPC_BGEUC = (0x06 << 26),
123 OPC_BGTZALC = (0x07 << 26),
124 OPC_BLTZALC = (0x07 << 26),
125 OPC_BLTUC = (0x07 << 26),
126 OPC_BOVC = (0x08 << 26),
127 OPC_BEQZALC = (0x08 << 26),
128 OPC_BEQC = (0x08 << 26),
129 OPC_BLEZC = (0x16 << 26),
130 OPC_BGEZC = (0x16 << 26),
131 OPC_BGEC = (0x16 << 26),
132 OPC_BGTZC = (0x17 << 26),
133 OPC_BLTZC = (0x17 << 26),
134 OPC_BLTC = (0x17 << 26),
135 OPC_BNVC = (0x18 << 26),
136 OPC_BNEZALC = (0x18 << 26),
137 OPC_BNEC = (0x18 << 26),
138 OPC_BC = (0x32 << 26),
139 OPC_BEQZC = (0x36 << 26),
140 OPC_JIC = (0x36 << 26),
141 OPC_BALC = (0x3A << 26),
142 OPC_BNEZC = (0x3E << 26),
143 OPC_JIALC = (0x3E << 26),
144 /* MDMX ASE specific */
145 OPC_MDMX = (0x1E << 26),
146 /* MSA ASE, same as MDMX */
147 OPC_MSA = OPC_MDMX,
148 /* Cache and prefetch */
149 OPC_CACHE = (0x2F << 26),
150 OPC_PREF = (0x33 << 26),
151 /* PC-relative address computation / loads */
152 OPC_PCREL = (0x3B << 26),
153 };
154
155 /* PC-relative address computation / loads */
156 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
157 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
158 enum {
159 /* Instructions determined by bits 19 and 20 */
160 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
161 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
162 OPC_LWUPC = OPC_PCREL | (2 << 19),
163
164 /* Instructions determined by bits 16 ... 20 */
165 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
166 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
167
168 /* Other */
169 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
170 };
171
172 /* MIPS special opcodes */
173 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
174
175 enum {
176 /* Shifts */
177 OPC_SLL = 0x00 | OPC_SPECIAL,
178 /* NOP is SLL r0, r0, 0 */
179 /* SSNOP is SLL r0, r0, 1 */
180 /* EHB is SLL r0, r0, 3 */
181 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
182 OPC_ROTR = OPC_SRL | (1 << 21),
183 OPC_SRA = 0x03 | OPC_SPECIAL,
184 OPC_SLLV = 0x04 | OPC_SPECIAL,
185 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
186 OPC_ROTRV = OPC_SRLV | (1 << 6),
187 OPC_SRAV = 0x07 | OPC_SPECIAL,
188 OPC_DSLLV = 0x14 | OPC_SPECIAL,
189 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
190 OPC_DROTRV = OPC_DSRLV | (1 << 6),
191 OPC_DSRAV = 0x17 | OPC_SPECIAL,
192 OPC_DSLL = 0x38 | OPC_SPECIAL,
193 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
194 OPC_DROTR = OPC_DSRL | (1 << 21),
195 OPC_DSRA = 0x3B | OPC_SPECIAL,
196 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
197 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
198 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
199 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
200 /* Multiplication / division */
201 OPC_MULT = 0x18 | OPC_SPECIAL,
202 OPC_MULTU = 0x19 | OPC_SPECIAL,
203 OPC_DIV = 0x1A | OPC_SPECIAL,
204 OPC_DIVU = 0x1B | OPC_SPECIAL,
205 OPC_DMULT = 0x1C | OPC_SPECIAL,
206 OPC_DMULTU = 0x1D | OPC_SPECIAL,
207 OPC_DDIV = 0x1E | OPC_SPECIAL,
208 OPC_DDIVU = 0x1F | OPC_SPECIAL,
209
210 /* 2 registers arithmetic / logic */
211 OPC_ADD = 0x20 | OPC_SPECIAL,
212 OPC_ADDU = 0x21 | OPC_SPECIAL,
213 OPC_SUB = 0x22 | OPC_SPECIAL,
214 OPC_SUBU = 0x23 | OPC_SPECIAL,
215 OPC_AND = 0x24 | OPC_SPECIAL,
216 OPC_OR = 0x25 | OPC_SPECIAL,
217 OPC_XOR = 0x26 | OPC_SPECIAL,
218 OPC_NOR = 0x27 | OPC_SPECIAL,
219 OPC_SLT = 0x2A | OPC_SPECIAL,
220 OPC_SLTU = 0x2B | OPC_SPECIAL,
221 OPC_DADD = 0x2C | OPC_SPECIAL,
222 OPC_DADDU = 0x2D | OPC_SPECIAL,
223 OPC_DSUB = 0x2E | OPC_SPECIAL,
224 OPC_DSUBU = 0x2F | OPC_SPECIAL,
225 /* Jumps */
226 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
227 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
228 /* Traps */
229 OPC_TGE = 0x30 | OPC_SPECIAL,
230 OPC_TGEU = 0x31 | OPC_SPECIAL,
231 OPC_TLT = 0x32 | OPC_SPECIAL,
232 OPC_TLTU = 0x33 | OPC_SPECIAL,
233 OPC_TEQ = 0x34 | OPC_SPECIAL,
234 OPC_TNE = 0x36 | OPC_SPECIAL,
235 /* HI / LO registers load & stores */
236 OPC_MFHI = 0x10 | OPC_SPECIAL,
237 OPC_MTHI = 0x11 | OPC_SPECIAL,
238 OPC_MFLO = 0x12 | OPC_SPECIAL,
239 OPC_MTLO = 0x13 | OPC_SPECIAL,
240 /* Conditional moves */
241 OPC_MOVZ = 0x0A | OPC_SPECIAL,
242 OPC_MOVN = 0x0B | OPC_SPECIAL,
243
244 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
245 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
246
247 OPC_MOVCI = 0x01 | OPC_SPECIAL,
248
249 /* Special */
250 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
251 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
252 OPC_BREAK = 0x0D | OPC_SPECIAL,
253 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
254 OPC_SYNC = 0x0F | OPC_SPECIAL,
255
256 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
257 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
258 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
259 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
260 };
261
262 /* R6 Multiply and Divide instructions have the same Opcode
263 and function field as legacy OPC_MULT[U]/OPC_DIV[U] */
264 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
265
266 enum {
267 R6_OPC_MUL = OPC_MULT | (2 << 6),
268 R6_OPC_MUH = OPC_MULT | (3 << 6),
269 R6_OPC_MULU = OPC_MULTU | (2 << 6),
270 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
271 R6_OPC_DIV = OPC_DIV | (2 << 6),
272 R6_OPC_MOD = OPC_DIV | (3 << 6),
273 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
274 R6_OPC_MODU = OPC_DIVU | (3 << 6),
275
276 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
277 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
278 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
279 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
280 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
281 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
282 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
283 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
284
285 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
286 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
287 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
288 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
289 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
290
291 OPC_LSA = 0x05 | OPC_SPECIAL,
292 OPC_DLSA = 0x15 | OPC_SPECIAL,
293 };
294
295 /* Multiplication variants of the vr54xx. */
296 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
297
298 enum {
299 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
300 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
301 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
302 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
303 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
304 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
305 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
306 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
307 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
308 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
309 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
310 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
311 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
312 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
313 };
314
315 /* REGIMM (rt field) opcodes */
316 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
317
318 enum {
319 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
320 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
321 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
322 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
323 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
324 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
325 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
326 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
327 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
328 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
329 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
330 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
331 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
332 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
333 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
334 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
335
336 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
337 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
338 };
339
340 /* Special2 opcodes */
341 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
342
343 enum {
344 /* Multiply & xxx operations */
345 OPC_MADD = 0x00 | OPC_SPECIAL2,
346 OPC_MADDU = 0x01 | OPC_SPECIAL2,
347 OPC_MUL = 0x02 | OPC_SPECIAL2,
348 OPC_MSUB = 0x04 | OPC_SPECIAL2,
349 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
350 /* Loongson 2F */
351 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
352 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
353 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
354 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
355 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
356 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
357 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
358 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
359 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
360 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
361 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
362 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
363 /* Misc */
364 OPC_CLZ = 0x20 | OPC_SPECIAL2,
365 OPC_CLO = 0x21 | OPC_SPECIAL2,
366 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
367 OPC_DCLO = 0x25 | OPC_SPECIAL2,
368 /* Special */
369 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
370 };
371
372 /* Special3 opcodes */
373 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
374
375 enum {
376 OPC_EXT = 0x00 | OPC_SPECIAL3,
377 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
378 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
379 OPC_DEXT = 0x03 | OPC_SPECIAL3,
380 OPC_INS = 0x04 | OPC_SPECIAL3,
381 OPC_DINSM = 0x05 | OPC_SPECIAL3,
382 OPC_DINSU = 0x06 | OPC_SPECIAL3,
383 OPC_DINS = 0x07 | OPC_SPECIAL3,
384 OPC_FORK = 0x08 | OPC_SPECIAL3,
385 OPC_YIELD = 0x09 | OPC_SPECIAL3,
386 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
387 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
388 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
389
390 /* Loongson 2E */
391 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
392 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
393 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
394 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
395 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
396 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
397 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
398 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
399 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
400 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
401 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
402 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
403
404 /* MIPS DSP Load */
405 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
406 /* MIPS DSP Arithmetic */
407 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
408 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
409 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
410 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
411 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
412 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
413 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
414 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
415 /* MIPS DSP GPR-Based Shift Sub-class */
416 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
417 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
418 /* MIPS DSP Multiply Sub-class insns */
419 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
420 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
421 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
422 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
423 /* DSP Bit/Manipulation Sub-class */
424 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
425 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
426 /* MIPS DSP Append Sub-class */
427 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
428 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
429 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
430 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
431 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
432
433 /* EVA */
434 OPC_LWLE = 0x19 | OPC_SPECIAL3,
435 OPC_LWRE = 0x1A | OPC_SPECIAL3,
436 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
437 OPC_SBE = 0x1C | OPC_SPECIAL3,
438 OPC_SHE = 0x1D | OPC_SPECIAL3,
439 OPC_SCE = 0x1E | OPC_SPECIAL3,
440 OPC_SWE = 0x1F | OPC_SPECIAL3,
441 OPC_SWLE = 0x21 | OPC_SPECIAL3,
442 OPC_SWRE = 0x22 | OPC_SPECIAL3,
443 OPC_PREFE = 0x23 | OPC_SPECIAL3,
444 OPC_LBUE = 0x28 | OPC_SPECIAL3,
445 OPC_LHUE = 0x29 | OPC_SPECIAL3,
446 OPC_LBE = 0x2C | OPC_SPECIAL3,
447 OPC_LHE = 0x2D | OPC_SPECIAL3,
448 OPC_LLE = 0x2E | OPC_SPECIAL3,
449 OPC_LWE = 0x2F | OPC_SPECIAL3,
450
451 /* R6 */
452 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
453 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
454 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
455 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
456 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
457 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
458 };
459
460 /* BSHFL opcodes */
461 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
462
463 enum {
464 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
465 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
466 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
467 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
468 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
469 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
470 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
471 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
472 };
473
474 /* DBSHFL opcodes */
475 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
476
477 enum {
478 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
479 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
480 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
481 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
482 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
483 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
484 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
485 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
486 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
487 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
488 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
489 };
490
491 /* MIPS DSP REGIMM opcodes */
492 enum {
493 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
494 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
495 };
496
497 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
498 /* MIPS DSP Load */
499 enum {
500 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
501 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
502 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
503 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
504 };
505
506 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
507 enum {
508 /* MIPS DSP Arithmetic Sub-class */
509 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
510 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
511 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
512 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
513 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
514 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
515 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
516 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
517 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
518 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
519 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
520 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
521 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
522 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
523 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
524 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
525 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
526 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
527 /* MIPS DSP Multiply Sub-class insns */
528 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
529 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
530 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
531 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
532 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
533 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
534 };
535
536 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
537 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
538 enum {
539 /* MIPS DSP Arithmetic Sub-class */
540 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
541 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
542 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
543 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
544 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
545 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
546 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
547 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
548 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
549 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
550 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
551 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
552 /* MIPS DSP Multiply Sub-class insns */
553 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
554 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
555 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
556 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
557 };
558
559 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
560 enum {
561 /* MIPS DSP Arithmetic Sub-class */
562 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
563 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
564 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
565 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
566 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
567 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
568 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
569 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
570 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
571 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
572 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
573 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
574 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
575 /* DSP Bit/Manipulation Sub-class */
576 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
577 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
578 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
579 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
580 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
581 };
582
583 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
584 enum {
585 /* MIPS DSP Arithmetic Sub-class */
586 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
587 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
588 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
589 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
590 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
591 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
592 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
593 /* DSP Compare-Pick Sub-class */
594 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
595 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
596 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
597 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
598 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
599 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
600 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
601 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
602 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
603 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
604 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
605 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
606 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
607 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
608 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
609 };
610
611 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
612 enum {
613 /* MIPS DSP GPR-Based Shift Sub-class */
614 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
615 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
616 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
617 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
618 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
619 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
620 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
621 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
622 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
623 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
624 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
625 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
626 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
627 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
628 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
629 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
630 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
631 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
632 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
633 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
634 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
635 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
636 };
637
638 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
639 enum {
640 /* MIPS DSP Multiply Sub-class insns */
641 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
642 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
643 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
644 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
645 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
646 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
647 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
648 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
649 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
650 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
651 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
652 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
653 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
654 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
655 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
656 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
657 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
658 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
659 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
660 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
661 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
662 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
663 };
664
665 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
666 enum {
667 /* DSP Bit/Manipulation Sub-class */
668 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
669 };
670
671 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
672 enum {
673 /* MIPS DSP Append Sub-class */
674 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
675 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
676 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
677 };
678
679 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
680 enum {
681 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
682 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
683 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
684 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
685 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
686 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
687 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
688 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
689 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
690 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
691 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
692 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
693 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
694 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
695 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
696 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
697 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
698 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
699 };
700
701 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
702 enum {
703 /* MIPS DSP Arithmetic Sub-class */
704 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
705 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
706 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
707 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
708 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
709 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
710 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
711 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
712 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
713 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
714 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
715 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
716 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
717 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
718 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
719 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
720 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
721 /* DSP Bit/Manipulation Sub-class */
722 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
723 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
724 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
725 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
726 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
727 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
728 };
729
730 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
731 enum {
732 /* MIPS DSP Multiply Sub-class insns */
733 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
734 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
735 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
736 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
737 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
738 /* MIPS DSP Arithmetic Sub-class */
739 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
740 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
741 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
742 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
743 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
744 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
745 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
746 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
747 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
748 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
749 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
750 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
751 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
752 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
753 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
754 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
755 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
756 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
757 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
758 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
759 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
760 };
761
762 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
763 enum {
764 /* DSP Compare-Pick Sub-class */
765 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
766 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
767 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
768 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
769 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
770 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
771 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
772 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
773 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
774 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
775 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
776 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
777 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
778 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
779 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
780 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
781 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
782 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
783 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
784 /* MIPS DSP Arithmetic Sub-class */
785 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
786 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
787 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
788 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
789 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
790 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
791 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
792 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
793 };
794
795 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
796 enum {
797 /* DSP Append Sub-class */
798 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
799 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
800 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
801 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
802 };
803
804 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
805 enum {
806 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
807 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
808 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
809 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
810 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
811 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
812 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
813 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
814 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
815 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
816 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
817 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
818 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
819 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
820 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
821 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
822 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
823 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
824 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
825 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
826 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
827 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
828 };
829
830 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
831 enum {
832 /* DSP Bit/Manipulation Sub-class */
833 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
834 };
835
836 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
837 enum {
838 /* MIPS DSP Multiply Sub-class insns */
839 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
840 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
841 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
842 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
843 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
844 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
845 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
846 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
847 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
848 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
849 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
850 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
851 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
852 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
853 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
854 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
855 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
856 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
857 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
858 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
859 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
860 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
861 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
862 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
863 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
864 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
865 };
866
867 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
868 enum {
869 /* MIPS DSP GPR-Based Shift Sub-class */
870 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
871 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
872 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
873 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
874 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
875 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
876 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
877 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
878 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
879 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
880 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
881 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
882 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
883 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
884 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
885 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
886 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
887 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
888 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
889 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
890 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
891 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
892 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
893 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
894 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
895 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
896 };
897
898 /* Coprocessor 0 (rs field) */
899 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
900
901 enum {
902 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
903 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
904 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
905 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
906 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
907 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
908 OPC_MFTR = (0x08 << 21) | OPC_CP0,
909 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
910 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
911 OPC_MTTR = (0x0C << 21) | OPC_CP0,
912 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
913 OPC_C0 = (0x10 << 21) | OPC_CP0,
914 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
915 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
916 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
917 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
918 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
919 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
920 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
921 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
922 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
923 OPC_C0_A = (0x1A << 21) | OPC_CP0,
924 OPC_C0_B = (0x1B << 21) | OPC_CP0,
925 OPC_C0_C = (0x1C << 21) | OPC_CP0,
926 OPC_C0_D = (0x1D << 21) | OPC_CP0,
927 OPC_C0_E = (0x1E << 21) | OPC_CP0,
928 OPC_C0_F = (0x1F << 21) | OPC_CP0,
929 };
930
931 /* MFMC0 opcodes */
932 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
933
934 enum {
935 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
936 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
937 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
938 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
939 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
940 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
941 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
942 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
943 };
944
945 /* Coprocessor 0 (with rs == C0) */
946 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
947
948 enum {
949 OPC_TLBR = 0x01 | OPC_C0,
950 OPC_TLBWI = 0x02 | OPC_C0,
951 OPC_TLBINV = 0x03 | OPC_C0,
952 OPC_TLBINVF = 0x04 | OPC_C0,
953 OPC_TLBWR = 0x06 | OPC_C0,
954 OPC_TLBP = 0x08 | OPC_C0,
955 OPC_RFE = 0x10 | OPC_C0,
956 OPC_ERET = 0x18 | OPC_C0,
957 OPC_DERET = 0x1F | OPC_C0,
958 OPC_WAIT = 0x20 | OPC_C0,
959 };
960
961 /* Coprocessor 1 (rs field) */
962 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
963
964 /* Values for the fmt field in FP instructions */
965 enum {
966 /* 0 - 15 are reserved */
967 FMT_S = 16, /* single fp */
968 FMT_D = 17, /* double fp */
969 FMT_E = 18, /* extended fp */
970 FMT_Q = 19, /* quad fp */
971 FMT_W = 20, /* 32-bit fixed */
972 FMT_L = 21, /* 64-bit fixed */
973 FMT_PS = 22, /* paired single fp */
974 /* 23 - 31 are reserved */
975 };
976
977 enum {
978 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
979 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
980 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
981 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
982 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
983 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
984 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
985 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
986 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
987 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
988 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
989 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
990 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
991 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
992 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
993 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
994 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
995 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
996 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
997 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
998 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
999 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
1000 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
1001 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
1002 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
1003 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
1004 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
1005 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
1006 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
1007 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
1008 };
1009
1010 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
1011 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
1012
1013 enum {
1014 OPC_BC1F = (0x00 << 16) | OPC_BC1,
1015 OPC_BC1T = (0x01 << 16) | OPC_BC1,
1016 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
1017 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
1018 };
1019
1020 enum {
1021 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
1022 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
1023 };
1024
1025 enum {
1026 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
1027 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
1028 };
1029
1030 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
1031
1032 enum {
1033 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1034 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1035 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1036 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1037 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1038 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1039 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1040 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1041 OPC_BC2 = (0x08 << 21) | OPC_CP2,
1042 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1043 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1044 };
1045
1046 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1047
1048 enum {
1049 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1050 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1051 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1052 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1053 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1054 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1055 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1056 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1057
1058 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1059 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1060 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1061 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1062 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1063 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1064 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1065 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1066
1067 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1068 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1069 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1070 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1071 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1072 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1073 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1074 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1075
1076 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1077 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1078 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1079 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1080 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1081 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1082 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1083 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1084
1085 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1086 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1087 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1088 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1089 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1090 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1091
1092 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1093 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1094 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1095 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1096 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1097 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1098
1099 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1100 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1101 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1102 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1103 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1104 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1105
1106 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1107 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1108 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1109 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1110 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1111 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1112
1113 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1114 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1115 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1116 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1117 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1118 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1119
1120 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1121 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1122 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1123 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1124 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1125 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1126
1127 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1128 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1129 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1130 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1131 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1132 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1133
1134 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1135 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1136 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1137 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1138 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1139 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1140 };
1141
1142
1143 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
1144
1145 enum {
1146 OPC_LWXC1 = 0x00 | OPC_CP3,
1147 OPC_LDXC1 = 0x01 | OPC_CP3,
1148 OPC_LUXC1 = 0x05 | OPC_CP3,
1149 OPC_SWXC1 = 0x08 | OPC_CP3,
1150 OPC_SDXC1 = 0x09 | OPC_CP3,
1151 OPC_SUXC1 = 0x0D | OPC_CP3,
1152 OPC_PREFX = 0x0F | OPC_CP3,
1153 OPC_ALNV_PS = 0x1E | OPC_CP3,
1154 OPC_MADD_S = 0x20 | OPC_CP3,
1155 OPC_MADD_D = 0x21 | OPC_CP3,
1156 OPC_MADD_PS = 0x26 | OPC_CP3,
1157 OPC_MSUB_S = 0x28 | OPC_CP3,
1158 OPC_MSUB_D = 0x29 | OPC_CP3,
1159 OPC_MSUB_PS = 0x2E | OPC_CP3,
1160 OPC_NMADD_S = 0x30 | OPC_CP3,
1161 OPC_NMADD_D = 0x31 | OPC_CP3,
1162 OPC_NMADD_PS= 0x36 | OPC_CP3,
1163 OPC_NMSUB_S = 0x38 | OPC_CP3,
1164 OPC_NMSUB_D = 0x39 | OPC_CP3,
1165 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1166 };
1167
1168 /* MSA Opcodes */
1169 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1170 enum {
1171 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1172 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1173 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1174 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1175 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1176 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1177 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1178 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1179 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1180 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1181 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1182 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1183 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1184 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1185 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1186 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1187 OPC_MSA_ELM = 0x19 | OPC_MSA,
1188 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1189 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1190 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1191 OPC_MSA_VEC = 0x1E | OPC_MSA,
1192
1193 /* MI10 instruction */
1194 OPC_LD_B = (0x20) | OPC_MSA,
1195 OPC_LD_H = (0x21) | OPC_MSA,
1196 OPC_LD_W = (0x22) | OPC_MSA,
1197 OPC_LD_D = (0x23) | OPC_MSA,
1198 OPC_ST_B = (0x24) | OPC_MSA,
1199 OPC_ST_H = (0x25) | OPC_MSA,
1200 OPC_ST_W = (0x26) | OPC_MSA,
1201 OPC_ST_D = (0x27) | OPC_MSA,
1202 };
1203
1204 enum {
1205 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1206 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1207 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1208 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1209 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1210 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1211 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1212 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1213 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1214 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1215 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1216 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1217 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1218
1219 /* I8 instruction */
1220 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1221 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1222 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1223 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1224 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1225 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1226 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1227 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1228 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1229 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1230
1231 /* VEC/2R/2RF instruction */
1232 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1233 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1234 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1235 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1236 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1237 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1238 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1239
1240 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1241 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1242
1243 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1244 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1245 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1246 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1247 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1248
1249 /* 2RF instruction df(bit 16) = _w, _d */
1250 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1251 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1252 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1253 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1254 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1255 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1256 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1257 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1258 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1259 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1260 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1261 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1262 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1263 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1264 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1265 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1266
1267 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1268 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1269 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1270 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1271 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1272 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1273 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1274 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1275 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1276 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1277 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1278 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1279 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1280 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1281 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1282 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1283 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1284 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1285 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1286 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1287 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1288 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1289 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1290 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1291 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1292 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1293 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1294 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1295 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1296 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1297 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1298 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1299 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1300 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1301 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1302 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1303 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1304 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1305 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1306 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1307 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1308 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1309 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1310 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1311 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1312 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1313 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1314 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1315 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1316 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1317 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1318 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1319 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1320 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1321 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1322 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1323 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1324 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1325 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1326 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1327 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1328 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1329 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1330 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1331
1332 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1333 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1334 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1335 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1336 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1337 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1338 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1339 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1340 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1341 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1342
1343 /* 3RF instruction _df(bit 21) = _w, _d */
1344 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1345 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1346 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1347 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1348 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1349 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1350 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1351 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1352 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1353 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1354 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1355 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1356 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1357 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1358 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1359 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1360 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1361 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1362 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1363 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1364 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1365 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1366 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1367 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1368 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1369 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1370 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1371 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1372 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1373 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1374 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1375 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1376 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1377 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1378 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1379 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1380 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1381 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1382 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1383 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1384 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1385
1386 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1387 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1388 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1389 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1390 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1391 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1392 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1393 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1394 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1395 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1396 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1397 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1398 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1399 };
1400
1401
1402 /*
1403 *
1404 * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
1405 * ============================================
1406 *
1407 *
1408 * MXU (full name: MIPS eXtension/enhanced Unit) is a SIMD extension of MIPS32
1409 * instructions set. It is designed to fit the needs of signal, graphical and
1410 * video processing applications. MXU instruction set is used in Xburst family
1411 * of microprocessors by Ingenic.
1412 *
1413 * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
1414 * the control register.
1415 *
1416 *
1417 * The notation used in MXU assembler mnemonics
1418 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1419 *
1420 * Register operands:
1421 *
1422 * XRa, XRb, XRc, XRd - MXU registers
1423 * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
1424 *
1425 * Non-register operands:
1426 *
1427 * aptn1 - 1-bit accumulate add/subtract pattern
1428 * aptn2 - 2-bit accumulate add/subtract pattern
1429 * eptn2 - 2-bit execute add/subtract pattern
1430 * optn2 - 2-bit operand pattern
1431 * optn3 - 3-bit operand pattern
1432 * sft4 - 4-bit shift amount
1433 * strd2 - 2-bit stride amount
1434 *
1435 * Prefixes:
1436 *
1437 * Level of parallelism: Operand size:
1438 * S - single operation at a time 32 - word
1439 * D - two operations in parallel 16 - half word
1440 * Q - four operations in parallel 8 - byte
1441 *
1442 * Operations:
1443 *
1444 * ADD - Add or subtract
1445 * ADDC - Add with carry-in
1446 * ACC - Accumulate
1447 * ASUM - Sum together then accumulate (add or subtract)
1448 * ASUMC - Sum together then accumulate (add or subtract) with carry-in
1449 * AVG - Average between 2 operands
1450 * ABD - Absolute difference
1451 * ALN - Align data
1452 * AND - Logical bitwise 'and' operation
1453 * CPS - Copy sign
1454 * EXTR - Extract bits
1455 * I2M - Move from GPR register to MXU register
1456 * LDD - Load data from memory to XRF
1457 * LDI - Load data from memory to XRF (and increase the address base)
1458 * LUI - Load unsigned immediate
1459 * MUL - Multiply
1460 * MULU - Unsigned multiply
1461 * MADD - 64-bit operand add 32x32 product
1462 * MSUB - 64-bit operand subtract 32x32 product
1463 * MAC - Multiply and accumulate (add or subtract)
1464 * MAD - Multiply and add or subtract
1465 * MAX - Maximum between 2 operands
1466 * MIN - Minimum between 2 operands
1467 * M2I - Move from MXU register to GPR register
1468 * MOVZ - Move if zero
1469 * MOVN - Move if non-zero
1470 * NOR - Logical bitwise 'nor' operation
1471 * OR - Logical bitwise 'or' operation
1472 * STD - Store data from XRF to memory
1473 * SDI - Store data from XRF to memory (and increase the address base)
1474 * SLT - Set of less than comparison
1475 * SAD - Sum of absolute differences
1476 * SLL - Logical shift left
1477 * SLR - Logical shift right
1478 * SAR - Arithmetic shift right
1479 * SAT - Saturation
1480 * SFL - Shuffle
1481 * SCOP - Calculate x’s scope (-1, means x<0; 0, means x==0; 1, means x>0)
1482 * XOR - Logical bitwise 'exclusive or' operation
1483 *
1484 * Suffixes:
1485 *
1486 * E - Expand results
1487 * F - Fixed point multiplication
1488 * L - Low part result
1489 * R - Doing rounding
1490 * V - Variable instead of immediate
1491 * W - Combine above L and V
1492 *
1493 *
1494 * The list of MXU instructions grouped by functionality
1495 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1496 *
1497 * Load/Store instructions Multiplication instructions
1498 * ----------------------- ---------------------------
1499 *
1500 * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
1501 * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
1502 * S32LDDV XRa, Rb, rc, strd2 S32MSUB XRa, XRd, Rs, Rt
1503 * S32STDV XRa, Rb, rc, strd2 S32MSUBU XRa, XRd, Rs, Rt
1504 * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
1505 * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
1506 * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
1507 * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
1508 * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
1509 * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
1510 * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
1511 * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
1512 * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
1513 * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
1514 * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
1515 * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
1516 * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
1517 * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
1518 * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
1519 * S16SDI XRa, Rb, s10, eptn2
1520 * S8LDD XRa, Rb, s8, eptn3
1521 * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
1522 * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
1523 * S8SDI XRa, Rb, s8, eptn3
1524 * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
1525 * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
1526 * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
1527 * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
1528 * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
1529 * S32CPS XRa, XRb, XRc
1530 * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
1531 * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
1532 * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
1533 * D16ASUM XRa, XRb, XRc, XRd, eptn2
1534 * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
1535 * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
1536 * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
1537 * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
1538 * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
1539 * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
1540 * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
1541 * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
1542 * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
1543 * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
1544 * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
1545 * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
1546 * Q8SLT XRa, XRb, XRc
1547 * Q8SLTU XRa, XRb, XRc
1548 * Q8MOVZ XRa, XRb, XRc Shift instructions
1549 * Q8MOVN XRa, XRb, XRc ------------------
1550 *
1551 * D32SLL XRa, XRb, XRc, XRd, sft4
1552 * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
1553 * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
1554 * D32SARL XRa, XRb, XRc, sft4
1555 * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
1556 * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
1557 * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
1558 * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
1559 * Q16SLL XRa, XRb, XRc, XRd, sft4
1560 * Q16SLR XRa, XRb, XRc, XRd, sft4
1561 * Miscellaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
1562 * ------------------------- Q16SLLV XRa, XRb, Rb
1563 * Q16SLRV XRa, XRb, Rb
1564 * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
1565 * S32ALN XRa, XRb, XRc, Rb
1566 * S32ALNI XRa, XRb, XRc, s3
1567 * S32LUI XRa, s8, optn3 Move instructions
1568 * S32EXTR XRa, XRb, Rb, bits5 -----------------
1569 * S32EXTRV XRa, XRb, Rs, Rt
1570 * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
1571 * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
1572 *
1573 *
1574 * The opcode organization of MXU instructions
1575 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1576 *
1577 * The bits 31..26 of all MXU instructions are equal to 0x1C (also referred
1578 * as opcode SPECIAL2 in the base MIPS ISA). The organization and meaning of
1579 * other bits up to the instruction level is as follows:
1580 *
1581 * bits
1582 * 05..00
1583 *
1584 * ┌─ 000000 ─ OPC_MXU_S32MADD
1585 * ├─ 000001 ─ OPC_MXU_S32MADDU
1586 * ├─ 000010 ─ <not assigned> (non-MXU OPC_MUL)
1587 * │
1588 * │ 20..18
1589 * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
1590 * │ ├─ 001 ─ OPC_MXU_S32MIN
1591 * │ ├─ 010 ─ OPC_MXU_D16MAX
1592 * │ ├─ 011 ─ OPC_MXU_D16MIN
1593 * │ ├─ 100 ─ OPC_MXU_Q8MAX
1594 * │ ├─ 101 ─ OPC_MXU_Q8MIN
1595 * │ ├─ 110 ─ OPC_MXU_Q8SLT
1596 * │ └─ 111 ─ OPC_MXU_Q8SLTU
1597 * ├─ 000100 ─ OPC_MXU_S32MSUB
1598 * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
1599 * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
1600 * │ ├─ 001 ─ OPC_MXU_D16SLT
1601 * │ ├─ 010 ─ OPC_MXU_D16AVG
1602 * │ ├─ 011 ─ OPC_MXU_D16AVGR
1603 * │ ├─ 100 ─ OPC_MXU_Q8AVG
1604 * │ ├─ 101 ─ OPC_MXU_Q8AVGR
1605 * │ └─ 111 ─ OPC_MXU_Q8ADD
1606 * │
1607 * │ 20..18
1608 * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
1609 * │ ├─ 010 ─ OPC_MXU_D16CPS
1610 * │ ├─ 100 ─ OPC_MXU_Q8ABD
1611 * │ └─ 110 ─ OPC_MXU_Q16SAT
1612 * ├─ 001000 ─ OPC_MXU_D16MUL
1613 * │ 25..24
1614 * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
1615 * │ └─ 01 ─ OPC_MXU_D16MULE
1616 * ├─ 001010 ─ OPC_MXU_D16MAC
1617 * ├─ 001011 ─ OPC_MXU_D16MACF
1618 * ├─ 001100 ─ OPC_MXU_D16MADL
1619 * ├─ 001101 ─ OPC_MXU_S16MAD
1620 * ├─ 001110 ─ OPC_MXU_Q16ADD
1621 * ├─ 001111 ─ OPC_MXU_D16MACE 23
1622 * │ ┌─ 0 ─ OPC_MXU_S32LDD
1623 * ├─ 010000 ─ OPC_MXU__POOL04 ─┴─ 1 ─ OPC_MXU_S32LDDR
1624 * │
1625 * │ 23
1626 * ├─ 010001 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32STD
1627 * │ └─ 1 ─ OPC_MXU_S32STDR
1628 * │
1629 * │ 13..10
1630 * ├─ 010010 ─ OPC_MXU__POOL06 ─┬─ 0000 ─ OPC_MXU_S32LDDV
1631 * │ └─ 0001 ─ OPC_MXU_S32LDDVR
1632 * │
1633 * │ 13..10
1634 * ├─ 010011 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32STDV
1635 * │ └─ 0001 ─ OPC_MXU_S32STDVR
1636 * │
1637 * │ 23
1638 * ├─ 010100 ─ OPC_MXU__POOL08 ─┬─ 0 ─ OPC_MXU_S32LDI
1639 * │ └─ 1 ─ OPC_MXU_S32LDIR
1640 * │
1641 * │ 23
1642 * ├─ 010101 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32SDI
1643 * │ └─ 1 ─ OPC_MXU_S32SDIR
1644 * │
1645 * │ 13..10
1646 * ├─ 010110 ─ OPC_MXU__POOL10 ─┬─ 0000 ─ OPC_MXU_S32LDIV
1647 * │ └─ 0001 ─ OPC_MXU_S32LDIVR
1648 * │
1649 * │ 13..10
1650 * ├─ 010111 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32SDIV
1651 * │ └─ 0001 ─ OPC_MXU_S32SDIVR
1652 * ├─ 011000 ─ OPC_MXU_D32ADD
1653 * │ 23..22
1654 * MXU ├─ 011001 ─ OPC_MXU__POOL12 ─┬─ 00 ─ OPC_MXU_D32ACC
1655 * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
1656 * │ └─ 10 ─ OPC_MXU_D32ASUM
1657 * ├─ 011010 ─ <not assigned>
1658 * │ 23..22
1659 * ├─ 011011 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_Q16ACC
1660 * │ ├─ 01 ─ OPC_MXU_Q16ACCM
1661 * │ └─ 10 ─ OPC_MXU_Q16ASUM
1662 * │
1663 * │ 23..22
1664 * ├─ 011100 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q8ADDE
1665 * │ ├─ 01 ─ OPC_MXU_D8SUM
1666 * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
1667 * ├─ 011110 ─ <not assigned>
1668 * ├─ 011111 ─ <not assigned>
1669 * ├─ 100000 ─ <not assigned> (overlaps with CLZ)
1670 * ├─ 100001 ─ <not assigned> (overlaps with CLO)
1671 * ├─ 100010 ─ OPC_MXU_S8LDD
1672 * ├─ 100011 ─ OPC_MXU_S8STD 15..14
1673 * ├─ 100100 ─ OPC_MXU_S8LDI ┌─ 00 ─ OPC_MXU_S32MUL
1674 * ├─ 100101 ─ OPC_MXU_S8SDI ├─ 00 ─ OPC_MXU_S32MULU
1675 * │ ├─ 00 ─ OPC_MXU_S32EXTR
1676 * ├─ 100110 ─ OPC_MXU__POOL15 ─┴─ 00 ─ OPC_MXU_S32EXTRV
1677 * │
1678 * │ 20..18
1679 * ├─ 100111 ─ OPC_MXU__POOL16 ─┬─ 000 ─ OPC_MXU_D32SARW
1680 * │ ├─ 001 ─ OPC_MXU_S32ALN
1681 * │ ├─ 010 ─ OPC_MXU_S32ALNI
1682 * │ ├─ 011 ─ OPC_MXU_S32LUI
1683 * │ ├─ 100 ─ OPC_MXU_S32NOR
1684 * │ ├─ 101 ─ OPC_MXU_S32AND
1685 * │ ├─ 110 ─ OPC_MXU_S32OR
1686 * │ └─ 111 ─ OPC_MXU_S32XOR
1687 * │
1688 * │ 7..5
1689 * ├─ 101000 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_LXB
1690 * │ ├─ 001 ─ OPC_MXU_LXH
1691 * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_LXW
1692 * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_LXBU
1693 * ├─ 101011 ─ OPC_MXU_S16STD └─ 101 ─ OPC_MXU_LXHU
1694 * ├─ 101100 ─ OPC_MXU_S16LDI
1695 * ├─ 101101 ─ OPC_MXU_S16SDI
1696 * ├─ 101110 ─ OPC_MXU_S32M2I
1697 * ├─ 101111 ─ OPC_MXU_S32I2M
1698 * ├─ 110000 ─ OPC_MXU_D32SLL
1699 * ├─ 110001 ─ OPC_MXU_D32SLR 20..18
1700 * ├─ 110010 ─ OPC_MXU_D32SARL ┌─ 000 ─ OPC_MXU_D32SLLV
1701 * ├─ 110011 ─ OPC_MXU_D32SAR ├─ 001 ─ OPC_MXU_D32SLRV
1702 * ├─ 110100 ─ OPC_MXU_Q16SLL ├─ 010 ─ OPC_MXU_D32SARV
1703 * ├─ 110101 ─ OPC_MXU_Q16SLR ├─ 011 ─ OPC_MXU_Q16SLLV
1704 * │ ├─ 100 ─ OPC_MXU_Q16SLRV
1705 * ├─ 110110 ─ OPC_MXU__POOL18 ─┴─ 101 ─ OPC_MXU_Q16SARV
1706 * │
1707 * ├─ 110111 ─ OPC_MXU_Q16SAR
1708 * │ 23..22
1709 * ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL
1710 * │ └─ 01 ─ OPC_MXU_Q8MULSU
1711 * │
1712 * │ 20..18
1713 * ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
1714 * │ ├─ 001 ─ OPC_MXU_Q8MOVN
1715 * │ ├─ 010 ─ OPC_MXU_D16MOVZ
1716 * │ ├─ 011 ─ OPC_MXU_D16MOVN
1717 * │ ├─ 100 ─ OPC_MXU_S32MOVZ
1718 * │ └─ 101 ─ OPC_MXU_S32MOVN
1719 * │
1720 * │ 23..22
1721 * ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC
1722 * │ └─ 10 ─ OPC_MXU_Q8MACSU
1723 * ├─ 111011 ─ OPC_MXU_Q16SCOP
1724 * ├─ 111100 ─ OPC_MXU_Q8MADL
1725 * ├─ 111101 ─ OPC_MXU_S32SFL
1726 * ├─ 111110 ─ OPC_MXU_Q8SAD
1727 * └─ 111111 ─ <not assigned> (overlaps with SDBBP)
1728 *
1729 *
1730 * Compiled after:
1731 *
1732 * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
1733 * Programming Manual", Ingenic Semiconductor Co, Ltd., revision June 2, 2017
1734 */
1735
1736 enum {
1737 OPC_MXU_S32MADD = 0x00,
1738 OPC_MXU_S32MADDU = 0x01,
1739 OPC__MXU_MUL = 0x02,
1740 OPC_MXU__POOL00 = 0x03,
1741 OPC_MXU_S32MSUB = 0x04,
1742 OPC_MXU_S32MSUBU = 0x05,
1743 OPC_MXU__POOL01 = 0x06,
1744 OPC_MXU__POOL02 = 0x07,
1745 OPC_MXU_D16MUL = 0x08,
1746 OPC_MXU__POOL03 = 0x09,
1747 OPC_MXU_D16MAC = 0x0A,
1748 OPC_MXU_D16MACF = 0x0B,
1749 OPC_MXU_D16MADL = 0x0C,
1750 OPC_MXU_S16MAD = 0x0D,
1751 OPC_MXU_Q16ADD = 0x0E,
1752 OPC_MXU_D16MACE = 0x0F,
1753 OPC_MXU__POOL04 = 0x10,
1754 OPC_MXU__POOL05 = 0x11,
1755 OPC_MXU__POOL06 = 0x12,
1756 OPC_MXU__POOL07 = 0x13,
1757 OPC_MXU__POOL08 = 0x14,
1758 OPC_MXU__POOL09 = 0x15,
1759 OPC_MXU__POOL10 = 0x16,
1760 OPC_MXU__POOL11 = 0x17,
1761 OPC_MXU_D32ADD = 0x18,
1762 OPC_MXU__POOL12 = 0x19,
1763 /* not assigned 0x1A */
1764 OPC_MXU__POOL13 = 0x1B,
1765 OPC_MXU__POOL14 = 0x1C,
1766 OPC_MXU_Q8ACCE = 0x1D,
1767 /* not assigned 0x1E */
1768 /* not assigned 0x1F */
1769 /* not assigned 0x20 */
1770 /* not assigned 0x21 */
1771 OPC_MXU_S8LDD = 0x22,
1772 OPC_MXU_S8STD = 0x23,
1773 OPC_MXU_S8LDI = 0x24,
1774 OPC_MXU_S8SDI = 0x25,
1775 OPC_MXU__POOL15 = 0x26,
1776 OPC_MXU__POOL16 = 0x27,
1777 OPC_MXU__POOL17 = 0x28,
1778 /* not assigned 0x29 */
1779 OPC_MXU_S16LDD = 0x2A,
1780 OPC_MXU_S16STD = 0x2B,
1781 OPC_MXU_S16LDI = 0x2C,
1782 OPC_MXU_S16SDI = 0x2D,
1783 OPC_MXU_S32M2I = 0x2E,
1784 OPC_MXU_S32I2M = 0x2F,
1785 OPC_MXU_D32SLL = 0x30,
1786 OPC_MXU_D32SLR = 0x31,
1787 OPC_MXU_D32SARL = 0x32,
1788 OPC_MXU_D32SAR = 0x33,
1789 OPC_MXU_Q16SLL = 0x34,
1790 OPC_MXU_Q16SLR = 0x35,
1791 OPC_MXU__POOL18 = 0x36,
1792 OPC_MXU_Q16SAR = 0x37,
1793 OPC_MXU__POOL19 = 0x38,
1794 OPC_MXU__POOL20 = 0x39,
1795 OPC_MXU__POOL21 = 0x3A,
1796 OPC_MXU_Q16SCOP = 0x3B,
1797 OPC_MXU_Q8MADL = 0x3C,
1798 OPC_MXU_S32SFL = 0x3D,
1799 OPC_MXU_Q8SAD = 0x3E,
1800 /* not assigned 0x3F */
1801 };
1802
1803
1804 /*
1805 * MXU pool 00
1806 */
1807 enum {
1808 OPC_MXU_S32MAX = 0x00,
1809 OPC_MXU_S32MIN = 0x01,
1810 OPC_MXU_D16MAX = 0x02,
1811 OPC_MXU_D16MIN = 0x03,
1812 OPC_MXU_Q8MAX = 0x04,
1813 OPC_MXU_Q8MIN = 0x05,
1814 OPC_MXU_Q8SLT = 0x06,
1815 OPC_MXU_Q8SLTU = 0x07,
1816 };
1817
1818 /*
1819 * MXU pool 01
1820 */
1821 enum {
1822 OPC_MXU_S32SLT = 0x00,
1823 OPC_MXU_D16SLT = 0x01,
1824 OPC_MXU_D16AVG = 0x02,
1825 OPC_MXU_D16AVGR = 0x03,
1826 OPC_MXU_Q8AVG = 0x04,
1827 OPC_MXU_Q8AVGR = 0x05,
1828 OPC_MXU_Q8ADD = 0x07,
1829 };
1830
1831 /*
1832 * MXU pool 02
1833 */
1834 enum {
1835 OPC_MXU_S32CPS = 0x00,
1836 OPC_MXU_D16CPS = 0x02,
1837 OPC_MXU_Q8ABD = 0x04,
1838 OPC_MXU_Q16SAT = 0x06,
1839 };
1840
1841 /*
1842 * MXU pool 03
1843 */
1844 enum {
1845 OPC_MXU_D16MULF = 0x00,
1846 OPC_MXU_D16MULE = 0x01,
1847 };
1848
1849 /*
1850 * MXU pool 04
1851 */
1852 enum {
1853 OPC_MXU_S32LDD = 0x00,
1854 OPC_MXU_S32LDDR = 0x01,
1855 };
1856
1857 /*
1858 * MXU pool 05
1859 */
1860 enum {
1861 OPC_MXU_S32STD = 0x00,
1862 OPC_MXU_S32STDR = 0x01,
1863 };
1864
1865 /*
1866 * MXU pool 06
1867 */
1868 enum {
1869 OPC_MXU_S32LDDV = 0x00,
1870 OPC_MXU_S32LDDVR = 0x01,
1871 };
1872
1873 /*
1874 * MXU pool 07
1875 */
1876 enum {
1877 OPC_MXU_S32STDV = 0x00,
1878 OPC_MXU_S32STDVR = 0x01,
1879 };
1880
1881 /*
1882 * MXU pool 08
1883 */
1884 enum {
1885 OPC_MXU_S32LDI = 0x00,
1886 OPC_MXU_S32LDIR = 0x01,
1887 };
1888
1889 /*
1890 * MXU pool 09
1891 */
1892 enum {
1893 OPC_MXU_S32SDI = 0x00,
1894 OPC_MXU_S32SDIR = 0x01,
1895 };
1896
1897 /*
1898 * MXU pool 10
1899 */
1900 enum {
1901 OPC_MXU_S32LDIV = 0x00,
1902 OPC_MXU_S32LDIVR = 0x01,
1903 };
1904
1905 /*
1906 * MXU pool 11
1907 */
1908 enum {
1909 OPC_MXU_S32SDIV = 0x00,
1910 OPC_MXU_S32SDIVR = 0x01,
1911 };
1912
1913 /*
1914 * MXU pool 12
1915 */
1916 enum {
1917 OPC_MXU_D32ACC = 0x00,
1918 OPC_MXU_D32ACCM = 0x01,
1919 OPC_MXU_D32ASUM = 0x02,
1920 };
1921
1922 /*
1923 * MXU pool 13
1924 */
1925 enum {
1926 OPC_MXU_Q16ACC = 0x00,
1927 OPC_MXU_Q16ACCM = 0x01,
1928 OPC_MXU_Q16ASUM = 0x02,
1929 };
1930
1931 /*
1932 * MXU pool 14
1933 */
1934 enum {
1935 OPC_MXU_Q8ADDE = 0x00,
1936 OPC_MXU_D8SUM = 0x01,
1937 OPC_MXU_D8SUMC = 0x02,
1938 };
1939
1940 /*
1941 * MXU pool 15
1942 */
1943 enum {
1944 OPC_MXU_S32MUL = 0x00,
1945 OPC_MXU_S32MULU = 0x01,
1946 OPC_MXU_S32EXTR = 0x02,
1947 OPC_MXU_S32EXTRV = 0x03,
1948 };
1949
1950 /*
1951 * MXU pool 16
1952 */
1953 enum {
1954 OPC_MXU_D32SARW = 0x00,
1955 OPC_MXU_S32ALN = 0x01,
1956 OPC_MXU_S32ALNI = 0x02,
1957 OPC_MXU_S32LUI = 0x03,
1958 OPC_MXU_S32NOR = 0x04,
1959 OPC_MXU_S32AND = 0x05,
1960 OPC_MXU_S32OR = 0x06,
1961 OPC_MXU_S32XOR = 0x07,
1962 };
1963
1964 /*
1965 * MXU pool 17
1966 */
1967 enum {
1968 OPC_MXU_LXB = 0x00,
1969 OPC_MXU_LXH = 0x01,
1970 OPC_MXU_LXW = 0x03,
1971 OPC_MXU_LXBU = 0x04,
1972 OPC_MXU_LXHU = 0x05,
1973 };
1974
1975 /*
1976 * MXU pool 18
1977 */
1978 enum {
1979 OPC_MXU_D32SLLV = 0x00,
1980 OPC_MXU_D32SLRV = 0x01,
1981 OPC_MXU_D32SARV = 0x03,
1982 OPC_MXU_Q16SLLV = 0x04,
1983 OPC_MXU_Q16SLRV = 0x05,
1984 OPC_MXU_Q16SARV = 0x07,
1985 };
1986
1987 /*
1988 * MXU pool 19
1989 */
1990 enum {
1991 OPC_MXU_Q8MUL = 0x00,
1992 OPC_MXU_Q8MULSU = 0x01,
1993 };
1994
1995 /*
1996 * MXU pool 20
1997 */
1998 enum {
1999 OPC_MXU_Q8MOVZ = 0x00,
2000 OPC_MXU_Q8MOVN = 0x01,
2001 OPC_MXU_D16MOVZ = 0x02,
2002 OPC_MXU_D16MOVN = 0x03,
2003 OPC_MXU_S32MOVZ = 0x04,
2004 OPC_MXU_S32MOVN = 0x05,
2005 };
2006
2007 /*
2008 * MXU pool 21
2009 */
2010 enum {
2011 OPC_MXU_Q8MAC = 0x00,
2012 OPC_MXU_Q8MACSU = 0x01,
2013 };
2014
2015 /*
2016 * Overview of the TX79-specific instruction set
2017 * =============================================
2018 *
2019 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
2020 * are only used by the specific quadword (128-bit) LQ/SQ load/store
2021 * instructions and certain multimedia instructions (MMIs). These MMIs
2022 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
2023 * or sixteen 8-bit paths.
2024 *
2025 * Reference:
2026 *
2027 * The Toshiba TX System RISC TX79 Core Architecture manual,
2028 * https://wiki.qemu.org/File:C790.pdf
2029 *
2030 * Three-Operand Multiply and Multiply-Add (4 instructions)
2031 * --------------------------------------------------------
2032 * MADD [rd,] rs, rt Multiply/Add
2033 * MADDU [rd,] rs, rt Multiply/Add Unsigned
2034 * MULT [rd,] rs, rt Multiply (3-operand)
2035 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
2036 *
2037 * Multiply Instructions for Pipeline 1 (10 instructions)
2038 * ------------------------------------------------------
2039 * MULT1 [rd,] rs, rt Multiply Pipeline 1
2040 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
2041 * DIV1 rs, rt Divide Pipeline 1
2042 * DIVU1 rs, rt Divide Unsigned Pipeline 1
2043 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
2044 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
2045 * MFHI1 rd Move From HI1 Register
2046 * MFLO1 rd Move From LO1 Register
2047 * MTHI1 rs Move To HI1 Register
2048 * MTLO1 rs Move To LO1 Register
2049 *
2050 * Arithmetic (19 instructions)
2051 * ----------------------------
2052 * PADDB rd, rs, rt Parallel Add Byte
2053 * PSUBB rd, rs, rt Parallel Subtract Byte
2054 * PADDH rd, rs, rt Parallel Add Halfword
2055 * PSUBH rd, rs, rt Parallel Subtract Halfword
2056 * PADDW rd, rs, rt Parallel Add Word
2057 * PSUBW rd, rs, rt Parallel Subtract Word
2058 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
2059 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
2060 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
2061 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
2062 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
2063 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
2064 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
2065 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
2066 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
2067 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
2068 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
2069 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
2070 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
2071 *
2072 * Min/Max (4 instructions)
2073 * ------------------------
2074 * PMAXH rd, rs, rt Parallel Maximum Halfword
2075 * PMINH rd, rs, rt Parallel Minimum Halfword
2076 * PMAXW rd, rs, rt Parallel Maximum Word
2077 * PMINW rd, rs, rt Parallel Minimum Word
2078 *
2079 * Absolute (2 instructions)
2080 * -------------------------
2081 * PABSH rd, rt Parallel Absolute Halfword
2082 * PABSW rd, rt Parallel Absolute Word
2083 *
2084 * Logical (4 instructions)
2085 * ------------------------
2086 * PAND rd, rs, rt Parallel AND
2087 * POR rd, rs, rt Parallel OR
2088 * PXOR rd, rs, rt Parallel XOR
2089 * PNOR rd, rs, rt Parallel NOR
2090 *
2091 * Shift (9 instructions)
2092 * ----------------------
2093 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
2094 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
2095 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
2096 * PSLLW rd, rt, sa Parallel Shift Left Logical Word
2097 * PSRLW rd, rt, sa Parallel Shift Right Logical Word
2098 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
2099 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
2100 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
2101 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
2102 *
2103 * Compare (6 instructions)
2104 * ------------------------
2105 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
2106 * PCEQB rd, rs, rt Parallel Compare for Equal Byte
2107 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
2108 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
2109 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
2110 * PCEQW rd, rs, rt Parallel Compare for Equal Word
2111 *
2112 * LZC (1 instruction)
2113 * -------------------
2114 * PLZCW rd, rs Parallel Leading Zero or One Count Word
2115 *
2116 * Quadword Load and Store (2 instructions)
2117 * ----------------------------------------
2118 * LQ rt, offset(base) Load Quadword
2119 * SQ rt, offset(base) Store Quadword
2120 *
2121 * Multiply and Divide (19 instructions)
2122 * -------------------------------------
2123 * PMULTW rd, rs, rt Parallel Multiply Word
2124 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
2125 * PDIVW rs, rt Parallel Divide Word
2126 * PDIVUW rs, rt Parallel Divide Unsigned Word
2127 * PMADDW rd, rs, rt Parallel Multiply-Add Word
2128 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
2129 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
2130 * PMULTH rd, rs, rt Parallel Multiply Halfword
2131 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
2132 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
2133 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
2134 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
2135 * PDIVBW rs, rt Parallel Divide Broadcast Word
2136 * PMFHI rd Parallel Move From HI Register
2137 * PMFLO rd Parallel Move From LO Register
2138 * PMTHI rs Parallel Move To HI Register
2139 * PMTLO rs Parallel Move To LO Register
2140 * PMFHL rd Parallel Move From HI/LO Register
2141 * PMTHL rs Parallel Move To HI/LO Register
2142 *
2143 * Pack/Extend (11 instructions)
2144 * -----------------------------
2145 * PPAC5 rd, rt Parallel Pack to 5 bits
2146 * PPACB rd, rs, rt Parallel Pack to Byte
2147 * PPACH rd, rs, rt Parallel Pack to Halfword
2148 * PPACW rd, rs, rt Parallel Pack to Word
2149 * PEXT5 rd, rt Parallel Extend Upper from 5 bits
2150 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
2151 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
2152 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
2153 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
2154 * PEXTUW rd, rs, rt Parallel Extend Upper from Word
2155 * PEXTLW rd, rs, rt Parallel Extend Lower from Word
2156 *
2157 * Others (16 instructions)
2158 * ------------------------
2159 * PCPYH rd, rt Parallel Copy Halfword
2160 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
2161 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
2162 * PREVH rd, rt Parallel Reverse Halfword
2163 * PINTH rd, rs, rt Parallel Interleave Halfword
2164 * PINTEH rd, rs, rt Parallel Interleave Even Halfword
2165 * PEXEH rd, rt Parallel Exchange Even Halfword
2166 * PEXCH rd, rt Parallel Exchange Center Halfword
2167 * PEXEW rd, rt Parallel Exchange Even Word
2168 * PEXCW rd, rt Parallel Exchange Center Word
2169 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
2170 * MFSA rd Move from Shift Amount Register
2171 * MTSA rs Move to Shift Amount Register
2172 * MTSAB rs, immediate Move Byte Count to Shift Amount Register
2173 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
2174 * PROT3W rd, rt Parallel Rotate 3 Words
2175 *
2176 * MMI (MultiMedia Instruction) encodings
2177 * ======================================
2178 *
2179 * MMI instructions encoding table keys:
2180 *
2181 * * This code is reserved for future use. An attempt to execute it
2182 * causes a Reserved Instruction exception.
2183 * % This code indicates an instruction class. The instruction word
2184 * must be further decoded by examining additional tables that show
2185 * the values for other instruction fields.
2186 * # This code is reserved for the unsupported instructions DMULT,
2187 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
2188 * to execute it causes a Reserved Instruction exception.
2189 *
2190 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
2191 *
2192 * 31 26 0
2193 * +--------+----------------------------------------+
2194 * | opcode | |
2195 * +--------+----------------------------------------+
2196 *
2197 * opcode bits 28..26
2198 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2199 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2200 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2201 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
2202 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
2203 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
2204 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
2205 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
2206 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
2207 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
2208 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
2209 */
2210
2211 enum {
2212 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
2213 MMI_OPC_LQ = 0x1E << 26, /* Same as OPC_MSA */
2214 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
2215 };
2216
2217 /*
2218 * MMI instructions with opcode field = MMI:
2219 *
2220 * 31 26 5 0
2221 * +--------+-------------------------------+--------+
2222 * | MMI | |function|
2223 * +--------+-------------------------------+--------+
2224 *
2225 * function bits 2..0
2226 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2227 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2228 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2229 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
2230 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
2231 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
2232 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
2233 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
2234 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
2235 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
2236 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
2237 */
2238
2239 #define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
2240 enum {
2241 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
2242 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
2243 MMI_OPC_PLZCW = 0x04 | MMI_OPC_CLASS_MMI,
2244 MMI_OPC_CLASS_MMI0 = 0x08 | MMI_OPC_CLASS_MMI,
2245 MMI_OPC_CLASS_MMI2 = 0x09 | MMI_OPC_CLASS_MMI,
2246 MMI_OPC_MFHI1 = 0x10 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFHI */
2247 MMI_OPC_MTHI1 = 0x11 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTHI */
2248 MMI_OPC_MFLO1 = 0x12 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFLO */
2249 MMI_OPC_MTLO1 = 0x13 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTLO */
2250 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
2251 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
2252 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
2253 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
2254 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
2255 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
2256 MMI_OPC_CLASS_MMI1 = 0x28 | MMI_OPC_CLASS_MMI,
2257 MMI_OPC_CLASS_MMI3 = 0x29 | MMI_OPC_CLASS_MMI,
2258 MMI_OPC_PMFHL = 0x30 | MMI_OPC_CLASS_MMI,
2259 MMI_OPC_PMTHL = 0x31 | MMI_OPC_CLASS_MMI,
2260 MMI_OPC_PSLLH = 0x34 | MMI_OPC_CLASS_MMI,
2261 MMI_OPC_PSRLH = 0x36 | MMI_OPC_CLASS_MMI,
2262 MMI_OPC_PSRAH = 0x37 | MMI_OPC_CLASS_MMI,
2263 MMI_OPC_PSLLW = 0x3C | MMI_OPC_CLASS_MMI,
2264 MMI_OPC_PSRLW = 0x3E | MMI_OPC_CLASS_MMI,
2265 MMI_OPC_PSRAW = 0x3F | MMI_OPC_CLASS_MMI,
2266 };
2267
2268 /*
2269 * MMI instructions with opcode field = MMI and bits 5..0 = MMI0:
2270 *
2271 * 31 26 10 6 5 0
2272 * +--------+----------------------+--------+--------+
2273 * | MMI | |function| MMI0 |
2274 * +--------+----------------------+--------+--------+
2275 *
2276 * function bits 7..6
2277 * bits | 0 | 1 | 2 | 3
2278 * 10..8 | 00 | 01 | 10 | 11
2279 * -------+-------+-------+-------+-------
2280 * 0 000 | PADDW | PSUBW | PCGTW | PMAXW
2281 * 1 001 | PADDH | PSUBH | PCGTH | PMAXH
2282 * 2 010 | PADDB | PSUBB | PCGTB | *
2283 * 3 011 | * | * | * | *
2284 * 4 100 | PADDSW| PSUBSW| PEXTLW| PPACW
2285 * 5 101 | PADDSH| PSUBSH| PEXTLH| PPACH
2286 * 6 110 | PADDSB| PSUBSB| PEXTLB| PPACB
2287 * 7 111 | * | * | PEXT5 | PPAC5
2288 */
2289
2290 #define MASK_MMI0(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2291 enum {
2292 MMI_OPC_0_PADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI0,
2293 MMI_OPC_0_PSUBW = (0x01 << 6) | MMI_OPC_CLASS_MMI0,
2294 MMI_OPC_0_PCGTW = (0x02 << 6) | MMI_OPC_CLASS_MMI0,
2295 MMI_OPC_0_PMAXW = (0x03 << 6) | MMI_OPC_CLASS_MMI0,
2296 MMI_OPC_0_PADDH = (0x04 << 6) | MMI_OPC_CLASS_MMI0,
2297 MMI_OPC_0_PSUBH = (0x05 << 6) | MMI_OPC_CLASS_MMI0,
2298 MMI_OPC_0_PCGTH = (0x06 << 6) | MMI_OPC_CLASS_MMI0,
2299 MMI_OPC_0_PMAXH = (0x07 << 6) | MMI_OPC_CLASS_MMI0,
2300 MMI_OPC_0_PADDB = (0x08 << 6) | MMI_OPC_CLASS_MMI0,
2301 MMI_OPC_0_PSUBB = (0x09 << 6) | MMI_OPC_CLASS_MMI0,
2302 MMI_OPC_0_PCGTB = (0x0A << 6) | MMI_OPC_CLASS_MMI0,
2303 MMI_OPC_0_PADDSW = (0x10 << 6) | MMI_OPC_CLASS_MMI0,
2304 MMI_OPC_0_PSUBSW = (0x11 << 6) | MMI_OPC_CLASS_MMI0,
2305 MMI_OPC_0_PEXTLW = (0x12 << 6) | MMI_OPC_CLASS_MMI0,
2306 MMI_OPC_0_PPACW = (0x13 << 6) | MMI_OPC_CLASS_MMI0,
2307 MMI_OPC_0_PADDSH = (0x14 << 6) | MMI_OPC_CLASS_MMI0,
2308 MMI_OPC_0_PSUBSH = (0x15 << 6) | MMI_OPC_CLASS_MMI0,
2309 MMI_OPC_0_PEXTLH = (0x16 << 6) | MMI_OPC_CLASS_MMI0,
2310 MMI_OPC_0_PPACH = (0x17 << 6) | MMI_OPC_CLASS_MMI0,
2311 MMI_OPC_0_PADDSB = (0x18 << 6) | MMI_OPC_CLASS_MMI0,
2312 MMI_OPC_0_PSUBSB = (0x19 << 6) | MMI_OPC_CLASS_MMI0,
2313 MMI_OPC_0_PEXTLB = (0x1A << 6) | MMI_OPC_CLASS_MMI0,
2314 MMI_OPC_0_PPACB = (0x1B << 6) | MMI_OPC_CLASS_MMI0,
2315 MMI_OPC_0_PEXT5 = (0x1E << 6) | MMI_OPC_CLASS_MMI0,
2316 MMI_OPC_0_PPAC5 = (0x1F << 6) | MMI_OPC_CLASS_MMI0,
2317 };
2318
2319 /*
2320 * MMI instructions with opcode field = MMI and bits 5..0 = MMI1:
2321 *
2322 * 31 26 10 6 5 0
2323 * +--------+----------------------+--------+--------+
2324 * | MMI | |function| MMI1 |
2325 * +--------+----------------------+--------+--------+
2326 *
2327 * function bits 7..6
2328 * bits | 0 | 1 | 2 | 3
2329 * 10..8 | 00 | 01 | 10 | 11
2330 * -------+-------+-------+-------+-------
2331 * 0 000 | * | PABSW | PCEQW | PMINW
2332 * 1 001 | PADSBH| PABSH | PCEQH | PMINH
2333 * 2 010 | * | * | PCEQB | *
2334 * 3 011 | * | * | * | *
2335 * 4 100 | PADDUW| PSUBUW| PEXTUW| *
2336 * 5 101 | PADDUH| PSUBUH| PEXTUH| *
2337 * 6 110 | PADDUB| PSUBUB| PEXTUB| QFSRV
2338 * 7 111 | * | * | * | *
2339 */
2340
2341 #define MASK_MMI1(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2342 enum {
2343 MMI_OPC_1_PABSW = (0x01 << 6) | MMI_OPC_CLASS_MMI1,
2344 MMI_OPC_1_PCEQW = (0x02 << 6) | MMI_OPC_CLASS_MMI1,
2345 MMI_OPC_1_PMINW = (0x03 << 6) | MMI_OPC_CLASS_MMI1,
2346 MMI_OPC_1_PADSBH = (0x04 << 6) | MMI_OPC_CLASS_MMI1,
2347 MMI_OPC_1_PABSH = (0x05 << 6) | MMI_OPC_CLASS_MMI1,
2348 MMI_OPC_1_PCEQH = (0x06 << 6) | MMI_OPC_CLASS_MMI1,
2349 MMI_OPC_1_PMINH = (0x07 << 6) | MMI_OPC_CLASS_MMI1,
2350 MMI_OPC_1_PCEQB = (0x0A << 6) | MMI_OPC_CLASS_MMI1,
2351 MMI_OPC_1_PADDUW = (0x10 << 6) | MMI_OPC_CLASS_MMI1,
2352 MMI_OPC_1_PSUBUW = (0x11 << 6) | MMI_OPC_CLASS_MMI1,
2353 MMI_OPC_1_PEXTUW = (0x12 << 6) | MMI_OPC_CLASS_MMI1,
2354 MMI_OPC_1_PADDUH = (0x14 << 6) | MMI_OPC_CLASS_MMI1,
2355 MMI_OPC_1_PSUBUH = (0x15 << 6) | MMI_OPC_CLASS_MMI1,
2356 MMI_OPC_1_PEXTUH = (0x16 << 6) | MMI_OPC_CLASS_MMI1,
2357 MMI_OPC_1_PADDUB = (0x18 << 6) | MMI_OPC_CLASS_MMI1,
2358 MMI_OPC_1_PSUBUB = (0x19 << 6) | MMI_OPC_CLASS_MMI1,
2359 MMI_OPC_1_PEXTUB = (0x1A << 6) | MMI_OPC_CLASS_MMI1,
2360 MMI_OPC_1_QFSRV = (0x1B << 6) | MMI_OPC_CLASS_MMI1,
2361 };
2362
2363 /*
2364 * MMI instructions with opcode field = MMI and bits 5..0 = MMI2:
2365 *
2366 * 31 26 10 6 5 0
2367 * +--------+----------------------+--------+--------+
2368 * | MMI | |function| MMI2 |
2369 * +--------+----------------------+--------+--------+
2370 *
2371 * function bits 7..6
2372 * bits | 0 | 1 | 2 | 3
2373 * 10..8 | 00 | 01 | 10 | 11
2374 * -------+-------+-------+-------+-------
2375 * 0 000 | PMADDW| * | PSLLVW| PSRLVW
2376 * 1 001 | PMSUBW| * | * | *
2377 * 2 010 | PMFHI | PMFLO | PINTH | *
2378 * 3 011 | PMULTW| PDIVW | PCPYLD| *
2379 * 4 100 | PMADDH| PHMADH| PAND | PXOR
2380 * 5 101 | PMSUBH| PHMSBH| * | *
2381 * 6 110 | * | * | PEXEH | PREVH
2382 * 7 111 | PMULTH| PDIVBW| PEXEW | PROT3W
2383 */
2384
2385 #define MASK_MMI2(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2386 enum {
2387 MMI_OPC_2_PMADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI2,
2388 MMI_OPC_2_PSLLVW = (0x02 << 6) | MMI_OPC_CLASS_MMI2,
2389 MMI_OPC_2_PSRLVW = (0x03 << 6) | MMI_OPC_CLASS_MMI2,
2390 MMI_OPC_2_PMSUBW = (0x04 << 6) | MMI_OPC_CLASS_MMI2,
2391 MMI_OPC_2_PMFHI = (0x08 << 6) | MMI_OPC_CLASS_MMI2,
2392 MMI_OPC_2_PMFLO = (0x09 << 6) | MMI_OPC_CLASS_MMI2,
2393 MMI_OPC_2_PINTH = (0x0A << 6) | MMI_OPC_CLASS_MMI2,
2394 MMI_OPC_2_PMULTW = (0x0C << 6) | MMI_OPC_CLASS_MMI2,
2395 MMI_OPC_2_PDIVW = (0x0D << 6) | MMI_OPC_CLASS_MMI2,
2396 MMI_OPC_2_PCPYLD = (0x0E << 6) | MMI_OPC_CLASS_MMI2,
2397 MMI_OPC_2_PMADDH = (0x10 << 6) | MMI_OPC_CLASS_MMI2,
2398 MMI_OPC_2_PHMADH = (0x11 << 6) | MMI_OPC_CLASS_MMI2,
2399 MMI_OPC_2_PAND = (0x12 << 6) | MMI_OPC_CLASS_MMI2,
2400 MMI_OPC_2_PXOR = (0x13 << 6) | MMI_OPC_CLASS_MMI2,
2401 MMI_OPC_2_PMSUBH = (0x14 << 6) | MMI_OPC_CLASS_MMI2,
2402 MMI_OPC_2_PHMSBH = (0x15 << 6) | MMI_OPC_CLASS_MMI2,
2403 MMI_OPC_2_PEXEH = (0x1A << 6) | MMI_OPC_CLASS_MMI2,
2404 MMI_OPC_2_PREVH = (0x1B << 6) | MMI_OPC_CLASS_MMI2,
2405 MMI_OPC_2_PMULTH = (0x1C << 6) | MMI_OPC_CLASS_MMI2,
2406 MMI_OPC_2_PDIVBW = (0x1D << 6) | MMI_OPC_CLASS_MMI2,
2407 MMI_OPC_2_PEXEW = (0x1E << 6) | MMI_OPC_CLASS_MMI2,
2408 MMI_OPC_2_PROT3W = (0x1F << 6) | MMI_OPC_CLASS_MMI2,
2409 };
2410
2411 /*
2412 * MMI instructions with opcode field = MMI and bits 5..0 = MMI3:
2413 *
2414 * 31 26 10 6 5 0
2415 * +--------+----------------------+--------+--------+
2416 * | MMI | |function| MMI3 |
2417 * +--------+----------------------+--------+--------+
2418 *
2419 * function bits 7..6
2420 * bits | 0 | 1 | 2 | 3
2421 * 10..8 | 00 | 01 | 10 | 11
2422 * -------+-------+-------+-------+-------
2423 * 0 000 |PMADDUW| * | * | PSRAVW
2424 * 1 001 | * | * | * | *
2425 * 2 010 | PMTHI | PMTLO | PINTEH| *
2426 * 3 011 |PMULTUW| PDIVUW| PCPYUD| *
2427 * 4 100 | * | * | POR | PNOR
2428 * 5 101 | * | * | * | *
2429 * 6 110 | * | * | PEXCH | PCPYH
2430 * 7 111 | * | * | PEXCW | *
2431 */
2432
2433 #define MASK_MMI3(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2434 enum {
2435 MMI_OPC_3_PMADDUW = (0x00 << 6) | MMI_OPC_CLASS_MMI3,
2436 MMI_OPC_3_PSRAVW = (0x03 << 6) | MMI_OPC_CLASS_MMI3,
2437 MMI_OPC_3_PMTHI = (0x08 << 6) | MMI_OPC_CLASS_MMI3,
2438 MMI_OPC_3_PMTLO = (0x09 << 6) | MMI_OPC_CLASS_MMI3,
2439 MMI_OPC_3_PINTEH = (0x0A << 6) | MMI_OPC_CLASS_MMI3,
2440 MMI_OPC_3_PMULTUW = (0x0C << 6) | MMI_OPC_CLASS_MMI3,
2441 MMI_OPC_3_PDIVUW = (0x0D << 6) | MMI_OPC_CLASS_MMI3,
2442 MMI_OPC_3_PCPYUD = (0x0E << 6) | MMI_OPC_CLASS_MMI3,
2443 MMI_OPC_3_POR = (0x12 << 6) | MMI_OPC_CLASS_MMI3,
2444 MMI_OPC_3_PNOR = (0x13 << 6) | MMI_OPC_CLASS_MMI3,
2445 MMI_OPC_3_PEXCH = (0x1A << 6) | MMI_OPC_CLASS_MMI3,
2446 MMI_OPC_3_PCPYH = (0x1B << 6) | MMI_OPC_CLASS_MMI3,
2447 MMI_OPC_3_PEXCW = (0x1E << 6) | MMI_OPC_CLASS_MMI3,
2448 };
2449
2450 /* global register indices */
2451 static TCGv cpu_gpr[32], cpu_PC;
2452 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
2453 static TCGv cpu_dspctrl, btarget, bcond;
2454 static TCGv cpu_lladdr, cpu_llval;
2455 static TCGv_i32 hflags;
2456 static TCGv_i32 fpu_fcr0, fpu_fcr31;
2457 static TCGv_i64 fpu_f64[32];
2458 static TCGv_i64 msa_wr_d[64];
2459
2460 #if defined(TARGET_MIPS64)
2461 /* Upper halves of R5900's 128-bit registers: MMRs (multimedia registers) */
2462 static TCGv_i64 cpu_mmr[32];
2463 #endif
2464
2465 #if !defined(TARGET_MIPS64)
2466 /* MXU registers */
2467 static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1];
2468 static TCGv mxu_CR;
2469 #endif
2470
2471 #include "exec/gen-icount.h"
2472
2473 #define gen_helper_0e0i(name, arg) do { \
2474 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
2475 gen_helper_##name(cpu_env, helper_tmp); \
2476 tcg_temp_free_i32(helper_tmp); \
2477 } while(0)
2478
2479 #define gen_helper_0e1i(name, arg1, arg2) do { \
2480 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2481 gen_helper_##name(cpu_env, arg1, helper_tmp); \
2482 tcg_temp_free_i32(helper_tmp); \
2483 } while(0)
2484
2485 #define gen_helper_1e0i(name, ret, arg1) do { \
2486 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
2487 gen_helper_##name(ret, cpu_env, helper_tmp); \
2488 tcg_temp_free_i32(helper_tmp); \
2489 } while(0)
2490
2491 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
2492 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2493 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
2494 tcg_temp_free_i32(helper_tmp); \
2495 } while(0)
2496
2497 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
2498 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2499 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
2500 tcg_temp_free_i32(helper_tmp); \
2501 } while(0)
2502
2503 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
2504 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2505 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
2506 tcg_temp_free_i32(helper_tmp); \
2507 } while(0)
2508
2509 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
2510 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
2511 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
2512 tcg_temp_free_i32(helper_tmp); \
2513 } while(0)
2514
2515 typedef struct DisasContext {
2516 DisasContextBase base;
2517 target_ulong saved_pc;
2518 target_ulong page_start;
2519 uint32_t opcode;
2520 uint64_t insn_flags;
2521 int32_t CP0_Config1;
2522 int32_t CP0_Config2;
2523 int32_t CP0_Config3;
2524 int32_t CP0_Config5;
2525 /* Routine used to access memory */
2526 int mem_idx;
2527 TCGMemOp default_tcg_memop_mask;
2528 uint32_t hflags, saved_hflags;
2529 target_ulong btarget;
2530 bool ulri;
2531 int kscrexist;
2532 bool rxi;
2533 int ie;
2534 bool bi;
2535 bool bp;
2536 uint64_t PAMask;
2537 bool mvh;
2538 bool eva;
2539 bool sc;
2540 int CP0_LLAddr_shift;
2541 bool ps;
2542 bool vp;
2543 bool cmgcr;
2544 bool mrp;
2545 bool nan2008;
2546 bool abs2008;
2547 bool saar;
2548 } DisasContext;
2549
2550 #define DISAS_STOP DISAS_TARGET_0
2551 #define DISAS_EXIT DISAS_TARGET_1
2552
2553 static const char * const regnames[] = {
2554 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2555 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2556 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2557 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2558 };
2559
2560 static const char * const regnames_HI[] = {
2561 "HI0", "HI1", "HI2", "HI3",
2562 };
2563
2564 static const char * const regnames_LO[] = {
2565 "LO0", "LO1", "LO2", "LO3",
2566 };
2567
2568 static const char * const fregnames[] = {
2569 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2570 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2571 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2572 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2573 };
2574
2575 static const char * const msaregnames[] = {
2576 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
2577 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
2578 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
2579 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
2580 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
2581 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
2582 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
2583 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
2584 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
2585 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
2586 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
2587 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
2588 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
2589 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
2590 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
2591 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
2592 };
2593
2594 #if !defined(TARGET_MIPS64)
2595 static const char * const mxuregnames[] = {
2596 "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8",
2597 "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR",
2598 };
2599 #endif
2600
2601 #define LOG_DISAS(...) \
2602 do { \
2603 if (MIPS_DEBUG_DISAS) { \
2604 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
2605 } \
2606 } while (0)
2607
2608 #define MIPS_INVAL(op) \
2609 do { \
2610 if (MIPS_DEBUG_DISAS) { \
2611 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
2612 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
2613 ctx->base.pc_next, ctx->opcode, op, \
2614 ctx->opcode >> 26, ctx->opcode & 0x3F, \
2615 ((ctx->opcode >> 16) & 0x1F)); \
2616 } \
2617 } while (0)
2618
2619 /* General purpose registers moves. */
2620 static inline void gen_load_gpr(TCGv t, int reg)
2621 {
2622 if (reg == 0) {
2623 tcg_gen_movi_tl(t, 0);
2624 } else {
2625 tcg_gen_mov_tl(t, cpu_gpr[reg]);
2626 }
2627 }
2628
2629 static inline void gen_store_gpr(TCGv t, int reg)
2630 {
2631 if (reg != 0) {
2632 tcg_gen_mov_tl(cpu_gpr[reg], t);
2633 }
2634 }
2635
2636 /* Moves to/from shadow registers. */
2637 static inline void gen_load_srsgpr(int from, int to)
2638 {
2639 TCGv t0 = tcg_temp_new();
2640
2641 if (from == 0) {
2642 tcg_gen_movi_tl(t0, 0);
2643 } else {
2644 TCGv_i32 t2 = tcg_temp_new_i32();
2645 TCGv_ptr addr = tcg_temp_new_ptr();
2646
2647 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2648 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2649 tcg_gen_andi_i32(t2, t2, 0xf);
2650 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2651 tcg_gen_ext_i32_ptr(addr, t2);
2652 tcg_gen_add_ptr(addr, cpu_env, addr);
2653
2654 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
2655 tcg_temp_free_ptr(addr);
2656 tcg_temp_free_i32(t2);
2657 }
2658 gen_store_gpr(t0, to);
2659 tcg_temp_free(t0);
2660 }
2661
2662 static inline void gen_store_srsgpr (int from, int to)
2663 {
2664 if (to != 0) {
2665 TCGv t0 = tcg_temp_new();
2666 TCGv_i32 t2 = tcg_temp_new_i32();
2667 TCGv_ptr addr = tcg_temp_new_ptr();
2668
2669 gen_load_gpr(t0, from);
2670 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2671 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2672 tcg_gen_andi_i32(t2, t2, 0xf);
2673 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2674 tcg_gen_ext_i32_ptr(addr, t2);
2675 tcg_gen_add_ptr(addr, cpu_env, addr);
2676
2677 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
2678 tcg_temp_free_ptr(addr);
2679 tcg_temp_free_i32(t2);
2680 tcg_temp_free(t0);
2681 }
2682 }
2683
2684 #if !defined(TARGET_MIPS64)
2685 /* MXU General purpose registers moves. */
2686 static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg)
2687 {
2688 if (reg == 0) {
2689 tcg_gen_movi_tl(t, 0);
2690 } else if (reg <= 15) {
2691 tcg_gen_mov_tl(t, mxu_gpr[reg - 1]);
2692 }
2693 }
2694
2695 static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg)
2696 {
2697 if (reg > 0 && reg <= 15) {
2698 tcg_gen_mov_tl(mxu_gpr[reg - 1], t);
2699 }
2700 }
2701
2702 /* MXU control register moves. */
2703 static inline void gen_load_mxu_cr(TCGv t)
2704 {
2705 tcg_gen_mov_tl(t, mxu_CR);
2706 }
2707
2708 static inline void gen_store_mxu_cr(TCGv t)
2709 {
2710 /* TODO: Add handling of RW rules for MXU_CR. */
2711 tcg_gen_mov_tl(mxu_CR, t);
2712 }
2713 #endif
2714
2715
2716 /* Tests */
2717 static inline void gen_save_pc(target_ulong pc)
2718 {
2719 tcg_gen_movi_tl(cpu_PC, pc);
2720 }
2721
2722 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2723 {
2724 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
2725 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2726 gen_save_pc(ctx->base.pc_next);
2727 ctx->saved_pc = ctx->base.pc_next;
2728 }
2729 if (ctx->hflags != ctx->saved_hflags) {
2730 tcg_gen_movi_i32(hflags, ctx->hflags);
2731 ctx->saved_hflags = ctx->hflags;
2732 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2733 case MIPS_HFLAG_BR:
2734 break;
2735 case MIPS_HFLAG_BC:
2736 case MIPS_HFLAG_BL:
2737 case MIPS_HFLAG_B:
2738 tcg_gen_movi_tl(btarget, ctx->btarget);
2739 break;
2740 }
2741 }
2742 }
2743
2744 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2745 {
2746 ctx->saved_hflags = ctx->hflags;
2747 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2748 case MIPS_HFLAG_BR:
2749 break;
2750 case MIPS_HFLAG_BC:
2751 case MIPS_HFLAG_BL:
2752 case MIPS_HFLAG_B:
2753 ctx->btarget = env->btarget;
2754 break;
2755 }
2756 }
2757
2758 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
2759 {
2760 TCGv_i32 texcp = tcg_const_i32(excp);
2761 TCGv_i32 terr = tcg_const_i32(err);
2762 save_cpu_state(ctx, 1);
2763 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2764 tcg_temp_free_i32(terr);
2765 tcg_temp_free_i32(texcp);
2766 ctx->base.is_jmp = DISAS_NORETURN;
2767 }
2768
2769 static inline void generate_exception(DisasContext *ctx, int excp)
2770 {
2771 gen_helper_0e0i(raise_exception, excp);
2772 }
2773
2774 static inline void generate_exception_end(DisasContext *ctx, int excp)
2775 {
2776 generate_exception_err(ctx, excp, 0);
2777 }
2778
2779 /* Floating point register moves. */
2780 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2781 {
2782 if (ctx->hflags & MIPS_HFLAG_FRE) {
2783 generate_exception(ctx, EXCP_RI);
2784 }
2785 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
2786 }
2787
2788 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2789 {
2790 TCGv_i64 t64;
2791 if (ctx->hflags & MIPS_HFLAG_FRE) {
2792 generate_exception(ctx, EXCP_RI);
2793 }
2794 t64 = tcg_temp_new_i64();
2795 tcg_gen_extu_i32_i64(t64, t);
2796 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2797 tcg_temp_free_i64(t64);
2798 }
2799
2800 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2801 {
2802 if (ctx->hflags & MIPS_HFLAG_F64) {
2803 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
2804 } else {
2805 gen_load_fpr32(ctx, t, reg | 1);
2806 }
2807 }
2808
2809 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2810 {
2811 if (ctx->hflags & MIPS_HFLAG_F64) {
2812 TCGv_i64 t64 = tcg_temp_new_i64();
2813 tcg_gen_extu_i32_i64(t64, t);
2814 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2815 tcg_temp_free_i64(t64);
2816 } else {
2817 gen_store_fpr32(ctx, t, reg | 1);
2818 }
2819 }
2820
2821 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2822 {
2823 if (ctx->hflags & MIPS_HFLAG_F64) {
2824 tcg_gen_mov_i64(t, fpu_f64[reg]);
2825 } else {
2826 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
2827 }
2828 }
2829
2830 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2831 {
2832 if (ctx->hflags & MIPS_HFLAG_F64) {
2833 tcg_gen_mov_i64(fpu_f64[reg], t);
2834 } else {
2835 TCGv_i64 t0;
2836 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2837 t0 = tcg_temp_new_i64();
2838 tcg_gen_shri_i64(t0, t, 32);
2839 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
2840 tcg_temp_free_i64(t0);
2841 }
2842 }
2843
2844 static inline int get_fp_bit(int cc)
2845 {
2846 if (cc) {
2847 return 24 + cc;
2848 } else {
2849 return 23;
2850 }
2851 }
2852
2853 /* Addresses computation */
2854 static inline void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0,
2855 TCGv arg1)
2856 {
2857 tcg_gen_add_tl(ret, arg0, arg1);
2858
2859 #if defined(TARGET_MIPS64)
2860 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2861 tcg_gen_ext32s_i64(ret, ret);
2862 }
2863 #endif
2864 }
2865
2866 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2867 target_long ofs)
2868 {
2869 tcg_gen_addi_tl(ret, base, ofs);
2870
2871 #if defined(TARGET_MIPS64)
2872 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2873 tcg_gen_ext32s_i64(ret, ret);
2874 }
2875 #endif
2876 }
2877
2878 /* Addresses computation (translation time) */
2879 static target_long addr_add(DisasContext *ctx, target_long base,
2880 target_long offset)
2881 {
2882 target_long sum = base + offset;
2883
2884 #if defined(TARGET_MIPS64)
2885 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2886 sum = (int32_t)sum;
2887 }
2888 #endif
2889 return sum;
2890 }
2891
2892 /* Sign-extract the low 32-bits to a target_long. */
2893 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
2894 {
2895 #if defined(TARGET_MIPS64)
2896 tcg_gen_ext32s_i64(ret, arg);
2897 #else
2898 tcg_gen_extrl_i64_i32(ret, arg);
2899 #endif
2900 }
2901
2902 /* Sign-extract the high 32-bits to a target_long. */
2903 static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
2904 {
2905 #if defined(TARGET_MIPS64)
2906 tcg_gen_sari_i64(ret, arg, 32);
2907 #else
2908 tcg_gen_extrh_i64_i32(ret, arg);
2909 #endif
2910 }
2911
2912 static inline void check_cp0_enabled(DisasContext *ctx)
2913 {
2914 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
2915 generate_exception_err(ctx, EXCP_CpU, 0);
2916 }
2917 }
2918
2919 static inline void check_cp1_enabled(DisasContext *ctx)
2920 {
2921 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) {
2922 generate_exception_err(ctx, EXCP_CpU, 1);
2923 }
2924 }
2925
2926 /* Verify that the processor is running with COP1X instructions enabled.
2927 This is associated with the nabla symbol in the MIPS32 and MIPS64
2928 opcode tables. */
2929
2930 static inline void check_cop1x(DisasContext *ctx)
2931 {
2932 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) {
2933 generate_exception_end(ctx, EXCP_RI);
2934 }
2935 }
2936
2937 /* Verify that the processor is running with 64-bit floating-point
2938 operations enabled. */
2939
2940 static inline void check_cp1_64bitmode(DisasContext *ctx)
2941 {
2942 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) {
2943 generate_exception_end(ctx, EXCP_RI);
2944 }
2945 }
2946
2947 /*
2948 * Verify if floating point register is valid; an operation is not defined
2949 * if bit 0 of any register specification is set and the FR bit in the
2950 * Status register equals zero, since the register numbers specify an
2951 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2952 * in the Status register equals one, both even and odd register numbers
2953 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2954 *
2955 * Multiple 64 bit wide registers can be checked by calling
2956 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2957 */
2958 static inline void check_cp1_registers(DisasContext *ctx, int regs)
2959 {
2960 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) {
2961 generate_exception_end(ctx, EXCP_RI);
2962 }
2963 }
2964
2965 /* Verify that the processor is running with DSP instructions enabled.
2966 This is enabled by CP0 Status register MX(24) bit.
2967 */
2968
2969 static inline void check_dsp(DisasContext *ctx)
2970 {
2971 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
2972 if (ctx->insn_flags & ASE_DSP) {
2973 generate_exception_end(ctx, EXCP_DSPDIS);
2974 } else {
2975 generate_exception_end(ctx, EXCP_RI);
2976 }
2977 }
2978 }
2979
2980 static inline void check_dsp_r2(DisasContext *ctx)
2981 {
2982 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
2983 if (ctx->insn_flags & ASE_DSP) {
2984 generate_exception_end(ctx, EXCP_DSPDIS);
2985 } else {
2986 generate_exception_end(ctx, EXCP_RI);
2987 }
2988 }
2989 }
2990
2991 static inline void check_dsp_r3(DisasContext *ctx)
2992 {
2993 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
2994 if (ctx->insn_flags & ASE_DSP) {
2995 generate_exception_end(ctx, EXCP_DSPDIS);
2996 } else {
2997 generate_exception_end(ctx, EXCP_RI);
2998 }
2999 }
3000 }
3001
3002 /* This code generates a "reserved instruction" exception if the
3003 CPU does not support the instruction set corresponding to flags. */
3004 static inline void check_insn(DisasContext *ctx, uint64_t flags)
3005 {
3006 if (unlikely(!(ctx->insn_flags & flags))) {
3007 generate_exception_end(ctx, EXCP_RI);
3008 }
3009 }
3010
3011 /* This code generates a "reserved instruction" exception if the
3012 CPU has corresponding flag set which indicates that the instruction
3013 has been removed. */
3014 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
3015 {
3016 if (unlikely(ctx->insn_flags & flags)) {
3017 generate_exception_end(ctx, EXCP_RI);
3018 }
3019 }
3020
3021 /*
3022 * The Linux kernel traps certain reserved instruction exceptions to
3023 * emulate the corresponding instructions. QEMU is the kernel in user
3024 * mode, so those traps are emulated by accepting the instructions.
3025 *
3026 * A reserved instruction exception is generated for flagged CPUs if
3027 * QEMU runs in system mode.
3028 */
3029 static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
3030 {
3031 #ifndef CONFIG_USER_ONLY
3032 check_insn_opc_removed(ctx, flags);
3033 #endif
3034 }
3035
3036 /* This code generates a "reserved instruction" exception if the
3037 CPU does not support 64-bit paired-single (PS) floating point data type */
3038 static inline void check_ps(DisasContext *ctx)
3039 {
3040 if (unlikely(!ctx->ps)) {
3041 generate_exception(ctx, EXCP_RI);
3042 }
3043 check_cp1_64bitmode(ctx);
3044 }
3045
3046 #ifdef TARGET_MIPS64
3047 /* This code generates a "reserved instruction" exception if 64-bit
3048 instructions are not enabled. */
3049 static inline void check_mips_64(DisasContext *ctx)
3050 {
3051 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64))) {
3052 generate_exception_end(ctx, EXCP_RI);
3053 }
3054 }
3055 #endif
3056
3057 #ifndef CONFIG_USER_ONLY
3058 static inline void check_mvh(DisasContext *ctx)
3059 {
3060 if (unlikely(!ctx->mvh)) {
3061 generate_exception(ctx, EXCP_RI);
3062 }
3063 }
3064 #endif
3065
3066 /*
3067 * This code generates a "reserved instruction" exception if the
3068 * Config5 XNP bit is set.
3069 */
3070 static inline void check_xnp(DisasContext *ctx)
3071 {
3072 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
3073 generate_exception_end(ctx, EXCP_RI);
3074 }
3075 }
3076
3077 #ifndef CONFIG_USER_ONLY
3078 /*
3079 * This code generates a "reserved instruction" exception if the
3080 * Config3 PW bit is NOT set.
3081 */
3082 static inline void check_pw(DisasContext *ctx)
3083 {
3084 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
3085 generate_exception_end(ctx, EXCP_RI);
3086 }
3087 }
3088 #endif
3089
3090 /*
3091 * This code generates a "reserved instruction" exception if the
3092 * Config3 MT bit is NOT set.
3093 */
3094 static inline void check_mt(DisasContext *ctx)
3095 {
3096 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3097 generate_exception_end(ctx, EXCP_RI);
3098 }
3099 }
3100
3101 #ifndef CONFIG_USER_ONLY
3102 /*
3103 * This code generates a "coprocessor unusable" exception if CP0 is not
3104 * available, and, if that is not the case, generates a "reserved instruction"
3105 * exception if the Config5 MT bit is NOT set. This is needed for availability
3106 * control of some of MT ASE instructions.
3107 */
3108 static inline void check_cp0_mt(DisasContext *ctx)
3109 {
3110 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
3111 generate_exception_err(ctx, EXCP_CpU, 0);
3112 } else {
3113 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3114 generate_exception_err(ctx, EXCP_RI, 0);
3115 }
3116 }
3117 }
3118 #endif
3119
3120 /*
3121 * This code generates a "reserved instruction" exception if the
3122 * Config5 NMS bit is set.
3123 */
3124 static inline void check_nms(DisasContext *ctx)
3125 {
3126 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
3127 generate_exception_end(ctx, EXCP_RI);
3128 }
3129 }
3130
3131 /*
3132 * This code generates a "reserved instruction" exception if the
3133 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
3134 * Config2 TL, and Config5 L2C are unset.
3135 */
3136 static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
3137 {
3138 if (unlikely((ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
3139 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
3140 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
3141 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
3142 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
3143 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))) {
3144 generate_exception_end(ctx, EXCP_RI);
3145 }
3146 }
3147
3148 /*
3149 * This code generates a "reserved instruction" exception if the
3150 * Config5 EVA bit is NOT set.
3151 */
3152 static inline void check_eva(DisasContext *ctx)
3153 {
3154 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
3155 generate_exception_end(ctx, EXCP_RI);
3156 }
3157 }
3158
3159
3160 /* Define small wrappers for gen_load_fpr* so that we have a uniform
3161 calling interface for 32 and 64-bit FPRs. No sense in changing
3162 all callers for gen_load_fpr32 when we need the CTX parameter for
3163 this one use. */
3164 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
3165 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
3166 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
3167 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
3168 int ft, int fs, int cc) \
3169 { \
3170 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
3171 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
3172 switch (ifmt) { \
3173 case FMT_PS: \
3174 check_ps(ctx); \
3175 break; \
3176 case FMT_D: \
3177 if (abs) { \
3178 check_cop1x(ctx); \
3179 } \
3180 check_cp1_registers(ctx, fs | ft); \
3181 break; \
3182 case FMT_S: \
3183 if (abs) { \
3184 check_cop1x(ctx); \
3185 } \
3186 break; \
3187 } \
3188 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
3189 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
3190 switch (n) { \
3191 case 0: \
3192 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); \
3193 break; \
3194 case 1: \
3195 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); \
3196 break; \
3197 case 2: \
3198 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); \
3199 break; \
3200 case 3: \
3201 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); \
3202 break; \
3203 case 4: \
3204 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); \
3205 break; \
3206 case 5: \
3207 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); \
3208 break; \
3209 case 6: \
3210 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); \
3211 break; \
3212 case 7: \
3213 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); \
3214 break; \
3215 case 8: \
3216 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); \
3217 break; \
3218 case 9: \
3219 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); \
3220 break; \
3221 case 10: \
3222 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); \
3223 break; \
3224 case 11: \
3225 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); \
3226 break; \
3227 case 12: \
3228 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); \
3229 break; \
3230 case 13: \
3231 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); \
3232 break; \
3233 case 14: \
3234 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); \
3235 break; \
3236 case 15: \
3237 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); \
3238 break; \
3239 default: \
3240 abort(); \
3241 } \
3242 tcg_temp_free_i##bits (fp0); \
3243 tcg_temp_free_i##bits (fp1); \
3244 }
3245
3246 FOP_CONDS(, 0, d, FMT_D, 64)
3247 FOP_CONDS(abs, 1, d, FMT_D, 64)
3248 FOP_CONDS(, 0, s, FMT_S, 32)
3249 FOP_CONDS(abs, 1, s, FMT_S, 32)
3250 FOP_CONDS(, 0, ps, FMT_PS, 64)
3251 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
3252 #undef FOP_CONDS
3253
3254 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
3255 static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
3256 int ft, int fs, int fd) \
3257 { \
3258 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
3259 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
3260 if (ifmt == FMT_D) { \
3261 check_cp1_registers(ctx, fs | ft | fd); \
3262 } \
3263 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
3264 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
3265 switch (n) { \
3266 case 0: \
3267 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
3268 break; \
3269 case 1: \
3270 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
3271 break; \
3272 case 2: \
3273 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
3274 break; \
3275 case 3: \
3276 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
3277 break; \
3278 case 4: \
3279 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
3280 break; \
3281 case 5: \
3282 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
3283 break; \
3284 case 6: \
3285 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
3286 break; \
3287 case 7: \
3288 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
3289 break; \
3290 case 8: \
3291 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
3292 break; \
3293 case 9: \
3294 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
3295 break; \
3296 case 10: \
3297 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
3298 break; \
3299 case 11: \
3300 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
3301 break; \
3302 case 12: \
3303 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
3304 break; \
3305 case 13: \
3306 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
3307 break; \
3308 case 14: \
3309 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
3310 break; \
3311 case 15: \
3312 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
3313 break; \
3314 case 17: \
3315 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
3316 break; \
3317 case 18: \
3318 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
3319 break; \
3320 case 19: \
3321 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
3322 break; \
3323 case 25: \
3324 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
3325 break; \
3326 case 26: \
3327 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
3328 break; \
3329 case 27: \
3330 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
3331 break; \
3332 default: \
3333 abort(); \
3334 } \
3335 STORE; \
3336 tcg_temp_free_i ## bits (fp0); \
3337 tcg_temp_free_i ## bits (fp1); \
3338 }
3339
3340 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
3341 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3342 #undef FOP_CONDNS
3343 #undef gen_ldcmp_fpr32
3344 #undef gen_ldcmp_fpr64
3345
3346 /* load/store instructions. */
3347 #ifdef CONFIG_USER_ONLY
3348 #define OP_LD_ATOMIC(insn,fname) \
3349 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3350 DisasContext *ctx) \
3351 { \
3352 TCGv t0 = tcg_temp_new(); \
3353 tcg_gen_mov_tl(t0, arg1); \
3354 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
3355 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3356 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
3357 tcg_temp_free(t0); \
3358 }
3359 #else
3360 #define OP_LD_ATOMIC(insn,fname) \
3361 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3362 DisasContext *ctx) \
3363 { \
3364 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
3365 }
3366 #endif
3367 OP_LD_ATOMIC(ll,ld32s);
3368 #if defined(TARGET_MIPS64)
3369 OP_LD_ATOMIC(lld,ld64);
3370 #endif
3371 #undef OP_LD_ATOMIC
3372
3373 static void gen_base_offset_addr(DisasContext *ctx, TCGv addr,
3374 int base, int offset)
3375 {
3376 if (base == 0) {
3377 tcg_gen_movi_tl(addr, offset);
3378 } else if (offset == 0) {
3379 gen_load_gpr(addr, base);
3380 } else {
3381 tcg_gen_movi_tl(addr, offset);
3382 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
3383 }
3384 }
3385
3386 static target_ulong pc_relative_pc(DisasContext *ctx)
3387 {
3388 target_ulong pc = ctx->base.pc_next;
3389
3390 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3391 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
3392
3393 pc -= branch_bytes;
3394 }
3395
3396 pc &= ~(target_ulong)3;
3397 return pc;
3398 }
3399
3400 /* Load */
3401 static void gen_ld(DisasContext *ctx, uint32_t opc,
3402 int rt, int base, int offset)
3403 {
3404 TCGv t0, t1, t2;
3405 int mem_idx = ctx->mem_idx;
3406
3407 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
3408 /* Loongson CPU uses a load to zero register for prefetch.
3409 We emulate it as a NOP. On other CPU we must perform the
3410 actual memory access. */
3411 return;
3412 }
3413
3414 t0 = tcg_temp_new();
3415 gen_base_offset_addr(ctx, t0, base, offset);
3416
3417 switch (opc) {
3418 #if defined(TARGET_MIPS64)
3419 case OPC_LWU:
3420 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
3421 ctx->default_tcg_memop_mask);
3422 gen_store_gpr(t0, rt);
3423 break;
3424 case OPC_LD:
3425 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
3426 ctx->default_tcg_memop_mask);
3427 gen_store_gpr(t0, rt);
3428 break;
3429 case OPC_LLD:
3430 case R6_OPC_LLD:
3431 op_ld_lld(t0, t0, mem_idx, ctx);
3432 gen_store_gpr(t0, rt);
3433 break;
3434 case OPC_LDL:
3435 t1 = tcg_temp_new();
3436 /* Do a byte access to possibly trigger a page
3437 fault with the unaligned address. */
3438 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3439 tcg_gen_andi_tl(t1, t0, 7);
3440 #ifndef TARGET_WORDS_BIGENDIAN
3441 tcg_gen_xori_tl(t1, t1, 7);
3442 #endif
3443 tcg_gen_shli_tl(t1, t1, 3);
3444 tcg_gen_andi_tl(t0, t0, ~7);
3445 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3446 tcg_gen_shl_tl(t0, t0, t1);
3447 t2 = tcg_const_tl(-1);
3448 tcg_gen_shl_tl(t2, t2, t1);
3449 gen_load_gpr(t1, rt);
3450 tcg_gen_andc_tl(t1, t1, t2);
3451 tcg_temp_free(t2);
3452 tcg_gen_or_tl(t0, t0, t1);
3453 tcg_temp_free(t1);
3454 gen_store_gpr(t0, rt);
3455 break;
3456 case OPC_LDR:
3457 t1 = tcg_temp_new();
3458 /* Do a byte access to possibly trigger a page
3459 fault with the unaligned address. */
3460 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3461 tcg_gen_andi_tl(t1, t0, 7);
3462 #ifdef TARGET_WORDS_BIGENDIAN
3463 tcg_gen_xori_tl(t1, t1, 7);
3464 #endif
3465 tcg_gen_shli_tl(t1, t1, 3);
3466 tcg_gen_andi_tl(t0, t0, ~7);
3467 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3468 tcg_gen_shr_tl(t0, t0, t1);
3469 tcg_gen_xori_tl(t1, t1, 63);
3470 t2 = tcg_const_tl(0xfffffffffffffffeull);
3471 tcg_gen_shl_tl(t2, t2, t1);
3472 gen_load_gpr(t1, rt);
3473 tcg_gen_and_tl(t1, t1, t2);
3474 tcg_temp_free(t2);
3475 tcg_gen_or_tl(t0, t0, t1);
3476 tcg_temp_free(t1);
3477 gen_store_gpr(t0, rt);
3478 break;
3479 case OPC_LDPC:
3480 t1 = tcg_const_tl(pc_relative_pc(ctx));
3481 gen_op_addr_add(ctx, t0, t0, t1);
3482 tcg_temp_free(t1);
3483 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3484 gen_store_gpr(t0, rt);
3485 break;
3486 #endif
3487 case OPC_LWPC:
3488 t1 = tcg_const_tl(pc_relative_pc(ctx));
3489 gen_op_addr_add(ctx, t0, t0, t1);
3490 tcg_temp_free(t1);
3491 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
3492 gen_store_gpr(t0, rt);
3493 break;
3494 case OPC_LWE:
3495 mem_idx = MIPS_HFLAG_UM;
3496 /* fall through */
3497 case OPC_LW:
3498 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
3499 ctx->default_tcg_memop_mask);
3500 gen_store_gpr(t0, rt);
3501 break;
3502 case OPC_LHE:
3503 mem_idx = MIPS_HFLAG_UM;
3504 /* fall through */
3505 case OPC_LH:
3506 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
3507 ctx->default_tcg_memop_mask);
3508 gen_store_gpr(t0, rt);
3509 break;
3510 case OPC_LHUE:
3511 mem_idx = MIPS_HFLAG_UM;
3512 /* fall through */
3513 case OPC_LHU:
3514 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
3515 ctx->default_tcg_memop_mask);
3516 gen_store_gpr(t0, rt);
3517 break;
3518 case OPC_LBE:
3519 mem_idx = MIPS_HFLAG_UM;
3520 /* fall through */
3521 case OPC_LB:
3522 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
3523 gen_store_gpr(t0, rt);
3524 break;
3525 case OPC_LBUE:
3526 mem_idx = MIPS_HFLAG_UM;
3527 /* fall through */
3528 case OPC_LBU:
3529 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
3530 gen_store_gpr(t0, rt);
3531 break;
3532 case OPC_LWLE:
3533 mem_idx = MIPS_HFLAG_UM;
3534 /* fall through */
3535 case OPC_LWL:
3536 t1 = tcg_temp_new();
3537 /* Do a byte access to possibly trigger a page
3538 fault with the unaligned address. */
3539 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3540 tcg_gen_andi_tl(t1, t0, 3);
3541 #ifndef TARGET_WORDS_BIGENDIAN
3542 tcg_gen_xori_tl(t1, t1, 3);
3543 #endif
3544 tcg_gen_shli_tl(t1, t1, 3);
3545 tcg_gen_andi_tl(t0, t0, ~3);
3546 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3547 tcg_gen_shl_tl(t0, t0, t1);
3548 t2 = tcg_const_tl(-1);
3549 tcg_gen_shl_tl(t2, t2, t1);
3550 gen_load_gpr(t1, rt);
3551 tcg_gen_andc_tl(t1, t1, t2);
3552 tcg_temp_free(t2);
3553 tcg_gen_or_tl(t0, t0, t1);
3554 tcg_temp_free(t1);
3555 tcg_gen_ext32s_tl(t0, t0);
3556 gen_store_gpr(t0, rt);
3557 break;
3558 case OPC_LWRE:
3559 mem_idx = MIPS_HFLAG_UM;
3560 /* fall through */
3561 case OPC_LWR:
3562 t1 = tcg_temp_new();
3563 /* Do a byte access to possibly trigger a page
3564 fault with the unaligned address. */
3565 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3566 tcg_gen_andi_tl(t1, t0, 3);
3567 #ifdef TARGET_WORDS_BIGENDIAN
3568 tcg_gen_xori_tl(t1, t1, 3);
3569 #endif
3570 tcg_gen_shli_tl(t1, t1, 3);
3571 tcg_gen_andi_tl(t0, t0, ~3);
3572 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3573 tcg_gen_shr_tl(t0, t0, t1);
3574 tcg_gen_xori_tl(t1, t1, 31);
3575 t2 = tcg_const_tl(0xfffffffeull);
3576 tcg_gen_shl_tl(t2, t2, t1);
3577 gen_load_gpr(t1, rt);
3578 tcg_gen_and_tl(t1, t1, t2);
3579 tcg_temp_free(t2);
3580 tcg_gen_or_tl(t0, t0, t1);
3581 tcg_temp_free(t1);
3582 tcg_gen_ext32s_tl(t0, t0);
3583 gen_store_gpr(t0, rt);
3584 break;
3585 case OPC_LLE:
3586 mem_idx = MIPS_HFLAG_UM;
3587 /* fall through */
3588 case OPC_LL:
3589 case R6_OPC_LL:
3590 op_ld_ll(t0, t0, mem_idx, ctx);
3591 gen_store_gpr(t0, rt);
3592 break;
3593 }
3594 tcg_temp_free(t0);
3595 }
3596
3597 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3598 uint32_t reg1, uint32_t reg2)
3599 {
3600 TCGv taddr = tcg_temp_new();
3601 TCGv_i64 tval = tcg_temp_new_i64();
3602 TCGv tmp1 = tcg_temp_new();
3603 TCGv tmp2 = tcg_temp_new();
3604
3605 gen_base_offset_addr(ctx, taddr, base, offset);
3606 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3607 #ifdef TARGET_WORDS_BIGENDIAN
3608 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3609 #else
3610 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3611 #endif
3612 gen_store_gpr(tmp1, reg1);
3613 tcg_temp_free(tmp1);
3614 gen_store_gpr(tmp2, reg2);
3615 tcg_temp_free(tmp2);
3616 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3617 tcg_temp_free_i64(tval);
3618 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3619 tcg_temp_free(taddr);
3620 }
3621
3622 /* Store */
3623 static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
3624 int base, int offset)
3625 {
3626 TCGv t0 = tcg_temp_new();
3627 TCGv t1 = tcg_temp_new();
3628 int mem_idx = ctx->mem_idx;
3629
3630 gen_base_offset_addr(ctx, t0, base, offset);
3631 gen_load_gpr(t1, rt);
3632 switch (opc) {
3633 #if defined(TARGET_MIPS64)
3634 case OPC_SD:
3635 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
3636 ctx->default_tcg_memop_mask);
3637 break;
3638 case OPC_SDL:
3639 gen_helper_0e2i(sdl, t1, t0, mem_idx);
3640 break;
3641 case OPC_SDR:
3642 gen_helper_0e2i(sdr, t1, t0, mem_idx);
3643 break;
3644 #endif
3645 case OPC_SWE:
3646 mem_idx = MIPS_HFLAG_UM;
3647 /* fall through */
3648 case OPC_SW:
3649 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
3650 ctx->default_tcg_memop_mask);
3651 break;
3652 case OPC_SHE:
3653 mem_idx = MIPS_HFLAG_UM;
3654 /* fall through */
3655 case OPC_SH:
3656 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
3657 ctx->default_tcg_memop_mask);
3658 break;
3659 case OPC_SBE:
3660 mem_idx = MIPS_HFLAG_UM;
3661 /* fall through */
3662 case OPC_SB:
3663 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
3664 break;
3665 case OPC_SWLE:
3666 mem_idx = MIPS_HFLAG_UM;
3667 /* fall through */
3668 case OPC_SWL:
3669 gen_helper_0e2i(swl, t1, t0, mem_idx);
3670 break;
3671 case OPC_SWRE:
3672 mem_idx = MIPS_HFLAG_UM;
3673 /* fall through */
3674 case OPC_SWR:
3675 gen_helper_0e2i(swr, t1, t0, mem_idx);
3676 break;
3677 }
3678 tcg_temp_free(t0);
3679 tcg_temp_free(t1);
3680 }
3681
3682
3683 /* Store conditional */
3684 static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
3685 TCGMemOp tcg_mo, bool eva)
3686 {
3687 TCGv addr, t0, val;
3688 TCGLabel *l1 = gen_new_label();
3689 TCGLabel *done = gen_new_label();
3690
3691 t0 = tcg_temp_new();
3692 addr = tcg_temp_new();
3693 /* compare the address against that of the preceeding LL */
3694 gen_base_offset_addr(ctx, addr, base, offset);
3695 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
3696 tcg_temp_free(addr);
3697 tcg_gen_movi_tl(t0, 0);
3698 gen_store_gpr(t0, rt);
3699 tcg_gen_br(done);
3700
3701 gen_set_label(l1);
3702 /* generate cmpxchg */
3703 val = tcg_temp_new();
3704 gen_load_gpr(val, rt);
3705 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
3706 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
3707 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
3708 gen_store_gpr(t0, rt);
3709 tcg_temp_free(val);
3710
3711 gen_set_label(done);
3712 tcg_temp_free(t0);
3713 }
3714
3715
3716 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
3717 uint32_t reg1, uint32_t reg2, bool eva)
3718 {
3719 TCGv taddr = tcg_temp_local_new();
3720 TCGv lladdr = tcg_temp_local_new();
3721 TCGv_i64 tval = tcg_temp_new_i64();
3722 TCGv_i64 llval = tcg_temp_new_i64();
3723 TCGv_i64 val = tcg_temp_new_i64();
3724 TCGv tmp1 = tcg_temp_new();
3725 TCGv tmp2 = tcg_temp_new();
3726 TCGLabel *lab_fail = gen_new_label();
3727 TCGLabel *lab_done = gen_new_label();
3728
3729 gen_base_offset_addr(ctx, taddr, base, offset);
3730
3731 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3732 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3733
3734 gen_load_gpr(tmp1, reg1);
3735 gen_load_gpr(tmp2, reg2);
3736
3737 #ifdef TARGET_WORDS_BIGENDIAN
3738 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3739 #else
3740 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3741 #endif
3742
3743 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3744 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
3745 eva ? MIPS_HFLAG_UM : ctx->mem_idx, MO_64);
3746 if (reg1 != 0) {
3747 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3748 }
3749 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3750
3751 gen_set_label(lab_fail);
3752
3753 if (reg1 != 0) {
3754 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3755 }
3756 gen_set_label(lab_done);
3757 tcg_gen_movi_tl(lladdr, -1);
3758 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3759 }
3760
3761 /* Load and store */
3762 static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
3763 TCGv t0)
3764 {
3765 /* Don't do NOP if destination is zero: we must perform the actual
3766 memory access. */
3767 switch (opc) {
3768 case OPC_LWC1:
3769 {
3770 TCGv_i32 fp0 = tcg_temp_new_i32();
3771 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3772 ctx->default_tcg_memop_mask);
3773 gen_store_fpr32(ctx, fp0, ft);
3774 tcg_temp_free_i32(fp0);
3775 }
3776 break;
3777 case OPC_SWC1:
3778 {
3779 TCGv_i32 fp0 = tcg_temp_new_i32();
3780 gen_load_fpr32(ctx, fp0, ft);
3781 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3782 ctx->default_tcg_memop_mask);
3783 tcg_temp_free_i32(fp0);
3784 }
3785 break;
3786 case OPC_LDC1:
3787 {
3788 TCGv_i64 fp0 = tcg_temp_new_i64();
3789 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3790 ctx->default_tcg_memop_mask);
3791 gen_store_fpr64(ctx, fp0, ft);
3792 tcg_temp_free_i64(fp0);
3793 }
3794 break;
3795 case OPC_SDC1:
3796 {
3797 TCGv_i64 fp0 = tcg_temp_new_i64();
3798 gen_load_fpr64(ctx, fp0, ft);
3799 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3800 ctx->default_tcg_memop_mask);
3801 tcg_temp_free_i64(fp0);
3802 }
3803 break;
3804 default:
3805 MIPS_INVAL("flt_ldst");
3806 generate_exception_end(ctx, EXCP_RI);
3807 break;
3808 }
3809 }
3810
3811 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3812 int rs, int16_t imm)
3813 {
3814 TCGv t0 = tcg_temp_new();
3815
3816 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3817 check_cp1_enabled(ctx);
3818 switch (op) {
3819 case OPC_LDC1:
3820 case OPC_SDC1:
3821 check_insn(ctx, ISA_MIPS2);
3822 /* Fallthrough */
3823 default:
3824 gen_base_offset_addr(ctx, t0, rs, imm);
3825 gen_flt_ldst(ctx, op, rt, t0);
3826 }
3827 } else {
3828 generate_exception_err(ctx, EXCP_CpU, 1);
3829 }
3830 tcg_temp_free(t0);
3831 }
3832
3833 /* Arithmetic with immediate operand */
3834 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
3835 int rt, int rs, int imm)
3836 {
3837 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3838
3839 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
3840 /* If no destination, treat it as a NOP.
3841 For addi, we must generate the overflow exception when needed. */
3842 return;
3843 }
3844 switch (opc) {
3845 case OPC_ADDI:
3846 {
3847 TCGv t0 = tcg_temp_local_new();
3848 TCGv t1 = tcg_temp_new();
3849 TCGv t2 = tcg_temp_new();
3850 TCGLabel *l1 = gen_new_label();
3851
3852 gen_load_gpr(t1, rs);
3853 tcg_gen_addi_tl(t0, t1, uimm);
3854 tcg_gen_ext32s_tl(t0, t0);
3855
3856 tcg_gen_xori_tl(t1, t1, ~uimm);
3857 tcg_gen_xori_tl(t2, t0, uimm);
3858 tcg_gen_and_tl(t1, t1, t2);
3859 tcg_temp_free(t2);
3860 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3861 tcg_temp_free(t1);
3862 /* operands of same sign, result different sign */
3863 generate_exception(ctx, EXCP_OVERFLOW);
3864 gen_set_label(l1);
3865 tcg_gen_ext32s_tl(t0, t0);
3866 gen_store_gpr(t0, rt);
3867 tcg_temp_free(t0);
3868 }
3869 break;
3870 case OPC_ADDIU:
3871 if (rs != 0) {
3872 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3873 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3874 } else {
3875 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3876 }
3877 break;
3878 #if defined(TARGET_MIPS64)
3879 case OPC_DADDI:
3880 {
3881 TCGv t0 = tcg_temp_local_new();
3882 TCGv t1 = tcg_temp_new();
3883 TCGv t2 = tcg_temp_new();
3884 TCGLabel *l1 = gen_new_label();
3885
3886 gen_load_gpr(t1, rs);
3887 tcg_gen_addi_tl(t0, t1, uimm);
3888
3889 tcg_gen_xori_tl(t1, t1, ~uimm);
3890 tcg_gen_xori_tl(t2, t0, uimm);
3891 tcg_gen_and_tl(t1, t1, t2);
3892 tcg_temp_free(t2);
3893 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3894 tcg_temp_free(t1);
3895 /* operands of same sign, result different sign */
3896 generate_exception(ctx, EXCP_OVERFLOW);
3897 gen_set_label(l1);
3898 gen_store_gpr(t0, rt);
3899 tcg_temp_free(t0);
3900 }
3901 break;
3902 case OPC_DADDIU:
3903 if (rs != 0) {
3904 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3905 } else {
3906 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3907 }
3908 break;
3909 #endif
3910 }
3911 }
3912
3913 /* Logic with immediate operand */
3914 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
3915 int rt, int rs, int16_t imm)
3916 {
3917 target_ulong uimm;
3918
3919 if (rt == 0) {
3920 /* If no destination, treat it as a NOP. */
3921 return;
3922 }
3923 uimm = (uint16_t)imm;
3924 switch (opc) {
3925 case OPC_ANDI:
3926 if (likely(rs != 0)) {
3927 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3928 } else {
3929 tcg_gen_movi_tl(cpu_gpr[rt], 0);
3930 }
3931 break;
3932 case OPC_ORI:
3933 if (rs != 0) {
3934 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3935 } else {
3936 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3937 }
3938 break;
3939 case OPC_XORI:
3940 if (likely(rs != 0)) {
3941 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3942 } else {
3943 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3944 }
3945 break;
3946 case OPC_LUI:
3947 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
3948 /* OPC_AUI */
3949 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3950 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3951 } else {
3952 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
3953 }
3954 break;
3955
3956 default:
3957 break;
3958 }
3959 }
3960
3961 /* Set on less than with immediate operand */
3962 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
3963 int rt, int rs, int16_t imm)
3964 {
3965 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3966 TCGv t0;
3967
3968 if (rt == 0) {
3969 /* If no destination, treat it as a NOP. */
3970 return;
3971 }
3972 t0 = tcg_temp_new();
3973 gen_load_gpr(t0, rs);
3974 switch (opc) {
3975 case OPC_SLTI:
3976 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
3977 break;
3978 case OPC_SLTIU:
3979 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
3980 break;
3981 }
3982 tcg_temp_free(t0);
3983 }
3984
3985 /* Shifts with immediate operand */
3986 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
3987 int rt, int rs, int16_t imm)
3988 {
3989 target_ulong uimm = ((uint16_t)imm) & 0x1f;
3990 TCGv t0;
3991
3992 if (rt == 0) {
3993 /* If no destination, treat it as a NOP. */
3994 return;
3995 }
3996
3997 t0 = tcg_temp_new();
3998 gen_load_gpr(t0, rs);
3999 switch (opc) {
4000 case OPC_SLL:
4001 tcg_gen_shli_tl(t0, t0, uimm);
4002 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
4003 break;
4004 case OPC_SRA:
4005 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
4006 break;
4007 case OPC_SRL:
4008 if (uimm != 0) {
4009 tcg_gen_ext32u_tl(t0, t0);
4010 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
4011 } else {
4012 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
4013 }
4014 break;
4015 case OPC_ROTR:
4016 if (uimm != 0) {
4017 TCGv_i32 t1 = tcg_temp_new_i32();
4018
4019 tcg_gen_trunc_tl_i32(t1, t0);
4020 tcg_gen_rotri_i32(t1, t1, uimm);
4021 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
4022 tcg_temp_free_i32(t1);
4023 } else {
4024 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
4025 }
4026 break;
4027 #if defined(TARGET_MIPS64)
4028 case OPC_DSLL:
4029 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
4030 break;
4031 case OPC_DSRA:
4032 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
4033 break;
4034 case OPC_DSRL:
4035 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
4036 break;
4037 case OPC_DROTR:
4038 if (uimm != 0) {
4039 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
4040 } else {
4041 tcg_gen_mov_tl(cpu_gpr[rt], t0);
4042 }
4043 break;
4044 case OPC_DSLL32:
4045 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
4046 break;
4047 case OPC_DSRA32:
4048 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
4049 break;
4050 case OPC_DSRL32:
4051 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
4052 break;
4053 case OPC_DROTR32:
4054 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
4055 break;
4056 #endif
4057 }
4058 tcg_temp_free(t0);
4059 }
4060
4061 /* Arithmetic */
4062 static void gen_arith(DisasContext *ctx, uint32_t opc,
4063 int rd, int rs, int rt)
4064 {
4065 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
4066 && opc != OPC_DADD && opc != OPC_DSUB) {
4067 /* If no destination, treat it as a NOP.
4068 For add & sub, we must generate the overflow exception when needed. */
4069 return;
4070 }
4071
4072 switch (opc) {
4073 case OPC_ADD:
4074 {
4075 TCGv t0 = tcg_temp_local_new();
4076 TCGv t1 = tcg_temp_new();
4077 TCGv t2 = tcg_temp_new();
4078 TCGLabel *l1 = gen_new_label();
4079
4080 gen_load_gpr(t1, rs);
4081 gen_load_gpr(t2, rt);
4082 tcg_gen_add_tl(t0, t1, t2);
4083 tcg_gen_ext32s_tl(t0, t0);
4084 tcg_gen_xor_tl(t1, t1, t2);
4085 tcg_gen_xor_tl(t2, t0, t2);
4086 tcg_gen_andc_tl(t1, t2, t1);
4087 tcg_temp_free(t2);
4088 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4089 tcg_temp_free(t1);
4090 /* operands of same sign, result different sign */
4091 generate_exception(ctx, EXCP_OVERFLOW);
4092 gen_set_label(l1);
4093 gen_store_gpr(t0, rd);
4094 tcg_temp_free(t0);
4095 }
4096 break;
4097 case OPC_ADDU:
4098 if (rs != 0 && rt != 0) {
4099 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4100 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4101 } else if (rs == 0 && rt != 0) {
4102 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4103 } else if (rs != 0 && rt == 0) {
4104 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4105 } else {
4106 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4107 }
4108 break;
4109 case OPC_SUB:
4110 {
4111 TCGv t0 = tcg_temp_local_new();
4112 TCGv t1 = tcg_temp_new();
4113 TCGv t2 = tcg_temp_new();
4114 TCGLabel *l1 = gen_new_label();
4115
4116 gen_load_gpr(t1, rs);
4117 gen_load_gpr(t2, rt);
4118 tcg_gen_sub_tl(t0, t1, t2);
4119 tcg_gen_ext32s_tl(t0, t0);
4120 tcg_gen_xor_tl(t2, t1, t2);
4121 tcg_gen_xor_tl(t1, t0, t1);
4122 tcg_gen_and_tl(t1, t1, t2);
4123 tcg_temp_free(t2);
4124 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4125 tcg_temp_free(t1);
4126 /* operands of different sign, first operand and result different sign */
4127 generate_exception(ctx, EXCP_OVERFLOW);
4128 gen_set_label(l1);
4129 gen_store_gpr(t0, rd);
4130 tcg_temp_free(t0);
4131 }
4132 break;
4133 case OPC_SUBU:
4134 if (rs != 0 && rt != 0) {
4135 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4136 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4137 } else if (rs == 0 && rt != 0) {
4138 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4139 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4140 } else if (rs != 0 && rt == 0) {
4141 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4142 } else {
4143 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4144 }
4145 break;
4146 #if defined(TARGET_MIPS64)
4147 case OPC_DADD:
4148 {
4149 TCGv t0 = tcg_temp_local_new();
4150 TCGv t1 = tcg_temp_new();
4151 TCGv t2 = tcg_temp_new();
4152 TCGLabel *l1 = gen_new_label();
4153
4154 gen_load_gpr(t1, rs);
4155 gen_load_gpr(t2, rt);
4156 tcg_gen_add_tl(t0, t1, t2);
4157 tcg_gen_xor_tl(t1, t1, t2);
4158 tcg_gen_xor_tl(t2, t0, t2);
4159 tcg_gen_andc_tl(t1, t2, t1);
4160 tcg_temp_free(t2);
4161 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4162 tcg_temp_free(t1);
4163 /* operands of same sign, result different sign */
4164 generate_exception(ctx, EXCP_OVERFLOW);
4165 gen_set_label(l1);
4166 gen_store_gpr(t0, rd);
4167 tcg_temp_free(t0);
4168 }
4169 break;
4170 case OPC_DADDU:
4171 if (rs != 0 && rt != 0) {
4172 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4173 } else if (rs == 0 && rt != 0) {
4174 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4175 } else if (rs != 0 && rt == 0) {
4176 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4177 } else {
4178 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4179 }
4180 break;
4181 case OPC_DSUB:
4182 {
4183 TCGv t0 = tcg_temp_local_new();
4184 TCGv t1 = tcg_temp_new();
4185 TCGv t2 = tcg_temp_new();
4186 TCGLabel *l1 = gen_new_label();
4187
4188 gen_load_gpr(t1, rs);
4189 gen_load_gpr(t2, rt);
4190 tcg_gen_sub_tl(t0, t1, t2);
4191 tcg_gen_xor_tl(t2, t1, t2);
4192 tcg_gen_xor_tl(t1, t0, t1);
4193 tcg_gen_and_tl(t1, t1, t2);
4194 tcg_temp_free(t2);
4195 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4196 tcg_temp_free(t1);
4197 /* operands of different sign, first operand and result different sign */
4198 generate_exception(ctx, EXCP_OVERFLOW);
4199 gen_set_label(l1);
4200 gen_store_gpr(t0, rd);
4201 tcg_temp_free(t0);
4202 }
4203 break;
4204 case OPC_DSUBU:
4205 if (rs != 0 && rt != 0) {
4206 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4207 } else if (rs == 0 && rt != 0) {
4208 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4209 } else if (rs != 0 && rt == 0) {
4210 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4211 } else {
4212 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4213 }
4214 break;
4215 #endif
4216 case OPC_MUL:
4217 if (likely(rs != 0 && rt != 0)) {
4218 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4219 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4220 } else {
4221 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4222 }
4223 break;
4224 }
4225 }
4226
4227 /* Conditional move */
4228 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
4229 int rd, int rs, int rt)
4230 {
4231 TCGv t0, t1, t2;
4232
4233 if (rd == 0) {
4234 /* If no destination, treat it as a NOP. */
4235 return;
4236 }
4237
4238 t0 = tcg_temp_new();
4239 gen_load_gpr(t0, rt);
4240 t1 = tcg_const_tl(0);
4241 t2 = tcg_temp_new();
4242 gen_load_gpr(t2, rs);
4243 switch (opc) {
4244 case OPC_MOVN:
4245 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4246 break;
4247 case OPC_MOVZ:
4248 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4249 break;
4250 case OPC_SELNEZ:
4251 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
4252 break;
4253 case OPC_SELEQZ:
4254 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
4255 break;
4256 }
4257 tcg_temp_free(t2);
4258 tcg_temp_free(t1);
4259 tcg_temp_free(t0);
4260 }
4261
4262 /* Logic */
4263 static void gen_logic(DisasContext *ctx, uint32_t opc,
4264 int rd, int rs, int rt)
4265 {
4266 if (rd == 0) {
4267 /* If no destination, treat it as a NOP. */
4268 return;
4269 }
4270
4271 switch (opc) {
4272 case OPC_AND:
4273 if (likely(rs != 0 && rt != 0)) {
4274 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4275 } else {
4276 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4277 }
4278 break;
4279 case OPC_NOR:
4280 if (rs != 0 && rt != 0) {
4281 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4282 } else if (rs == 0 && rt != 0) {
4283 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
4284 } else if (rs != 0 && rt == 0) {
4285 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
4286 } else {
4287 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
4288 }
4289 break;
4290 case OPC_OR:
4291 if (likely(rs != 0 && rt != 0)) {
4292 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4293 } else if (rs == 0 && rt != 0) {
4294 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4295 } else if (rs != 0 && rt == 0) {
4296 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4297 } else {
4298 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4299 }
4300 break;
4301 case OPC_XOR:
4302 if (likely(rs != 0 && rt != 0)) {
4303 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4304 } else if (rs == 0 && rt != 0) {
4305 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4306 } else if (rs != 0 && rt == 0) {
4307 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4308 } else {
4309 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4310 }
4311 break;
4312 }
4313 }
4314
4315 /* Set on lower than */
4316 static void gen_slt(DisasContext *ctx, uint32_t opc,
4317 int rd, int rs, int rt)
4318 {
4319 TCGv t0, t1;
4320
4321 if (rd == 0) {
4322 /* If no destination, treat it as a NOP. */
4323 return;
4324 }
4325
4326 t0 = tcg_temp_new();
4327 t1 = tcg_temp_new();
4328 gen_load_gpr(t0, rs);
4329 gen_load_gpr(t1, rt);
4330 switch (opc) {
4331 case OPC_SLT:
4332 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
4333 break;
4334 case OPC_SLTU:
4335 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
4336 break;
4337 }
4338 tcg_temp_free(t0);
4339 tcg_temp_free(t1);
4340 }
4341
4342 /* Shifts */
4343 static void gen_shift(DisasContext *ctx, uint32_t opc,
4344 int rd, int rs, int rt)
4345 {
4346 TCGv t0, t1;
4347
4348 if (rd == 0) {
4349 /* If no destination, treat it as a NOP.
4350 For add & sub, we must generate the overflow exception when needed. */
4351 return;
4352 }
4353
4354 t0 = tcg_temp_new();
4355 t1 = tcg_temp_new();
4356 gen_load_gpr(t0, rs);
4357 gen_load_gpr(t1, rt);
4358 switch (opc) {
4359 case OPC_SLLV:
4360 tcg_gen_andi_tl(t0, t0, 0x1f);
4361 tcg_gen_shl_tl(t0, t1, t0);
4362 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4363 break;
4364 case OPC_SRAV:
4365 tcg_gen_andi_tl(t0, t0, 0x1f);
4366 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4367 break;
4368 case OPC_SRLV:
4369 tcg_gen_ext32u_tl(t1, t1);
4370 tcg_gen_andi_tl(t0, t0, 0x1f);
4371 tcg_gen_shr_tl(t0, t1, t0);
4372 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4373 break;
4374 case OPC_ROTRV:
4375 {
4376 TCGv_i32 t2 = tcg_temp_new_i32();
4377 TCGv_i32 t3 = tcg_temp_new_i32();
4378
4379 tcg_gen_trunc_tl_i32(t2, t0);
4380 tcg_gen_trunc_tl_i32(t3, t1);
4381 tcg_gen_andi_i32(t2, t2, 0x1f);
4382 tcg_gen_rotr_i32(t2, t3, t2);
4383 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4384 tcg_temp_free_i32(t2);
4385 tcg_temp_free_i32(t3);
4386 }
4387 break;
4388 #if defined(TARGET_MIPS64)
4389 case OPC_DSLLV:
4390 tcg_gen_andi_tl(t0, t0, 0x3f);
4391 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
4392 break;
4393 case OPC_DSRAV:
4394 tcg_gen_andi_tl(t0, t0, 0x3f);
4395 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4396 break;
4397 case OPC_DSRLV:
4398 tcg_gen_andi_tl(t0, t0, 0x3f);
4399 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
4400 break;
4401 case OPC_DROTRV:
4402 tcg_gen_andi_tl(t0, t0, 0x3f);
4403 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
4404 break;
4405 #endif
4406 }
4407 tcg_temp_free(t0);
4408 tcg_temp_free(t1);
4409 }
4410
4411 #if defined(TARGET_MIPS64)
4412 /* Copy GPR to and from TX79 HI1/LO1 register. */
4413 static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg)
4414 {
4415 if (reg == 0 && (opc == MMI_OPC_MFHI1 || opc == MMI_OPC_MFLO1)) {
4416 /* Treat as NOP. */
4417 return;
4418 }
4419
4420 switch (opc) {
4421 case MMI_OPC_MFHI1:
4422 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[1]);
4423 break;
4424 case MMI_OPC_MFLO1:
4425 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[1]);
4426 break;
4427 case MMI_OPC_MTHI1:
4428 if (reg != 0) {
4429 tcg_gen_mov_tl(cpu_HI[1], cpu_gpr[reg]);
4430 } else {
4431 tcg_gen_movi_tl(cpu_HI[1], 0);
4432 }
4433 break;
4434 case MMI_OPC_MTLO1:
4435 if (reg != 0) {
4436 tcg_gen_mov_tl(cpu_LO[1], cpu_gpr[reg]);
4437 } else {
4438 tcg_gen_movi_tl(cpu_LO[1], 0);
4439 }
4440 break;
4441 default:
4442 MIPS_INVAL("mfthilo1 TX79");
4443 generate_exception_end(ctx, EXCP_RI);
4444 break;
4445 }
4446 }
4447 #endif
4448
4449 /* Arithmetic on HI/LO registers */
4450 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
4451 {
4452 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
4453 /* Treat as NOP. */
4454 return;
4455 }
4456
4457 if (acc != 0) {
4458 check_dsp(ctx);
4459 }
4460
4461 switch (opc) {
4462 case OPC_MFHI:
4463 #if defined(TARGET_MIPS64)
4464 if (acc != 0) {
4465 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
4466 } else
4467 #endif
4468 {
4469 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
4470 }
4471 break;
4472 case OPC_MFLO:
4473 #if defined(TARGET_MIPS64)
4474 if (acc != 0) {
4475 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
4476 } else
4477 #endif
4478 {
4479 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
4480 }
4481 break;
4482 case OPC_MTHI:
4483 if (reg != 0) {
4484 #if defined(TARGET_MIPS64)
4485 if (acc != 0) {
4486 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
4487 } else
4488 #endif
4489 {
4490 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
4491 }
4492 } else {
4493 tcg_gen_movi_tl(cpu_HI[acc], 0);
4494 }
4495 break;
4496 case OPC_MTLO:
4497 if (reg != 0) {
4498 #if defined(TARGET_MIPS64)
4499 if (acc != 0) {
4500 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
4501 } else
4502 #endif
4503 {
4504 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
4505 }
4506 } else {
4507 tcg_gen_movi_tl(cpu_LO[acc], 0);
4508 }
4509 break;
4510 }
4511 }
4512
4513 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
4514 TCGMemOp memop)
4515 {
4516 TCGv t0 = tcg_const_tl(addr);
4517 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
4518 gen_store_gpr(t0, reg);
4519 tcg_temp_free(t0);
4520 }
4521
4522 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
4523 int rs)
4524 {
4525 target_long offset;
4526 target_long addr;
4527
4528 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
4529 case OPC_ADDIUPC:
4530 if (rs != 0) {
4531 offset = sextract32(ctx->opcode << 2, 0, 21);
4532 addr = addr_add(ctx, pc, offset);
4533 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4534 }
4535 break;
4536 case R6_OPC_LWPC:
4537 offset = sextract32(ctx->opcode << 2, 0, 21);
4538 addr = addr_add(ctx, pc, offset);
4539 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4540 break;
4541 #if defined(TARGET_MIPS64)
4542 case OPC_LWUPC:
4543 check_mips_64(ctx);
4544 offset = sextract32(ctx->opcode << 2, 0, 21);
4545 addr = addr_add(ctx, pc, offset);
4546 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4547 break;
4548 #endif
4549 default:
4550 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
4551 case OPC_AUIPC:
4552 if (rs != 0) {
4553 offset = sextract32(ctx->opcode, 0, 16) << 16;
4554 addr = addr_add(ctx, pc, offset);
4555 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4556 }
4557 break;
4558 case OPC_ALUIPC:
4559 if (rs != 0) {
4560 offset = sextract32(ctx->opcode, 0, 16) << 16;
4561 addr = ~0xFFFF & addr_add(ctx, pc, offset);
4562 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4563 }
4564 break;
4565 #if defined(TARGET_MIPS64)
4566 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4567 case R6_OPC_LDPC + (1 << 16):
4568 case R6_OPC_LDPC + (2 << 16):
4569 case R6_OPC_LDPC + (3 << 16):
4570 check_mips_64(ctx);
4571 offset = sextract32(ctx->opcode << 3, 0, 21);
4572 addr = addr_add(ctx, (pc & ~0x7), offset);
4573 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4574 break;
4575 #endif
4576 default:
4577 MIPS_INVAL("OPC_PCREL");
4578 generate_exception_end(ctx, EXCP_RI);
4579 break;
4580 }
4581 break;
4582 }
4583 }
4584
4585 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4586 {
4587 TCGv t0, t1;
4588
4589 if (rd == 0) {
4590 /* Treat as NOP. */
4591 return;
4592 }
4593
4594 t0 = tcg_temp_new();
4595 t1 = tcg_temp_new();
4596
4597 gen_load_gpr(t0, rs);
4598 gen_load_gpr(t1, rt);
4599
4600 switch (opc) {
4601 case R6_OPC_DIV:
4602 {
4603 TCGv t2 = tcg_temp_new();
4604 TCGv t3 = tcg_temp_new();
4605 tcg_gen_ext32s_tl(t0, t0);
4606 tcg_gen_ext32s_tl(t1, t1);
4607 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4608 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4609 tcg_gen_and_tl(t2, t2, t3);
4610 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4611 tcg_gen_or_tl(t2, t2, t3);
4612 tcg_gen_movi_tl(t3, 0);
4613 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4614 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4615 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4616 tcg_temp_free(t3);
4617 tcg_temp_free(t2);
4618 }
4619 break;
4620 case R6_OPC_MOD:
4621 {
4622 TCGv t2 = tcg_temp_new();
4623 TCGv t3 = tcg_temp_new();
4624 tcg_gen_ext32s_tl(t0, t0);
4625 tcg_gen_ext32s_tl(t1, t1);
4626 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4627 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4628 tcg_gen_and_tl(t2, t2, t3);
4629 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4630 tcg_gen_or_tl(t2, t2, t3);
4631 tcg_gen_movi_tl(t3, 0);
4632 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4633 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4634 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4635 tcg_temp_free(t3);
4636 tcg_temp_free(t2);
4637 }
4638 break;
4639 case R6_OPC_DIVU:
4640 {
4641 TCGv t2 = tcg_const_tl(0);
4642 TCGv t3 = tcg_const_tl(1);
4643 tcg_gen_ext32u_tl(t0, t0);
4644 tcg_gen_ext32u_tl(t1, t1);
4645 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4646 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4647 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4648 tcg_temp_free(t3);
4649 tcg_temp_free(t2);
4650 }
4651 break;
4652 case R6_OPC_MODU:
4653 {
4654 TCGv t2 = tcg_const_tl(0);
4655 TCGv t3 = tcg_const_tl(1);
4656 tcg_gen_ext32u_tl(t0, t0);
4657 tcg_gen_ext32u_tl(t1, t1);
4658 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4659 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4660 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4661 tcg_temp_free(t3);
4662 tcg_temp_free(t2);
4663 }
4664 break;
4665 case R6_OPC_MUL:
4666 {
4667 TCGv_i32 t2 = tcg_temp_new_i32();
4668 TCGv_i32 t3 = tcg_temp_new_i32();
4669 tcg_gen_trunc_tl_i32(t2, t0);
4670 tcg_gen_trunc_tl_i32(t3, t1);
4671 tcg_gen_mul_i32(t2, t2, t3);
4672 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4673 tcg_temp_free_i32(t2);
4674 tcg_temp_free_i32(t3);
4675 }
4676 break;
4677 case R6_OPC_MUH:
4678 {
4679 TCGv_i32 t2 = tcg_temp_new_i32();
4680 TCGv_i32 t3 = tcg_temp_new_i32();
4681 tcg_gen_trunc_tl_i32(t2, t0);
4682 tcg_gen_trunc_tl_i32(t3, t1);
4683 tcg_gen_muls2_i32(t2, t3, t2, t3);
4684 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4685 tcg_temp_free_i32(t2);
4686 tcg_temp_free_i32(t3);
4687 }
4688 break;
4689 case R6_OPC_MULU:
4690 {
4691 TCGv_i32 t2 = tcg_temp_new_i32();
4692 TCGv_i32 t3 = tcg_temp_new_i32();
4693 tcg_gen_trunc_tl_i32(t2, t0);
4694 tcg_gen_trunc_tl_i32(t3, t1);
4695 tcg_gen_mul_i32(t2, t2, t3);
4696 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4697 tcg_temp_free_i32(t2);
4698 tcg_temp_free_i32(t3);
4699 }
4700 break;
4701 case R6_OPC_MUHU:
4702 {
4703 TCGv_i32 t2 = tcg_temp_new_i32();
4704 TCGv_i32 t3 = tcg_temp_new_i32();
4705 tcg_gen_trunc_tl_i32(t2, t0);
4706 tcg_gen_trunc_tl_i32(t3, t1);
4707 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4708 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4709 tcg_temp_free_i32(t2);
4710 tcg_temp_free_i32(t3);
4711 }
4712 break;
4713 #if defined(TARGET_MIPS64)
4714 case R6_OPC_DDIV:
4715 {
4716 TCGv t2 = tcg_temp_new();
4717 TCGv t3 = tcg_temp_new();
4718 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4719 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4720 tcg_gen_and_tl(t2, t2, t3);
4721 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4722 tcg_gen_or_tl(t2, t2, t3);
4723 tcg_gen_movi_tl(t3, 0);
4724 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4725 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4726 tcg_temp_free(t3);
4727 tcg_temp_free(t2);
4728 }
4729 break;
4730 case R6_OPC_DMOD:
4731 {
4732 TCGv t2 = tcg_temp_new();
4733 TCGv t3 = tcg_temp_new();
4734 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4735 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4736 tcg_gen_and_tl(t2, t2, t3);
4737 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4738 tcg_gen_or_tl(t2, t2, t3);
4739 tcg_gen_movi_tl(t3, 0);
4740 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4741 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4742 tcg_temp_free(t3);
4743 tcg_temp_free(t2);
4744 }
4745 break;
4746 case R6_OPC_DDIVU:
4747 {
4748 TCGv t2 = tcg_const_tl(0);
4749 TCGv t3 = tcg_const_tl(1);
4750 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4751 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4752 tcg_temp_free(t3);
4753 tcg_temp_free(t2);
4754 }
4755 break;
4756 case R6_OPC_DMODU:
4757 {
4758 TCGv t2 = tcg_const_tl(0);
4759 TCGv t3 = tcg_const_tl(1);
4760 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4761 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4762 tcg_temp_free(t3);
4763 tcg_temp_free(t2);
4764 }
4765 break;
4766 case R6_OPC_DMUL:
4767 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4768 break;
4769 case R6_OPC_DMUH:
4770 {
4771 TCGv t2 = tcg_temp_new();
4772 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4773 tcg_temp_free(t2);
4774 }
4775 break;
4776 case R6_OPC_DMULU:
4777 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4778 break;
4779 case R6_OPC_DMUHU:
4780 {
4781 TCGv t2 = tcg_temp_new();
4782 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4783 tcg_temp_free(t2);
4784 }
4785 break;
4786 #endif
4787 default:
4788 MIPS_INVAL("r6 mul/div");
4789 generate_exception_end(ctx, EXCP_RI);
4790 goto out;
4791 }
4792 out:
4793 tcg_temp_free(t0);
4794 tcg_temp_free(t1);
4795 }
4796
4797 #if defined(TARGET_MIPS64)
4798 static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
4799 {
4800 TCGv t0, t1;
4801
4802 t0 = tcg_temp_new();
4803 t1 = tcg_temp_new();
4804
4805 gen_load_gpr(t0, rs);
4806 gen_load_gpr(t1, rt);
4807
4808 switch (opc) {
4809 case MMI_OPC_DIV1:
4810 {
4811 TCGv t2 = tcg_temp_new();
4812 TCGv t3 = tcg_temp_new();
4813 tcg_gen_ext32s_tl(t0, t0);
4814 tcg_gen_ext32s_tl(t1, t1);
4815 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4816 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4817 tcg_gen_and_tl(t2, t2, t3);
4818 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4819 tcg_gen_or_tl(t2, t2, t3);
4820 tcg_gen_movi_tl(t3, 0);
4821 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4822 tcg_gen_div_tl(cpu_LO[1], t0, t1);
4823 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
4824 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4825 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4826 tcg_temp_free(t3);
4827 tcg_temp_free(t2);
4828 }
4829 break;
4830 case MMI_OPC_DIVU1:
4831 {
4832 TCGv t2 = tcg_const_tl(0);
4833 TCGv t3 = tcg_const_tl(1);
4834 tcg_gen_ext32u_tl(t0, t0);
4835 tcg_gen_ext32u_tl(t1, t1);
4836 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4837 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
4838 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
4839 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4840 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4841 tcg_temp_free(t3);
4842 tcg_temp_free(t2);
4843 }
4844 break;
4845 default:
4846 MIPS_INVAL("div1 TX79");
4847 generate_exception_end(ctx, EXCP_RI);
4848 goto out;
4849 }
4850 out:
4851 tcg_temp_free(t0);
4852 tcg_temp_free(t1);
4853 }
4854 #endif
4855
4856 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4857 int acc, int rs, int rt)
4858 {
4859 TCGv t0, t1;
4860
4861 t0 = tcg_temp_new();
4862 t1 = tcg_temp_new();
4863
4864 gen_load_gpr(t0, rs);
4865 gen_load_gpr(t1, rt);
4866
4867 if (acc != 0) {
4868 check_dsp(ctx);
4869 }
4870
4871 switch (opc) {
4872 case OPC_DIV:
4873 {
4874 TCGv t2 = tcg_temp_new();
4875 TCGv t3 = tcg_temp_new();
4876 tcg_gen_ext32s_tl(t0, t0);
4877 tcg_gen_ext32s_tl(t1, t1);
4878 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4879 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4880 tcg_gen_and_tl(t2, t2, t3);
4881 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4882 tcg_gen_or_tl(t2, t2, t3);
4883 tcg_gen_movi_tl(t3, 0);
4884 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4885 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4886 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4887 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4888 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4889 tcg_temp_free(t3);
4890 tcg_temp_free(t2);
4891 }
4892 break;
4893 case OPC_DIVU:
4894 {
4895 TCGv t2 = tcg_const_tl(0);
4896 TCGv t3 = tcg_const_tl(1);
4897 tcg_gen_ext32u_tl(t0, t0);
4898 tcg_gen_ext32u_tl(t1, t1);
4899 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4900 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4901 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4902 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4903 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4904 tcg_temp_free(t3);
4905 tcg_temp_free(t2);
4906 }
4907 break;
4908 case OPC_MULT:
4909 {
4910 TCGv_i32 t2 = tcg_temp_new_i32();
4911 TCGv_i32 t3 = tcg_temp_new_i32();
4912 tcg_gen_trunc_tl_i32(t2, t0);
4913 tcg_gen_trunc_tl_i32(t3, t1);
4914 tcg_gen_muls2_i32(t2, t3, t2, t3);
4915 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4916 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4917 tcg_temp_free_i32(t2);
4918 tcg_temp_free_i32(t3);
4919 }
4920 break;
4921 case OPC_MULTU:
4922 {
4923 TCGv_i32 t2 = tcg_temp_new_i32();
4924 TCGv_i32 t3 = tcg_temp_new_i32();
4925 tcg_gen_trunc_tl_i32(t2, t0);
4926 tcg_gen_trunc_tl_i32(t3, t1);
4927 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4928 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4929 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4930 tcg_temp_free_i32(t2);
4931 tcg_temp_free_i32(t3);
4932 }
4933 break;
4934 #if defined(TARGET_MIPS64)
4935 case OPC_DDIV:
4936 {
4937 TCGv t2 = tcg_temp_new();
4938 TCGv t3 = tcg_temp_new();
4939 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4940 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4941 tcg_gen_and_tl(t2, t2, t3);
4942 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4943 tcg_gen_or_tl(t2, t2, t3);
4944 tcg_gen_movi_tl(t3, 0);
4945 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4946 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4947 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4948 tcg_temp_free(t3);
4949 tcg_temp_free(t2);
4950 }
4951 break;
4952 case OPC_DDIVU:
4953 {
4954 TCGv t2 = tcg_const_tl(0);
4955 TCGv t3 = tcg_const_tl(1);
4956 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4957 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
4958 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
4959 tcg_temp_free(t3);
4960 tcg_temp_free(t2);
4961 }
4962 break;
4963 case OPC_DMULT:
4964 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4965 break;
4966 case OPC_DMULTU:
4967 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4968 break;
4969 #endif
4970 case OPC_MADD:
4971 {
4972 TCGv_i64 t2 = tcg_temp_new_i64();
4973 TCGv_i64 t3 = tcg_temp_new_i64();
4974
4975 tcg_gen_ext_tl_i64(t2, t0);
4976 tcg_gen_ext_tl_i64(t3, t1);
4977 tcg_gen_mul_i64(t2, t2, t3);
4978 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4979 tcg_gen_add_i64(t2, t2, t3);
4980 tcg_temp_free_i64(t3);
4981 gen_move_low32(cpu_LO[acc], t2);
4982 gen_move_high32(cpu_HI[acc], t2);
4983 tcg_temp_free_i64(t2);
4984 }
4985 break;
4986 case OPC_MADDU:
4987 {
4988 TCGv_i64 t2 = tcg_temp_new_i64();
4989 TCGv_i64 t3 = tcg_temp_new_i64();
4990
4991 tcg_gen_ext32u_tl(t0, t0);
4992 tcg_gen_ext32u_tl(t1, t1);
4993 tcg_gen_extu_tl_i64(t2, t0);
4994 tcg_gen_extu_tl_i64(t3, t1);
4995 tcg_gen_mul_i64(t2, t2, t3);
4996 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4997 tcg_gen_add_i64(t2, t2, t3);
4998 tcg_temp_free_i64(t3);
4999 gen_move_low32(cpu_LO[acc], t2);
5000 gen_move_high32(cpu_HI[acc], t2);
5001 tcg_temp_free_i64(t2);
5002 }
5003 break;
5004 case OPC_MSUB:
5005 {
5006 TCGv_i64 t2 = tcg_temp_new_i64();
5007 TCGv_i64 t3 = tcg_temp_new_i64();
5008
5009 tcg_gen_ext_tl_i64(t2, t0);
5010 tcg_gen_ext_tl_i64(t3, t1);
5011 tcg_gen_mul_i64(t2, t2, t3);
5012 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5013 tcg_gen_sub_i64(t2, t3, t2);
5014 tcg_temp_free_i64(t3);
5015 gen_move_low32(cpu_LO[acc], t2);
5016 gen_move_high32(cpu_HI[acc], t2);
5017 tcg_temp_free_i64(t2);
5018 }
5019 break;
5020 case OPC_MSUBU:
5021 {
5022 TCGv_i64 t2 = tcg_temp_new_i64();
5023 TCGv_i64 t3 = tcg_temp_new_i64();
5024
5025 tcg_gen_ext32u_tl(t0, t0);
5026 tcg_gen_ext32u_tl(t1, t1);
5027 tcg_gen_extu_tl_i64(t2, t0);
5028 tcg_gen_extu_tl_i64(t3, t1);
5029 tcg_gen_mul_i64(t2, t2, t3);
5030 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5031 tcg_gen_sub_i64(t2, t3, t2);
5032 tcg_temp_free_i64(t3);
5033 gen_move_low32(cpu_LO[acc], t2);
5034 gen_move_high32(cpu_HI[acc], t2);
5035 tcg_temp_free_i64(t2);
5036 }
5037 break;
5038 default:
5039 MIPS_INVAL("mul/div");
5040 generate_exception_end(ctx, EXCP_RI);
5041 goto out;
5042 }
5043 out:
5044 tcg_temp_free(t0);
5045 tcg_temp_free(t1);
5046 }
5047
5048 /*
5049 * These MULT[U] and MADD[U] instructions implemented in for example
5050 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
5051 * architectures are special three-operand variants with the syntax
5052 *
5053 * MULT[U][1] rd, rs, rt
5054 *
5055 * such that
5056 *
5057 * (rd, LO, HI) <- rs * rt
5058 *
5059 * and
5060 *
5061 * MADD[U][1] rd, rs, rt
5062 *
5063 * such that
5064 *
5065 * (rd, LO, HI) <- (LO, HI) + rs * rt
5066 *
5067 * where the low-order 32-bits of the result is placed into both the
5068 * GPR rd and the special register LO. The high-order 32-bits of the
5069 * result is placed into the special register HI.
5070 *
5071 * If the GPR rd is omitted in assembly language, it is taken to be 0,
5072 * which is the zero register that always reads as 0.
5073 */
5074 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
5075 int rd, int rs, int rt)
5076 {
5077 TCGv t0 = tcg_temp_new();
5078 TCGv t1 = tcg_temp_new();
5079 int acc = 0;
5080
5081 gen_load_gpr(t0, rs);
5082 gen_load_gpr(t1, rt);
5083
5084 switch (opc) {
5085 case MMI_OPC_MULT1:
5086 acc = 1;
5087 /* Fall through */
5088 case OPC_MULT:
5089 {
5090 TCGv_i32 t2 = tcg_temp_new_i32();
5091 TCGv_i32 t3 = tcg_temp_new_i32();
5092 tcg_gen_trunc_tl_i32(t2, t0);
5093 tcg_gen_trunc_tl_i32(t3, t1);
5094 tcg_gen_muls2_i32(t2, t3, t2, t3);
5095 if (rd) {
5096 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5097 }
5098 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5099 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5100 tcg_temp_free_i32(t2);
5101 tcg_temp_free_i32(t3);
5102 }
5103 break;
5104 case MMI_OPC_MULTU1:
5105 acc = 1;
5106 /* Fall through */
5107 case OPC_MULTU:
5108 {
5109 TCGv_i32 t2 = tcg_temp_new_i32();
5110 TCGv_i32 t3 = tcg_temp_new_i32();
5111 tcg_gen_trunc_tl_i32(t2, t0);
5112 tcg_gen_trunc_tl_i32(t3, t1);
5113 tcg_gen_mulu2_i32(t2, t3, t2, t3);
5114 if (rd) {
5115 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5116 }
5117 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5118 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5119 tcg_temp_free_i32(t2);
5120 tcg_temp_free_i32(t3);
5121 }
5122 break;
5123 case MMI_OPC_MADD1:
5124 acc = 1;
5125 /* Fall through */
5126 case MMI_OPC_MADD:
5127 {
5128 TCGv_i64 t2 = tcg_temp_new_i64();
5129 TCGv_i64 t3 = tcg_temp_new_i64();
5130
5131 tcg_gen_ext_tl_i64(t2, t0);
5132 tcg_gen_ext_tl_i64(t3, t1);
5133 tcg_gen_mul_i64(t2, t2, t3);
5134 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5135 tcg_gen_add_i64(t2, t2, t3);
5136 tcg_temp_free_i64(t3);
5137 gen_move_low32(cpu_LO[acc], t2);
5138 gen_move_high32(cpu_HI[acc], t2);
5139 if (rd) {
5140 gen_move_low32(cpu_gpr[rd], t2);
5141 }
5142 tcg_temp_free_i64(t2);
5143 }
5144 break;
5145 case MMI_OPC_MADDU1:
5146 acc = 1;
5147 /* Fall through */
5148 case MMI_OPC_MADDU:
5149 {
5150 TCGv_i64 t2 = tcg_temp_new_i64();
5151 TCGv_i64 t3 = tcg_temp_new_i64();
5152
5153 tcg_gen_ext32u_tl(t0, t0);
5154 tcg_gen_ext32u_tl(t1, t1);
5155 tcg_gen_extu_tl_i64(t2, t0);
5156 tcg_gen_extu_tl_i64(t3, t1);
5157 tcg_gen_mul_i64(t2, t2, t3);
5158 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5159 tcg_gen_add_i64(t2, t2, t3);
5160 tcg_temp_free_i64(t3);
5161 gen_move_low32(cpu_LO[acc], t2);
5162 gen_move_high32(cpu_HI[acc], t2);
5163 if (rd) {
5164 gen_move_low32(cpu_gpr[rd], t2);
5165 }
5166 tcg_temp_free_i64(t2);
5167 }
5168 break;
5169 default:
5170 MIPS_INVAL("mul/madd TXx9");
5171 generate_exception_end(ctx, EXCP_RI);
5172 goto out;
5173 }
5174
5175 out:
5176 tcg_temp_free(t0);
5177 tcg_temp_free(t1);
5178 }
5179
5180 static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc,
5181 int rd, int rs, int rt)
5182 {
5183 TCGv t0 = tcg_temp_new();
5184 TCGv t1 = tcg_temp_new();
5185
5186 gen_load_gpr(t0, rs);
5187 gen_load_gpr(t1, rt);
5188
5189 switch (opc) {
5190 case OPC_VR54XX_MULS:
5191 gen_helper_muls(t0, cpu_env, t0, t1);
5192 break;
5193 case OPC_VR54XX_MULSU:
5194 gen_helper_mulsu(t0, cpu_env, t0, t1);
5195 break;
5196 case OPC_VR54XX_MACC:
5197 gen_helper_macc(t0, cpu_env, t0, t1);
5198 break;
5199 case OPC_VR54XX_MACCU:
5200 gen_helper_maccu(t0, cpu_env, t0, t1);
5201 break;
5202 case OPC_VR54XX_MSAC:
5203 gen_helper_msac(t0, cpu_env, t0, t1);
5204 break;
5205 case OPC_VR54XX_MSACU:
5206 gen_helper_msacu(t0, cpu_env, t0, t1);
5207 break;
5208 case OPC_VR54XX_MULHI:
5209 gen_helper_mulhi(t0, cpu_env, t0, t1);
5210 break;
5211 case OPC_VR54XX_MULHIU:
5212 gen_helper_mulhiu(t0, cpu_env, t0, t1);
5213 break;
5214 case OPC_VR54XX_MULSHI:
5215 gen_helper_mulshi(t0, cpu_env, t0, t1);
5216 break;
5217 case OPC_VR54XX_MULSHIU:
5218 gen_helper_mulshiu(t0, cpu_env, t0, t1);
5219 break;
5220 case OPC_VR54XX_MACCHI:
5221 gen_helper_macchi(t0, cpu_env, t0, t1);
5222 break;
5223 case OPC_VR54XX_MACCHIU:
5224 gen_helper_macchiu(t0, cpu_env, t0, t1);
5225 break;
5226 case OPC_VR54XX_MSACHI:
5227 gen_helper_msachi(t0, cpu_env, t0, t1);
5228 break;
5229 case OPC_VR54XX_MSACHIU:
5230 gen_helper_msachiu(t0, cpu_env, t0, t1);
5231 break;
5232 default:
5233 MIPS_INVAL("mul vr54xx");
5234 generate_exception_end(ctx, EXCP_RI);
5235 goto out;
5236 }
5237 gen_store_gpr(t0, rd);
5238
5239 out:
5240 tcg_temp_free(t0);
5241 tcg_temp_free(t1);
5242 }
5243
5244 static void gen_cl(DisasContext *ctx, uint32_t opc,
5245 int rd, int rs)
5246 {
5247 TCGv t0;
5248
5249 if (rd == 0) {
5250 /* Treat as NOP. */
5251 return;
5252 }
5253 t0 = cpu_gpr[rd];
5254 gen_load_gpr(t0, rs);
5255
5256 switch (opc) {
5257 case OPC_CLO:
5258 case R6_OPC_CLO:
5259 #if defined(TARGET_MIPS64)
5260 case OPC_DCLO:
5261 case R6_OPC_DCLO:
5262 #endif
5263 tcg_gen_not_tl(t0, t0);
5264 break;
5265 }
5266
5267 switch (opc) {
5268 case OPC_CLO:
5269 case R6_OPC_CLO:
5270 case OPC_CLZ:
5271 case R6_OPC_CLZ:
5272 tcg_gen_ext32u_tl(t0, t0);
5273 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
5274 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
5275 break;
5276 #if defined(TARGET_MIPS64)
5277 case OPC_DCLO:
5278 case R6_OPC_DCLO:
5279 case OPC_DCLZ:
5280 case R6_OPC_DCLZ:
5281 tcg_gen_clzi_i64(t0, t0, 64);
5282 break;
5283 #endif
5284 }
5285 }
5286
5287 /* Godson integer instructions */
5288 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
5289 int rd, int rs, int rt)
5290 {
5291 TCGv t0, t1;
5292
5293 if (rd == 0) {
5294 /* Treat as NOP. */
5295 return;
5296 }
5297
5298 switch (opc) {
5299 case OPC_MULT_G_2E:
5300 case OPC_MULT_G_2F:
5301 case OPC_MULTU_G_2E:
5302 case OPC_MULTU_G_2F:
5303 #if defined(TARGET_MIPS64)
5304 case OPC_DMULT_G_2E:
5305 case OPC_DMULT_G_2F:
5306 case OPC_DMULTU_G_2E:
5307 case OPC_DMULTU_G_2F:
5308 #endif
5309 t0 = tcg_temp_new();
5310 t1 = tcg_temp_new();
5311 break;
5312 default:
5313 t0 = tcg_temp_local_new();
5314 t1 = tcg_temp_local_new();
5315 break;
5316 }
5317
5318 gen_load_gpr(t0, rs);
5319 gen_load_gpr(t1, rt);
5320
5321 switch (opc) {
5322 case OPC_MULT_G_2E:
5323 case OPC_MULT_G_2F:
5324 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5325 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5326 break;
5327 case OPC_MULTU_G_2E:
5328 case OPC_MULTU_G_2F:
5329 tcg_gen_ext32u_tl(t0, t0);
5330 tcg_gen_ext32u_tl(t1, t1);
5331 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5332 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5333 break;
5334 case OPC_DIV_G_2E:
5335 case OPC_DIV_G_2F:
5336 {
5337 TCGLabel *l1 = gen_new_label();
5338 TCGLabel *l2 = gen_new_label();
5339 TCGLabel *l3 = gen_new_label();
5340 tcg_gen_ext32s_tl(t0, t0);
5341 tcg_gen_ext32s_tl(t1, t1);
5342 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5343 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5344 tcg_gen_br(l3);
5345 gen_set_label(l1);
5346 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5347 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5348 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5349 tcg_gen_br(l3);
5350 gen_set_label(l2);
5351 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5352 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5353 gen_set_label(l3);
5354 }
5355 break;
5356 case OPC_DIVU_G_2E:
5357 case OPC_DIVU_G_2F:
5358 {
5359 TCGLabel *l1 = gen_new_label();
5360 TCGLabel *l2 = gen_new_label();
5361 tcg_gen_ext32u_tl(t0, t0);
5362 tcg_gen_ext32u_tl(t1, t1);
5363 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5364 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5365 tcg_gen_br(l2);
5366 gen_set_label(l1);
5367 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5368 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5369 gen_set_label(l2);
5370 }
5371 break;
5372 case OPC_MOD_G_2E:
5373 case OPC_MOD_G_2F:
5374 {
5375 TCGLabel *l1 = gen_new_label();
5376 TCGLabel *l2 = gen_new_label();
5377 TCGLabel *l3 = gen_new_label();
5378 tcg_gen_ext32u_tl(t0, t0);
5379 tcg_gen_ext32u_tl(t1, t1);
5380 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5381 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5382 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5383 gen_set_label(l1);
5384 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5385 tcg_gen_br(l3);
5386 gen_set_label(l2);
5387 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5388 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5389 gen_set_label(l3);
5390 }
5391 break;
5392 case OPC_MODU_G_2E:
5393 case OPC_MODU_G_2F:
5394 {
5395 TCGLabel *l1 = gen_new_label();
5396 TCGLabel *l2 = gen_new_label();
5397 tcg_gen_ext32u_tl(t0, t0);
5398 tcg_gen_ext32u_tl(t1, t1);
5399 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5400 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5401 tcg_gen_br(l2);
5402 gen_set_label(l1);
5403 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5404 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5405 gen_set_label(l2);
5406 }
5407 break;
5408 #if defined(TARGET_MIPS64)
5409 case OPC_DMULT_G_2E:
5410 case OPC_DMULT_G_2F:
5411 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5412 break;
5413 case OPC_DMULTU_G_2E:
5414 case OPC_DMULTU_G_2F:
5415 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5416 break;
5417 case OPC_DDIV_G_2E:
5418 case OPC_DDIV_G_2F:
5419 {
5420 TCGLabel *l1 = gen_new_label();
5421 TCGLabel *l2 = gen_new_label();
5422 TCGLabel *l3 = gen_new_label();
5423 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5424 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5425 tcg_gen_br(l3);
5426 gen_set_label(l1);
5427 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5428 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5429 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5430 tcg_gen_br(l3);
5431 gen_set_label(l2);
5432 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5433 gen_set_label(l3);
5434 }
5435 break;
5436 case OPC_DDIVU_G_2E:
5437 case OPC_DDIVU_G_2F:
5438 {
5439 TCGLabel *l1 = gen_new_label();
5440 TCGLabel *l2 = gen_new_label();
5441 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5442 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5443 tcg_gen_br(l2);
5444 gen_set_label(l1);
5445 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5446 gen_set_label(l2);
5447 }
5448 break;
5449 case OPC_DMOD_G_2E:
5450 case OPC_DMOD_G_2F:
5451 {
5452 TCGLabel *l1 = gen_new_label();
5453 TCGLabel *l2 = gen_new_label();
5454 TCGLabel *l3 = gen_new_label();
5455 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5456 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5457 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5458 gen_set_label(l1);
5459 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5460 tcg_gen_br(l3);
5461 gen_set_label(l2);
5462 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5463 gen_set_label(l3);
5464 }
5465 break;
5466 case OPC_DMODU_G_2E:
5467 case OPC_DMODU_G_2F:
5468 {
5469 TCGLabel *l1 = gen_new_label();
5470 TCGLabel *l2 = gen_new_label();
5471 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5472 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5473 tcg_gen_br(l2);
5474 gen_set_label(l1);
5475 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5476 gen_set_label(l2);
5477 }
5478 break;
5479 #endif
5480 }
5481
5482 tcg_temp_free(t0);
5483 tcg_temp_free(t1);
5484 }
5485
5486 /* Loongson multimedia instructions */
5487 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
5488 {
5489 uint32_t opc, shift_max;
5490 TCGv_i64 t0, t1;
5491
5492 opc = MASK_LMI(ctx->opcode);
5493 switch (opc) {
5494 case OPC_ADD_CP2:
5495 case OPC_SUB_CP2:
5496 case OPC_DADD_CP2:
5497 case OPC_DSUB_CP2:
5498 t0 = tcg_temp_local_new_i64();
5499 t1 = tcg_temp_local_new_i64();
5500 break;
5501 default:
5502 t0 = tcg_temp_new_i64();
5503 t1 = tcg_temp_new_i64();
5504 break;
5505 }
5506
5507 check_cp1_enabled(ctx);
5508 gen_load_fpr64(ctx, t0, rs);
5509 gen_load_fpr64(ctx, t1, rt);
5510
5511 #define LMI_HELPER(UP, LO) \
5512 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
5513 #define LMI_HELPER_1(UP, LO) \
5514 case OPC_##UP: gen_helper_##LO(t0, t0); break
5515 #define LMI_DIRECT(UP, LO, OP) \
5516 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
5517
5518 switch (opc) {
5519 LMI_HELPER(PADDSH, paddsh);
5520 LMI_HELPER(PADDUSH, paddush);
5521 LMI_HELPER(PADDH, paddh);
5522 LMI_HELPER(PADDW, paddw);
5523 LMI_HELPER(PADDSB, paddsb);
5524 LMI_HELPER(PADDUSB, paddusb);
5525 LMI_HELPER(PADDB, paddb);
5526
5527 LMI_HELPER(PSUBSH, psubsh);
5528 LMI_HELPER(PSUBUSH, psubush);
5529 LMI_HELPER(PSUBH, psubh);
5530 LMI_HELPER(PSUBW, psubw);
5531 LMI_HELPER(PSUBSB, psubsb);
5532 LMI_HELPER(PSUBUSB, psubusb);
5533 LMI_HELPER(PSUBB, psubb);
5534
5535 LMI_HELPER(PSHUFH, pshufh);
5536 LMI_HELPER(PACKSSWH, packsswh);
5537 LMI_HELPER(PACKSSHB, packsshb);
5538 LMI_HELPER(PACKUSHB, packushb);
5539
5540 LMI_HELPER(PUNPCKLHW, punpcklhw);
5541 LMI_HELPER(PUNPCKHHW, punpckhhw);
5542 LMI_HELPER(PUNPCKLBH, punpcklbh);
5543 LMI_HELPER(PUNPCKHBH, punpckhbh);
5544 LMI_HELPER(PUNPCKLWD, punpcklwd);
5545 LMI_HELPER(PUNPCKHWD, punpckhwd);
5546
5547 LMI_HELPER(PAVGH, pavgh);
5548 LMI_HELPER(PAVGB, pavgb);
5549 LMI_HELPER(PMAXSH, pmaxsh);
5550 LMI_HELPER(PMINSH, pminsh);
5551 LMI_HELPER(PMAXUB, pmaxub);
5552 LMI_HELPER(PMINUB, pminub);
5553
5554 LMI_HELPER(PCMPEQW, pcmpeqw);
5555 LMI_HELPER(PCMPGTW, pcmpgtw);
5556 LMI_HELPER(PCMPEQH, pcmpeqh);
5557 LMI_HELPER(PCMPGTH, pcmpgth);
5558 LMI_HELPER(PCMPEQB, pcmpeqb);
5559 LMI_HELPER(PCMPGTB, pcmpgtb);
5560
5561 LMI_HELPER(PSLLW, psllw);
5562 LMI_HELPER(PSLLH, psllh);
5563 LMI_HELPER(PSRLW, psrlw);
5564 LMI_HELPER(PSRLH, psrlh);
5565 LMI_HELPER(PSRAW, psraw);
5566 LMI_HELPER(PSRAH, psrah);
5567
5568 LMI_HELPER(PMULLH, pmullh);
5569 LMI_HELPER(PMULHH, pmulhh);
5570 LMI_HELPER(PMULHUH, pmulhuh);
5571 LMI_HELPER(PMADDHW, pmaddhw);
5572
5573 LMI_HELPER(PASUBUB, pasubub);
5574 LMI_HELPER_1(BIADD, biadd);
5575 LMI_HELPER_1(PMOVMSKB, pmovmskb);
5576
5577 LMI_DIRECT(PADDD, paddd, add);
5578 LMI_DIRECT(PSUBD, psubd, sub);
5579 LMI_DIRECT(XOR_CP2, xor, xor);
5580 LMI_DIRECT(NOR_CP2, nor, nor);
5581 LMI_DIRECT(AND_CP2, and, and);
5582 LMI_DIRECT(OR_CP2, or, or);
5583
5584 case OPC_PANDN:
5585 tcg_gen_andc_i64(t0, t1, t0);
5586 break;
5587
5588 case OPC_PINSRH_0:
5589 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
5590 break;
5591 case OPC_PINSRH_1:
5592 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
5593 break;
5594 case OPC_PINSRH_2:
5595 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
5596 break;
5597 case OPC_PINSRH_3:
5598 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
5599 break;
5600
5601 case OPC_PEXTRH:
5602 tcg_gen_andi_i64(t1, t1, 3);
5603 tcg_gen_shli_i64(t1, t1, 4);
5604 tcg_gen_shr_i64(t0, t0, t1);
5605 tcg_gen_ext16u_i64(t0, t0);
5606 break;
5607
5608 case OPC_ADDU_CP2:
5609 tcg_gen_add_i64(t0, t0, t1);
5610 tcg_gen_ext32s_i64(t0, t0);
5611 break;
5612 case OPC_SUBU_CP2:
5613 tcg_gen_sub_i64(t0, t0, t1);
5614 tcg_gen_ext32s_i64(t0, t0);
5615 break;
5616
5617 case OPC_SLL_CP2:
5618 shift_max = 32;
5619 goto do_shift;
5620 case OPC_SRL_CP2:
5621 shift_max = 32;
5622 goto do_shift;
5623 case OPC_SRA_CP2:
5624 shift_max = 32;
5625 goto do_shift;
5626 case OPC_DSLL_CP2:
5627 shift_max = 64;
5628 goto do_shift;
5629 case OPC_DSRL_CP2:
5630 shift_max = 64;
5631 goto do_shift;
5632 case OPC_DSRA_CP2:
5633 shift_max = 64;
5634 goto do_shift;
5635 do_shift:
5636 /* Make sure shift count isn't TCG undefined behaviour. */
5637 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5638
5639 switch (opc) {
5640 case OPC_SLL_CP2:
5641 case OPC_DSLL_CP2:
5642 tcg_gen_shl_i64(t0, t0, t1);
5643 break;
5644 case OPC_SRA_CP2:
5645 case OPC_DSRA_CP2:
5646 /* Since SRA is UndefinedResult without sign-extended inputs,
5647 we can treat SRA and DSRA the same. */
5648 tcg_gen_sar_i64(t0, t0, t1);
5649 break;
5650 case OPC_SRL_CP2:
5651 /* We want to shift in zeros for SRL; zero-extend first. */
5652 tcg_gen_ext32u_i64(t0, t0);
5653 /* FALLTHRU */
5654 case OPC_DSRL_CP2:
5655 tcg_gen_shr_i64(t0, t0, t1);
5656 break;
5657 }
5658
5659 if (shift_max == 32) {
5660 tcg_gen_ext32s_i64(t0, t0);
5661 }
5662
5663 /* Shifts larger than MAX produce zero. */
5664 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5665 tcg_gen_neg_i64(t1, t1);
5666 tcg_gen_and_i64(t0, t0, t1);
5667 break;
5668
5669 case OPC_ADD_CP2:
5670 case OPC_DADD_CP2:
5671 {
5672 TCGv_i64 t2 = tcg_temp_new_i64();
5673 TCGLabel *lab = gen_new_label();
5674
5675 tcg_gen_mov_i64(t2, t0);
5676 tcg_gen_add_i64(t0, t1, t2);
5677 if (opc == OPC_ADD_CP2) {
5678 tcg_gen_ext32s_i64(t0, t0);
5679 }
5680 tcg_gen_xor_i64(t1, t1, t2);
5681 tcg_gen_xor_i64(t2, t2, t0);
5682 tcg_gen_andc_i64(t1, t2, t1);
5683 tcg_temp_free_i64(t2);
5684 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5685 generate_exception(ctx, EXCP_OVERFLOW);
5686 gen_set_label(lab);
5687 break;
5688 }
5689
5690 case OPC_SUB_CP2:
5691 case OPC_DSUB_CP2:
5692 {
5693 TCGv_i64 t2 = tcg_temp_new_i64();
5694 TCGLabel *lab = gen_new_label();
5695
5696 tcg_gen_mov_i64(t2, t0);
5697 tcg_gen_sub_i64(t0, t1, t2);
5698 if (opc == OPC_SUB_CP2) {
5699 tcg_gen_ext32s_i64(t0, t0);
5700 }
5701 tcg_gen_xor_i64(t1, t1, t2);
5702 tcg_gen_xor_i64(t2, t2, t0);
5703 tcg_gen_and_i64(t1, t1, t2);
5704 tcg_temp_free_i64(t2);
5705 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5706 generate_exception(ctx, EXCP_OVERFLOW);
5707 gen_set_label(lab);
5708 break;
5709 }
5710
5711 case OPC_PMULUW:
5712 tcg_gen_ext32u_i64(t0, t0);
5713 tcg_gen_ext32u_i64(t1, t1);
5714 tcg_gen_mul_i64(t0, t0, t1);
5715 break;
5716
5717 case OPC_SEQU_CP2:
5718 case OPC_SEQ_CP2:
5719 case OPC_SLTU_CP2:
5720 case OPC_SLT_CP2:
5721 case OPC_SLEU_CP2:
5722 case OPC_SLE_CP2:
5723 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
5724 FD field is the CC field? */
5725 default:
5726 MIPS_INVAL("loongson_cp2");
5727 generate_exception_end(ctx, EXCP_RI);
5728 return;
5729 }
5730
5731 #undef LMI_HELPER
5732 #undef LMI_DIRECT
5733
5734 gen_store_fpr64(ctx, t0, rd);
5735
5736 tcg_temp_free_i64(t0);
5737 tcg_temp_free_i64(t1);
5738 }
5739
5740 /* Traps */
5741 static void gen_trap (DisasContext *ctx, uint32_t opc,
5742 int rs, int rt, int16_t imm)
5743 {
5744 int cond;
5745 TCGv t0 = tcg_temp_new();
5746 TCGv t1 = tcg_temp_new();
5747
5748 cond = 0;
5749 /* Load needed operands */
5750 switch (opc) {
5751 case OPC_TEQ:
5752 case OPC_TGE:
5753 case OPC_TGEU:
5754 case OPC_TLT:
5755 case OPC_TLTU:
5756 case OPC_TNE:
5757 /* Compare two registers */
5758 if (rs != rt) {
5759 gen_load_gpr(t0, rs);
5760 gen_load_gpr(t1, rt);
5761 cond = 1;
5762 }
5763 break;
5764 case OPC_TEQI:
5765 case OPC_TGEI:
5766 case OPC_TGEIU:
5767 case OPC_TLTI:
5768 case OPC_TLTIU:
5769 case OPC_TNEI:
5770 /* Compare register to immediate */
5771 if (rs != 0 || imm != 0) {
5772 gen_load_gpr(t0, rs);
5773 tcg_gen_movi_tl(t1, (int32_t)imm);
5774 cond = 1;
5775 }
5776 break;
5777 }
5778 if (cond == 0) {
5779 switch (opc) {
5780 case OPC_TEQ: /* rs == rs */
5781 case OPC_TEQI: /* r0 == 0 */
5782 case OPC_TGE: /* rs >= rs */
5783 case OPC_TGEI: /* r0 >= 0 */
5784 case OPC_TGEU: /* rs >= rs unsigned */
5785 case OPC_TGEIU: /* r0 >= 0 unsigned */
5786 /* Always trap */
5787 generate_exception_end(ctx, EXCP_TRAP);
5788 break;
5789 case OPC_TLT: /* rs < rs */
5790 case OPC_TLTI: /* r0 < 0 */
5791 case OPC_TLTU: /* rs < rs unsigned */
5792 case OPC_TLTIU: /* r0 < 0 unsigned */
5793 case OPC_TNE: /* rs != rs */
5794 case OPC_TNEI: /* r0 != 0 */
5795 /* Never trap: treat as NOP. */
5796 break;
5797 }
5798 } else {
5799 TCGLabel *l1 = gen_new_label();
5800
5801 switch (opc) {
5802 case OPC_TEQ:
5803 case OPC_TEQI:
5804 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
5805 break;
5806 case OPC_TGE:
5807 case OPC_TGEI:
5808 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
5809 break;
5810 case OPC_TGEU:
5811 case OPC_TGEIU:
5812 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
5813 break;
5814 case OPC_TLT:
5815 case OPC_TLTI:
5816 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
5817 break;
5818 case OPC_TLTU:
5819 case OPC_TLTIU:
5820 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
5821 break;
5822 case OPC_TNE:
5823 case OPC_TNEI:
5824 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
5825 break;
5826 }
5827 generate_exception(ctx, EXCP_TRAP);
5828 gen_set_label(l1);
5829 }
5830 tcg_temp_free(t0);
5831 tcg_temp_free(t1);
5832 }
5833
5834 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
5835 {
5836 if (unlikely(ctx->base.singlestep_enabled)) {
5837 return false;
5838 }
5839
5840 #ifndef CONFIG_USER_ONLY
5841 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
5842 #else
5843 return true;
5844 #endif
5845 }
5846
5847 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
5848 {
5849 if (use_goto_tb(ctx, dest)) {
5850 tcg_gen_goto_tb(n);
5851 gen_save_pc(dest);
5852 tcg_gen_exit_tb(ctx->base.tb, n);
5853 } else {
5854 gen_save_pc(dest);
5855 if (ctx->base.singlestep_enabled) {
5856 save_cpu_state(ctx, 0);
5857 gen_helper_raise_exception_debug(cpu_env);
5858 }
5859 tcg_gen_lookup_and_goto_ptr();
5860 }
5861 }
5862
5863 /* Branches (before delay slot) */
5864 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
5865 int insn_bytes,
5866 int rs, int rt, int32_t offset,
5867 int delayslot_size)
5868 {
5869 target_ulong btgt = -1;
5870 int blink = 0;
5871 int bcond_compute = 0;
5872 TCGv t0 = tcg_temp_new();
5873 TCGv t1 = tcg_temp_new();
5874
5875 if (ctx->hflags & MIPS_HFLAG_BMASK) {
5876 #ifdef MIPS_DEBUG_DISAS
5877 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
5878 TARGET_FMT_lx "\n", ctx->base.pc_next);
5879 #endif
5880 generate_exception_end(ctx, EXCP_RI);
5881 goto out;
5882 }
5883
5884 /* Load needed operands */
5885 switch (opc) {
5886 case OPC_BEQ:
5887 case OPC_BEQL:
5888 case OPC_BNE:
5889 case OPC_BNEL:
5890 /* Compare two registers */
5891 if (rs != rt) {
5892 gen_load_gpr(t0, rs);
5893 gen_load_gpr(t1, rt);
5894 bcond_compute = 1;
5895 }
5896 btgt = ctx->base.pc_next + insn_bytes + offset;
5897 break;
5898 case OPC_BGEZ:
5899 case OPC_BGEZAL:
5900 case OPC_BGEZALL:
5901 case OPC_BGEZL:
5902 case OPC_BGTZ:
5903 case OPC_BGTZL:
5904 case OPC_BLEZ:
5905 case OPC_BLEZL:
5906 case OPC_BLTZ:
5907 case OPC_BLTZAL:
5908 case OPC_BLTZALL:
5909 case OPC_BLTZL:
5910 /* Compare to zero */
5911 if (rs != 0) {
5912 gen_load_gpr(t0, rs);
5913 bcond_compute = 1;
5914 }
5915 btgt = ctx->base.pc_next + insn_bytes + offset;
5916 break;
5917 case OPC_BPOSGE32:
5918 #if defined(TARGET_MIPS64)
5919 case OPC_BPOSGE64:
5920 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
5921 #else
5922 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5923 #endif
5924 bcond_compute = 1;
5925 btgt = ctx->base.pc_next + insn_bytes + offset;
5926 break;
5927 case OPC_J:
5928 case OPC_JAL:
5929 case OPC_JALX:
5930 /* Jump to immediate */
5931 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
5932 (uint32_t)offset;
5933 break;
5934 case OPC_JR:
5935 case OPC_JALR:
5936 /* Jump to register */
5937 if (offset != 0 && offset != 16) {
5938 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5939 others are reserved. */
5940 MIPS_INVAL("jump hint");
5941 generate_exception_end(ctx, EXCP_RI);
5942 goto out;
5943 }
5944 gen_load_gpr(btarget, rs);
5945 break;
5946 default:
5947 MIPS_INVAL("branch/jump");
5948 generate_exception_end(ctx, EXCP_RI);
5949 goto out;
5950 }
5951 if (bcond_compute == 0) {
5952 /* No condition to be computed */
5953 switch (opc) {
5954 case OPC_BEQ: /* rx == rx */
5955 case OPC_BEQL: /* rx == rx likely */
5956 case OPC_BGEZ: /* 0 >= 0 */
5957 case OPC_BGEZL: /* 0 >= 0 likely */
5958 case OPC_BLEZ: /* 0 <= 0 */
5959 case OPC_BLEZL: /* 0 <= 0 likely */
5960 /* Always take */
5961 ctx->hflags |= MIPS_HFLAG_B;
5962 break;
5963 case OPC_BGEZAL: /* 0 >= 0 */
5964 case OPC_BGEZALL: /* 0 >= 0 likely */
5965 /* Always take and link */
5966 blink = 31;
5967 ctx->hflags |= MIPS_HFLAG_B;
5968 break;
5969 case OPC_BNE: /* rx != rx */
5970 case OPC_BGTZ: /* 0 > 0 */
5971 case OPC_BLTZ: /* 0 < 0 */
5972 /* Treat as NOP. */
5973 goto out;
5974 case OPC_BLTZAL: /* 0 < 0 */
5975 /* Handle as an unconditional branch to get correct delay
5976 slot checking. */
5977 blink = 31;
5978 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
5979 ctx->hflags |= MIPS_HFLAG_B;
5980 break;
5981 case OPC_BLTZALL: /* 0 < 0 likely */
5982 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5983 /* Skip the instruction in the delay slot */
5984 ctx->base.pc_next += 4;
5985 goto out;
5986 case OPC_BNEL: /* rx != rx likely */
5987 case OPC_BGTZL: /* 0 > 0 likely */
5988 case OPC_BLTZL: /* 0 < 0 likely */
5989 /* Skip the instruction in the delay slot */
5990 ctx->base.pc_next += 4;
5991 goto out;
5992 case OPC_J:
5993 ctx->hflags |= MIPS_HFLAG_B;
5994 break;
5995 case OPC_JALX:
5996 ctx->hflags |= MIPS_HFLAG_BX;
5997 /* Fallthrough */
5998 case OPC_JAL:
5999 blink = 31;
6000 ctx->hflags |= MIPS_HFLAG_B;
6001 break;
6002 case OPC_JR:
6003 ctx->hflags |= MIPS_HFLAG_BR;
6004 break;
6005 case OPC_JALR:
6006 blink = rt;
6007 ctx->hflags |= MIPS_HFLAG_BR;
6008 break;
6009 default:
6010 MIPS_INVAL("branch/jump");
6011 generate_exception_end(ctx, EXCP_RI);
6012 goto out;
6013 }
6014 } else {
6015 switch (opc) {
6016 case OPC_BEQ:
6017 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6018 goto not_likely;
6019 case OPC_BEQL:
6020 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6021 goto likely;
6022 case OPC_BNE:
6023 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6024 goto not_likely;
6025 case OPC_BNEL:
6026 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6027 goto likely;
6028 case OPC_BGEZ:
6029 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6030 goto not_likely;
6031 case OPC_BGEZL:
6032 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6033 goto likely;
6034 case OPC_BGEZAL:
6035 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6036 blink = 31;
6037 goto not_likely;
6038 case OPC_BGEZALL:
6039 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6040 blink = 31;
6041 goto likely;
6042 case OPC_BGTZ:
6043 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6044 goto not_likely;
6045 case OPC_BGTZL:
6046 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6047 goto likely;
6048 case OPC_BLEZ:
6049 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6050 goto not_likely;
6051 case OPC_BLEZL:
6052 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6053 goto likely;
6054 case OPC_BLTZ:
6055 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6056 goto not_likely;
6057 case OPC_BLTZL:
6058 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6059 goto likely;
6060 case OPC_BPOSGE32:
6061 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6062 goto not_likely;
6063 #if defined(TARGET_MIPS64)
6064 case OPC_BPOSGE64:
6065 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
6066 goto not_likely;
6067 #endif
6068 case OPC_BLTZAL:
6069 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6070 blink = 31;
6071 not_likely:
6072 ctx->hflags |= MIPS_HFLAG_BC;
6073 break;
6074 case OPC_BLTZALL:
6075 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6076 blink = 31;
6077 likely:
6078 ctx->hflags |= MIPS_HFLAG_BL;
6079 break;
6080 default:
6081 MIPS_INVAL("conditional branch/jump");
6082 generate_exception_end(ctx, EXCP_RI);
6083 goto out;
6084 }
6085 }
6086
6087 ctx->btarget = btgt;
6088
6089 switch (delayslot_size) {
6090 case 2:
6091 ctx->hflags |= MIPS_HFLAG_BDS16;
6092 break;
6093 case 4:
6094 ctx->hflags |= MIPS_HFLAG_BDS32;
6095 break;
6096 }
6097
6098 if (blink > 0) {
6099 int post_delay = insn_bytes + delayslot_size;
6100 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
6101
6102 tcg_gen_movi_tl(cpu_gpr[blink],
6103 ctx->base.pc_next + post_delay + lowbit);
6104 }
6105
6106 out:
6107 if (insn_bytes == 2) {
6108 ctx->hflags |= MIPS_HFLAG_B16;
6109 }
6110 tcg_temp_free(t0);
6111 tcg_temp_free(t1);
6112 }
6113
6114
6115 /* nanoMIPS Branches */
6116 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
6117 int insn_bytes,
6118 int rs, int rt, int32_t offset)
6119 {
6120 target_ulong btgt = -1;
6121 int bcond_compute = 0;
6122 TCGv t0 = tcg_temp_new();
6123 TCGv t1 = tcg_temp_new();
6124
6125 /* Load needed operands */
6126 switch (opc) {
6127 case OPC_BEQ:
6128 case OPC_BNE:
6129 /* Compare two registers */
6130 if (rs != rt) {
6131 gen_load_gpr(t0, rs);
6132 gen_load_gpr(t1, rt);
6133 bcond_compute = 1;
6134 }
6135 btgt = ctx->base.pc_next + insn_bytes + offset;
6136 break;
6137 case OPC_BGEZAL:
6138 /* Compare to zero */
6139 if (rs != 0) {
6140 gen_load_gpr(t0, rs);
6141 bcond_compute = 1;
6142 }
6143 btgt = ctx->base.pc_next + insn_bytes + offset;
6144 break;
6145 case OPC_BPOSGE32:
6146 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6147 bcond_compute = 1;
6148 btgt = ctx->base.pc_next + insn_bytes + offset;
6149 break;
6150 case OPC_JR:
6151 case OPC_JALR:
6152 /* Jump to register */
6153 if (offset != 0 && offset != 16) {
6154 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6155 others are reserved. */
6156 MIPS_INVAL("jump hint");
6157 generate_exception_end(ctx, EXCP_RI);
6158 goto out;
6159 }
6160 gen_load_gpr(btarget, rs);
6161 break;
6162 default:
6163 MIPS_INVAL("branch/jump");
6164 generate_exception_end(ctx, EXCP_RI);
6165 goto out;
6166 }
6167 if (bcond_compute == 0) {
6168 /* No condition to be computed */
6169 switch (opc) {
6170 case OPC_BEQ: /* rx == rx */
6171 /* Always take */
6172 ctx->hflags |= MIPS_HFLAG_B;
6173 break;
6174 case OPC_BGEZAL: /* 0 >= 0 */
6175 /* Always take and link */
6176 tcg_gen_movi_tl(cpu_gpr[31],
6177 ctx->base.pc_next + insn_bytes);
6178 ctx->hflags |= MIPS_HFLAG_B;
6179 break;
6180 case OPC_BNE: /* rx != rx */
6181 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6182 /* Skip the instruction in the delay slot */
6183 ctx->base.pc_next += 4;
6184 goto out;
6185 case OPC_JR:
6186 ctx->hflags |= MIPS_HFLAG_BR;
6187 break;
6188 case OPC_JALR:
6189 if (rt > 0) {
6190 tcg_gen_movi_tl(cpu_gpr[rt],
6191 ctx->base.pc_next + insn_bytes);
6192 }
6193 ctx->hflags |= MIPS_HFLAG_BR;
6194 break;
6195 default:
6196 MIPS_INVAL("branch/jump");
6197 generate_exception_end(ctx, EXCP_RI);
6198 goto out;
6199 }
6200 } else {
6201 switch (opc) {
6202 case OPC_BEQ:
6203 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6204 goto not_likely;
6205 case OPC_BNE:
6206 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6207 goto not_likely;
6208 case OPC_BGEZAL:
6209 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6210 tcg_gen_movi_tl(cpu_gpr[31],
6211 ctx->base.pc_next + insn_bytes);
6212 goto not_likely;
6213 case OPC_BPOSGE32:
6214 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6215 not_likely:
6216 ctx->hflags |= MIPS_HFLAG_BC;
6217 break;
6218 default:
6219 MIPS_INVAL("conditional branch/jump");
6220 generate_exception_end(ctx, EXCP_RI);
6221 goto out;
6222 }
6223 }
6224
6225 ctx->btarget = btgt;
6226
6227 out:
6228 if (insn_bytes == 2) {
6229 ctx->hflags |= MIPS_HFLAG_B16;
6230 }
6231 tcg_temp_free(t0);
6232 tcg_temp_free(t1);
6233 }
6234
6235
6236 /* special3 bitfield operations */
6237 static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
6238 int rs, int lsb, int msb)
6239 {
6240 TCGv t0 = tcg_temp_new();
6241 TCGv t1 = tcg_temp_new();
6242
6243 gen_load_gpr(t1, rs);
6244 switch (opc) {
6245 case OPC_EXT:
6246 if (lsb + msb > 31) {
6247 goto fail;
6248 }
6249 if (msb != 31) {
6250 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6251 } else {
6252 /* The two checks together imply that lsb == 0,
6253 so this is a simple sign-extension. */
6254 tcg_gen_ext32s_tl(t0, t1);
6255 }
6256 break;
6257 #if defined(TARGET_MIPS64)
6258 case OPC_DEXTU:
6259 lsb += 32;
6260 goto do_dext;
6261 case OPC_DEXTM:
6262 msb += 32;
6263 goto do_dext;
6264 case OPC_DEXT:
6265 do_dext:
6266 if (lsb + msb > 63) {
6267 goto fail;
6268 }
6269 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6270 break;
6271 #endif
6272 case OPC_INS:
6273 if (lsb > msb) {
6274 goto fail;
6275 }
6276 gen_load_gpr(t0, rt);
6277 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6278 tcg_gen_ext32s_tl(t0, t0);
6279 break;
6280 #if defined(TARGET_MIPS64)
6281 case OPC_DINSU:
6282 lsb += 32;
6283 /* FALLTHRU */
6284 case OPC_DINSM:
6285 msb += 32;
6286 /* FALLTHRU */
6287 case OPC_DINS:
6288 if (lsb > msb) {
6289 goto fail;
6290 }
6291 gen_load_gpr(t0, rt);
6292 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6293 break;
6294 #endif
6295 default:
6296 fail:
6297 MIPS_INVAL("bitops");
6298 generate_exception_end(ctx, EXCP_RI);
6299 tcg_temp_free(t0);
6300 tcg_temp_free(t1);
6301 return;
6302 }
6303 gen_store_gpr(t0, rt);
6304 tcg_temp_free(t0);
6305 tcg_temp_free(t1);
6306 }
6307
6308 static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
6309 {
6310 TCGv t0;
6311
6312 if (rd == 0) {
6313 /* If no destination, treat it as a NOP. */
6314 return;
6315 }
6316
6317 t0 = tcg_temp_new();
6318 gen_load_gpr(t0, rt);
6319 switch (op2) {
6320 case OPC_WSBH:
6321 {
6322 TCGv t1 = tcg_temp_new();
6323 TCGv t2 = tcg_const_tl(0x00FF00FF);
6324
6325 tcg_gen_shri_tl(t1, t0, 8);
6326 tcg_gen_and_tl(t1, t1, t2);
6327 tcg_gen_and_tl(t0, t0, t2);
6328 tcg_gen_shli_tl(t0, t0, 8);
6329 tcg_gen_or_tl(t0, t0, t1);
6330 tcg_temp_free(t2);
6331 tcg_temp_free(t1);
6332 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6333 }
6334 break;
6335 case OPC_SEB:
6336 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
6337 break;
6338 case OPC_SEH:
6339 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
6340 break;
6341 #if defined(TARGET_MIPS64)
6342 case OPC_DSBH:
6343 {
6344 TCGv t1 = tcg_temp_new();
6345 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
6346
6347 tcg_gen_shri_tl(t1, t0, 8);
6348 tcg_gen_and_tl(t1, t1, t2);
6349 tcg_gen_and_tl(t0, t0, t2);
6350 tcg_gen_shli_tl(t0, t0, 8);
6351 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6352 tcg_temp_free(t2);
6353 tcg_temp_free(t1);
6354 }
6355 break;
6356 case OPC_DSHD:
6357 {
6358 TCGv t1 = tcg_temp_new();
6359 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
6360
6361 tcg_gen_shri_tl(t1, t0, 16);
6362 tcg_gen_and_tl(t1, t1, t2);
6363 tcg_gen_and_tl(t0, t0, t2);
6364 tcg_gen_shli_tl(t0, t0, 16);
6365 tcg_gen_or_tl(t0, t0, t1);
6366 tcg_gen_shri_tl(t1, t0, 32);
6367 tcg_gen_shli_tl(t0, t0, 32);
6368 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6369 tcg_temp_free(t2);
6370 tcg_temp_free(t1);
6371 }
6372 break;
6373 #endif
6374 default:
6375 MIPS_INVAL("bsfhl");
6376 generate_exception_end(ctx, EXCP_RI);
6377 tcg_temp_free(t0);
6378 return;
6379 }
6380 tcg_temp_free(t0);
6381 }
6382
6383 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
6384 int imm2)
6385 {
6386 TCGv t0;
6387 TCGv t1;
6388 if (rd == 0) {
6389 /* Treat as NOP. */
6390 return;
6391 }
6392 t0 = tcg_temp_new();
6393 t1 = tcg_temp_new();
6394 gen_load_gpr(t0, rs);
6395 gen_load_gpr(t1, rt);
6396 tcg_gen_shli_tl(t0, t0, imm2 + 1);
6397 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
6398 if (opc == OPC_LSA) {
6399 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
6400 }
6401
6402 tcg_temp_free(t1);
6403 tcg_temp_free(t0);
6404
6405 return;
6406 }
6407
6408 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
6409 int rt, int bits)
6410 {
6411 TCGv t0;
6412 if (rd == 0) {
6413 /* Treat as NOP. */
6414 return;
6415 }
6416 t0 = tcg_temp_new();
6417 if (bits == 0 || bits == wordsz) {
6418 if (bits == 0) {
6419 gen_load_gpr(t0, rt);
6420 } else {
6421 gen_load_gpr(t0, rs);
6422 }
6423 switch (wordsz) {
6424 case 32:
6425 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6426 break;
6427 #if defined(TARGET_MIPS64)
6428 case 64:
6429 tcg_gen_mov_tl(cpu_gpr[rd], t0);
6430 break;
6431 #endif
6432 }
6433 } else {
6434 TCGv t1 = tcg_temp_new();
6435 gen_load_gpr(t0, rt);
6436 gen_load_gpr(t1, rs);
6437 switch (wordsz) {
6438 case 32:
6439 {
6440 TCGv_i64 t2 = tcg_temp_new_i64();
6441 tcg_gen_concat_tl_i64(t2, t1, t0);
6442 tcg_gen_shri_i64(t2, t2, 32 - bits);
6443 gen_move_low32(cpu_gpr[rd], t2);
6444 tcg_temp_free_i64(t2);
6445 }
6446 break;
6447 #if defined(TARGET_MIPS64)
6448 case 64:
6449 tcg_gen_shli_tl(t0, t0, bits);
6450 tcg_gen_shri_tl(t1, t1, 64 - bits);
6451 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
6452 break;
6453 #endif
6454 }
6455 tcg_temp_free(t1);
6456 }
6457
6458 tcg_temp_free(t0);
6459 }
6460
6461 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6462 int bp)
6463 {
6464 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
6465 }
6466
6467 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6468 int shift)
6469 {
6470 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
6471 }
6472
6473 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
6474 {
6475 TCGv t0;
6476 if (rd == 0) {
6477 /* Treat as NOP. */
6478 return;
6479 }
6480 t0 = tcg_temp_new();
6481 gen_load_gpr(t0, rt);
6482 switch (opc) {
6483 case OPC_BITSWAP:
6484 gen_helper_bitswap(cpu_gpr[rd], t0);
6485 break;
6486 #if defined(TARGET_MIPS64)
6487 case OPC_DBITSWAP:
6488 gen_helper_dbitswap(cpu_gpr[rd], t0);
6489 break;
6490 #endif
6491 }
6492 tcg_temp_free(t0);
6493 }
6494
6495 #ifndef CONFIG_USER_ONLY
6496 /* CP0 (MMU and control) */
6497 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
6498 {
6499 TCGv_i64 t0 = tcg_temp_new_i64();
6500 TCGv_i64 t1 = tcg_temp_new_i64();
6501
6502 tcg_gen_ext_tl_i64(t0, arg);
6503 tcg_gen_ld_i64(t1, cpu_env, off);
6504 #if defined(TARGET_MIPS64)
6505 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
6506 #else
6507 tcg_gen_concat32_i64(t1, t1, t0);
6508 #endif
6509 tcg_gen_st_i64(t1, cpu_env, off);
6510 tcg_temp_free_i64(t1);
6511 tcg_temp_free_i64(t0);
6512 }
6513
6514 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
6515 {
6516 TCGv_i64 t0 = tcg_temp_new_i64();
6517 TCGv_i64 t1 = tcg_temp_new_i64();
6518
6519 tcg_gen_ext_tl_i64(t0, arg);
6520 tcg_gen_ld_i64(t1, cpu_env, off);
6521 tcg_gen_concat32_i64(t1, t1, t0);
6522 tcg_gen_st_i64(t1, cpu_env, off);
6523 tcg_temp_free_i64(t1);
6524 tcg_temp_free_i64(t0);
6525 }
6526
6527 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
6528 {
6529 TCGv_i64 t0 = tcg_temp_new_i64();
6530
6531 tcg_gen_ld_i64(t0, cpu_env, off);
6532 #if defined(TARGET_MIPS64)
6533 tcg_gen_shri_i64(t0, t0, 30);
6534 #else
6535 tcg_gen_shri_i64(t0, t0, 32);
6536 #endif
6537 gen_move_low32(arg, t0);
6538 tcg_temp_free_i64(t0);
6539 }
6540
6541 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
6542 {
6543 TCGv_i64 t0 = tcg_temp_new_i64();
6544
6545 tcg_gen_ld_i64(t0, cpu_env, off);
6546 tcg_gen_shri_i64(t0, t0, 32 + shift);
6547 gen_move_low32(arg, t0);
6548 tcg_temp_free_i64(t0);
6549 }
6550
6551 static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
6552 {
6553 TCGv_i32 t0 = tcg_temp_new_i32();
6554
6555 tcg_gen_ld_i32(t0, cpu_env, off);
6556 tcg_gen_ext_i32_tl(arg, t0);
6557 tcg_temp_free_i32(t0);
6558 }
6559
6560 static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
6561 {
6562 tcg_gen_ld_tl(arg, cpu_env, off);
6563 tcg_gen_ext32s_tl(arg, arg);
6564 }
6565
6566 static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
6567 {
6568 TCGv_i32 t0 = tcg_temp_new_i32();
6569
6570 tcg_gen_trunc_tl_i32(t0, arg);
6571 tcg_gen_st_i32(t0, cpu_env, off);
6572 tcg_temp_free_i32(t0);
6573 }
6574
6575 #define CP0_CHECK(c) \
6576 do { \
6577 if (!(c)) { \
6578 goto cp0_unimplemented; \
6579 } \
6580 } while (0)
6581
6582 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6583 {
6584 const char *register_name = "invalid";
6585
6586 switch (reg) {
6587 case CP0_REGISTER_02:
6588 switch (sel) {
6589 case 0:
6590 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6591 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6592 register_name = "EntryLo0";
6593 break;
6594 default:
6595 goto cp0_unimplemented;
6596 }
6597 break;
6598 case CP0_REGISTER_03:
6599 switch (sel) {
6600 case 0:
6601 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6602 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6603 register_name = "EntryLo1";
6604 break;
6605 default:
6606 goto cp0_unimplemented;
6607 }
6608 break;
6609 case CP0_REGISTER_09:
6610 switch (sel) {
6611 case 7:
6612 CP0_CHECK(ctx->saar);
6613 gen_helper_mfhc0_saar(arg, cpu_env);
6614 register_name = "SAAR";
6615 break;
6616 default:
6617 goto cp0_unimplemented;
6618 }
6619 break;
6620 case CP0_REGISTER_17:
6621 switch (sel) {
6622 case 0:
6623 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
6624 ctx->CP0_LLAddr_shift);
6625 register_name = "LLAddr";
6626 break;
6627 case 1:
6628 CP0_CHECK(ctx->mrp);
6629 gen_helper_mfhc0_maar(arg, cpu_env);
6630 register_name = "MAAR";
6631 break;
6632 default:
6633 goto cp0_unimplemented;
6634 }
6635 break;
6636 case CP0_REGISTER_28:
6637 switch (sel) {
6638 case 0:
6639 case 2:
6640 case 4:
6641 case 6:
6642 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
6643 register_name = "TagLo";
6644 break;
6645 default:
6646 goto cp0_unimplemented;
6647 }
6648 break;
6649 default:
6650 goto cp0_unimplemented;
6651 }
6652 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
6653 return;
6654
6655 cp0_unimplemented:
6656 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
6657 register_name, reg, sel);
6658 tcg_gen_movi_tl(arg, 0);
6659 }
6660
6661 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6662 {
6663 const char *register_name = "invalid";
6664 uint64_t mask = ctx->PAMask >> 36;
6665
6666 switch (reg) {
6667 case CP0_REGISTER_02:
6668 switch (sel) {
6669 case 0:
6670 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6671 tcg_gen_andi_tl(arg, arg, mask);
6672 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6673 register_name = "EntryLo0";
6674 break;
6675 default:
6676 goto cp0_unimplemented;
6677 }
6678 break;
6679 case CP0_REGISTER_03:
6680 switch (sel) {
6681 case 0:
6682 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6683 tcg_gen_andi_tl(arg, arg, mask);
6684 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6685 register_name = "EntryLo1";
6686 break;
6687 default:
6688 goto cp0_unimplemented;
6689 }
6690 break;
6691 case CP0_REGISTER_09:
6692 switch (sel) {
6693 case 7:
6694 CP0_CHECK(ctx->saar);
6695 gen_helper_mthc0_saar(cpu_env, arg);
6696 register_name = "SAAR";
6697 break;
6698 default:
6699 goto cp0_unimplemented;
6700 }
6701 case CP0_REGISTER_17:
6702 switch (sel) {
6703 case 0:
6704 /* LLAddr is read-only (the only exception is bit 0 if LLB is
6705 supported); the CP0_LLAddr_rw_bitmask does not seem to be
6706 relevant for modern MIPS cores supporting MTHC0, therefore
6707 treating MTHC0 to LLAddr as NOP. */
6708 register_name = "LLAddr";
6709 break;
6710 case 1:
6711 CP0_CHECK(ctx->mrp);
6712 gen_helper_mthc0_maar(cpu_env, arg);
6713 register_name = "MAAR";
6714 break;
6715 default:
6716 goto cp0_unimplemented;
6717 }
6718 break;
6719 case CP0_REGISTER_28:
6720 switch (sel) {
6721 case 0:
6722 case 2:
6723 case 4:
6724 case 6:
6725 tcg_gen_andi_tl(arg, arg, mask);
6726 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
6727 register_name = "TagLo";
6728 break;
6729 default:
6730 goto cp0_unimplemented;
6731 }
6732 break;
6733 default:
6734 goto cp0_unimplemented;
6735 }
6736 trace_mips_translate_c0("mthc0", register_name, reg, sel);
6737
6738 cp0_unimplemented:
6739 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
6740 register_name, reg, sel);
6741 }
6742
6743 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
6744 {
6745 if (ctx->insn_flags & ISA_MIPS32R6) {
6746 tcg_gen_movi_tl(arg, 0);
6747 } else {
6748 tcg_gen_movi_tl(arg, ~0);
6749 }
6750 }
6751
6752 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6753 {
6754 const char *register_name = "invalid";
6755
6756 if (sel != 0) {
6757 check_insn(ctx, ISA_MIPS32);
6758 }
6759
6760 switch (reg) {
6761 case CP0_REGISTER_00:
6762 switch (sel) {
6763 case 0:
6764 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6765 register_name = "Index";
6766 break;
6767 case 1:
6768 CP0_CHECK(ctx->insn_flags & ASE_MT);
6769 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6770 register_name = "MVPControl";
6771 break;
6772 case 2:
6773 CP0_CHECK(ctx->insn_flags & ASE_MT);
6774 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6775 register_name = "MVPConf0";
6776 break;
6777 case 3:
6778 CP0_CHECK(ctx->insn_flags & ASE_MT);
6779 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6780 register_name = "MVPConf1";
6781 break;
6782 case 4:
6783 CP0_CHECK(ctx->vp);
6784 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6785 register_name = "VPControl";
6786 break;
6787 default:
6788 goto cp0_unimplemented;
6789 }
6790 break;
6791 case CP0_REGISTER_01:
6792 switch (sel) {
6793 case 0:
6794 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6795 gen_helper_mfc0_random(arg, cpu_env);
6796 register_name = "Random";
6797 break;
6798 case 1:
6799 CP0_CHECK(ctx->insn_flags & ASE_MT);
6800 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6801 register_name = "VPEControl";
6802 break;
6803 case 2:
6804 CP0_CHECK(ctx->insn_flags & ASE_MT);
6805 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6806 register_name = "VPEConf0";
6807 break;
6808 case 3:
6809 CP0_CHECK(ctx->insn_flags & ASE_MT);
6810 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6811 register_name = "VPEConf1";
6812 break;
6813 case 4:
6814 CP0_CHECK(ctx->insn_flags & ASE_MT);
6815 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
6816 register_name = "YQMask";
6817 break;
6818 case 5:
6819 CP0_CHECK(ctx->insn_flags & ASE_MT);
6820 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
6821 register_name = "VPESchedule";
6822 break;
6823 case 6:
6824 CP0_CHECK(ctx->insn_flags & ASE_MT);
6825 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6826 register_name = "VPEScheFBack";
6827 break;
6828 case 7:
6829 CP0_CHECK(ctx->insn_flags & ASE_MT);
6830 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6831 register_name = "VPEOpt";
6832 break;
6833 default:
6834 goto cp0_unimplemented;
6835 }
6836 break;
6837 case CP0_REGISTER_02:
6838 switch (sel) {
6839 case 0:
6840 {
6841 TCGv_i64 tmp = tcg_temp_new_i64();
6842 tcg_gen_ld_i64(tmp, cpu_env,
6843 offsetof(CPUMIPSState, CP0_EntryLo0));
6844 #if defined(TARGET_MIPS64)
6845 if (ctx->rxi) {
6846 /* Move RI/XI fields to bits 31:30 */
6847 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6848 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6849 }
6850 #endif
6851 gen_move_low32(arg, tmp);
6852 tcg_temp_free_i64(tmp);
6853 }
6854 register_name = "EntryLo0";
6855 break;
6856 case 1:
6857 CP0_CHECK(ctx->insn_flags & ASE_MT);
6858 gen_helper_mfc0_tcstatus(arg, cpu_env);
6859 register_name = "TCStatus";
6860 break;
6861 case 2:
6862 CP0_CHECK(ctx->insn_flags & ASE_MT);
6863 gen_helper_mfc0_tcbind(arg, cpu_env);
6864 register_name = "TCBind";
6865 break;
6866 case 3:
6867 CP0_CHECK(ctx->insn_flags & ASE_MT);
6868 gen_helper_mfc0_tcrestart(arg, cpu_env);
6869 register_name = "TCRestart";
6870 break;
6871 case 4:
6872 CP0_CHECK(ctx->insn_flags & ASE_MT);
6873 gen_helper_mfc0_tchalt(arg, cpu_env);
6874 register_name = "TCHalt";
6875 break;
6876 case 5:
6877 CP0_CHECK(ctx->insn_flags & ASE_MT);
6878 gen_helper_mfc0_tccontext(arg, cpu_env);
6879 register_name = "TCContext";
6880 break;
6881 case 6:
6882 CP0_CHECK(ctx->insn_flags & ASE_MT);
6883 gen_helper_mfc0_tcschedule(arg, cpu_env);
6884 register_name = "TCSchedule";
6885 break;
6886 case 7:
6887 CP0_CHECK(ctx->insn_flags & ASE_MT);
6888 gen_helper_mfc0_tcschefback(arg, cpu_env);
6889 register_name = "TCScheFBack";
6890 break;
6891 default:
6892 goto cp0_unimplemented;
6893 }
6894 break;
6895 case CP0_REGISTER_03:
6896 switch (sel) {
6897 case 0:
6898 {
6899 TCGv_i64 tmp = tcg_temp_new_i64();
6900 tcg_gen_ld_i64(tmp, cpu_env,
6901 offsetof(CPUMIPSState, CP0_EntryLo1));
6902 #if defined(TARGET_MIPS64)
6903 if (ctx->rxi) {
6904 /* Move RI/XI fields to bits 31:30 */
6905 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6906 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6907 }
6908 #endif
6909 gen_move_low32(arg, tmp);
6910 tcg_temp_free_i64(tmp);
6911 }
6912 register_name = "EntryLo1";
6913 break;
6914 case 1:
6915 CP0_CHECK(ctx->vp);
6916 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6917 register_name = "GlobalNumber";
6918 break;
6919 default:
6920 goto cp0_unimplemented;
6921 }
6922 break;
6923 case CP0_REGISTER_04:
6924 switch (sel) {
6925 case 0:
6926 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6927 tcg_gen_ext32s_tl(arg, arg);
6928 register_name = "Context";
6929 break;
6930 case 1:
6931 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
6932 register_name = "ContextConfig";
6933 goto cp0_unimplemented;
6934 case 2:
6935 CP0_CHECK(ctx->ulri);
6936 tcg_gen_ld_tl(arg, cpu_env,
6937 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6938 tcg_gen_ext32s_tl(arg, arg);
6939 register_name = "UserLocal";
6940 break;
6941 default:
6942 goto cp0_unimplemented;
6943 }
6944 break;
6945 case CP0_REGISTER_05:
6946 switch (sel) {
6947 case 0:
6948 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6949 register_name = "PageMask";
6950 break;
6951 case 1:
6952 check_insn(ctx, ISA_MIPS32R2);
6953 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6954 register_name = "PageGrain";
6955 break;
6956 case 2:
6957 CP0_CHECK(ctx->sc);
6958 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
6959 tcg_gen_ext32s_tl(arg, arg);
6960 register_name = "SegCtl0";
6961 break;
6962 case 3:
6963 CP0_CHECK(ctx->sc);
6964 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
6965 tcg_gen_ext32s_tl(arg, arg);
6966 register_name = "SegCtl1";
6967 break;
6968 case 4:
6969 CP0_CHECK(ctx->sc);
6970 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
6971 tcg_gen_ext32s_tl(arg, arg);
6972 register_name = "SegCtl2";
6973 break;
6974 case 5:
6975 check_pw(ctx);
6976 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
6977 register_name = "PWBase";
6978 break;
6979 case 6:
6980 check_pw(ctx);
6981 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
6982 register_name = "PWField";
6983 break;
6984 case 7:
6985 check_pw(ctx);
6986 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
6987 register_name = "PWSize";
6988 break;
6989 default:
6990 goto cp0_unimplemented;
6991 }
6992 break;
6993 case CP0_REGISTER_06:
6994 switch (sel) {
6995 case 0:
6996 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6997 register_name = "Wired";
6998 break;
6999 case 1:
7000 check_insn(ctx, ISA_MIPS32R2);
7001 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
7002 register_name = "SRSConf0";
7003 break;
7004 case 2:
7005 check_insn(ctx, ISA_MIPS32R2);
7006 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
7007 register_name = "SRSConf1";
7008 break;
7009 case 3:
7010 check_insn(ctx, ISA_MIPS32R2);
7011 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
7012 register_name = "SRSConf2";
7013 break;
7014 case 4:
7015 check_insn(ctx, ISA_MIPS32R2);
7016 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
7017 register_name = "SRSConf3";
7018 break;
7019 case 5:
7020 check_insn(ctx, ISA_MIPS32R2);
7021 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
7022 register_name = "SRSConf4";
7023 break;
7024 case 6:
7025 check_pw(ctx);
7026 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
7027 register_name = "PWCtl";
7028 break;
7029 default:
7030 goto cp0_unimplemented;
7031 }
7032 break;
7033 case CP0_REGISTER_07:
7034 switch (sel) {
7035 case 0:
7036 check_insn(ctx, ISA_MIPS32R2);
7037 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
7038 register_name = "HWREna";
7039 break;
7040 default:
7041 goto cp0_unimplemented;
7042 }
7043 break;
7044 case CP0_REGISTER_08:
7045 switch (sel) {
7046 case 0:
7047 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
7048 tcg_gen_ext32s_tl(arg, arg);
7049 register_name = "BadVAddr";
7050 break;
7051 case 1:
7052 CP0_CHECK(ctx->bi);
7053 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
7054 register_name = "BadInstr";
7055 break;
7056 case 2:
7057 CP0_CHECK(ctx->bp);
7058 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
7059 register_name = "BadInstrP";
7060 break;
7061 case 3:
7062 CP0_CHECK(ctx->bi);
7063 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7064 tcg_gen_andi_tl(arg, arg, ~0xffff);
7065 register_name = "BadInstrX";
7066 break;
7067 default:
7068 goto cp0_unimplemented;
7069 }
7070 break;
7071 case CP0_REGISTER_09:
7072 switch (sel) {
7073 case 0:
7074 /* Mark as an IO operation because we read the time. */
7075 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7076 gen_io_start();
7077 }
7078 gen_helper_mfc0_count(arg, cpu_env);
7079 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7080 gen_io_end();
7081 }
7082 /* Break the TB to be able to take timer interrupts immediately
7083 after reading count. DISAS_STOP isn't sufficient, we need to
7084 ensure we break completely out of translated code. */
7085 gen_save_pc(ctx->base.pc_next + 4);
7086 ctx->base.is_jmp = DISAS_EXIT;
7087 register_name = "Count";
7088 break;
7089 case 6:
7090 CP0_CHECK(ctx->saar);
7091 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
7092 register_name = "SAARI";
7093 break;
7094 case 7:
7095 CP0_CHECK(ctx->saar);
7096 gen_helper_mfc0_saar(arg, cpu_env);
7097 register_name = "SAAR";
7098 break;
7099 default:
7100 goto cp0_unimplemented;
7101 }
7102 break;
7103 case CP0_REGISTER_10:
7104 switch (sel) {
7105 case 0:
7106 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
7107 tcg_gen_ext32s_tl(arg, arg);
7108 register_name = "EntryHi";
7109 break;
7110 default:
7111 goto cp0_unimplemented;
7112 }
7113 break;
7114 case CP0_REGISTER_11:
7115 switch (sel) {
7116 case 0:
7117 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
7118 register_name = "Compare";
7119 break;
7120 /* 6,7 are implementation dependent */
7121 default:
7122 goto cp0_unimplemented;
7123 }
7124 break;
7125 case CP0_REGISTER_12:
7126 switch (sel) {
7127 case 0:
7128 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
7129 register_name = "Status";
7130 break;
7131 case 1:
7132 check_insn(ctx, ISA_MIPS32R2);
7133 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
7134 register_name = "IntCtl";
7135 break;
7136 case 2:
7137 check_insn(ctx, ISA_MIPS32R2);
7138 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
7139 register_name = "SRSCtl";
7140 break;
7141 case 3:
7142 check_insn(ctx, ISA_MIPS32R2);
7143 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7144 register_name = "SRSMap";
7145 break;
7146 default:
7147 goto cp0_unimplemented;
7148 }
7149 break;
7150 case CP0_REGISTER_13:
7151 switch (sel) {
7152 case 0:
7153 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
7154 register_name = "Cause";
7155 break;
7156 default:
7157 goto cp0_unimplemented;
7158 }
7159 break;
7160 case CP0_REGISTER_14:
7161 switch (sel) {
7162 case 0:
7163 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7164 tcg_gen_ext32s_tl(arg, arg);
7165 register_name = "EPC";
7166 break;
7167 default:
7168 goto cp0_unimplemented;
7169 }
7170 break;
7171 case CP0_REGISTER_15:
7172 switch (sel) {
7173 case 0:
7174 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
7175 register_name = "PRid";
7176 break;
7177 case 1:
7178 check_insn(ctx, ISA_MIPS32R2);
7179 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7180 tcg_gen_ext32s_tl(arg, arg);
7181 register_name = "EBase";
7182 break;
7183 case 3:
7184 check_insn(ctx, ISA_MIPS32R2);
7185 CP0_CHECK(ctx->cmgcr);
7186 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7187 tcg_gen_ext32s_tl(arg, arg);
7188 register_name = "CMGCRBase";
7189 break;
7190 default:
7191 goto cp0_unimplemented;
7192 }
7193 break;
7194 case CP0_REGISTER_16:
7195 switch (sel) {
7196 case 0:
7197 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
7198 register_name = "Config";
7199 break;
7200 case 1:
7201 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
7202 register_name = "Config1";
7203 break;
7204 case 2:
7205 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7206 register_name = "Config2";
7207 break;
7208 case 3:
7209 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7210 register_name = "Config3";
7211 break;
7212 case 4:
7213 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7214 register_name = "Config4";
7215 break;
7216 case 5:
7217 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7218 register_name = "Config5";
7219 break;
7220 /* 6,7 are implementation dependent */
7221 case 6:
7222 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
7223 register_name = "Config6";
7224 break;
7225 case 7:
7226 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
7227 register_name = "Config7";
7228 break;
7229 default:
7230 goto cp0_unimplemented;
7231 }
7232 break;
7233 case CP0_REGISTER_17:
7234 switch (sel) {
7235 case 0:
7236 gen_helper_mfc0_lladdr(arg, cpu_env);
7237 register_name = "LLAddr";
7238 break;
7239 case 1:
7240 CP0_CHECK(ctx->mrp);
7241 gen_helper_mfc0_maar(arg, cpu_env);
7242 register_name = "MAAR";
7243 break;
7244 case 2:
7245 CP0_CHECK(ctx->mrp);
7246 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7247 register_name = "MAARI";
7248 break;
7249 default:
7250 goto cp0_unimplemented;
7251 }
7252 break;
7253 case CP0_REGISTER_18:
7254 switch (sel) {
7255 case 0:
7256 case 1:
7257 case 2:
7258 case 3:
7259 case 4:
7260 case 5:
7261 case 6:
7262 case 7:
7263 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7264 gen_helper_1e0i(mfc0_watchlo, arg, sel);
7265 register_name = "WatchLo";
7266 break;
7267 default:
7268 goto cp0_unimplemented;
7269 }
7270 break;
7271 case CP0_REGISTER_19:
7272 switch (sel) {
7273 case 0:
7274 case 1:
7275 case 2:
7276 case 3:
7277 case 4:
7278 case 5:
7279 case 6:
7280 case 7:
7281 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7282 gen_helper_1e0i(mfc0_watchhi, arg, sel);
7283 register_name = "WatchHi";
7284 break;
7285 default:
7286 goto cp0_unimplemented;
7287 }
7288 break;
7289 case CP0_REGISTER_20:
7290 switch (sel) {
7291 case 0:
7292 #if defined(TARGET_MIPS64)
7293 check_insn(ctx, ISA_MIPS3);
7294 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
7295 tcg_gen_ext32s_tl(arg, arg);
7296 register_name = "XContext";
7297 break;
7298 #endif
7299 default:
7300 goto cp0_unimplemented;
7301 }
7302 break;
7303 case CP0_REGISTER_21:
7304 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7305 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7306 switch (sel) {
7307 case 0:
7308 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
7309 register_name = "Framemask";
7310 break;
7311 default:
7312 goto cp0_unimplemented;
7313 }
7314 break;
7315 case CP0_REGISTER_22:
7316 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7317 register_name = "'Diagnostic"; /* implementation dependent */
7318 break;
7319 case CP0_REGISTER_23:
7320 switch (sel) {
7321 case 0:
7322 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
7323 register_name = "Debug";
7324 break;
7325 case 1:
7326 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
7327 register_name = "TraceControl";
7328 goto cp0_unimplemented;
7329 case 2:
7330 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
7331 register_name = "TraceControl2";
7332 goto cp0_unimplemented;
7333 case 3:
7334 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
7335 register_name = "UserTraceData";
7336 goto cp0_unimplemented;
7337 case 4:
7338 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
7339 register_name = "TraceBPC";
7340 goto cp0_unimplemented;
7341 default:
7342 goto cp0_unimplemented;
7343 }
7344 break;
7345 case CP0_REGISTER_24:
7346 switch (sel) {
7347 case 0:
7348 /* EJTAG support */
7349 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7350 tcg_gen_ext32s_tl(arg, arg);
7351 register_name = "DEPC";
7352 break;
7353 default:
7354 goto cp0_unimplemented;
7355 }
7356 break;
7357 case CP0_REGISTER_25:
7358 switch (sel) {
7359 case 0:
7360 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
7361 register_name = "Performance0";
7362 break;
7363 case 1:
7364 // gen_helper_mfc0_performance1(arg);
7365 register_name = "Performance1";
7366 goto cp0_unimplemented;
7367 case 2:
7368 // gen_helper_mfc0_performance2(arg);
7369 register_name = "Performance2";
7370 goto cp0_unimplemented;
7371 case 3:
7372 // gen_helper_mfc0_performance3(arg);
7373 register_name = "Performance3";
7374 goto cp0_unimplemented;
7375 case 4:
7376 // gen_helper_mfc0_performance4(arg);
7377 register_name = "Performance4";
7378 goto cp0_unimplemented;
7379 case 5:
7380 // gen_helper_mfc0_performance5(arg);
7381 register_name = "Performance5";
7382 goto cp0_unimplemented;
7383 case 6:
7384 // gen_helper_mfc0_performance6(arg);
7385 register_name = "Performance6";
7386 goto cp0_unimplemented;
7387 case 7:
7388 // gen_helper_mfc0_performance7(arg);
7389 register_name = "Performance7";
7390 goto cp0_unimplemented;
7391 default:
7392 goto cp0_unimplemented;
7393 }
7394 break;
7395 case CP0_REGISTER_26:
7396 switch (sel) {
7397 case 0:
7398 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7399 register_name = "ErrCtl";
7400 break;
7401 default:
7402 goto cp0_unimplemented;
7403 }
7404 break;
7405 case CP0_REGISTER_27:
7406 switch (sel) {
7407 case 0:
7408 case 1:
7409 case 2:
7410 case 3:
7411 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7412 register_name = "CacheErr";
7413 break;
7414 default:
7415 goto cp0_unimplemented;
7416 }
7417 break;
7418 case CP0_REGISTER_28:
7419 switch (sel) {
7420 case 0:
7421 case 2:
7422 case 4:
7423 case 6:
7424 {
7425 TCGv_i64 tmp = tcg_temp_new_i64();
7426 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
7427 gen_move_low32(arg, tmp);
7428 tcg_temp_free_i64(tmp);
7429 }
7430 register_name = "TagLo";
7431 break;
7432 case 1:
7433 case 3:
7434 case 5:
7435 case 7:
7436 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7437 register_name = "DataLo";
7438 break;
7439 default:
7440 goto cp0_unimplemented;
7441 }
7442 break;
7443 case CP0_REGISTER_29:
7444 switch (sel) {
7445 case 0:
7446 case 2:
7447 case 4:
7448 case 6:
7449 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7450 register_name = "TagHi";
7451 break;
7452 case 1:
7453 case 3:
7454 case 5:
7455 case 7:
7456 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7457 register_name = "DataHi";
7458 break;
7459 default:
7460 goto cp0_unimplemented;
7461 }
7462 break;
7463 case CP0_REGISTER_30:
7464 switch (sel) {
7465 case 0:
7466 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7467 tcg_gen_ext32s_tl(arg, arg);
7468 register_name = "ErrorEPC";
7469 break;
7470 default:
7471 goto cp0_unimplemented;
7472 }
7473 break;
7474 case CP0_REGISTER_31:
7475 switch (sel) {
7476 case 0:
7477 /* EJTAG support */
7478 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7479 register_name = "DESAVE";
7480 break;
7481 case 2:
7482 case 3:
7483 case 4:
7484 case 5:
7485 case 6:
7486 case 7:
7487 CP0_CHECK(ctx->kscrexist & (1 << sel));
7488 tcg_gen_ld_tl(arg, cpu_env,
7489 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7490 tcg_gen_ext32s_tl(arg, arg);
7491 register_name = "KScratch";
7492 break;
7493 default:
7494 goto cp0_unimplemented;
7495 }
7496 break;
7497 default:
7498 goto cp0_unimplemented;
7499 }
7500 trace_mips_translate_c0("mfc0", register_name, reg, sel);
7501 return;
7502
7503 cp0_unimplemented:
7504 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
7505 register_name, reg, sel);
7506 gen_mfc0_unimplemented(ctx, arg);
7507 }
7508
7509 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7510 {
7511 const char *register_name = "invalid";
7512
7513 if (sel != 0) {
7514 check_insn(ctx, ISA_MIPS32);
7515 }
7516
7517 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7518 gen_io_start();
7519 }
7520
7521 switch (reg) {
7522 case CP0_REGISTER_00:
7523 switch (sel) {
7524 case 0:
7525 gen_helper_mtc0_index(cpu_env, arg);
7526 register_name = "Index";
7527 break;
7528 case 1:
7529 CP0_CHECK(ctx->insn_flags & ASE_MT);
7530 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7531 register_name = "MVPControl";
7532 break;
7533 case 2:
7534 CP0_CHECK(ctx->insn_flags & ASE_MT);
7535 /* ignored */
7536 register_name = "MVPConf0";
7537 break;
7538 case 3:
7539 CP0_CHECK(ctx->insn_flags & ASE_MT);
7540 /* ignored */
7541 register_name = "MVPConf1";
7542 break;
7543 case 4:
7544 CP0_CHECK(ctx->vp);
7545 /* ignored */
7546 register_name = "VPControl";
7547 break;
7548 default:
7549 goto cp0_unimplemented;
7550 }
7551 break;
7552 case CP0_REGISTER_01:
7553 switch (sel) {
7554 case 0:
7555 /* ignored */
7556 register_name = "Random";
7557 break;
7558 case 1:
7559 CP0_CHECK(ctx->insn_flags & ASE_MT);
7560 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7561 register_name = "VPEControl";
7562 break;
7563 case 2:
7564 CP0_CHECK(ctx->insn_flags & ASE_MT);
7565 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7566 register_name = "VPEConf0";
7567 break;
7568 case 3:
7569 CP0_CHECK(ctx->insn_flags & ASE_MT);
7570 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7571 register_name = "VPEConf1";
7572 break;
7573 case 4:
7574 CP0_CHECK(ctx->insn_flags & ASE_MT);
7575 gen_helper_mtc0_yqmask(cpu_env, arg);
7576 register_name = "YQMask";
7577 break;
7578 case 5:
7579 CP0_CHECK(ctx->insn_flags & ASE_MT);
7580 tcg_gen_st_tl(arg, cpu_env,
7581 offsetof(CPUMIPSState, CP0_VPESchedule));
7582 register_name = "VPESchedule";
7583 break;
7584 case 6:
7585 CP0_CHECK(ctx->insn_flags & ASE_MT);
7586 tcg_gen_st_tl(arg, cpu_env,
7587 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7588 register_name = "VPEScheFBack";
7589 break;
7590 case 7:
7591 CP0_CHECK(ctx->insn_flags & ASE_MT);
7592 gen_helper_mtc0_vpeopt(cpu_env, arg);
7593 register_name = "VPEOpt";
7594 break;
7595 default:
7596 goto cp0_unimplemented;
7597 }
7598 break;
7599 case CP0_REGISTER_02:
7600 switch (sel) {
7601 case 0:
7602 gen_helper_mtc0_entrylo0(cpu_env, arg);
7603 register_name = "EntryLo0";
7604 break;
7605 case 1:
7606 CP0_CHECK(ctx->insn_flags & ASE_MT);
7607 gen_helper_mtc0_tcstatus(cpu_env, arg);
7608 register_name = "TCStatus";
7609 break;
7610 case 2:
7611 CP0_CHECK(ctx->insn_flags & ASE_MT);
7612 gen_helper_mtc0_tcbind(cpu_env, arg);
7613 register_name = "TCBind";
7614 break;
7615 case 3:
7616 CP0_CHECK(ctx->insn_flags & ASE_MT);
7617 gen_helper_mtc0_tcrestart(cpu_env, arg);
7618 register_name = "TCRestart";
7619 break;
7620 case 4:
7621 CP0_CHECK(ctx->insn_flags & ASE_MT);
7622 gen_helper_mtc0_tchalt(cpu_env, arg);
7623 register_name = "TCHalt";
7624 break;
7625 case 5:
7626 CP0_CHECK(ctx->insn_flags & ASE_MT);
7627 gen_helper_mtc0_tccontext(cpu_env, arg);
7628 register_name = "TCContext";
7629 break;
7630 case 6:
7631 CP0_CHECK(ctx->insn_flags & ASE_MT);
7632 gen_helper_mtc0_tcschedule(cpu_env, arg);
7633 register_name = "TCSchedule";
7634 break;
7635 case 7:
7636 CP0_CHECK(ctx->insn_flags & ASE_MT);
7637 gen_helper_mtc0_tcschefback(cpu_env, arg);
7638 register_name = "TCScheFBack";
7639 break;
7640 default:
7641 goto cp0_unimplemented;
7642 }
7643 break;
7644 case CP0_REGISTER_03:
7645 switch (sel) {
7646 case 0:
7647 gen_helper_mtc0_entrylo1(cpu_env, arg);
7648 register_name = "EntryLo1";
7649 break;
7650 case 1:
7651 CP0_CHECK(ctx->vp);
7652 /* ignored */
7653 register_name = "GlobalNumber";
7654 break;
7655 default:
7656 goto cp0_unimplemented;
7657 }
7658 break;
7659 case CP0_REGISTER_04:
7660 switch (sel) {
7661 case 0:
7662 gen_helper_mtc0_context(cpu_env, arg);
7663 register_name = "Context";
7664 break;
7665 case 1:
7666 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
7667 register_name = "ContextConfig";
7668 goto cp0_unimplemented;
7669 case 2:
7670 CP0_CHECK(ctx->ulri);
7671 tcg_gen_st_tl(arg, cpu_env,
7672 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7673 register_name = "UserLocal";
7674 break;
7675 default:
7676 goto cp0_unimplemented;
7677 }
7678 break;
7679 case CP0_REGISTER_05:
7680 switch (sel) {
7681 case 0:
7682 gen_helper_mtc0_pagemask(cpu_env, arg);
7683 register_name = "PageMask";
7684 break;
7685 case 1:
7686 check_insn(ctx, ISA_MIPS32R2);
7687 gen_helper_mtc0_pagegrain(cpu_env, arg);
7688 register_name = "PageGrain";
7689 ctx->base.is_jmp = DISAS_STOP;
7690 break;
7691 case 2:
7692 CP0_CHECK(ctx->sc);
7693 gen_helper_mtc0_segctl0(cpu_env, arg);
7694 register_name = "SegCtl0";
7695 break;
7696 case 3:
7697 CP0_CHECK(ctx->sc);
7698 gen_helper_mtc0_segctl1(cpu_env, arg);
7699 register_name = "SegCtl1";
7700 break;
7701 case 4:
7702 CP0_CHECK(ctx->sc);
7703 gen_helper_mtc0_segctl2(cpu_env, arg);
7704 register_name = "SegCtl2";
7705 break;
7706 case 5:
7707 check_pw(ctx);
7708 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7709 register_name = "PWBase";
7710 break;
7711 case 6:
7712 check_pw(ctx);
7713 gen_helper_mtc0_pwfield(cpu_env, arg);
7714 register_name = "PWField";
7715 break;
7716 case 7:
7717 check_pw(ctx);
7718 gen_helper_mtc0_pwsize(cpu_env, arg);
7719 register_name = "PWSize";
7720 break;
7721 default:
7722 goto cp0_unimplemented;
7723 }
7724 break;
7725 case CP0_REGISTER_06:
7726 switch (sel) {
7727 case 0:
7728 gen_helper_mtc0_wired(cpu_env, arg);
7729 register_name = "Wired";
7730 break;
7731 case 1:
7732 check_insn(ctx, ISA_MIPS32R2);
7733 gen_helper_mtc0_srsconf0(cpu_env, arg);
7734 register_name = "SRSConf0";
7735 break;
7736 case 2:
7737 check_insn(ctx, ISA_MIPS32R2);
7738 gen_helper_mtc0_srsconf1(cpu_env, arg);
7739 register_name = "SRSConf1";
7740 break;
7741 case 3:
7742 check_insn(ctx, ISA_MIPS32R2);
7743 gen_helper_mtc0_srsconf2(cpu_env, arg);
7744 register_name = "SRSConf2";
7745 break;
7746 case 4:
7747 check_insn(ctx, ISA_MIPS32R2);
7748 gen_helper_mtc0_srsconf3(cpu_env, arg);
7749 register_name = "SRSConf3";
7750 break;
7751 case 5:
7752 check_insn(ctx, ISA_MIPS32R2);
7753 gen_helper_mtc0_srsconf4(cpu_env, arg);
7754 register_name = "SRSConf4";
7755 break;
7756 case 6:
7757 check_pw(ctx);
7758 gen_helper_mtc0_pwctl(cpu_env, arg);
7759 register_name = "PWCtl";
7760 break;
7761 default:
7762 goto cp0_unimplemented;
7763 }
7764 break;
7765 case CP0_REGISTER_07:
7766 switch (sel) {
7767 case 0:
7768 check_insn(ctx, ISA_MIPS32R2);
7769 gen_helper_mtc0_hwrena(cpu_env, arg);
7770 ctx->base.is_jmp = DISAS_STOP;
7771 register_name = "HWREna";
7772 break;
7773 default:
7774 goto cp0_unimplemented;
7775 }
7776 break;
7777 case CP0_REGISTER_08:
7778 switch (sel) {
7779 case 0:
7780 /* ignored */
7781 register_name = "BadVAddr";
7782 break;
7783 case 1:
7784 /* ignored */
7785 register_name = "BadInstr";
7786 break;
7787 case 2:
7788 /* ignored */
7789 register_name = "BadInstrP";
7790 break;
7791 case 3:
7792 /* ignored */
7793 register_name = "BadInstrX";
7794 break;
7795 default:
7796 goto cp0_unimplemented;
7797 }
7798 break;
7799 case CP0_REGISTER_09:
7800 switch (sel) {
7801 case 0:
7802 gen_helper_mtc0_count(cpu_env, arg);
7803 register_name = "Count";
7804 break;
7805 case 6:
7806 CP0_CHECK(ctx->saar);
7807 gen_helper_mtc0_saari(cpu_env, arg);
7808 register_name = "SAARI";
7809 break;
7810 case 7:
7811 CP0_CHECK(ctx->saar);
7812 gen_helper_mtc0_saar(cpu_env, arg);
7813 register_name = "SAAR";
7814 break;
7815 default:
7816 goto cp0_unimplemented;
7817 }
7818 break;
7819 case CP0_REGISTER_10:
7820 switch (sel) {
7821 case 0:
7822 gen_helper_mtc0_entryhi(cpu_env, arg);
7823 register_name = "EntryHi";
7824 break;
7825 default:
7826 goto cp0_unimplemented;
7827 }
7828 break;
7829 case CP0_REGISTER_11:
7830 switch (sel) {
7831 case 0:
7832 gen_helper_mtc0_compare(cpu_env, arg);
7833 register_name = "Compare";
7834 break;
7835 /* 6,7 are implementation dependent */
7836 default:
7837 goto cp0_unimplemented;
7838 }
7839 break;
7840 case CP0_REGISTER_12:
7841 switch (sel) {
7842 case 0:
7843 save_cpu_state(ctx, 1);
7844 gen_helper_mtc0_status(cpu_env, arg);
7845 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7846 gen_save_pc(ctx->base.pc_next + 4);
7847 ctx->base.is_jmp = DISAS_EXIT;
7848 register_name = "Status";
7849 break;
7850 case 1:
7851 check_insn(ctx, ISA_MIPS32R2);
7852 gen_helper_mtc0_intctl(cpu_env, arg);
7853 /* Stop translation as we may have switched the execution mode */
7854 ctx->base.is_jmp = DISAS_STOP;
7855 register_name = "IntCtl";
7856 break;
7857 case 2:
7858 check_insn(ctx, ISA_MIPS32R2);
7859 gen_helper_mtc0_srsctl(cpu_env, arg);
7860 /* Stop translation as we may have switched the execution mode */
7861 ctx->base.is_jmp = DISAS_STOP;
7862 register_name = "SRSCtl";
7863 break;
7864 case 3:
7865 check_insn(ctx, ISA_MIPS32R2);
7866 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7867 /* Stop translation as we may have switched the execution mode */
7868 ctx->base.is_jmp = DISAS_STOP;
7869 register_name = "SRSMap";
7870 break;
7871 default:
7872 goto cp0_unimplemented;
7873 }
7874 break;
7875 case CP0_REGISTER_13:
7876 switch (sel) {
7877 case 0:
7878 save_cpu_state(ctx, 1);
7879 gen_helper_mtc0_cause(cpu_env, arg);
7880 /* Stop translation as we may have triggered an interrupt.
7881 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7882 * translated code to check for pending interrupts. */
7883 gen_save_pc(ctx->base.pc_next + 4);
7884 ctx->base.is_jmp = DISAS_EXIT;
7885 register_name = "Cause";
7886 break;
7887 default:
7888 goto cp0_unimplemented;
7889 }
7890 break;
7891 case CP0_REGISTER_14:
7892 switch (sel) {
7893 case 0:
7894 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7895 register_name = "EPC";
7896 break;
7897 default:
7898 goto cp0_unimplemented;
7899 }
7900 break;
7901 case CP0_REGISTER_15:
7902 switch (sel) {
7903 case 0:
7904 /* ignored */
7905 register_name = "PRid";
7906 break;
7907 case 1:
7908 check_insn(ctx, ISA_MIPS32R2);
7909 gen_helper_mtc0_ebase(cpu_env, arg);
7910 register_name = "EBase";
7911 break;
7912 default:
7913 goto cp0_unimplemented;
7914 }
7915 break;
7916 case CP0_REGISTER_16:
7917 switch (sel) {
7918 case 0:
7919 gen_helper_mtc0_config0(cpu_env, arg);
7920 register_name = "Config";
7921 /* Stop translation as we may have switched the execution mode */
7922 ctx->base.is_jmp = DISAS_STOP;
7923 break;
7924 case 1:
7925 /* ignored, read only */
7926 register_name = "Config1";
7927 break;
7928 case 2:
7929 gen_helper_mtc0_config2(cpu_env, arg);
7930 register_name = "Config2";
7931 /* Stop translation as we may have switched the execution mode */
7932 ctx->base.is_jmp = DISAS_STOP;
7933 break;
7934 case 3:
7935 gen_helper_mtc0_config3(cpu_env, arg);
7936 register_name = "Config3";
7937 /* Stop translation as we may have switched the execution mode */
7938 ctx->base.is_jmp = DISAS_STOP;
7939 break;
7940 case 4:
7941 gen_helper_mtc0_config4(cpu_env, arg);
7942 register_name = "Config4";
7943 ctx->base.is_jmp = DISAS_STOP;
7944 break;
7945 case 5:
7946 gen_helper_mtc0_config5(cpu_env, arg);
7947 register_name = "Config5";
7948 /* Stop translation as we may have switched the execution mode */
7949 ctx->base.is_jmp = DISAS_STOP;
7950 break;
7951 /* 6,7 are implementation dependent */
7952 case 6:
7953 /* ignored */
7954 register_name = "Config6";
7955 break;
7956 case 7:
7957 /* ignored */
7958 register_name = "Config7";
7959 break;
7960 default:
7961 register_name = "Invalid config selector";
7962 goto cp0_unimplemented;
7963 }
7964 break;
7965 case CP0_REGISTER_17:
7966 switch (sel) {
7967 case 0:
7968 gen_helper_mtc0_lladdr(cpu_env, arg);
7969 register_name = "LLAddr";
7970 break;
7971 case 1:
7972 CP0_CHECK(ctx->mrp);
7973 gen_helper_mtc0_maar(cpu_env, arg);
7974 register_name = "MAAR";
7975 break;
7976 case 2:
7977 CP0_CHECK(ctx->mrp);
7978 gen_helper_mtc0_maari(cpu_env, arg);
7979 register_name = "MAARI";
7980 break;
7981 default:
7982 goto cp0_unimplemented;
7983 }
7984 break;
7985 case CP0_REGISTER_18:
7986 switch (sel) {
7987 case 0:
7988 case 1:
7989 case 2:
7990 case 3:
7991 case 4:
7992 case 5:
7993 case 6:
7994 case 7:
7995 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7996 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7997 register_name = "WatchLo";
7998 break;
7999 default:
8000 goto cp0_unimplemented;
8001 }
8002 break;
8003 case CP0_REGISTER_19:
8004 switch (sel) {
8005 case 0:
8006 case 1:
8007 case 2:
8008 case 3:
8009 case 4:
8010 case 5:
8011 case 6:
8012 case 7:
8013 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8014 gen_helper_0e1i(mtc0_watchhi, arg, sel);
8015 register_name = "WatchHi";
8016 break;
8017 default:
8018 goto cp0_unimplemented;
8019 }
8020 break;
8021 case CP0_REGISTER_20:
8022 switch (sel) {
8023 case 0:
8024 #if defined(TARGET_MIPS64)
8025 check_insn(ctx, ISA_MIPS3);
8026 gen_helper_mtc0_xcontext(cpu_env, arg);
8027 register_name = "XContext";
8028 break;
8029 #endif
8030 default:
8031 goto cp0_unimplemented;
8032 }
8033 break;
8034 case CP0_REGISTER_21:
8035 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8036 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8037 switch (sel) {
8038 case 0:
8039 gen_helper_mtc0_framemask(cpu_env, arg);
8040 register_name = "Framemask";
8041 break;
8042 default:
8043 goto cp0_unimplemented;
8044 }
8045 break;
8046 case CP0_REGISTER_22:
8047 /* ignored */
8048 register_name = "Diagnostic"; /* implementation dependent */
8049 break;
8050 case CP0_REGISTER_23:
8051 switch (sel) {
8052 case 0:
8053 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8054 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8055 gen_save_pc(ctx->base.pc_next + 4);
8056 ctx->base.is_jmp = DISAS_EXIT;
8057 register_name = "Debug";
8058 break;
8059 case 1:
8060 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
8061 register_name = "TraceControl";
8062 /* Stop translation as we may have switched the execution mode */
8063 ctx->base.is_jmp = DISAS_STOP;
8064 goto cp0_unimplemented;
8065 case 2:
8066 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
8067 register_name = "TraceControl2";
8068 /* Stop translation as we may have switched the execution mode */
8069 ctx->base.is_jmp = DISAS_STOP;
8070 goto cp0_unimplemented;
8071 case 3:
8072 /* Stop translation as we may have switched the execution mode */
8073 ctx->base.is_jmp = DISAS_STOP;
8074 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
8075 register_name = "UserTraceData";
8076 /* Stop translation as we may have switched the execution mode */
8077 ctx->base.is_jmp = DISAS_STOP;
8078 goto cp0_unimplemented;
8079 case 4:
8080 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
8081 /* Stop translation as we may have switched the execution mode */
8082 ctx->base.is_jmp = DISAS_STOP;
8083 register_name = "TraceBPC";
8084 goto cp0_unimplemented;
8085 default:
8086 goto cp0_unimplemented;
8087 }
8088 break;
8089 case CP0_REGISTER_24:
8090 switch (sel) {
8091 case 0:
8092 /* EJTAG support */
8093 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8094 register_name = "DEPC";
8095 break;
8096 default:
8097 goto cp0_unimplemented;
8098 }
8099 break;
8100 case CP0_REGISTER_25:
8101 switch (sel) {
8102 case 0:
8103 gen_helper_mtc0_performance0(cpu_env, arg);
8104 register_name = "Performance0";
8105 break;
8106 case 1:
8107 // gen_helper_mtc0_performance1(arg);
8108 register_name = "Performance1";
8109 goto cp0_unimplemented;
8110 case 2:
8111 // gen_helper_mtc0_performance2(arg);
8112 register_name = "Performance2";
8113 goto cp0_unimplemented;
8114 case 3:
8115 // gen_helper_mtc0_performance3(arg);
8116 register_name = "Performance3";
8117 goto cp0_unimplemented;
8118 case 4:
8119 // gen_helper_mtc0_performance4(arg);
8120 register_name = "Performance4";
8121 goto cp0_unimplemented;
8122 case 5:
8123 // gen_helper_mtc0_performance5(arg);
8124 register_name = "Performance5";
8125 goto cp0_unimplemented;
8126 case 6:
8127 // gen_helper_mtc0_performance6(arg);
8128 register_name = "Performance6";
8129 goto cp0_unimplemented;
8130 case 7:
8131 // gen_helper_mtc0_performance7(arg);
8132 register_name = "Performance7";
8133 goto cp0_unimplemented;
8134 default:
8135 goto cp0_unimplemented;
8136 }
8137 break;
8138 case CP0_REGISTER_26:
8139 switch (sel) {
8140 case 0:
8141 gen_helper_mtc0_errctl(cpu_env, arg);
8142 ctx->base.is_jmp = DISAS_STOP;
8143 register_name = "ErrCtl";
8144 break;
8145 default:
8146 goto cp0_unimplemented;
8147 }
8148 break;
8149 case CP0_REGISTER_27:
8150 switch (sel) {
8151 case 0:
8152 case 1:
8153 case 2:
8154 case 3:
8155 /* ignored */
8156 register_name = "CacheErr";
8157 break;
8158 default:
8159 goto cp0_unimplemented;
8160 }
8161 break;
8162 case CP0_REGISTER_28:
8163 switch (sel) {
8164 case 0:
8165 case 2:
8166 case 4:
8167 case 6:
8168 gen_helper_mtc0_taglo(cpu_env, arg);
8169 register_name = "TagLo";
8170 break;
8171 case 1:
8172 case 3:
8173 case 5:
8174 case 7:
8175 gen_helper_mtc0_datalo(cpu_env, arg);
8176 register_name = "DataLo";
8177 break;
8178 default:
8179 goto cp0_unimplemented;
8180 }
8181 break;
8182 case CP0_REGISTER_29:
8183 switch (sel) {
8184 case 0:
8185 case 2:
8186 case 4:
8187 case 6:
8188 gen_helper_mtc0_taghi(cpu_env, arg);
8189 register_name = "TagHi";
8190 break;
8191 case 1:
8192 case 3:
8193 case 5:
8194 case 7:
8195 gen_helper_mtc0_datahi(cpu_env, arg);
8196 register_name = "DataHi";
8197 break;
8198 default:
8199 register_name = "invalid sel";
8200 goto cp0_unimplemented;
8201 }
8202 break;
8203 case CP0_REGISTER_30:
8204 switch (sel) {
8205 case 0:
8206 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8207 register_name = "ErrorEPC";
8208 break;
8209 default:
8210 goto cp0_unimplemented;
8211 }
8212 break;
8213 case CP0_REGISTER_31:
8214 switch (sel) {
8215 case 0:
8216 /* EJTAG support */
8217 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8218 register_name = "DESAVE";
8219 break;
8220 case 2:
8221 case 3:
8222 case 4:
8223 case 5:
8224 case 6:
8225 case 7:
8226 CP0_CHECK(ctx->kscrexist & (1 << sel));
8227 tcg_gen_st_tl(arg, cpu_env,
8228 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
8229 register_name = "KScratch";
8230 break;
8231 default:
8232 goto cp0_unimplemented;
8233 }
8234 break;
8235 default:
8236 goto cp0_unimplemented;
8237 }
8238 trace_mips_translate_c0("mtc0", register_name, reg, sel);
8239
8240 /* For simplicity assume that all writes can cause interrupts. */
8241 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8242 gen_io_end();
8243 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
8244 * translated code to check for pending interrupts. */
8245 gen_save_pc(ctx->base.pc_next + 4);
8246 ctx->base.is_jmp = DISAS_EXIT;
8247 }
8248 return;
8249
8250 cp0_unimplemented:
8251 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
8252 register_name, reg, sel);
8253 }
8254
8255 #if defined(TARGET_MIPS64)
8256 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8257 {
8258 const char *register_name = "invalid";
8259
8260 if (sel != 0) {
8261 check_insn(ctx, ISA_MIPS64);
8262 }
8263
8264 switch (reg) {
8265 case CP0_REGISTER_00:
8266 switch (sel) {
8267 case 0:
8268 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
8269 register_name = "Index";
8270 break;
8271 case 1:
8272 CP0_CHECK(ctx->insn_flags & ASE_MT);
8273 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
8274 register_name = "MVPControl";
8275 break;
8276 case 2:
8277 CP0_CHECK(ctx->insn_flags & ASE_MT);
8278 gen_helper_mfc0_mvpconf0(arg, cpu_env);
8279 register_name = "MVPConf0";
8280 break;
8281 case 3:
8282 CP0_CHECK(ctx->insn_flags & ASE_MT);
8283 gen_helper_mfc0_mvpconf1(arg, cpu_env);
8284 register_name = "MVPConf1";
8285 break;
8286 case 4:
8287 CP0_CHECK(ctx->vp);
8288 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
8289 register_name = "VPControl";
8290 break;
8291 default:
8292 goto cp0_unimplemented;
8293 }
8294 break;
8295 case CP0_REGISTER_01:
8296 switch (sel) {
8297 case 0:
8298 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8299 gen_helper_mfc0_random(arg, cpu_env);
8300 register_name = "Random";
8301 break;
8302 case 1:
8303 CP0_CHECK(ctx->insn_flags & ASE_MT);
8304 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
8305 register_name = "VPEControl";
8306 break;
8307 case 2:
8308 CP0_CHECK(ctx->insn_flags & ASE_MT);
8309 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
8310 register_name = "VPEConf0";
8311 break;
8312 case 3:
8313 CP0_CHECK(ctx->insn_flags & ASE_MT);
8314 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
8315 register_name = "VPEConf1";
8316 break;
8317 case 4:
8318 CP0_CHECK(ctx->insn_flags & ASE_MT);
8319 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
8320 register_name = "YQMask";
8321 break;
8322 case 5:
8323 CP0_CHECK(ctx->insn_flags & ASE_MT);
8324 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
8325 register_name = "VPESchedule";
8326 break;
8327 case 6:
8328 CP0_CHECK(ctx->insn_flags & ASE_MT);
8329 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
8330 register_name = "VPEScheFBack";
8331 break;
8332 case 7:
8333 CP0_CHECK(ctx->insn_flags & ASE_MT);
8334 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
8335 register_name = "VPEOpt";
8336 break;
8337 default:
8338 goto cp0_unimplemented;
8339 }
8340 break;
8341 case CP0_REGISTER_02:
8342 switch (sel) {
8343 case 0:
8344 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
8345 register_name = "EntryLo0";
8346 break;
8347 case 1:
8348 CP0_CHECK(ctx->insn_flags & ASE_MT);
8349 gen_helper_mfc0_tcstatus(arg, cpu_env);
8350 register_name = "TCStatus";
8351 break;
8352 case 2:
8353 CP0_CHECK(ctx->insn_flags & ASE_MT);
8354 gen_helper_mfc0_tcbind(arg, cpu_env);
8355 register_name = "TCBind";
8356 break;
8357 case 3:
8358 CP0_CHECK(ctx->insn_flags & ASE_MT);
8359 gen_helper_dmfc0_tcrestart(arg, cpu_env);
8360 register_name = "TCRestart";
8361 break;
8362 case 4:
8363 CP0_CHECK(ctx->insn_flags & ASE_MT);
8364 gen_helper_dmfc0_tchalt(arg, cpu_env);
8365 register_name = "TCHalt";
8366 break;
8367 case 5:
8368 CP0_CHECK(ctx->insn_flags & ASE_MT);
8369 gen_helper_dmfc0_tccontext(arg, cpu_env);
8370 register_name = "TCContext";
8371 break;
8372 case 6:
8373 CP0_CHECK(ctx->insn_flags & ASE_MT);
8374 gen_helper_dmfc0_tcschedule(arg, cpu_env);
8375 register_name = "TCSchedule";
8376 break;
8377 case 7:
8378 CP0_CHECK(ctx->insn_flags & ASE_MT);
8379 gen_helper_dmfc0_tcschefback(arg, cpu_env);
8380 register_name = "TCScheFBack";
8381 break;
8382 default:
8383 goto cp0_unimplemented;
8384 }
8385 break;
8386 case CP0_REGISTER_03:
8387 switch (sel) {
8388 case 0:
8389 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
8390 register_name = "EntryLo1";
8391 break;
8392 case 1:
8393 CP0_CHECK(ctx->vp);
8394 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
8395 register_name = "GlobalNumber";
8396 break;
8397 default:
8398 goto cp0_unimplemented;
8399 }
8400 break;
8401 case CP0_REGISTER_04:
8402 switch (sel) {
8403 case 0:
8404 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
8405 register_name = "Context";
8406 break;
8407 case 1:
8408 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
8409 register_name = "ContextConfig";
8410 goto cp0_unimplemented;
8411 case 2:
8412 CP0_CHECK(ctx->ulri);
8413 tcg_gen_ld_tl(arg, cpu_env,
8414 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8415 register_name = "UserLocal";
8416 break;
8417 default:
8418 goto cp0_unimplemented;
8419 }
8420 break;
8421 case CP0_REGISTER_05:
8422 switch (sel) {
8423 case 0:
8424 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
8425 register_name = "PageMask";
8426 break;
8427 case 1:
8428 check_insn(ctx, ISA_MIPS32R2);
8429 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
8430 register_name = "PageGrain";
8431 break;
8432 case 2:
8433 CP0_CHECK(ctx->sc);
8434 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
8435 register_name = "SegCtl0";
8436 break;
8437 case 3:
8438 CP0_CHECK(ctx->sc);
8439 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
8440 register_name = "SegCtl1";
8441 break;
8442 case 4:
8443 CP0_CHECK(ctx->sc);
8444 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
8445 register_name = "SegCtl2";
8446 break;
8447 case 5:
8448 check_pw(ctx);
8449 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8450 register_name = "PWBase";
8451 break;
8452 case 6:
8453 check_pw(ctx);
8454 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
8455 register_name = "PWField";
8456 break;
8457 case 7:
8458 check_pw(ctx);
8459 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
8460 register_name = "PWSize";
8461 break;
8462 default:
8463 goto cp0_unimplemented;
8464 }
8465 break;
8466 case CP0_REGISTER_06:
8467 switch (sel) {
8468 case 0:
8469 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
8470 register_name = "Wired";
8471 break;
8472 case 1:
8473 check_insn(ctx, ISA_MIPS32R2);
8474 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
8475 register_name = "SRSConf0";
8476 break;
8477 case 2:
8478 check_insn(ctx, ISA_MIPS32R2);
8479 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
8480 register_name = "SRSConf1";
8481 break;
8482 case 3:
8483 check_insn(ctx, ISA_MIPS32R2);
8484 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
8485 register_name = "SRSConf2";
8486 break;
8487 case 4:
8488 check_insn(ctx, ISA_MIPS32R2);
8489 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
8490 register_name = "SRSConf3";
8491 break;
8492 case 5:
8493 check_insn(ctx, ISA_MIPS32R2);
8494 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
8495 register_name = "SRSConf4";
8496 break;
8497 case 6:
8498 check_pw(ctx);
8499 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
8500 register_name = "PWCtl";
8501 break;
8502 default:
8503 goto cp0_unimplemented;
8504 }
8505 break;
8506 case CP0_REGISTER_07:
8507 switch (sel) {
8508 case 0:
8509 check_insn(ctx, ISA_MIPS32R2);
8510 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
8511 register_name = "HWREna";
8512 break;
8513 default:
8514 goto cp0_unimplemented;
8515 }
8516 break;
8517 case CP0_REGISTER_08:
8518 switch (sel) {
8519 case 0:
8520 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
8521 register_name = "BadVAddr";
8522 break;
8523 case 1:
8524 CP0_CHECK(ctx->bi);
8525 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
8526 register_name = "BadInstr";
8527 break;
8528 case 2:
8529 CP0_CHECK(ctx->bp);
8530 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
8531 register_name = "BadInstrP";
8532 break;
8533 case 3:
8534 CP0_CHECK(ctx->bi);
8535 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
8536 tcg_gen_andi_tl(arg, arg, ~0xffff);
8537 register_name = "BadInstrX";
8538 break;
8539 default:
8540 goto cp0_unimplemented;
8541 }
8542 break;
8543 case CP0_REGISTER_09:
8544 switch (sel) {
8545 case 0:
8546 /* Mark as an IO operation because we read the time. */
8547 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8548 gen_io_start();
8549 }
8550 gen_helper_mfc0_count(arg, cpu_env);
8551 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8552 gen_io_end();
8553 }
8554 /* Break the TB to be able to take timer interrupts immediately
8555 after reading count. DISAS_STOP isn't sufficient, we need to
8556 ensure we break completely out of translated code. */
8557 gen_save_pc(ctx->base.pc_next + 4);
8558 ctx->base.is_jmp = DISAS_EXIT;
8559 register_name = "Count";
8560 break;
8561 case 6:
8562 CP0_CHECK(ctx->saar);
8563 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
8564 register_name = "SAARI";
8565 break;
8566 case 7:
8567 CP0_CHECK(ctx->saar);
8568 gen_helper_dmfc0_saar(arg, cpu_env);
8569 register_name = "SAAR";
8570 break;
8571 default:
8572 goto cp0_unimplemented;
8573 }
8574 break;
8575 case CP0_REGISTER_10:
8576 switch (sel) {
8577 case 0:
8578 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
8579 register_name = "EntryHi";
8580 break;
8581 default:
8582 goto cp0_unimplemented;
8583 }
8584 break;
8585 case CP0_REGISTER_11:
8586 switch (sel) {
8587 case 0:
8588 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
8589 register_name = "Compare";
8590 break;
8591 /* 6,7 are implementation dependent */
8592 default:
8593 goto cp0_unimplemented;
8594 }
8595 break;
8596 case CP0_REGISTER_12:
8597 switch (sel) {
8598 case 0:
8599 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
8600 register_name = "Status";
8601 break;
8602 case 1:
8603 check_insn(ctx, ISA_MIPS32R2);
8604 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
8605 register_name = "IntCtl";
8606 break;
8607 case 2:
8608 check_insn(ctx, ISA_MIPS32R2);
8609 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
8610 register_name = "SRSCtl";
8611 break;
8612 case 3:
8613 check_insn(ctx, ISA_MIPS32R2);
8614 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8615 register_name = "SRSMap";
8616 break;
8617 default:
8618 goto cp0_unimplemented;
8619 }
8620 break;
8621 case CP0_REGISTER_13:
8622 switch (sel) {
8623 case 0:
8624 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
8625 register_name = "Cause";
8626 break;
8627 default:
8628 goto cp0_unimplemented;
8629 }
8630 break;
8631 case CP0_REGISTER_14:
8632 switch (sel) {
8633 case 0:
8634 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8635 register_name = "EPC";
8636 break;
8637 default:
8638 goto cp0_unimplemented;
8639 }
8640 break;
8641 case CP0_REGISTER_15:
8642 switch (sel) {
8643 case 0:
8644 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
8645 register_name = "PRid";
8646 break;
8647 case 1:
8648 check_insn(ctx, ISA_MIPS32R2);
8649 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
8650 register_name = "EBase";
8651 break;
8652 case 3:
8653 check_insn(ctx, ISA_MIPS32R2);
8654 CP0_CHECK(ctx->cmgcr);
8655 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
8656 register_name = "CMGCRBase";
8657 break;
8658 default:
8659 goto cp0_unimplemented;
8660 }
8661 break;
8662 case CP0_REGISTER_16:
8663 switch (sel) {
8664 case 0:
8665 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
8666 register_name = "Config";
8667 break;
8668 case 1:
8669 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
8670 register_name = "Config1";
8671 break;
8672 case 2:
8673 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
8674 register_name = "Config2";
8675 break;
8676 case 3:
8677 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
8678 register_name = "Config3";
8679 break;
8680 case 4:
8681 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
8682 register_name = "Config4";
8683 break;
8684 case 5:
8685 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
8686 register_name = "Config5";
8687 break;
8688 /* 6,7 are implementation dependent */
8689 case 6:
8690 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
8691 register_name = "Config6";
8692 break;
8693 case 7:
8694 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
8695 register_name = "Config7";
8696 break;
8697 default:
8698 goto cp0_unimplemented;
8699 }
8700 break;
8701 case CP0_REGISTER_17:
8702 switch (sel) {
8703 case 0:
8704 gen_helper_dmfc0_lladdr(arg, cpu_env);
8705 register_name = "LLAddr";
8706 break;
8707 case 1:
8708 CP0_CHECK(ctx->mrp);
8709 gen_helper_dmfc0_maar(arg, cpu_env);
8710 register_name = "MAAR";
8711 break;
8712 case 2:
8713 CP0_CHECK(ctx->mrp);
8714 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
8715 register_name = "MAARI";
8716 break;
8717 default:
8718 goto cp0_unimplemented;
8719 }
8720 break;
8721 case CP0_REGISTER_18:
8722 switch (sel) {
8723 case 0:
8724 case 1:
8725 case 2:
8726 case 3:
8727 case 4:
8728 case 5:
8729 case 6:
8730 case 7:
8731 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8732 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
8733 register_name = "WatchLo";
8734 break;
8735 default:
8736 goto cp0_unimplemented;
8737 }
8738 break;
8739 case CP0_REGISTER_19:
8740 switch (sel) {
8741 case 0:
8742 case 1:
8743 case 2:
8744 case 3:
8745 case 4:
8746 case 5:
8747 case 6:
8748 case 7:
8749 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8750 gen_helper_1e0i(mfc0_watchhi, arg, sel);
8751 register_name = "WatchHi";
8752 break;
8753 default:
8754 goto cp0_unimplemented;
8755 }
8756 break;
8757 case CP0_REGISTER_20:
8758 switch (sel) {
8759 case 0:
8760 check_insn(ctx, ISA_MIPS3);
8761 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
8762 register_name = "XContext";
8763 break;
8764 default:
8765 goto cp0_unimplemented;
8766 }
8767 break;
8768 case CP0_REGISTER_21:
8769 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8770 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8771 switch (sel) {
8772 case 0:
8773 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
8774 register_name = "Framemask";
8775 break;
8776 default:
8777 goto cp0_unimplemented;
8778 }
8779 break;
8780 case CP0_REGISTER_22:
8781 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8782 register_name = "'Diagnostic"; /* implementation dependent */
8783 break;
8784 case CP0_REGISTER_23:
8785 switch (sel) {
8786 case 0:
8787 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
8788 register_name = "Debug";
8789 break;
8790 case 1:
8791 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
8792 register_name = "TraceControl";
8793 goto cp0_unimplemented;
8794 case 2:
8795 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
8796 register_name = "TraceControl2";
8797 goto cp0_unimplemented;
8798 case 3:
8799 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
8800 register_name = "UserTraceData";
8801 goto cp0_unimplemented;
8802 case 4:
8803 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
8804 register_name = "TraceBPC";
8805 goto cp0_unimplemented;
8806 default:
8807 goto cp0_unimplemented;
8808 }
8809 break;
8810 case CP0_REGISTER_24:
8811 switch (sel) {
8812 case 0:
8813 /* EJTAG support */
8814 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8815 register_name = "DEPC";
8816 break;
8817 default:
8818 goto cp0_unimplemented;
8819 }
8820 break;
8821 case CP0_REGISTER_25:
8822 switch (sel) {
8823 case 0:
8824 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
8825 register_name = "Performance0";
8826 break;
8827 case 1:
8828 // gen_helper_dmfc0_performance1(arg);
8829 register_name = "Performance1";
8830 goto cp0_unimplemented;
8831 case 2:
8832 // gen_helper_dmfc0_performance2(arg);
8833 register_name = "Performance2";
8834 goto cp0_unimplemented;
8835 case 3:
8836 // gen_helper_dmfc0_performance3(arg);
8837 register_name = "Performance3";
8838 goto cp0_unimplemented;
8839 case 4:
8840 // gen_helper_dmfc0_performance4(arg);
8841 register_name = "Performance4";
8842 goto cp0_unimplemented;
8843 case 5:
8844 // gen_helper_dmfc0_performance5(arg);
8845 register_name = "Performance5";
8846 goto cp0_unimplemented;
8847 case 6:
8848 // gen_helper_dmfc0_performance6(arg);
8849 register_name = "Performance6";
8850 goto cp0_unimplemented;
8851 case 7:
8852 // gen_helper_dmfc0_performance7(arg);
8853 register_name = "Performance7";
8854 goto cp0_unimplemented;
8855 default:
8856 goto cp0_unimplemented;
8857 }
8858 break;
8859 case CP0_REGISTER_26:
8860 switch (sel) {
8861 case 0:
8862 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
8863 register_name = "ErrCtl";
8864 break;
8865 default:
8866 goto cp0_unimplemented;
8867 }
8868 break;
8869 case CP0_REGISTER_27:
8870 switch (sel) {
8871 /* ignored */
8872 case 0:
8873 case 1:
8874 case 2:
8875 case 3:
8876 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8877 register_name = "CacheErr";
8878 break;
8879 default:
8880 goto cp0_unimplemented;
8881 }
8882 break;
8883 case CP0_REGISTER_28:
8884 switch (sel) {
8885 case 0:
8886 case 2:
8887 case 4:
8888 case 6:
8889 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
8890 register_name = "TagLo";
8891 break;
8892 case 1:
8893 case 3:
8894 case 5:
8895 case 7:
8896 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
8897 register_name = "DataLo";
8898 break;
8899 default:
8900 goto cp0_unimplemented;
8901 }
8902 break;
8903 case CP0_REGISTER_29:
8904 switch (sel) {
8905 case 0:
8906 case 2:
8907 case 4:
8908 case 6:
8909 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
8910 register_name = "TagHi";
8911 break;
8912 case 1:
8913 case 3:
8914 case 5:
8915 case 7:
8916 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
8917 register_name = "DataHi";
8918 break;
8919 default:
8920 goto cp0_unimplemented;
8921 }
8922 break;
8923 case CP0_REGISTER_30:
8924 switch (sel) {
8925 case 0:
8926 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8927 register_name = "ErrorEPC";
8928 break;
8929 default:
8930 goto cp0_unimplemented;
8931 }
8932 break;
8933 case CP0_REGISTER_31:
8934 switch (sel) {
8935 case 0:
8936 /* EJTAG support */
8937 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8938 register_name = "DESAVE";
8939 break;
8940 case 2:
8941 case 3:
8942 case 4:
8943 case 5:
8944 case 6:
8945 case 7:
8946 CP0_CHECK(ctx->kscrexist & (1 << sel));
8947 tcg_gen_ld_tl(arg, cpu_env,
8948 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
8949 register_name = "KScratch";
8950 break;
8951 default:
8952 goto cp0_unimplemented;
8953 }
8954 break;
8955 default:
8956 goto cp0_unimplemented;
8957 }
8958 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
8959 return;
8960
8961 cp0_unimplemented:
8962 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
8963 register_name, reg, sel);
8964 gen_mfc0_unimplemented(ctx, arg);
8965 }
8966
8967 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8968 {
8969 const char *register_name = "invalid";
8970
8971 if (sel != 0) {
8972 check_insn(ctx, ISA_MIPS64);
8973 }
8974
8975 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8976 gen_io_start();
8977 }
8978
8979 switch (reg) {
8980 case CP0_REGISTER_00:
8981 switch (sel) {
8982 case 0:
8983 gen_helper_mtc0_index(cpu_env, arg);
8984 register_name = "Index";
8985 break;
8986 case 1:
8987 CP0_CHECK(ctx->insn_flags & ASE_MT);
8988 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
8989 register_name = "MVPControl";
8990 break;
8991 case 2:
8992 CP0_CHECK(ctx->insn_flags & ASE_MT);
8993 /* ignored */
8994 register_name = "MVPConf0";
8995 break;
8996 case 3:
8997 CP0_CHECK(ctx->insn_flags & ASE_MT);
8998 /* ignored */
8999 register_name = "MVPConf1";
9000 break;
9001 case 4:
9002 CP0_CHECK(ctx->vp);
9003 /* ignored */
9004 register_name = "VPControl";
9005 break;
9006 default:
9007 goto cp0_unimplemented;
9008 }
9009 break;
9010 case CP0_REGISTER_01:
9011 switch (sel) {
9012 case 0:
9013 /* ignored */
9014 register_name = "Random";
9015 break;
9016 case 1:
9017 CP0_CHECK(ctx->insn_flags & ASE_MT);
9018 gen_helper_mtc0_vpecontrol(cpu_env, arg);
9019 register_name = "VPEControl";
9020 break;
9021 case 2:
9022 CP0_CHECK(ctx->insn_flags & ASE_MT);
9023 gen_helper_mtc0_vpeconf0(cpu_env, arg);
9024 register_name = "VPEConf0";
9025 break;
9026 case 3:
9027 CP0_CHECK(ctx->insn_flags & ASE_MT);
9028 gen_helper_mtc0_vpeconf1(cpu_env, arg);
9029 register_name = "VPEConf1";
9030 break;
9031 case 4:
9032 CP0_CHECK(ctx->insn_flags & ASE_MT);
9033 gen_helper_mtc0_yqmask(cpu_env, arg);
9034 register_name = "YQMask";
9035 break;
9036 case 5:
9037 CP0_CHECK(ctx->insn_flags & ASE_MT);
9038 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
9039 register_name = "VPESchedule";
9040 break;
9041 case 6:
9042 CP0_CHECK(ctx->insn_flags & ASE_MT);
9043 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
9044 register_name = "VPEScheFBack";
9045 break;
9046 case 7:
9047 CP0_CHECK(ctx->insn_flags & ASE_MT);
9048 gen_helper_mtc0_vpeopt(cpu_env, arg);
9049 register_name = "VPEOpt";
9050 break;
9051 default:
9052 goto cp0_unimplemented;
9053 }
9054 break;
9055 case CP0_REGISTER_02:
9056 switch (sel) {
9057 case 0:
9058 gen_helper_dmtc0_entrylo0(cpu_env, arg);
9059 register_name = "EntryLo0";
9060 break;
9061 case 1:
9062 CP0_CHECK(ctx->insn_flags & ASE_MT);
9063 gen_helper_mtc0_tcstatus(cpu_env, arg);
9064 register_name = "TCStatus";
9065 break;
9066 case 2:
9067 CP0_CHECK(ctx->insn_flags & ASE_MT);
9068 gen_helper_mtc0_tcbind(cpu_env, arg);
9069 register_name = "TCBind";
9070 break;
9071 case 3:
9072 CP0_CHECK(ctx->insn_flags & ASE_MT);
9073 gen_helper_mtc0_tcrestart(cpu_env, arg);
9074 register_name = "TCRestart";
9075 break;
9076 case 4:
9077 CP0_CHECK(ctx->insn_flags & ASE_MT);
9078 gen_helper_mtc0_tchalt(cpu_env, arg);
9079 register_name = "TCHalt";
9080 break;
9081 case 5:
9082 CP0_CHECK(ctx->insn_flags & ASE_MT);
9083 gen_helper_mtc0_tccontext(cpu_env, arg);
9084 register_name = "TCContext";
9085 break;
9086 case 6:
9087 CP0_CHECK(ctx->insn_flags & ASE_MT);
9088 gen_helper_mtc0_tcschedule(cpu_env, arg);
9089 register_name = "TCSchedule";
9090 break;
9091 case 7:
9092 CP0_CHECK(ctx->insn_flags & ASE_MT);
9093 gen_helper_mtc0_tcschefback(cpu_env, arg);
9094 register_name = "TCScheFBack";
9095 break;
9096 default:
9097 goto cp0_unimplemented;
9098 }
9099 break;
9100 case CP0_REGISTER_03:
9101 switch (sel) {
9102 case 0:
9103 gen_helper_dmtc0_entrylo1(cpu_env, arg);
9104 register_name = "EntryLo1";
9105 break;
9106 case 1:
9107 CP0_CHECK(ctx->vp);
9108 /* ignored */
9109 register_name = "GlobalNumber";
9110 break;
9111 default:
9112 goto cp0_unimplemented;
9113 }
9114 break;
9115 case CP0_REGISTER_04:
9116 switch (sel) {
9117 case 0:
9118 gen_helper_mtc0_context(cpu_env, arg);
9119 register_name = "Context";
9120 break;
9121 case 1:
9122 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
9123 register_name = "ContextConfig";
9124 goto cp0_unimplemented;
9125 case 2:
9126 CP0_CHECK(ctx->ulri);
9127 tcg_gen_st_tl(arg, cpu_env,
9128 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
9129 register_name = "UserLocal";
9130 break;
9131 default:
9132 goto cp0_unimplemented;
9133 }
9134 break;
9135 case CP0_REGISTER_05:
9136 switch (sel) {
9137 case 0:
9138 gen_helper_mtc0_pagemask(cpu_env, arg);
9139 register_name = "PageMask";
9140 break;
9141 case 1:
9142 check_insn(ctx, ISA_MIPS32R2);
9143 gen_helper_mtc0_pagegrain(cpu_env, arg);
9144 register_name = "PageGrain";
9145 break;
9146 case 2:
9147 CP0_CHECK(ctx->sc);
9148 gen_helper_mtc0_segctl0(cpu_env, arg);
9149 register_name = "SegCtl0";
9150 break;
9151 case 3:
9152 CP0_CHECK(ctx->sc);
9153 gen_helper_mtc0_segctl1(cpu_env, arg);
9154 register_name = "SegCtl1";
9155 break;
9156 case 4:
9157 CP0_CHECK(ctx->sc);
9158 gen_helper_mtc0_segctl2(cpu_env, arg);
9159 register_name = "SegCtl2";
9160 break;
9161 case 5:
9162 check_pw(ctx);
9163 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
9164 register_name = "PWBase";
9165 break;
9166 case 6:
9167 check_pw(ctx);
9168 gen_helper_mtc0_pwfield(cpu_env, arg);
9169 register_name = "PWField";
9170 break;
9171 case 7:
9172 check_pw(ctx);
9173 gen_helper_mtc0_pwsize(cpu_env, arg);
9174 register_name = "PWSize";
9175 break;
9176 default:
9177 goto cp0_unimplemented;
9178 }
9179 break;
9180 case CP0_REGISTER_06:
9181 switch (sel) {
9182 case 0:
9183 gen_helper_mtc0_wired(cpu_env, arg);
9184 register_name = "Wired";
9185 break;
9186 case 1:
9187 check_insn(ctx, ISA_MIPS32R2);
9188 gen_helper_mtc0_srsconf0(cpu_env, arg);
9189 register_name = "SRSConf0";
9190 break;
9191 case 2:
9192 check_insn(ctx, ISA_MIPS32R2);
9193 gen_helper_mtc0_srsconf1(cpu_env, arg);
9194 register_name = "SRSConf1";
9195 break;
9196 case 3:
9197 check_insn(ctx, ISA_MIPS32R2);
9198 gen_helper_mtc0_srsconf2(cpu_env, arg);
9199 register_name = "SRSConf2";
9200 break;
9201 case 4:
9202 check_insn(ctx, ISA_MIPS32R2);
9203 gen_helper_mtc0_srsconf3(cpu_env, arg);
9204 register_name = "SRSConf3";
9205 break;
9206 case 5:
9207 check_insn(ctx, ISA_MIPS32R2);
9208 gen_helper_mtc0_srsconf4(cpu_env, arg);
9209 register_name = "SRSConf4";
9210 break;
9211 case 6:
9212 check_pw(ctx);
9213 gen_helper_mtc0_pwctl(cpu_env, arg);
9214 register_name = "PWCtl";
9215 break;
9216 default:
9217 goto cp0_unimplemented;
9218 }
9219 break;
9220 case CP0_REGISTER_07:
9221 switch (sel) {
9222 case 0:
9223 check_insn(ctx, ISA_MIPS32R2);
9224 gen_helper_mtc0_hwrena(cpu_env, arg);
9225 ctx->base.is_jmp = DISAS_STOP;
9226 register_name = "HWREna";
9227 break;
9228 default:
9229 goto cp0_unimplemented;
9230 }
9231 break;
9232 case CP0_REGISTER_08:
9233 switch (sel) {
9234 case 0:
9235 /* ignored */
9236 register_name = "BadVAddr";
9237 break;
9238 case 1:
9239 /* ignored */
9240 register_name = "BadInstr";
9241 break;
9242 case 2:
9243 /* ignored */
9244 register_name = "BadInstrP";
9245 break;
9246 case 3:
9247 /* ignored */
9248 register_name = "BadInstrX";
9249 break;
9250 default:
9251 goto cp0_unimplemented;
9252 }
9253 break;
9254 case CP0_REGISTER_09:
9255 switch (sel) {
9256 case 0:
9257 gen_helper_mtc0_count(cpu_env, arg);
9258 register_name = "Count";
9259 break;
9260 case 6:
9261 CP0_CHECK(ctx->saar);
9262 gen_helper_mtc0_saari(cpu_env, arg);
9263 register_name = "SAARI";
9264 break;
9265 case 7:
9266 CP0_CHECK(ctx->saar);
9267 gen_helper_mtc0_saar(cpu_env, arg);
9268 register_name = "SAAR";
9269 break;
9270 default:
9271 goto cp0_unimplemented;
9272 }
9273 /* Stop translation as we may have switched the execution mode */
9274 ctx->base.is_jmp = DISAS_STOP;
9275 break;
9276 case CP0_REGISTER_10:
9277 switch (sel) {
9278 case 0:
9279 gen_helper_mtc0_entryhi(cpu_env, arg);
9280 register_name = "EntryHi";
9281 break;
9282 default:
9283 goto cp0_unimplemented;
9284 }
9285 break;
9286 case CP0_REGISTER_11:
9287 switch (sel) {
9288 case 0:
9289 gen_helper_mtc0_compare(cpu_env, arg);
9290 register_name = "Compare";
9291 break;
9292 /* 6,7 are implementation dependent */
9293 default:
9294 goto cp0_unimplemented;
9295 }
9296 /* Stop translation as we may have switched the execution mode */
9297 ctx->base.is_jmp = DISAS_STOP;
9298 break;
9299 case CP0_REGISTER_12:
9300 switch (sel) {
9301 case 0:
9302 save_cpu_state(ctx, 1);
9303 gen_helper_mtc0_status(cpu_env, arg);
9304 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9305 gen_save_pc(ctx->base.pc_next + 4);
9306 ctx->base.is_jmp = DISAS_EXIT;
9307 register_name = "Status";
9308 break;
9309 case 1:
9310 check_insn(ctx, ISA_MIPS32R2);
9311 gen_helper_mtc0_intctl(cpu_env, arg);
9312 /* Stop translation as we may have switched the execution mode */
9313 ctx->base.is_jmp = DISAS_STOP;
9314 register_name = "IntCtl";
9315 break;
9316 case 2:
9317 check_insn(ctx, ISA_MIPS32R2);
9318 gen_helper_mtc0_srsctl(cpu_env, arg);
9319 /* Stop translation as we may have switched the execution mode */
9320 ctx->base.is_jmp = DISAS_STOP;
9321 register_name = "SRSCtl";
9322 break;
9323 case 3:
9324 check_insn(ctx, ISA_MIPS32R2);
9325 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
9326 /* Stop translation as we may have switched the execution mode */
9327 ctx->base.is_jmp = DISAS_STOP;
9328 register_name = "SRSMap";
9329 break;
9330 default:
9331 goto cp0_unimplemented;
9332 }
9333 break;
9334 case CP0_REGISTER_13:
9335 switch (sel) {
9336 case 0:
9337 save_cpu_state(ctx, 1);
9338 gen_helper_mtc0_cause(cpu_env, arg);
9339 /* Stop translation as we may have triggered an interrupt.
9340 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9341 * translated code to check for pending interrupts. */
9342 gen_save_pc(ctx->base.pc_next + 4);
9343 ctx->base.is_jmp = DISAS_EXIT;
9344 register_name = "Cause";
9345 break;
9346 default:
9347 goto cp0_unimplemented;
9348 }
9349 break;
9350 case CP0_REGISTER_14:
9351 switch (sel) {
9352 case 0:
9353 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
9354 register_name = "EPC";
9355 break;
9356 default:
9357 goto cp0_unimplemented;
9358 }
9359 break;
9360 case CP0_REGISTER_15:
9361 switch (sel) {
9362 case 0:
9363 /* ignored */
9364 register_name = "PRid";
9365 break;
9366 case 1:
9367 check_insn(ctx, ISA_MIPS32R2);
9368 gen_helper_mtc0_ebase(cpu_env, arg);
9369 register_name = "EBase";
9370 break;
9371 default:
9372 goto cp0_unimplemented;
9373 }
9374 break;
9375 case CP0_REGISTER_16:
9376 switch (sel) {
9377 case 0:
9378 gen_helper_mtc0_config0(cpu_env, arg);
9379 register_name = "Config";
9380 /* Stop translation as we may have switched the execution mode */
9381 ctx->base.is_jmp = DISAS_STOP;
9382 break;
9383 case 1:
9384 /* ignored, read only */
9385 register_name = "Config1";
9386 break;
9387 case 2:
9388 gen_helper_mtc0_config2(cpu_env, arg);
9389 register_name = "Config2";
9390 /* Stop translation as we may have switched the execution mode */
9391 ctx->base.is_jmp = DISAS_STOP;
9392 break;
9393 case 3:
9394 gen_helper_mtc0_config3(cpu_env, arg);
9395 register_name = "Config3";
9396 /* Stop translation as we may have switched the execution mode */
9397 ctx->base.is_jmp = DISAS_STOP;
9398 break;
9399 case 4:
9400 /* currently ignored */
9401 register_name = "Config4";
9402 break;
9403 case 5:
9404 gen_helper_mtc0_config5(cpu_env, arg);
9405 register_name = "Config5";
9406 /* Stop translation as we may have switched the execution mode */
9407 ctx->base.is_jmp = DISAS_STOP;
9408 break;
9409 /* 6,7 are implementation dependent */
9410 default:
9411 register_name = "Invalid config selector";
9412 goto cp0_unimplemented;
9413 }
9414 break;
9415 case CP0_REGISTER_17:
9416 switch (sel) {
9417 case 0:
9418 gen_helper_mtc0_lladdr(cpu_env, arg);
9419 register_name = "LLAddr";
9420 break;
9421 case 1:
9422 CP0_CHECK(ctx->mrp);
9423 gen_helper_mtc0_maar(cpu_env, arg);
9424 register_name = "MAAR";
9425 break;
9426 case 2:
9427 CP0_CHECK(ctx->mrp);
9428 gen_helper_mtc0_maari(cpu_env, arg);
9429 register_name = "MAARI";
9430 break;
9431 default:
9432 goto cp0_unimplemented;
9433 }
9434 break;
9435 case CP0_REGISTER_18:
9436 switch (sel) {
9437 case 0:
9438 case 1:
9439 case 2:
9440 case 3:
9441 case 4:
9442 case 5:
9443 case 6:
9444 case 7:
9445 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9446 gen_helper_0e1i(mtc0_watchlo, arg, sel);
9447 register_name = "WatchLo";
9448 break;
9449 default:
9450 goto cp0_unimplemented;
9451 }
9452 break;
9453 case CP0_REGISTER_19:
9454 switch (sel) {
9455 case 0:
9456 case 1:
9457 case 2:
9458 case 3:
9459 case 4:
9460 case 5:
9461 case 6:
9462 case 7:
9463 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9464 gen_helper_0e1i(mtc0_watchhi, arg, sel);
9465 register_name = "WatchHi";
9466 break;
9467 default:
9468 goto cp0_unimplemented;
9469 }
9470 break;
9471 case CP0_REGISTER_20:
9472 switch (sel) {
9473 case 0:
9474 check_insn(ctx, ISA_MIPS3);
9475 gen_helper_mtc0_xcontext(cpu_env, arg);
9476 register_name = "XContext";
9477 break;
9478 default:
9479 goto cp0_unimplemented;
9480 }
9481 break;
9482 case CP0_REGISTER_21:
9483 /* Officially reserved, but sel 0 is used for R1x000 framemask */
9484 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9485 switch (sel) {
9486 case 0:
9487 gen_helper_mtc0_framemask(cpu_env, arg);
9488 register_name = "Framemask";
9489 break;
9490 default:
9491 goto cp0_unimplemented;
9492 }
9493 break;
9494 case CP0_REGISTER_22:
9495 /* ignored */
9496 register_name = "Diagnostic"; /* implementation dependent */
9497 break;
9498 case CP0_REGISTER_23:
9499 switch (sel) {
9500 case 0:
9501 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
9502 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9503 gen_save_pc(ctx->base.pc_next + 4);
9504 ctx->base.is_jmp = DISAS_EXIT;
9505 register_name = "Debug";
9506 break;
9507 case 1:
9508 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
9509 /* Stop translation as we may have switched the execution mode */
9510 ctx->base.is_jmp = DISAS_STOP;
9511 register_name = "TraceControl";
9512 goto cp0_unimplemented;
9513 case 2:
9514 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
9515 /* Stop translation as we may have switched the execution mode */
9516 ctx->base.is_jmp = DISAS_STOP;
9517 register_name = "TraceControl2";
9518 goto cp0_unimplemented;
9519 case 3:
9520 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
9521 /* Stop translation as we may have switched the execution mode */
9522 ctx->base.is_jmp = DISAS_STOP;
9523 register_name = "UserTraceData";
9524 goto cp0_unimplemented;
9525 case 4:
9526 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
9527 /* Stop translation as we may have switched the execution mode */
9528 ctx->base.is_jmp = DISAS_STOP;
9529 register_name = "TraceBPC";
9530 goto cp0_unimplemented;
9531 default:
9532 goto cp0_unimplemented;
9533 }
9534 break;
9535 case CP0_REGISTER_24:
9536 switch (sel) {
9537 case 0:
9538 /* EJTAG support */
9539 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
9540 register_name = "DEPC";
9541 break;
9542 default:
9543 goto cp0_unimplemented;
9544 }
9545 break;
9546 case CP0_REGISTER_25:
9547 switch (sel) {
9548 case 0:
9549 gen_helper_mtc0_performance0(cpu_env, arg);
9550 register_name = "Performance0";
9551 break;
9552 case 1:
9553 // gen_helper_mtc0_performance1(cpu_env, arg);
9554 register_name = "Performance1";
9555 goto cp0_unimplemented;
9556 case 2:
9557 // gen_helper_mtc0_performance2(cpu_env, arg);
9558 register_name = "Performance2";
9559 goto cp0_unimplemented;
9560 case 3:
9561 // gen_helper_mtc0_performance3(cpu_env, arg);
9562 register_name = "Performance3";
9563 goto cp0_unimplemented;
9564 case 4:
9565 // gen_helper_mtc0_performance4(cpu_env, arg);
9566 register_name = "Performance4";
9567 goto cp0_unimplemented;
9568 case 5:
9569 // gen_helper_mtc0_performance5(cpu_env, arg);
9570 register_name = "Performance5";
9571 goto cp0_unimplemented;
9572 case 6:
9573 // gen_helper_mtc0_performance6(cpu_env, arg);
9574 register_name = "Performance6";
9575 goto cp0_unimplemented;
9576 case 7:
9577 // gen_helper_mtc0_performance7(cpu_env, arg);
9578 register_name = "Performance7";
9579 goto cp0_unimplemented;
9580 default:
9581 goto cp0_unimplemented;
9582 }
9583 break;
9584 case CP0_REGISTER_26:
9585 switch (sel) {
9586 case 0:
9587 gen_helper_mtc0_errctl(cpu_env, arg);
9588 ctx->base.is_jmp = DISAS_STOP;
9589 register_name = "ErrCtl";
9590 break;
9591 default:
9592 goto cp0_unimplemented;
9593 }
9594 break;
9595 case CP0_REGISTER_27:
9596 switch (sel) {
9597 case 0:
9598 case 1:
9599 case 2:
9600 case 3:
9601 /* ignored */
9602 register_name = "CacheErr";
9603 break;
9604 default:
9605 goto cp0_unimplemented;
9606 }
9607 break;
9608 case CP0_REGISTER_28:
9609 switch (sel) {
9610 case 0:
9611 case 2:
9612 case 4:
9613 case 6:
9614 gen_helper_mtc0_taglo(cpu_env, arg);
9615 register_name = "TagLo";
9616 break;
9617 case 1:
9618 case 3:
9619 case 5:
9620 case 7:
9621 gen_helper_mtc0_datalo(cpu_env, arg);
9622 register_name = "DataLo";
9623 break;
9624 default:
9625 goto cp0_unimplemented;
9626 }
9627 break;
9628 case CP0_REGISTER_29:
9629 switch (sel) {
9630 case 0:
9631 case 2:
9632 case 4:
9633 case 6:
9634 gen_helper_mtc0_taghi(cpu_env, arg);
9635 register_name = "TagHi";
9636 break;
9637 case 1:
9638 case 3:
9639 case 5:
9640 case 7:
9641 gen_helper_mtc0_datahi(cpu_env, arg);
9642 register_name = "DataHi";
9643 break;
9644 default:
9645 register_name = "invalid sel";
9646 goto cp0_unimplemented;
9647 }
9648 break;
9649 case CP0_REGISTER_30:
9650 switch (sel) {
9651 case 0:
9652 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9653 register_name = "ErrorEPC";
9654 break;
9655 default:
9656 goto cp0_unimplemented;
9657 }
9658 break;
9659 case CP0_REGISTER_31:
9660 switch (sel) {
9661 case 0:
9662 /* EJTAG support */
9663 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9664 register_name = "DESAVE";
9665 break;
9666 case 2:
9667 case 3:
9668 case 4:
9669 case 5:
9670 case 6:
9671 case 7:
9672 CP0_CHECK(ctx->kscrexist & (1 << sel));
9673 tcg_gen_st_tl(arg, cpu_env,
9674 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
9675 register_name = "KScratch";
9676 break;
9677 default:
9678 goto cp0_unimplemented;
9679 }
9680 break;
9681 default:
9682 goto cp0_unimplemented;
9683 }
9684 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
9685
9686 /* For simplicity assume that all writes can cause interrupts. */
9687 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9688 gen_io_end();
9689 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
9690 * translated code to check for pending interrupts. */
9691 gen_save_pc(ctx->base.pc_next + 4);
9692 ctx->base.is_jmp = DISAS_EXIT;
9693 }
9694 return;
9695
9696 cp0_unimplemented:
9697 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
9698 register_name, reg, sel);
9699 }
9700 #endif /* TARGET_MIPS64 */
9701
9702 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
9703 int u, int sel, int h)
9704 {
9705 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9706 TCGv t0 = tcg_temp_local_new();
9707
9708 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9709 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9710 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
9711 tcg_gen_movi_tl(t0, -1);
9712 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9713 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
9714 tcg_gen_movi_tl(t0, -1);
9715 } else if (u == 0) {
9716 switch (rt) {
9717 case 1:
9718 switch (sel) {
9719 case 1:
9720 gen_helper_mftc0_vpecontrol(t0, cpu_env);
9721 break;
9722 case 2:
9723 gen_helper_mftc0_vpeconf0(t0, cpu_env);
9724 break;
9725 default:
9726 goto die;
9727 break;
9728 }
9729 break;
9730 case 2:
9731 switch (sel) {
9732 case 1:
9733 gen_helper_mftc0_tcstatus(t0, cpu_env);
9734 break;
9735 case 2:
9736 gen_helper_mftc0_tcbind(t0, cpu_env);
9737 break;
9738 case 3:
9739 gen_helper_mftc0_tcrestart(t0, cpu_env);
9740 break;
9741 case 4:
9742 gen_helper_mftc0_tchalt(t0, cpu_env);
9743 break;
9744 case 5:
9745 gen_helper_mftc0_tccontext(t0, cpu_env);
9746 break;
9747 case 6:
9748 gen_helper_mftc0_tcschedule(t0, cpu_env);
9749 break;
9750 case 7:
9751 gen_helper_mftc0_tcschefback(t0, cpu_env);
9752 break;
9753 default:
9754 gen_mfc0(ctx, t0, rt, sel);
9755 break;
9756 }
9757 break;
9758 case 10:
9759 switch (sel) {
9760 case 0:
9761 gen_helper_mftc0_entryhi(t0, cpu_env);
9762 break;
9763 default:
9764 gen_mfc0(ctx, t0, rt, sel);
9765 break;
9766 }
9767 case 12:
9768 switch (sel) {
9769 case 0:
9770 gen_helper_mftc0_status(t0, cpu_env);
9771 break;
9772 default:
9773 gen_mfc0(ctx, t0, rt, sel);
9774 break;
9775 }
9776 case 13:
9777 switch (sel) {
9778 case 0:
9779 gen_helper_mftc0_cause(t0, cpu_env);
9780 break;
9781 default:
9782 goto die;
9783 break;
9784 }
9785 break;
9786 case 14:
9787 switch (sel) {
9788 case 0:
9789 gen_helper_mftc0_epc(t0, cpu_env);
9790 break;
9791 default:
9792 goto die;
9793 break;
9794 }
9795 break;
9796 case 15:
9797 switch (sel) {
9798 case 1:
9799 gen_helper_mftc0_ebase(t0, cpu_env);
9800 break;
9801 default:
9802 goto die;
9803 break;
9804 }
9805 break;
9806 case 16:
9807 switch (sel) {
9808 case 0:
9809 case 1:
9810 case 2:
9811 case 3:
9812 case 4:
9813 case 5:
9814 case 6:
9815 case 7:
9816 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
9817 break;
9818 default:
9819 goto die;
9820 break;
9821 }
9822 break;
9823 case 23:
9824 switch (sel) {
9825 case 0:
9826 gen_helper_mftc0_debug(t0, cpu_env);
9827 break;
9828 default:
9829 gen_mfc0(ctx, t0, rt, sel);
9830 break;
9831 }
9832 break;
9833 default:
9834 gen_mfc0(ctx, t0, rt, sel);
9835 }
9836 } else switch (sel) {
9837 /* GPR registers. */
9838 case 0:
9839 gen_helper_1e0i(mftgpr, t0, rt);
9840 break;
9841 /* Auxiliary CPU registers */
9842 case 1:
9843 switch (rt) {
9844 case 0:
9845 gen_helper_1e0i(mftlo, t0, 0);
9846 break;
9847 case 1:
9848 gen_helper_1e0i(mfthi, t0, 0);
9849 break;
9850 case 2:
9851 gen_helper_1e0i(mftacx, t0, 0);
9852 break;
9853 case 4:
9854 gen_helper_1e0i(mftlo, t0, 1);
9855 break;
9856 case 5:
9857 gen_helper_1e0i(mfthi, t0, 1);
9858 break;
9859 case 6:
9860 gen_helper_1e0i(mftacx, t0, 1);
9861 break;
9862 case 8:
9863 gen_helper_1e0i(mftlo, t0, 2);
9864 break;
9865 case 9:
9866 gen_helper_1e0i(mfthi, t0, 2);
9867 break;
9868 case 10:
9869 gen_helper_1e0i(mftacx, t0, 2);
9870 break;
9871 case 12:
9872 gen_helper_1e0i(mftlo, t0, 3);
9873 break;
9874 case 13:
9875 gen_helper_1e0i(mfthi, t0, 3);
9876 break;
9877 case 14:
9878 gen_helper_1e0i(mftacx, t0, 3);
9879 break;
9880 case 16:
9881 gen_helper_mftdsp(t0, cpu_env);
9882 break;
9883 default:
9884 goto die;
9885 }
9886 break;
9887 /* Floating point (COP1). */
9888 case 2:
9889 /* XXX: For now we support only a single FPU context. */
9890 if (h == 0) {
9891 TCGv_i32 fp0 = tcg_temp_new_i32();
9892
9893 gen_load_fpr32(ctx, fp0, rt);
9894 tcg_gen_ext_i32_tl(t0, fp0);
9895 tcg_temp_free_i32(fp0);
9896 } else {
9897 TCGv_i32 fp0 = tcg_temp_new_i32();
9898
9899 gen_load_fpr32h(ctx, fp0, rt);
9900 tcg_gen_ext_i32_tl(t0, fp0);
9901 tcg_temp_free_i32(fp0);
9902 }
9903 break;
9904 case 3:
9905 /* XXX: For now we support only a single FPU context. */
9906 gen_helper_1e0i(cfc1, t0, rt);
9907 break;
9908 /* COP2: Not implemented. */
9909 case 4:
9910 case 5:
9911 /* fall through */
9912 default:
9913 goto die;
9914 }
9915 trace_mips_translate_tr("mftr", rt, u, sel, h);
9916 gen_store_gpr(t0, rd);
9917 tcg_temp_free(t0);
9918 return;
9919
9920 die:
9921 tcg_temp_free(t0);
9922 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
9923 generate_exception_end(ctx, EXCP_RI);
9924 }
9925
9926 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
9927 int u, int sel, int h)
9928 {
9929 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9930 TCGv t0 = tcg_temp_local_new();
9931
9932 gen_load_gpr(t0, rt);
9933 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9934 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9935 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
9936 /* NOP */ ;
9937 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9938 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
9939 /* NOP */ ;
9940 } else if (u == 0) {
9941 switch (rd) {
9942 case 1:
9943 switch (sel) {
9944 case 1:
9945 gen_helper_mttc0_vpecontrol(cpu_env, t0);
9946 break;
9947 case 2:
9948 gen_helper_mttc0_vpeconf0(cpu_env, t0);
9949 break;
9950 default:
9951 goto die;
9952 break;
9953 }
9954 break;
9955 case 2:
9956 switch (sel) {
9957 case 1:
9958 gen_helper_mttc0_tcstatus(cpu_env, t0);
9959 break;
9960 case 2:
9961 gen_helper_mttc0_tcbind(cpu_env, t0);
9962 break;
9963 case 3:
9964 gen_helper_mttc0_tcrestart(cpu_env, t0);
9965 break;
9966 case 4:
9967 gen_helper_mttc0_tchalt(cpu_env, t0);
9968 break;
9969 case 5:
9970 gen_helper_mttc0_tccontext(cpu_env, t0);
9971 break;
9972 case 6:
9973 gen_helper_mttc0_tcschedule(cpu_env, t0);
9974 break;
9975 case 7:
9976 gen_helper_mttc0_tcschefback(cpu_env, t0);
9977 break;
9978 default:
9979 gen_mtc0(ctx, t0, rd, sel);
9980 break;
9981 }
9982 break;
9983 case 10:
9984 switch (sel) {
9985 case 0:
9986 gen_helper_mttc0_entryhi(cpu_env, t0);
9987 break;
9988 default:
9989 gen_mtc0(ctx, t0, rd, sel);
9990 break;
9991 }
9992 case 12:
9993 switch (sel) {
9994 case 0:
9995 gen_helper_mttc0_status(cpu_env, t0);
9996 break;
9997 default:
9998 gen_mtc0(ctx, t0, rd, sel);
9999 break;
10000 }
10001 case 13:
10002 switch (sel) {
10003 case 0:
10004 gen_helper_mttc0_cause(cpu_env, t0);
10005 break;
10006 default:
10007 goto die;
10008 break;
10009 }
10010 break;
10011 case 15:
10012 switch (sel) {
10013 case 1:
10014 gen_helper_mttc0_ebase(cpu_env, t0);
10015 break;
10016 default:
10017 goto die;
10018 break;
10019 }
10020 break;
10021 case 23:
10022 switch (sel) {
10023 case 0:
10024 gen_helper_mttc0_debug(cpu_env, t0);
10025 break;
10026 default:
10027 gen_mtc0(ctx, t0, rd, sel);
10028 break;
10029 }
10030 break;
10031 default:
10032 gen_mtc0(ctx, t0, rd, sel);
10033 }
10034 } else switch (sel) {
10035 /* GPR registers. */
10036 case 0:
10037 gen_helper_0e1i(mttgpr, t0, rd);
10038 break;
10039 /* Auxiliary CPU registers */
10040 case 1:
10041 switch (rd) {
10042 case 0:
10043 gen_helper_0e1i(mttlo, t0, 0);
10044 break;
10045 case 1:
10046 gen_helper_0e1i(mtthi, t0, 0);
10047 break;
10048 case 2:
10049 gen_helper_0e1i(mttacx, t0, 0);
10050 break;
10051 case 4:
10052 gen_helper_0e1i(mttlo, t0, 1);
10053 break;
10054 case 5:
10055 gen_helper_0e1i(mtthi, t0, 1);
10056 break;
10057 case 6:
10058 gen_helper_0e1i(mttacx, t0, 1);
10059 break;
10060 case 8:
10061 gen_helper_0e1i(mttlo, t0, 2);
10062 break;
10063 case 9:
10064 gen_helper_0e1i(mtthi, t0, 2);
10065 break;
10066 case 10:
10067 gen_helper_0e1i(mttacx, t0, 2);
10068 break;
10069 case 12:
10070 gen_helper_0e1i(mttlo, t0, 3);
10071 break;
10072 case 13:
10073 gen_helper_0e1i(mtthi, t0, 3);
10074 break;
10075 case 14:
10076 gen_helper_0e1i(mttacx, t0, 3);
10077 break;
10078 case 16:
10079 gen_helper_mttdsp(cpu_env, t0);
10080 break;
10081 default:
10082 goto die;
10083 }
10084 break;
10085 /* Floating point (COP1). */
10086 case 2:
10087 /* XXX: For now we support only a single FPU context. */
10088 if (h == 0) {
10089 TCGv_i32 fp0 = tcg_temp_new_i32();
10090
10091 tcg_gen_trunc_tl_i32(fp0, t0);
10092 gen_store_fpr32(ctx, fp0, rd);
10093 tcg_temp_free_i32(fp0);
10094 } else {
10095 TCGv_i32 fp0 = tcg_temp_new_i32();
10096
10097 tcg_gen_trunc_tl_i32(fp0, t0);
10098 gen_store_fpr32h(ctx, fp0, rd);
10099 tcg_temp_free_i32(fp0);
10100 }
10101 break;
10102 case 3:
10103 /* XXX: For now we support only a single FPU context. */
10104 {
10105 TCGv_i32 fs_tmp = tcg_const_i32(rd);
10106
10107 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10108 tcg_temp_free_i32(fs_tmp);
10109 }
10110 /* Stop translation as we may have changed hflags */
10111 ctx->base.is_jmp = DISAS_STOP;
10112 break;
10113 /* COP2: Not implemented. */
10114 case 4:
10115 case 5:
10116 /* fall through */
10117 default:
10118 goto die;
10119 }
10120 trace_mips_translate_tr("mttr", rd, u, sel, h);
10121 tcg_temp_free(t0);
10122 return;
10123
10124 die:
10125 tcg_temp_free(t0);
10126 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
10127 generate_exception_end(ctx, EXCP_RI);
10128 }
10129
10130 static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
10131 int rt, int rd)
10132 {
10133 const char *opn = "ldst";
10134
10135 check_cp0_enabled(ctx);
10136 switch (opc) {
10137 case OPC_MFC0:
10138 if (rt == 0) {
10139 /* Treat as NOP. */
10140 return;
10141 }
10142 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10143 opn = "mfc0";
10144 break;
10145 case OPC_MTC0:
10146 {
10147 TCGv t0 = tcg_temp_new();
10148
10149 gen_load_gpr(t0, rt);
10150 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
10151 tcg_temp_free(t0);
10152 }
10153 opn = "mtc0";
10154 break;
10155 #if defined(TARGET_MIPS64)
10156 case OPC_DMFC0:
10157 check_insn(ctx, ISA_MIPS3);
10158 if (rt == 0) {
10159 /* Treat as NOP. */
10160 return;
10161 }
10162 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10163 opn = "dmfc0";
10164 break;
10165 case OPC_DMTC0:
10166 check_insn(ctx, ISA_MIPS3);
10167 {
10168 TCGv t0 = tcg_temp_new();
10169
10170 gen_load_gpr(t0, rt);
10171 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
10172 tcg_temp_free(t0);
10173 }
10174 opn = "dmtc0";
10175 break;
10176 #endif
10177 case OPC_MFHC0:
10178 check_mvh(ctx);
10179 if (rt == 0) {
10180 /* Treat as NOP. */
10181 return;
10182 }
10183 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10184 opn = "mfhc0";
10185 break;
10186 case OPC_MTHC0:
10187 check_mvh(ctx);
10188 {
10189 TCGv t0 = tcg_temp_new();
10190 gen_load_gpr(t0, rt);
10191 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
10192 tcg_temp_free(t0);
10193 }
10194 opn = "mthc0";
10195 break;
10196 case OPC_MFTR:
10197 check_cp0_enabled(ctx);
10198 if (rd == 0) {
10199 /* Treat as NOP. */
10200 return;
10201 }
10202 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
10203 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10204 opn = "mftr";
10205 break;
10206 case OPC_MTTR:
10207 check_cp0_enabled(ctx);
10208 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
10209 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10210 opn = "mttr";
10211 break;
10212 case OPC_TLBWI:
10213 opn = "tlbwi";
10214 if (!env->tlb->helper_tlbwi) {
10215 goto die;
10216 }
10217 gen_helper_tlbwi(cpu_env);
10218 break;
10219 case OPC_TLBINV:
10220 opn = "tlbinv";
10221 if (ctx->ie >= 2) {
10222 if (!env->tlb->helper_tlbinv) {
10223 goto die;
10224 }
10225 gen_helper_tlbinv(cpu_env);
10226 } /* treat as nop if TLBINV not supported */
10227 break;
10228 case OPC_TLBINVF:
10229 opn = "tlbinvf";
10230 if (ctx->ie >= 2) {
10231 if (!env->tlb->helper_tlbinvf) {
10232 goto die;
10233 }
10234 gen_helper_tlbinvf(cpu_env);
10235 } /* treat as nop if TLBINV not supported */
10236 break;
10237 case OPC_TLBWR:
10238 opn = "tlbwr";
10239 if (!env->tlb->helper_tlbwr) {
10240 goto die;
10241 }
10242 gen_helper_tlbwr(cpu_env);
10243 break;
10244 case OPC_TLBP:
10245 opn = "tlbp";
10246 if (!env->tlb->helper_tlbp) {
10247 goto die;
10248 }
10249 gen_helper_tlbp(cpu_env);
10250 break;
10251 case OPC_TLBR:
10252 opn = "tlbr";
10253 if (!env->tlb->helper_tlbr) {
10254 goto die;
10255 }
10256 gen_helper_tlbr(cpu_env);
10257 break;
10258 case OPC_ERET: /* OPC_ERETNC */
10259 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10260 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10261 goto die;
10262 } else {
10263 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
10264 if (ctx->opcode & (1 << bit_shift)) {
10265 /* OPC_ERETNC */
10266 opn = "eretnc";
10267 check_insn(ctx, ISA_MIPS32R5);
10268 gen_helper_eretnc(cpu_env);
10269 } else {
10270 /* OPC_ERET */
10271 opn = "eret";
10272 check_insn(ctx, ISA_MIPS2);
10273 gen_helper_eret(cpu_env);
10274 }
10275 ctx->base.is_jmp = DISAS_EXIT;
10276 }
10277 break;
10278 case OPC_DERET:
10279 opn = "deret";
10280 check_insn(ctx, ISA_MIPS32);
10281 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10282 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10283 goto die;
10284 }
10285 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10286 MIPS_INVAL(opn);
10287 generate_exception_end(ctx, EXCP_RI);
10288 } else {
10289 gen_helper_deret(cpu_env);
10290 ctx->base.is_jmp = DISAS_EXIT;
10291 }
10292 break;
10293 case OPC_WAIT:
10294 opn = "wait";
10295 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
10296 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10297 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10298 goto die;
10299 }
10300 /* If we get an exception, we want to restart at next instruction */
10301 ctx->base.pc_next += 4;
10302 save_cpu_state(ctx, 1);
10303 ctx->base.pc_next -= 4;
10304 gen_helper_wait(cpu_env);
10305 ctx->base.is_jmp = DISAS_NORETURN;
10306 break;
10307 default:
10308 die:
10309 MIPS_INVAL(opn);
10310 generate_exception_end(ctx, EXCP_RI);
10311 return;
10312 }
10313 (void)opn; /* avoid a compiler warning */
10314 }
10315 #endif /* !CONFIG_USER_ONLY */
10316
10317 /* CP1 Branches (before delay slot) */
10318 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
10319 int32_t cc, int32_t offset)
10320 {
10321 target_ulong btarget;
10322 TCGv_i32 t0 = tcg_temp_new_i32();
10323
10324 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
10325 generate_exception_end(ctx, EXCP_RI);
10326 goto out;
10327 }
10328
10329 if (cc != 0) {
10330 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
10331 }
10332
10333 btarget = ctx->base.pc_next + 4 + offset;
10334
10335 switch (op) {
10336 case OPC_BC1F:
10337 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10338 tcg_gen_not_i32(t0, t0);
10339 tcg_gen_andi_i32(t0, t0, 1);
10340 tcg_gen_extu_i32_tl(bcond, t0);
10341 goto not_likely;
10342 case OPC_BC1FL:
10343 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10344 tcg_gen_not_i32(t0, t0);
10345 tcg_gen_andi_i32(t0, t0, 1);
10346 tcg_gen_extu_i32_tl(bcond, t0);
10347 goto likely;
10348 case OPC_BC1T:
10349 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10350 tcg_gen_andi_i32(t0, t0, 1);
10351 tcg_gen_extu_i32_tl(bcond, t0);
10352 goto not_likely;
10353 case OPC_BC1TL:
10354 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10355 tcg_gen_andi_i32(t0, t0, 1);
10356 tcg_gen_extu_i32_tl(bcond, t0);
10357 likely:
10358 ctx->hflags |= MIPS_HFLAG_BL;
10359 break;
10360 case OPC_BC1FANY2:
10361 {
10362 TCGv_i32 t1 = tcg_temp_new_i32();
10363 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10364 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10365 tcg_gen_nand_i32(t0, t0, t1);
10366 tcg_temp_free_i32(t1);
10367 tcg_gen_andi_i32(t0, t0, 1);
10368 tcg_gen_extu_i32_tl(bcond, t0);
10369 }
10370 goto not_likely;
10371 case OPC_BC1TANY2:
10372 {
10373 TCGv_i32 t1 = tcg_temp_new_i32();
10374 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10375 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10376 tcg_gen_or_i32(t0, t0, t1);
10377 tcg_temp_free_i32(t1);
10378 tcg_gen_andi_i32(t0, t0, 1);
10379 tcg_gen_extu_i32_tl(bcond, t0);
10380 }
10381 goto not_likely;
10382 case OPC_BC1FANY4:
10383 {
10384 TCGv_i32 t1 = tcg_temp_new_i32();
10385 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10386 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10387 tcg_gen_and_i32(t0, t0, t1);
10388 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
10389 tcg_gen_and_i32(t0, t0, t1);
10390 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
10391 tcg_gen_nand_i32(t0, t0, t1);
10392 tcg_temp_free_i32(t1);
10393 tcg_gen_andi_i32(t0, t0, 1);
10394 tcg_gen_extu_i32_tl(bcond, t0);
10395 }
10396 goto not_likely;
10397 case OPC_BC1TANY4:
10398 {
10399 TCGv_i32 t1 = tcg_temp_new_i32();
10400 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10401 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10402 tcg_gen_or_i32(t0, t0, t1);
10403 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
10404 tcg_gen_or_i32(t0, t0, t1);
10405 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
10406 tcg_gen_or_i32(t0, t0, t1);
10407 tcg_temp_free_i32(t1);
10408 tcg_gen_andi_i32(t0, t0, 1);
10409 tcg_gen_extu_i32_tl(bcond, t0);
10410 }
10411 not_likely:
10412 ctx->hflags |= MIPS_HFLAG_BC;
10413 break;
10414 default:
10415 MIPS_INVAL("cp1 cond branch");
10416 generate_exception_end(ctx, EXCP_RI);
10417 goto out;
10418 }
10419 ctx->btarget = btarget;
10420 ctx->hflags |= MIPS_HFLAG_BDS32;
10421 out:
10422 tcg_temp_free_i32(t0);
10423 }
10424
10425 /* R6 CP1 Branches */
10426 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
10427 int32_t ft, int32_t offset,
10428 int delayslot_size)
10429 {
10430 target_ulong btarget;
10431 TCGv_i64 t0 = tcg_temp_new_i64();
10432
10433 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10434 #ifdef MIPS_DEBUG_DISAS
10435 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
10436 "\n", ctx->base.pc_next);
10437 #endif
10438 generate_exception_end(ctx, EXCP_RI);
10439 goto out;
10440 }
10441
10442 gen_load_fpr64(ctx, t0, ft);
10443 tcg_gen_andi_i64(t0, t0, 1);
10444
10445 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
10446
10447 switch (op) {
10448 case OPC_BC1EQZ:
10449 tcg_gen_xori_i64(t0, t0, 1);
10450 ctx->hflags |= MIPS_HFLAG_BC;
10451 break;
10452 case OPC_BC1NEZ:
10453 /* t0 already set */
10454 ctx->hflags |= MIPS_HFLAG_BC;
10455 break;
10456 default:
10457 MIPS_INVAL("cp1 cond branch");
10458 generate_exception_end(ctx, EXCP_RI);
10459 goto out;
10460 }
10461
10462 tcg_gen_trunc_i64_tl(bcond, t0);
10463
10464 ctx->btarget = btarget;
10465
10466 switch (delayslot_size) {
10467 case 2:
10468 ctx->hflags |= MIPS_HFLAG_BDS16;
10469 break;
10470 case 4:
10471 ctx->hflags |= MIPS_HFLAG_BDS32;
10472 break;
10473 }
10474
10475 out:
10476 tcg_temp_free_i64(t0);
10477 }
10478
10479 /* Coprocessor 1 (FPU) */
10480
10481 #define FOP(func, fmt) (((fmt) << 21) | (func))
10482
10483 enum fopcode {
10484 OPC_ADD_S = FOP(0, FMT_S),
10485 OPC_SUB_S = FOP(1, FMT_S),
10486 OPC_MUL_S = FOP(2, FMT_S),
10487 OPC_DIV_S = FOP(3, FMT_S),
10488 OPC_SQRT_S = FOP(4, FMT_S),
10489 OPC_ABS_S = FOP(5, FMT_S),
10490 OPC_MOV_S = FOP(6, FMT_S),
10491 OPC_NEG_S = FOP(7, FMT_S),
10492 OPC_ROUND_L_S = FOP(8, FMT_S),
10493 OPC_TRUNC_L_S = FOP(9, FMT_S),
10494 OPC_CEIL_L_S = FOP(10, FMT_S),
10495 OPC_FLOOR_L_S = FOP(11, FMT_S),
10496 OPC_ROUND_W_S = FOP(12, FMT_S),
10497 OPC_TRUNC_W_S = FOP(13, FMT_S),
10498 OPC_CEIL_W_S = FOP(14, FMT_S),
10499 OPC_FLOOR_W_S = FOP(15, FMT_S),
10500 OPC_SEL_S = FOP(16, FMT_S),
10501 OPC_MOVCF_S = FOP(17, FMT_S),
10502 OPC_MOVZ_S = FOP(18, FMT_S),
10503 OPC_MOVN_S = FOP(19, FMT_S),
10504 OPC_SELEQZ_S = FOP(20, FMT_S),
10505 OPC_RECIP_S = FOP(21, FMT_S),
10506 OPC_RSQRT_S = FOP(22, FMT_S),
10507 OPC_SELNEZ_S = FOP(23, FMT_S),
10508 OPC_MADDF_S = FOP(24, FMT_S),
10509 OPC_MSUBF_S = FOP(25, FMT_S),
10510 OPC_RINT_S = FOP(26, FMT_S),
10511 OPC_CLASS_S = FOP(27, FMT_S),
10512 OPC_MIN_S = FOP(28, FMT_S),
10513 OPC_RECIP2_S = FOP(28, FMT_S),
10514 OPC_MINA_S = FOP(29, FMT_S),
10515 OPC_RECIP1_S = FOP(29, FMT_S),
10516 OPC_MAX_S = FOP(30, FMT_S),
10517 OPC_RSQRT1_S = FOP(30, FMT_S),
10518 OPC_MAXA_S = FOP(31, FMT_S),
10519 OPC_RSQRT2_S = FOP(31, FMT_S),
10520 OPC_CVT_D_S = FOP(33, FMT_S),
10521 OPC_CVT_W_S = FOP(36, FMT_S),
10522 OPC_CVT_L_S = FOP(37, FMT_S),
10523 OPC_CVT_PS_S = FOP(38, FMT_S),
10524 OPC_CMP_F_S = FOP(48, FMT_S),
10525 OPC_CMP_UN_S = FOP(49, FMT_S),
10526 OPC_CMP_EQ_S = FOP(50, FMT_S),
10527 OPC_CMP_UEQ_S = FOP(51, FMT_S),
10528 OPC_CMP_OLT_S = FOP(52, FMT_S),
10529 OPC_CMP_ULT_S = FOP(53, FMT_S),
10530 OPC_CMP_OLE_S = FOP(54, FMT_S),
10531 OPC_CMP_ULE_S = FOP(55, FMT_S),
10532 OPC_CMP_SF_S = FOP(56, FMT_S),
10533 OPC_CMP_NGLE_S = FOP(57, FMT_S),
10534 OPC_CMP_SEQ_S = FOP(58, FMT_S),
10535 OPC_CMP_NGL_S = FOP(59, FMT_S),
10536 OPC_CMP_LT_S = FOP(60, FMT_S),
10537 OPC_CMP_NGE_S = FOP(61, FMT_S),
10538 OPC_CMP_LE_S = FOP(62, FMT_S),
10539 OPC_CMP_NGT_S = FOP(63, FMT_S),
10540
10541 OPC_ADD_D = FOP(0, FMT_D),
10542 OPC_SUB_D = FOP(1, FMT_D),
10543 OPC_MUL_D = FOP(2, FMT_D),
10544 OPC_DIV_D = FOP(3, FMT_D),
10545 OPC_SQRT_D = FOP(4, FMT_D),
10546 OPC_ABS_D = FOP(5, FMT_D),
10547 OPC_MOV_D = FOP(6, FMT_D),
10548 OPC_NEG_D = FOP(7, FMT_D),
10549 OPC_ROUND_L_D = FOP(8, FMT_D),
10550 OPC_TRUNC_L_D = FOP(9, FMT_D),
10551 OPC_CEIL_L_D = FOP(10, FMT_D),
10552 OPC_FLOOR_L_D = FOP(11, FMT_D),
10553 OPC_ROUND_W_D = FOP(12, FMT_D),
10554 OPC_TRUNC_W_D = FOP(13, FMT_D),
10555 OPC_CEIL_W_D = FOP(14, FMT_D),
10556 OPC_FLOOR_W_D = FOP(15, FMT_D),
10557 OPC_SEL_D = FOP(16, FMT_D),
10558 OPC_MOVCF_D = FOP(17, FMT_D),
10559 OPC_MOVZ_D = FOP(18, FMT_D),
10560 OPC_MOVN_D = FOP(19, FMT_D),
10561 OPC_SELEQZ_D = FOP(20, FMT_D),
10562 OPC_RECIP_D = FOP(21, FMT_D),
10563 OPC_RSQRT_D = FOP(22, FMT_D),
10564 OPC_SELNEZ_D = FOP(23, FMT_D),
10565 OPC_MADDF_D = FOP(24, FMT_D),
10566 OPC_MSUBF_D = FOP(25, FMT_D),
10567 OPC_RINT_D = FOP(26, FMT_D),
10568 OPC_CLASS_D = FOP(27, FMT_D),
10569 OPC_MIN_D = FOP(28, FMT_D),
10570 OPC_RECIP2_D = FOP(28, FMT_D),
10571 OPC_MINA_D = FOP(29, FMT_D),
10572 OPC_RECIP1_D = FOP(29, FMT_D),
10573 OPC_MAX_D = FOP(30, FMT_D),
10574 OPC_RSQRT1_D = FOP(30, FMT_D),
10575 OPC_MAXA_D = FOP(31, FMT_D),
10576 OPC_RSQRT2_D = FOP(31, FMT_D),
10577 OPC_CVT_S_D = FOP(32, FMT_D),
10578 OPC_CVT_W_D = FOP(36, FMT_D),
10579 OPC_CVT_L_D = FOP(37, FMT_D),
10580 OPC_CMP_F_D = FOP(48, FMT_D),
10581 OPC_CMP_UN_D = FOP(49, FMT_D),
10582 OPC_CMP_EQ_D = FOP(50, FMT_D),
10583 OPC_CMP_UEQ_D = FOP(51, FMT_D),
10584 OPC_CMP_OLT_D = FOP(52, FMT_D),
10585 OPC_CMP_ULT_D = FOP(53, FMT_D),
10586 OPC_CMP_OLE_D = FOP(54, FMT_D),
10587 OPC_CMP_ULE_D = FOP(55, FMT_D),
10588 OPC_CMP_SF_D = FOP(56, FMT_D),
10589 OPC_CMP_NGLE_D = FOP(57, FMT_D),
10590 OPC_CMP_SEQ_D = FOP(58, FMT_D),
10591 OPC_CMP_NGL_D = FOP(59, FMT_D),
10592 OPC_CMP_LT_D = FOP(60, FMT_D),
10593 OPC_CMP_NGE_D = FOP(61, FMT_D),
10594 OPC_CMP_LE_D = FOP(62, FMT_D),
10595 OPC_CMP_NGT_D = FOP(63, FMT_D),
10596
10597 OPC_CVT_S_W = FOP(32, FMT_W),
10598 OPC_CVT_D_W = FOP(33, FMT_W),
10599 OPC_CVT_S_L = FOP(32, FMT_L),
10600 OPC_CVT_D_L = FOP(33, FMT_L),
10601 OPC_CVT_PS_PW = FOP(38, FMT_W),
10602
10603 OPC_ADD_PS = FOP(0, FMT_PS),
10604 OPC_SUB_PS = FOP(1, FMT_PS),
10605 OPC_MUL_PS = FOP(2, FMT_PS),
10606 OPC_DIV_PS = FOP(3, FMT_PS),
10607 OPC_ABS_PS = FOP(5, FMT_PS),
10608 OPC_MOV_PS = FOP(6, FMT_PS),
10609 OPC_NEG_PS = FOP(7, FMT_PS),
10610 OPC_MOVCF_PS = FOP(17, FMT_PS),
10611 OPC_MOVZ_PS = FOP(18, FMT_PS),
10612 OPC_MOVN_PS = FOP(19, FMT_PS),
10613 OPC_ADDR_PS = FOP(24, FMT_PS),
10614 OPC_MULR_PS = FOP(26, FMT_PS),
10615 OPC_RECIP2_PS = FOP(28, FMT_PS),
10616 OPC_RECIP1_PS = FOP(29, FMT_PS),
10617 OPC_RSQRT1_PS = FOP(30, FMT_PS),
10618 OPC_RSQRT2_PS = FOP(31, FMT_PS),
10619
10620 OPC_CVT_S_PU = FOP(32, FMT_PS),
10621 OPC_CVT_PW_PS = FOP(36, FMT_PS),
10622 OPC_CVT_S_PL = FOP(40, FMT_PS),
10623 OPC_PLL_PS = FOP(44, FMT_PS),
10624 OPC_PLU_PS = FOP(45, FMT_PS),
10625 OPC_PUL_PS = FOP(46, FMT_PS),
10626 OPC_PUU_PS = FOP(47, FMT_PS),
10627 OPC_CMP_F_PS = FOP(48, FMT_PS),
10628 OPC_CMP_UN_PS = FOP(49, FMT_PS),
10629 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
10630 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
10631 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
10632 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
10633 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
10634 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
10635 OPC_CMP_SF_PS = FOP(56, FMT_PS),
10636 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
10637 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
10638 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
10639 OPC_CMP_LT_PS = FOP(60, FMT_PS),
10640 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
10641 OPC_CMP_LE_PS = FOP(62, FMT_PS),
10642 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
10643 };
10644
10645 enum r6_f_cmp_op {
10646 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
10647 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
10648 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
10649 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
10650 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
10651 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
10652 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
10653 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
10654 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
10655 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
10656 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
10657 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
10658 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
10659 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
10660 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
10661 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
10662 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
10663 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
10664 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
10665 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
10666 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
10667 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
10668
10669 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
10670 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
10671 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
10672 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
10673 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
10674 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
10675 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
10676 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
10677 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
10678 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
10679 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
10680 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
10681 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
10682 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
10683 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
10684 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
10685 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
10686 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
10687 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
10688 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
10689 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
10690 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
10691 };
10692
10693 static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
10694 {
10695 TCGv t0 = tcg_temp_new();
10696
10697 switch (opc) {
10698 case OPC_MFC1:
10699 {
10700 TCGv_i32 fp0 = tcg_temp_new_i32();
10701
10702 gen_load_fpr32(ctx, fp0, fs);
10703 tcg_gen_ext_i32_tl(t0, fp0);
10704 tcg_temp_free_i32(fp0);
10705 }
10706 gen_store_gpr(t0, rt);
10707 break;
10708 case OPC_MTC1:
10709 gen_load_gpr(t0, rt);
10710 {
10711 TCGv_i32 fp0 = tcg_temp_new_i32();
10712
10713 tcg_gen_trunc_tl_i32(fp0, t0);
10714 gen_store_fpr32(ctx, fp0, fs);
10715 tcg_temp_free_i32(fp0);
10716 }
10717 break;
10718 case OPC_CFC1:
10719 gen_helper_1e0i(cfc1, t0, fs);
10720 gen_store_gpr(t0, rt);
10721 break;
10722 case OPC_CTC1:
10723 gen_load_gpr(t0, rt);
10724 save_cpu_state(ctx, 0);
10725 {
10726 TCGv_i32 fs_tmp = tcg_const_i32(fs);
10727
10728 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10729 tcg_temp_free_i32(fs_tmp);
10730 }
10731 /* Stop translation as we may have changed hflags */
10732 ctx->base.is_jmp = DISAS_STOP;
10733 break;
10734 #if defined(TARGET_MIPS64)
10735 case OPC_DMFC1:
10736 gen_load_fpr64(ctx, t0, fs);
10737 gen_store_gpr(t0, rt);
10738 break;
10739 case OPC_DMTC1:
10740 gen_load_gpr(t0, rt);
10741 gen_store_fpr64(ctx, t0, fs);
10742 break;
10743 #endif
10744 case OPC_MFHC1:
10745 {
10746 TCGv_i32 fp0 = tcg_temp_new_i32();
10747
10748 gen_load_fpr32h(ctx, fp0, fs);
10749 tcg_gen_ext_i32_tl(t0, fp0);
10750 tcg_temp_free_i32(fp0);
10751 }
10752 gen_store_gpr(t0, rt);
10753 break;
10754 case OPC_MTHC1:
10755 gen_load_gpr(t0, rt);
10756 {
10757 TCGv_i32 fp0 = tcg_temp_new_i32();
10758
10759 tcg_gen_trunc_tl_i32(fp0, t0);
10760 gen_store_fpr32h(ctx, fp0, fs);
10761 tcg_temp_free_i32(fp0);
10762 }
10763 break;
10764 default:
10765 MIPS_INVAL("cp1 move");
10766 generate_exception_end(ctx, EXCP_RI);
10767 goto out;
10768 }
10769
10770 out:
10771 tcg_temp_free(t0);
10772 }
10773
10774 static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
10775 {
10776 TCGLabel *l1;
10777 TCGCond cond;
10778 TCGv_i32 t0;
10779
10780 if (rd == 0) {
10781 /* Treat as NOP. */
10782 return;
10783 }
10784
10785 if (tf) {
10786 cond = TCG_COND_EQ;
10787 } else {
10788 cond = TCG_COND_NE;
10789 }
10790
10791 l1 = gen_new_label();
10792 t0 = tcg_temp_new_i32();
10793 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10794 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10795 tcg_temp_free_i32(t0);
10796 if (rs == 0) {
10797 tcg_gen_movi_tl(cpu_gpr[rd], 0);
10798 } else {
10799 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
10800 }
10801 gen_set_label(l1);
10802 }
10803
10804 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
10805 int tf)
10806 {
10807 int cond;
10808 TCGv_i32 t0 = tcg_temp_new_i32();
10809 TCGLabel *l1 = gen_new_label();
10810
10811 if (tf) {
10812 cond = TCG_COND_EQ;
10813 } else {
10814 cond = TCG_COND_NE;
10815 }
10816
10817 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10818 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10819 gen_load_fpr32(ctx, t0, fs);
10820 gen_store_fpr32(ctx, t0, fd);
10821 gen_set_label(l1);
10822 tcg_temp_free_i32(t0);
10823 }
10824
10825 static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
10826 int tf)
10827 {
10828 int cond;
10829 TCGv_i32 t0 = tcg_temp_new_i32();
10830 TCGv_i64 fp0;
10831 TCGLabel *l1 = gen_new_label();
10832
10833 if (tf) {
10834 cond = TCG_COND_EQ;
10835 } else {
10836 cond = TCG_COND_NE;
10837 }
10838
10839 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10840 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10841 tcg_temp_free_i32(t0);
10842 fp0 = tcg_temp_new_i64();
10843 gen_load_fpr64(ctx, fp0, fs);
10844 gen_store_fpr64(ctx, fp0, fd);
10845 tcg_temp_free_i64(fp0);
10846 gen_set_label(l1);
10847 }
10848
10849 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
10850 int cc, int tf)
10851 {
10852 int cond;
10853 TCGv_i32 t0 = tcg_temp_new_i32();
10854 TCGLabel *l1 = gen_new_label();
10855 TCGLabel *l2 = gen_new_label();
10856
10857 if (tf) {
10858 cond = TCG_COND_EQ;
10859 } else {
10860 cond = TCG_COND_NE;
10861 }
10862
10863 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10864 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10865 gen_load_fpr32(ctx, t0, fs);
10866 gen_store_fpr32(ctx, t0, fd);
10867 gen_set_label(l1);
10868
10869 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
10870 tcg_gen_brcondi_i32(cond, t0, 0, l2);
10871 gen_load_fpr32h(ctx, t0, fs);
10872 gen_store_fpr32h(ctx, t0, fd);
10873 tcg_temp_free_i32(t0);
10874 gen_set_label(l2);
10875 }
10876
10877 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10878 int fs)
10879 {
10880 TCGv_i32 t1 = tcg_const_i32(0);
10881 TCGv_i32 fp0 = tcg_temp_new_i32();
10882 TCGv_i32 fp1 = tcg_temp_new_i32();
10883 TCGv_i32 fp2 = tcg_temp_new_i32();
10884 gen_load_fpr32(ctx, fp0, fd);
10885 gen_load_fpr32(ctx, fp1, ft);
10886 gen_load_fpr32(ctx, fp2, fs);
10887
10888 switch (op1) {
10889 case OPC_SEL_S:
10890 tcg_gen_andi_i32(fp0, fp0, 1);
10891 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10892 break;
10893 case OPC_SELEQZ_S:
10894 tcg_gen_andi_i32(fp1, fp1, 1);
10895 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10896 break;
10897 case OPC_SELNEZ_S:
10898 tcg_gen_andi_i32(fp1, fp1, 1);
10899 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10900 break;
10901 default:
10902 MIPS_INVAL("gen_sel_s");
10903 generate_exception_end(ctx, EXCP_RI);
10904 break;
10905 }
10906
10907 gen_store_fpr32(ctx, fp0, fd);
10908 tcg_temp_free_i32(fp2);
10909 tcg_temp_free_i32(fp1);
10910 tcg_temp_free_i32(fp0);
10911 tcg_temp_free_i32(t1);
10912 }
10913
10914 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10915 int fs)
10916 {
10917 TCGv_i64 t1 = tcg_const_i64(0);
10918 TCGv_i64 fp0 = tcg_temp_new_i64();
10919 TCGv_i64 fp1 = tcg_temp_new_i64();
10920 TCGv_i64 fp2 = tcg_temp_new_i64();
10921 gen_load_fpr64(ctx, fp0, fd);
10922 gen_load_fpr64(ctx, fp1, ft);
10923 gen_load_fpr64(ctx, fp2, fs);
10924
10925 switch (op1) {
10926 case OPC_SEL_D:
10927 tcg_gen_andi_i64(fp0, fp0, 1);
10928 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10929 break;
10930 case OPC_SELEQZ_D:
10931 tcg_gen_andi_i64(fp1, fp1, 1);
10932 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10933 break;
10934 case OPC_SELNEZ_D:
10935 tcg_gen_andi_i64(fp1, fp1, 1);
10936 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10937 break;
10938 default:
10939 MIPS_INVAL("gen_sel_d");
10940 generate_exception_end(ctx, EXCP_RI);
10941 break;
10942 }
10943
10944 gen_store_fpr64(ctx, fp0, fd);
10945 tcg_temp_free_i64(fp2);
10946 tcg_temp_free_i64(fp1);
10947 tcg_temp_free_i64(fp0);
10948 tcg_temp_free_i64(t1);
10949 }
10950
10951 static void gen_farith(DisasContext *ctx, enum fopcode op1,
10952 int ft, int fs, int fd, int cc)
10953 {
10954 uint32_t func = ctx->opcode & 0x3f;
10955 switch (op1) {
10956 case OPC_ADD_S:
10957 {
10958 TCGv_i32 fp0 = tcg_temp_new_i32();
10959 TCGv_i32 fp1 = tcg_temp_new_i32();
10960
10961 gen_load_fpr32(ctx, fp0, fs);
10962 gen_load_fpr32(ctx, fp1, ft);
10963 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
10964 tcg_temp_free_i32(fp1);
10965 gen_store_fpr32(ctx, fp0, fd);
10966 tcg_temp_free_i32(fp0);
10967 }
10968 break;
10969 case OPC_SUB_S:
10970 {
10971 TCGv_i32 fp0 = tcg_temp_new_i32();
10972 TCGv_i32 fp1 = tcg_temp_new_i32();
10973
10974 gen_load_fpr32(ctx, fp0, fs);
10975 gen_load_fpr32(ctx, fp1, ft);
10976 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
10977 tcg_temp_free_i32(fp1);
10978 gen_store_fpr32(ctx, fp0, fd);
10979 tcg_temp_free_i32(fp0);
10980 }
10981 break;
10982 case OPC_MUL_S:
10983 {
10984 TCGv_i32 fp0 = tcg_temp_new_i32();
10985 TCGv_i32 fp1 = tcg_temp_new_i32();
10986
10987 gen_load_fpr32(ctx, fp0, fs);
10988 gen_load_fpr32(ctx, fp1, ft);
10989 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
10990 tcg_temp_free_i32(fp1);
10991 gen_store_fpr32(ctx, fp0, fd);
10992 tcg_temp_free_i32(fp0);
10993 }
10994 break;
10995 case OPC_DIV_S:
10996 {
10997 TCGv_i32 fp0 = tcg_temp_new_i32();
10998 TCGv_i32 fp1 = tcg_temp_new_i32();
10999
11000 gen_load_fpr32(ctx, fp0, fs);
11001 gen_load_fpr32(ctx, fp1, ft);
11002 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
11003 tcg_temp_free_i32(fp1);
11004 gen_store_fpr32(ctx, fp0, fd);
11005 tcg_temp_free_i32(fp0);
11006 }
11007 break;
11008 case OPC_SQRT_S:
11009 {
11010 TCGv_i32 fp0 = tcg_temp_new_i32();
11011
11012 gen_load_fpr32(ctx, fp0, fs);
11013 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
11014 gen_store_fpr32(ctx, fp0, fd);
11015 tcg_temp_free_i32(fp0);
11016 }
11017 break;
11018 case OPC_ABS_S:
11019 {
11020 TCGv_i32 fp0 = tcg_temp_new_i32();
11021
11022 gen_load_fpr32(ctx, fp0, fs);
11023 if (ctx->abs2008) {
11024 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
11025 } else {
11026 gen_helper_float_abs_s(fp0, fp0);
11027 }
11028 gen_store_fpr32(ctx, fp0, fd);
11029 tcg_temp_free_i32(fp0);
11030 }
11031 break;
11032 case OPC_MOV_S:
11033 {
11034 TCGv_i32 fp0 = tcg_temp_new_i32();
11035
11036 gen_load_fpr32(ctx, fp0, fs);
11037 gen_store_fpr32(ctx, fp0, fd);
11038 tcg_temp_free_i32(fp0);
11039 }
11040 break;
11041 case OPC_NEG_S:
11042 {
11043 TCGv_i32 fp0 = tcg_temp_new_i32();
11044
11045 gen_load_fpr32(ctx, fp0, fs);
11046 if (ctx->abs2008) {
11047 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
11048 } else {
11049 gen_helper_float_chs_s(fp0, fp0);
11050 }
11051 gen_store_fpr32(ctx, fp0, fd);
11052 tcg_temp_free_i32(fp0);
11053 }
11054 break;
11055 case OPC_ROUND_L_S:
11056 check_cp1_64bitmode(ctx);
11057 {
11058 TCGv_i32 fp32 = tcg_temp_new_i32();
11059 TCGv_i64 fp64 = tcg_temp_new_i64();
11060
11061 gen_load_fpr32(ctx, fp32, fs);
11062 if (ctx->nan2008) {
11063 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
11064 } else {
11065 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
11066 }
11067 tcg_temp_free_i32(fp32);
11068 gen_store_fpr64(ctx, fp64, fd);
11069 tcg_temp_free_i64(fp64);
11070 }
11071 break;
11072 case OPC_TRUNC_L_S:
11073 check_cp1_64bitmode(ctx);
11074 {
11075 TCGv_i32 fp32 = tcg_temp_new_i32();
11076 TCGv_i64 fp64 = tcg_temp_new_i64();
11077
11078 gen_load_fpr32(ctx, fp32, fs);
11079 if (ctx->nan2008) {
11080 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
11081 } else {
11082 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
11083 }
11084 tcg_temp_free_i32(fp32);
11085 gen_store_fpr64(ctx, fp64, fd);
11086 tcg_temp_free_i64(fp64);
11087 }
11088 break;
11089 case OPC_CEIL_L_S:
11090 check_cp1_64bitmode(ctx);
11091 {
11092 TCGv_i32 fp32 = tcg_temp_new_i32();
11093 TCGv_i64 fp64 = tcg_temp_new_i64();
11094
11095 gen_load_fpr32(ctx, fp32, fs);
11096 if (ctx->nan2008) {
11097 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
11098 } else {
11099 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
11100 }
11101 tcg_temp_free_i32(fp32);
11102 gen_store_fpr64(ctx, fp64, fd);
11103 tcg_temp_free_i64(fp64);
11104 }
11105 break;
11106 case OPC_FLOOR_L_S:
11107 check_cp1_64bitmode(ctx);
11108 {
11109 TCGv_i32 fp32 = tcg_temp_new_i32();
11110 TCGv_i64 fp64 = tcg_temp_new_i64();
11111
11112 gen_load_fpr32(ctx, fp32, fs);
11113 if (ctx->nan2008) {
11114 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
11115 } else {
11116 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
11117 }
11118 tcg_temp_free_i32(fp32);
11119 gen_store_fpr64(ctx, fp64, fd);
11120 tcg_temp_free_i64(fp64);
11121 }
11122 break;
11123 case OPC_ROUND_W_S:
11124 {
11125 TCGv_i32 fp0 = tcg_temp_new_i32();
11126
11127 gen_load_fpr32(ctx, fp0, fs);
11128 if (ctx->nan2008) {
11129 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
11130 } else {
11131 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
11132 }
11133 gen_store_fpr32(ctx, fp0, fd);
11134 tcg_temp_free_i32(fp0);
11135 }
11136 break;
11137 case OPC_TRUNC_W_S:
11138 {
11139 TCGv_i32 fp0 = tcg_temp_new_i32();
11140
11141 gen_load_fpr32(ctx, fp0, fs);
11142 if (ctx->nan2008) {
11143 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
11144 } else {
11145 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
11146 }
11147 gen_store_fpr32(ctx, fp0, fd);
11148 tcg_temp_free_i32(fp0);
11149 }
11150 break;
11151 case OPC_CEIL_W_S:
11152 {
11153 TCGv_i32 fp0 = tcg_temp_new_i32();
11154
11155 gen_load_fpr32(ctx, fp0, fs);
11156 if (ctx->nan2008) {
11157 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
11158 } else {
11159 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
11160 }
11161 gen_store_fpr32(ctx, fp0, fd);
11162 tcg_temp_free_i32(fp0);
11163 }
11164 break;
11165 case OPC_FLOOR_W_S:
11166 {
11167 TCGv_i32 fp0 = tcg_temp_new_i32();
11168
11169 gen_load_fpr32(ctx, fp0, fs);
11170 if (ctx->nan2008) {
11171 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
11172 } else {
11173 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
11174 }
11175 gen_store_fpr32(ctx, fp0, fd);
11176 tcg_temp_free_i32(fp0);
11177 }
11178 break;
11179 case OPC_SEL_S:
11180 check_insn(ctx, ISA_MIPS32R6);
11181 gen_sel_s(ctx, op1, fd, ft, fs);
11182 break;
11183 case OPC_SELEQZ_S:
11184 check_insn(ctx, ISA_MIPS32R6);
11185 gen_sel_s(ctx, op1, fd, ft, fs);
11186 break;
11187 case OPC_SELNEZ_S:
11188 check_insn(ctx, ISA_MIPS32R6);
11189 gen_sel_s(ctx, op1, fd, ft, fs);
11190 break;
11191 case OPC_MOVCF_S:
11192 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11193 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11194 break;
11195 case OPC_MOVZ_S:
11196 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11197 {
11198 TCGLabel *l1 = gen_new_label();
11199 TCGv_i32 fp0;
11200
11201 if (ft != 0) {
11202 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11203 }
11204 fp0 = tcg_temp_new_i32();
11205 gen_load_fpr32(ctx, fp0, fs);
11206 gen_store_fpr32(ctx, fp0, fd);
11207 tcg_temp_free_i32(fp0);
11208 gen_set_label(l1);
11209 }
11210 break;
11211 case OPC_MOVN_S:
11212 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11213 {
11214 TCGLabel *l1 = gen_new_label();
11215 TCGv_i32 fp0;
11216
11217 if (ft != 0) {
11218 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11219 fp0 = tcg_temp_new_i32();
11220 gen_load_fpr32(ctx, fp0, fs);
11221 gen_store_fpr32(ctx, fp0, fd);
11222 tcg_temp_free_i32(fp0);
11223 gen_set_label(l1);
11224 }
11225 }
11226 break;
11227 case OPC_RECIP_S:
11228 {
11229 TCGv_i32 fp0 = tcg_temp_new_i32();
11230
11231 gen_load_fpr32(ctx, fp0, fs);
11232 gen_helper_float_recip_s(fp0, cpu_env, fp0);
11233 gen_store_fpr32(ctx, fp0, fd);
11234 tcg_temp_free_i32(fp0);
11235 }
11236 break;
11237 case OPC_RSQRT_S:
11238 {
11239 TCGv_i32 fp0 = tcg_temp_new_i32();
11240
11241 gen_load_fpr32(ctx, fp0, fs);
11242 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
11243 gen_store_fpr32(ctx, fp0, fd);
11244 tcg_temp_free_i32(fp0);
11245 }
11246 break;
11247 case OPC_MADDF_S:
11248 check_insn(ctx, ISA_MIPS32R6);
11249 {
11250 TCGv_i32 fp0 = tcg_temp_new_i32();
11251 TCGv_i32 fp1 = tcg_temp_new_i32();
11252 TCGv_i32 fp2 = tcg_temp_new_i32();
11253 gen_load_fpr32(ctx, fp0, fs);
11254 gen_load_fpr32(ctx, fp1, ft);
11255 gen_load_fpr32(ctx, fp2, fd);
11256 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
11257 gen_store_fpr32(ctx, fp2, fd);
11258 tcg_temp_free_i32(fp2);
11259 tcg_temp_free_i32(fp1);
11260 tcg_temp_free_i32(fp0);
11261 }
11262 break;
11263 case OPC_MSUBF_S:
11264 check_insn(ctx, ISA_MIPS32R6);
11265 {
11266 TCGv_i32 fp0 = tcg_temp_new_i32();
11267 TCGv_i32 fp1 = tcg_temp_new_i32();
11268 TCGv_i32 fp2 = tcg_temp_new_i32();
11269 gen_load_fpr32(ctx, fp0, fs);
11270 gen_load_fpr32(ctx, fp1, ft);
11271 gen_load_fpr32(ctx, fp2, fd);
11272 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
11273 gen_store_fpr32(ctx, fp2, fd);
11274 tcg_temp_free_i32(fp2);
11275 tcg_temp_free_i32(fp1);
11276 tcg_temp_free_i32(fp0);
11277 }
11278 break;
11279 case OPC_RINT_S:
11280 check_insn(ctx, ISA_MIPS32R6);
11281 {
11282 TCGv_i32 fp0 = tcg_temp_new_i32();
11283 gen_load_fpr32(ctx, fp0, fs);
11284 gen_helper_float_rint_s(fp0, cpu_env, fp0);
11285 gen_store_fpr32(ctx, fp0, fd);
11286 tcg_temp_free_i32(fp0);
11287 }
11288 break;
11289 case OPC_CLASS_S:
11290 check_insn(ctx, ISA_MIPS32R6);
11291 {
11292 TCGv_i32 fp0 = tcg_temp_new_i32();
11293 gen_load_fpr32(ctx, fp0, fs);
11294 gen_helper_float_class_s(fp0, cpu_env, fp0);
11295 gen_store_fpr32(ctx, fp0, fd);
11296 tcg_temp_free_i32(fp0);
11297 }
11298 break;
11299 case OPC_MIN_S: /* OPC_RECIP2_S */
11300 if (ctx->insn_flags & ISA_MIPS32R6) {
11301 /* OPC_MIN_S */
11302 TCGv_i32 fp0 = tcg_temp_new_i32();
11303 TCGv_i32 fp1 = tcg_temp_new_i32();
11304 TCGv_i32 fp2 = tcg_temp_new_i32();
11305 gen_load_fpr32(ctx, fp0, fs);
11306 gen_load_fpr32(ctx, fp1, ft);
11307 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
11308 gen_store_fpr32(ctx, fp2, fd);
11309 tcg_temp_free_i32(fp2);
11310 tcg_temp_free_i32(fp1);
11311 tcg_temp_free_i32(fp0);
11312 } else {
11313 /* OPC_RECIP2_S */
11314 check_cp1_64bitmode(ctx);
11315 {
11316 TCGv_i32 fp0 = tcg_temp_new_i32();
11317 TCGv_i32 fp1 = tcg_temp_new_i32();
11318
11319 gen_load_fpr32(ctx, fp0, fs);
11320 gen_load_fpr32(ctx, fp1, ft);
11321 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
11322 tcg_temp_free_i32(fp1);
11323 gen_store_fpr32(ctx, fp0, fd);
11324 tcg_temp_free_i32(fp0);
11325 }
11326 }
11327 break;
11328 case OPC_MINA_S: /* OPC_RECIP1_S */
11329 if (ctx->insn_flags & ISA_MIPS32R6) {
11330 /* OPC_MINA_S */
11331 TCGv_i32 fp0 = tcg_temp_new_i32();
11332 TCGv_i32 fp1 = tcg_temp_new_i32();
11333 TCGv_i32 fp2 = tcg_temp_new_i32();
11334 gen_load_fpr32(ctx, fp0, fs);
11335 gen_load_fpr32(ctx, fp1, ft);
11336 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
11337 gen_store_fpr32(ctx, fp2, fd);
11338 tcg_temp_free_i32(fp2);
11339 tcg_temp_free_i32(fp1);
11340 tcg_temp_free_i32(fp0);
11341 } else {
11342 /* OPC_RECIP1_S */
11343 check_cp1_64bitmode(ctx);
11344 {
11345 TCGv_i32 fp0 = tcg_temp_new_i32();
11346
11347 gen_load_fpr32(ctx, fp0, fs);
11348 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
11349 gen_store_fpr32(ctx, fp0, fd);
11350 tcg_temp_free_i32(fp0);
11351 }
11352 }
11353 break;
11354 case OPC_MAX_S: /* OPC_RSQRT1_S */
11355 if (ctx->insn_flags & ISA_MIPS32R6) {
11356 /* OPC_MAX_S */
11357 TCGv_i32 fp0 = tcg_temp_new_i32();
11358 TCGv_i32 fp1 = tcg_temp_new_i32();
11359 gen_load_fpr32(ctx, fp0, fs);
11360 gen_load_fpr32(ctx, fp1, ft);
11361 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
11362 gen_store_fpr32(ctx, fp1, fd);
11363 tcg_temp_free_i32(fp1);
11364 tcg_temp_free_i32(fp0);
11365 } else {
11366 /* OPC_RSQRT1_S */
11367 check_cp1_64bitmode(ctx);
11368 {
11369 TCGv_i32 fp0 = tcg_temp_new_i32();
11370
11371 gen_load_fpr32(ctx, fp0, fs);
11372 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
11373 gen_store_fpr32(ctx, fp0, fd);
11374 tcg_temp_free_i32(fp0);
11375 }
11376 }
11377 break;
11378 case OPC_MAXA_S: /* OPC_RSQRT2_S */
11379 if (ctx->insn_flags & ISA_MIPS32R6) {
11380 /* OPC_MAXA_S */
11381 TCGv_i32 fp0 = tcg_temp_new_i32();
11382 TCGv_i32 fp1 = tcg_temp_new_i32();
11383 gen_load_fpr32(ctx, fp0, fs);
11384 gen_load_fpr32(ctx, fp1, ft);
11385 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
11386 gen_store_fpr32(ctx, fp1, fd);
11387 tcg_temp_free_i32(fp1);
11388 tcg_temp_free_i32(fp0);
11389 } else {
11390 /* OPC_RSQRT2_S */
11391 check_cp1_64bitmode(ctx);
11392 {
11393 TCGv_i32 fp0 = tcg_temp_new_i32();
11394 TCGv_i32 fp1 = tcg_temp_new_i32();
11395
11396 gen_load_fpr32(ctx, fp0, fs);
11397 gen_load_fpr32(ctx, fp1, ft);
11398 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
11399 tcg_temp_free_i32(fp1);
11400 gen_store_fpr32(ctx, fp0, fd);
11401 tcg_temp_free_i32(fp0);
11402 }
11403 }
11404 break;
11405 case OPC_CVT_D_S:
11406 check_cp1_registers(ctx, fd);
11407 {
11408 TCGv_i32 fp32 = tcg_temp_new_i32();
11409 TCGv_i64 fp64 = tcg_temp_new_i64();
11410
11411 gen_load_fpr32(ctx, fp32, fs);
11412 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
11413 tcg_temp_free_i32(fp32);
11414 gen_store_fpr64(ctx, fp64, fd);
11415 tcg_temp_free_i64(fp64);
11416 }
11417 break;
11418 case OPC_CVT_W_S:
11419 {
11420 TCGv_i32 fp0 = tcg_temp_new_i32();
11421
11422 gen_load_fpr32(ctx, fp0, fs);
11423 if (ctx->nan2008) {
11424 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
11425 } else {
11426 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
11427 }
11428 gen_store_fpr32(ctx, fp0, fd);
11429 tcg_temp_free_i32(fp0);
11430 }
11431 break;
11432 case OPC_CVT_L_S:
11433 check_cp1_64bitmode(ctx);
11434 {
11435 TCGv_i32 fp32 = tcg_temp_new_i32();
11436 TCGv_i64 fp64 = tcg_temp_new_i64();
11437
11438 gen_load_fpr32(ctx, fp32, fs);
11439 if (ctx->nan2008) {
11440 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
11441 } else {
11442 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
11443 }
11444 tcg_temp_free_i32(fp32);
11445 gen_store_fpr64(ctx, fp64, fd);
11446 tcg_temp_free_i64(fp64);
11447 }
11448 break;
11449 case OPC_CVT_PS_S:
11450 check_ps(ctx);
11451 {
11452 TCGv_i64 fp64 = tcg_temp_new_i64();
11453 TCGv_i32 fp32_0 = tcg_temp_new_i32();
11454 TCGv_i32 fp32_1 = tcg_temp_new_i32();
11455
11456 gen_load_fpr32(ctx, fp32_0, fs);
11457 gen_load_fpr32(ctx, fp32_1, ft);
11458 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
11459 tcg_temp_free_i32(fp32_1);
11460 tcg_temp_free_i32(fp32_0);
11461 gen_store_fpr64(ctx, fp64, fd);
11462 tcg_temp_free_i64(fp64);
11463 }
11464 break;
11465 case OPC_CMP_F_S:
11466 case OPC_CMP_UN_S:
11467 case OPC_CMP_EQ_S:
11468 case OPC_CMP_UEQ_S:
11469 case OPC_CMP_OLT_S:
11470 case OPC_CMP_ULT_S:
11471 case OPC_CMP_OLE_S:
11472 case OPC_CMP_ULE_S:
11473 case OPC_CMP_SF_S:
11474 case OPC_CMP_NGLE_S:
11475 case OPC_CMP_SEQ_S:
11476 case OPC_CMP_NGL_S:
11477 case OPC_CMP_LT_S:
11478 case OPC_CMP_NGE_S:
11479 case OPC_CMP_LE_S:
11480 case OPC_CMP_NGT_S:
11481 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11482 if (ctx->opcode & (1 << 6)) {
11483 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
11484 } else {
11485 gen_cmp_s(ctx, func-48, ft, fs, cc);
11486 }
11487 break;
11488 case OPC_ADD_D:
11489 check_cp1_registers(ctx, fs | ft | fd);
11490 {
11491 TCGv_i64 fp0 = tcg_temp_new_i64();
11492 TCGv_i64 fp1 = tcg_temp_new_i64();
11493
11494 gen_load_fpr64(ctx, fp0, fs);
11495 gen_load_fpr64(ctx, fp1, ft);
11496 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
11497 tcg_temp_free_i64(fp1);
11498 gen_store_fpr64(ctx, fp0, fd);
11499 tcg_temp_free_i64(fp0);
11500 }
11501 break;
11502 case OPC_SUB_D:
11503 check_cp1_registers(ctx, fs | ft | fd);
11504 {
11505 TCGv_i64 fp0 = tcg_temp_new_i64();
11506 TCGv_i64 fp1 = tcg_temp_new_i64();
11507
11508 gen_load_fpr64(ctx, fp0, fs);
11509 gen_load_fpr64(ctx, fp1, ft);
11510 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
11511 tcg_temp_free_i64(fp1);
11512 gen_store_fpr64(ctx, fp0, fd);
11513 tcg_temp_free_i64(fp0);
11514 }
11515 break;
11516 case OPC_MUL_D:
11517 check_cp1_registers(ctx, fs | ft | fd);
11518 {
11519 TCGv_i64 fp0 = tcg_temp_new_i64();
11520 TCGv_i64 fp1 = tcg_temp_new_i64();
11521
11522 gen_load_fpr64(ctx, fp0, fs);
11523 gen_load_fpr64(ctx, fp1, ft);
11524 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
11525 tcg_temp_free_i64(fp1);
11526 gen_store_fpr64(ctx, fp0, fd);
11527 tcg_temp_free_i64(fp0);
11528 }
11529 break;
11530 case OPC_DIV_D:
11531 check_cp1_registers(ctx, fs | ft | fd);
11532 {
11533 TCGv_i64 fp0 = tcg_temp_new_i64();
11534 TCGv_i64 fp1 = tcg_temp_new_i64();
11535
11536 gen_load_fpr64(ctx, fp0, fs);
11537 gen_load_fpr64(ctx, fp1, ft);
11538 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
11539 tcg_temp_free_i64(fp1);
11540 gen_store_fpr64(ctx, fp0, fd);
11541 tcg_temp_free_i64(fp0);
11542 }
11543 break;
11544 case OPC_SQRT_D:
11545 check_cp1_registers(ctx, fs | fd);
11546 {
11547 TCGv_i64 fp0 = tcg_temp_new_i64();
11548
11549 gen_load_fpr64(ctx, fp0, fs);
11550 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
11551 gen_store_fpr64(ctx, fp0, fd);
11552 tcg_temp_free_i64(fp0);
11553 }
11554 break;
11555 case OPC_ABS_D:
11556 check_cp1_registers(ctx, fs | fd);
11557 {
11558 TCGv_i64 fp0 = tcg_temp_new_i64();
11559
11560 gen_load_fpr64(ctx, fp0, fs);
11561 if (ctx->abs2008) {
11562 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
11563 } else {
11564 gen_helper_float_abs_d(fp0, fp0);
11565 }
11566 gen_store_fpr64(ctx, fp0, fd);
11567 tcg_temp_free_i64(fp0);
11568 }
11569 break;
11570 case OPC_MOV_D:
11571 check_cp1_registers(ctx, fs | fd);
11572 {
11573 TCGv_i64 fp0 = tcg_temp_new_i64();
11574
11575 gen_load_fpr64(ctx, fp0, fs);
11576 gen_store_fpr64(ctx, fp0, fd);
11577 tcg_temp_free_i64(fp0);
11578 }
11579 break;
11580 case OPC_NEG_D:
11581 check_cp1_registers(ctx, fs | fd);
11582 {
11583 TCGv_i64 fp0 = tcg_temp_new_i64();
11584
11585 gen_load_fpr64(ctx, fp0, fs);
11586 if (ctx->abs2008) {
11587 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
11588 } else {
11589 gen_helper_float_chs_d(fp0, fp0);
11590 }
11591 gen_store_fpr64(ctx, fp0, fd);
11592 tcg_temp_free_i64(fp0);
11593 }
11594 break;
11595 case OPC_ROUND_L_D:
11596 check_cp1_64bitmode(ctx);
11597 {
11598 TCGv_i64 fp0 = tcg_temp_new_i64();
11599
11600 gen_load_fpr64(ctx, fp0, fs);
11601 if (ctx->nan2008) {
11602 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
11603 } else {
11604 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
11605 }
11606 gen_store_fpr64(ctx, fp0, fd);
11607 tcg_temp_free_i64(fp0);
11608 }
11609 break;
11610 case OPC_TRUNC_L_D:
11611 check_cp1_64bitmode(ctx);
11612 {
11613 TCGv_i64 fp0 = tcg_temp_new_i64();
11614
11615 gen_load_fpr64(ctx, fp0, fs);
11616 if (ctx->nan2008) {
11617 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
11618 } else {
11619 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
11620 }
11621 gen_store_fpr64(ctx, fp0, fd);
11622 tcg_temp_free_i64(fp0);
11623 }
11624 break;
11625 case OPC_CEIL_L_D:
11626 check_cp1_64bitmode(ctx);
11627 {
11628 TCGv_i64 fp0 = tcg_temp_new_i64();
11629
11630 gen_load_fpr64(ctx, fp0, fs);
11631 if (ctx->nan2008) {
11632 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
11633 } else {
11634 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
11635 }
11636 gen_store_fpr64(ctx, fp0, fd);
11637 tcg_temp_free_i64(fp0);
11638 }
11639 break;
11640 case OPC_FLOOR_L_D:
11641 check_cp1_64bitmode(ctx);
11642 {
11643 TCGv_i64 fp0 = tcg_temp_new_i64();
11644
11645 gen_load_fpr64(ctx, fp0, fs);
11646 if (ctx->nan2008) {
11647 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
11648 } else {
11649 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
11650 }
11651 gen_store_fpr64(ctx, fp0, fd);
11652 tcg_temp_free_i64(fp0);
11653 }
11654 break;
11655 case OPC_ROUND_W_D:
11656 check_cp1_registers(ctx, fs);
11657 {
11658 TCGv_i32 fp32 = tcg_temp_new_i32();
11659 TCGv_i64 fp64 = tcg_temp_new_i64();
11660
11661 gen_load_fpr64(ctx, fp64, fs);
11662 if (ctx->nan2008) {
11663 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
11664 } else {
11665 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
11666 }
11667 tcg_temp_free_i64(fp64);
11668 gen_store_fpr32(ctx, fp32, fd);
11669 tcg_temp_free_i32(fp32);
11670 }
11671 break;
11672 case OPC_TRUNC_W_D:
11673 check_cp1_registers(ctx, fs);
11674 {
11675 TCGv_i32 fp32 = tcg_temp_new_i32();
11676 TCGv_i64 fp64 = tcg_temp_new_i64();
11677
11678 gen_load_fpr64(ctx, fp64, fs);
11679 if (ctx->nan2008) {
11680 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
11681 } else {
11682 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
11683 }
11684 tcg_temp_free_i64(fp64);
11685 gen_store_fpr32(ctx, fp32, fd);
11686 tcg_temp_free_i32(fp32);
11687 }
11688 break;
11689 case OPC_CEIL_W_D:
11690 check_cp1_registers(ctx, fs);
11691 {
11692 TCGv_i32 fp32 = tcg_temp_new_i32();
11693 TCGv_i64 fp64 = tcg_temp_new_i64();
11694
11695 gen_load_fpr64(ctx, fp64, fs);
11696 if (ctx->nan2008) {
11697 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
11698 } else {
11699 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
11700 }
11701 tcg_temp_free_i64(fp64);
11702 gen_store_fpr32(ctx, fp32, fd);
11703 tcg_temp_free_i32(fp32);
11704 }
11705 break;
11706 case OPC_FLOOR_W_D:
11707 check_cp1_registers(ctx, fs);
11708 {
11709 TCGv_i32 fp32 = tcg_temp_new_i32();
11710 TCGv_i64 fp64 = tcg_temp_new_i64();
11711
11712 gen_load_fpr64(ctx, fp64, fs);
11713 if (ctx->nan2008) {
11714 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
11715 } else {
11716 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
11717 }
11718 tcg_temp_free_i64(fp64);
11719 gen_store_fpr32(ctx, fp32, fd);
11720 tcg_temp_free_i32(fp32);
11721 }
11722 break;
11723 case OPC_SEL_D:
11724 check_insn(ctx, ISA_MIPS32R6);
11725 gen_sel_d(ctx, op1, fd, ft, fs);
11726 break;
11727 case OPC_SELEQZ_D:
11728 check_insn(ctx, ISA_MIPS32R6);
11729 gen_sel_d(ctx, op1, fd, ft, fs);
11730 break;
11731 case OPC_SELNEZ_D:
11732 check_insn(ctx, ISA_MIPS32R6);
11733 gen_sel_d(ctx, op1, fd, ft, fs);
11734 break;
11735 case OPC_MOVCF_D:
11736 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11737 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11738 break;
11739 case OPC_MOVZ_D:
11740 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11741 {
11742 TCGLabel *l1 = gen_new_label();
11743 TCGv_i64 fp0;
11744
11745 if (ft != 0) {
11746 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11747 }
11748 fp0 = tcg_temp_new_i64();
11749 gen_load_fpr64(ctx, fp0, fs);
11750 gen_store_fpr64(ctx, fp0, fd);
11751 tcg_temp_free_i64(fp0);
11752 gen_set_label(l1);
11753 }
11754 break;
11755 case OPC_MOVN_D:
11756 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11757 {
11758 TCGLabel *l1 = gen_new_label();
11759 TCGv_i64 fp0;
11760
11761 if (ft != 0) {
11762 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11763 fp0 = tcg_temp_new_i64();
11764 gen_load_fpr64(ctx, fp0, fs);
11765 gen_store_fpr64(ctx, fp0, fd);
11766 tcg_temp_free_i64(fp0);
11767 gen_set_label(l1);
11768 }
11769 }
11770 break;
11771 case OPC_RECIP_D:
11772 check_cp1_registers(ctx, fs | fd);
11773 {
11774 TCGv_i64 fp0 = tcg_temp_new_i64();
11775
11776 gen_load_fpr64(ctx, fp0, fs);
11777 gen_helper_float_recip_d(fp0, cpu_env, fp0);
11778 gen_store_fpr64(ctx, fp0, fd);
11779 tcg_temp_free_i64(fp0);
11780 }
11781 break;
11782 case OPC_RSQRT_D:
11783 check_cp1_registers(ctx, fs | fd);
11784 {
11785 TCGv_i64 fp0 = tcg_temp_new_i64();
11786
11787 gen_load_fpr64(ctx, fp0, fs);
11788 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
11789 gen_store_fpr64(ctx, fp0, fd);
11790 tcg_temp_free_i64(fp0);
11791 }
11792 break;
11793 case OPC_MADDF_D:
11794 check_insn(ctx, ISA_MIPS32R6);
11795 {
11796 TCGv_i64 fp0 = tcg_temp_new_i64();
11797 TCGv_i64 fp1 = tcg_temp_new_i64();
11798 TCGv_i64 fp2 = tcg_temp_new_i64();
11799 gen_load_fpr64(ctx, fp0, fs);
11800 gen_load_fpr64(ctx, fp1, ft);
11801 gen_load_fpr64(ctx, fp2, fd);
11802 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
11803 gen_store_fpr64(ctx, fp2, fd);
11804 tcg_temp_free_i64(fp2);
11805 tcg_temp_free_i64(fp1);
11806 tcg_temp_free_i64(fp0);
11807 }
11808 break;
11809 case OPC_MSUBF_D:
11810 check_insn(ctx, ISA_MIPS32R6);
11811 {
11812 TCGv_i64 fp0 = tcg_temp_new_i64();
11813 TCGv_i64 fp1 = tcg_temp_new_i64();
11814 TCGv_i64 fp2 = tcg_temp_new_i64();
11815 gen_load_fpr64(ctx, fp0, fs);
11816 gen_load_fpr64(ctx, fp1, ft);
11817 gen_load_fpr64(ctx, fp2, fd);
11818 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
11819 gen_store_fpr64(ctx, fp2, fd);
11820 tcg_temp_free_i64(fp2);
11821 tcg_temp_free_i64(fp1);
11822 tcg_temp_free_i64(fp0);
11823 }
11824 break;
11825 case OPC_RINT_D:
11826 check_insn(ctx, ISA_MIPS32R6);
11827 {
11828 TCGv_i64 fp0 = tcg_temp_new_i64();
11829 gen_load_fpr64(ctx, fp0, fs);
11830 gen_helper_float_rint_d(fp0, cpu_env, fp0);
11831 gen_store_fpr64(ctx, fp0, fd);
11832 tcg_temp_free_i64(fp0);
11833 }
11834 break;
11835 case OPC_CLASS_D:
11836 check_insn(ctx, ISA_MIPS32R6);
11837 {
11838 TCGv_i64 fp0 = tcg_temp_new_i64();
11839 gen_load_fpr64(ctx, fp0, fs);
11840 gen_helper_float_class_d(fp0, cpu_env, fp0);
11841 gen_store_fpr64(ctx, fp0, fd);
11842 tcg_temp_free_i64(fp0);
11843 }
11844 break;
11845 case OPC_MIN_D: /* OPC_RECIP2_D */
11846 if (ctx->insn_flags & ISA_MIPS32R6) {
11847 /* OPC_MIN_D */
11848 TCGv_i64 fp0 = tcg_temp_new_i64();
11849 TCGv_i64 fp1 = tcg_temp_new_i64();
11850 gen_load_fpr64(ctx, fp0, fs);
11851 gen_load_fpr64(ctx, fp1, ft);
11852 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
11853 gen_store_fpr64(ctx, fp1, fd);
11854 tcg_temp_free_i64(fp1);
11855 tcg_temp_free_i64(fp0);
11856 } else {
11857 /* OPC_RECIP2_D */
11858 check_cp1_64bitmode(ctx);
11859 {
11860 TCGv_i64 fp0 = tcg_temp_new_i64();
11861 TCGv_i64 fp1 = tcg_temp_new_i64();
11862
11863 gen_load_fpr64(ctx, fp0, fs);
11864 gen_load_fpr64(ctx, fp1, ft);
11865 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
11866 tcg_temp_free_i64(fp1);
11867 gen_store_fpr64(ctx, fp0, fd);
11868 tcg_temp_free_i64(fp0);
11869 }
11870 }
11871 break;
11872 case OPC_MINA_D: /* OPC_RECIP1_D */
11873 if (ctx->insn_flags & ISA_MIPS32R6) {
11874 /* OPC_MINA_D */
11875 TCGv_i64 fp0 = tcg_temp_new_i64();
11876 TCGv_i64 fp1 = tcg_temp_new_i64();
11877 gen_load_fpr64(ctx, fp0, fs);
11878 gen_load_fpr64(ctx, fp1, ft);
11879 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
11880 gen_store_fpr64(ctx, fp1, fd);
11881 tcg_temp_free_i64(fp1);
11882 tcg_temp_free_i64(fp0);
11883 } else {
11884 /* OPC_RECIP1_D */
11885 check_cp1_64bitmode(ctx);
11886 {
11887 TCGv_i64 fp0 = tcg_temp_new_i64();
11888
11889 gen_load_fpr64(ctx, fp0, fs);
11890 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
11891 gen_store_fpr64(ctx, fp0, fd);
11892 tcg_temp_free_i64(fp0);
11893 }
11894 }
11895 break;
11896 case OPC_MAX_D: /* OPC_RSQRT1_D */
11897 if (ctx->insn_flags & ISA_MIPS32R6) {
11898 /* OPC_MAX_D */
11899 TCGv_i64 fp0 = tcg_temp_new_i64();
11900 TCGv_i64 fp1 = tcg_temp_new_i64();
11901 gen_load_fpr64(ctx, fp0, fs);
11902 gen_load_fpr64(ctx, fp1, ft);
11903 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
11904 gen_store_fpr64(ctx, fp1, fd);
11905 tcg_temp_free_i64(fp1);
11906 tcg_temp_free_i64(fp0);
11907 } else {
11908 /* OPC_RSQRT1_D */
11909 check_cp1_64bitmode(ctx);
11910 {
11911 TCGv_i64 fp0 = tcg_temp_new_i64();
11912
11913 gen_load_fpr64(ctx, fp0, fs);
11914 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
11915 gen_store_fpr64(ctx, fp0, fd);
11916 tcg_temp_free_i64(fp0);
11917 }
11918 }
11919 break;
11920 case OPC_MAXA_D: /* OPC_RSQRT2_D */
11921 if (ctx->insn_flags & ISA_MIPS32R6) {
11922 /* OPC_MAXA_D */
11923 TCGv_i64 fp0 = tcg_temp_new_i64();
11924 TCGv_i64 fp1 = tcg_temp_new_i64();
11925 gen_load_fpr64(ctx, fp0, fs);
11926 gen_load_fpr64(ctx, fp1, ft);
11927 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
11928 gen_store_fpr64(ctx, fp1, fd);
11929 tcg_temp_free_i64(fp1);
11930 tcg_temp_free_i64(fp0);
11931 } else {
11932 /* OPC_RSQRT2_D */
11933 check_cp1_64bitmode(ctx);
11934 {
11935 TCGv_i64 fp0 = tcg_temp_new_i64();
11936 TCGv_i64 fp1 = tcg_temp_new_i64();
11937
11938 gen_load_fpr64(ctx, fp0, fs);
11939 gen_load_fpr64(ctx, fp1, ft);
11940 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
11941 tcg_temp_free_i64(fp1);
11942 gen_store_fpr64(ctx, fp0, fd);
11943 tcg_temp_free_i64(fp0);
11944 }
11945 }
11946 break;
11947 case OPC_CMP_F_D:
11948 case OPC_CMP_UN_D:
11949 case OPC_CMP_EQ_D:
11950 case OPC_CMP_UEQ_D:
11951 case OPC_CMP_OLT_D:
11952 case OPC_CMP_ULT_D:
11953 case OPC_CMP_OLE_D:
11954 case OPC_CMP_ULE_D:
11955 case OPC_CMP_SF_D:
11956 case OPC_CMP_NGLE_D:
11957 case OPC_CMP_SEQ_D:
11958 case OPC_CMP_NGL_D:
11959 case OPC_CMP_LT_D:
11960 case OPC_CMP_NGE_D:
11961 case OPC_CMP_LE_D:
11962 case OPC_CMP_NGT_D:
11963 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11964 if (ctx->opcode & (1 << 6)) {
11965 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
11966 } else {
11967 gen_cmp_d(ctx, func-48, ft, fs, cc);
11968 }
11969 break;
11970 case OPC_CVT_S_D:
11971 check_cp1_registers(ctx, fs);
11972 {
11973 TCGv_i32 fp32 = tcg_temp_new_i32();
11974 TCGv_i64 fp64 = tcg_temp_new_i64();
11975
11976 gen_load_fpr64(ctx, fp64, fs);
11977 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
11978 tcg_temp_free_i64(fp64);
11979 gen_store_fpr32(ctx, fp32, fd);
11980 tcg_temp_free_i32(fp32);
11981 }
11982 break;
11983 case OPC_CVT_W_D:
11984 check_cp1_registers(ctx, fs);
11985 {
11986 TCGv_i32 fp32 = tcg_temp_new_i32();
11987 TCGv_i64 fp64 = tcg_temp_new_i64();
11988
11989 gen_load_fpr64(ctx, fp64, fs);
11990 if (ctx->nan2008) {
11991 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
11992 } else {
11993 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
11994 }
11995 tcg_temp_free_i64(fp64);
11996 gen_store_fpr32(ctx, fp32, fd);
11997 tcg_temp_free_i32(fp32);
11998 }
11999 break;
12000 case OPC_CVT_L_D:
12001 check_cp1_64bitmode(ctx);
12002 {
12003 TCGv_i64 fp0 = tcg_temp_new_i64();
12004
12005 gen_load_fpr64(ctx, fp0, fs);
12006 if (ctx->nan2008) {
12007 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
12008 } else {
12009 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
12010 }
12011 gen_store_fpr64(ctx, fp0, fd);
12012 tcg_temp_free_i64(fp0);
12013 }
12014 break;
12015 case OPC_CVT_S_W:
12016 {
12017 TCGv_i32 fp0 = tcg_temp_new_i32();
12018
12019 gen_load_fpr32(ctx, fp0, fs);
12020 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
12021 gen_store_fpr32(ctx, fp0, fd);
12022 tcg_temp_free_i32(fp0);
12023 }
12024 break;
12025 case OPC_CVT_D_W:
12026 check_cp1_registers(ctx, fd);
12027 {
12028 TCGv_i32 fp32 = tcg_temp_new_i32();
12029 TCGv_i64 fp64 = tcg_temp_new_i64();
12030
12031 gen_load_fpr32(ctx, fp32, fs);
12032 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
12033 tcg_temp_free_i32(fp32);
12034 gen_store_fpr64(ctx, fp64, fd);
12035 tcg_temp_free_i64(fp64);
12036 }
12037 break;
12038 case OPC_CVT_S_L:
12039 check_cp1_64bitmode(ctx);
12040 {
12041 TCGv_i32 fp32 = tcg_temp_new_i32();
12042 TCGv_i64 fp64 = tcg_temp_new_i64();
12043
12044 gen_load_fpr64(ctx, fp64, fs);
12045 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
12046 tcg_temp_free_i64(fp64);
12047 gen_store_fpr32(ctx, fp32, fd);
12048 tcg_temp_free_i32(fp32);
12049 }
12050 break;
12051 case OPC_CVT_D_L:
12052 check_cp1_64bitmode(ctx);
12053 {
12054 TCGv_i64 fp0 = tcg_temp_new_i64();
12055
12056 gen_load_fpr64(ctx, fp0, fs);
12057 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
12058 gen_store_fpr64(ctx, fp0, fd);
12059 tcg_temp_free_i64(fp0);
12060 }
12061 break;
12062 case OPC_CVT_PS_PW:
12063 check_ps(ctx);
12064 {
12065 TCGv_i64 fp0 = tcg_temp_new_i64();
12066
12067 gen_load_fpr64(ctx, fp0, fs);
12068 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
12069 gen_store_fpr64(ctx, fp0, fd);
12070 tcg_temp_free_i64(fp0);
12071 }
12072 break;
12073 case OPC_ADD_PS:
12074 check_ps(ctx);
12075 {
12076 TCGv_i64 fp0 = tcg_temp_new_i64();
12077 TCGv_i64 fp1 = tcg_temp_new_i64();
12078
12079 gen_load_fpr64(ctx, fp0, fs);
12080 gen_load_fpr64(ctx, fp1, ft);
12081 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
12082 tcg_temp_free_i64(fp1);
12083 gen_store_fpr64(ctx, fp0, fd);
12084 tcg_temp_free_i64(fp0);
12085 }
12086 break;
12087 case OPC_SUB_PS:
12088 check_ps(ctx);
12089 {
12090 TCGv_i64 fp0 = tcg_temp_new_i64();
12091 TCGv_i64 fp1 = tcg_temp_new_i64();
12092
12093 gen_load_fpr64(ctx, fp0, fs);
12094 gen_load_fpr64(ctx, fp1, ft);
12095 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
12096 tcg_temp_free_i64(fp1);
12097 gen_store_fpr64(ctx, fp0, fd);
12098 tcg_temp_free_i64(fp0);
12099 }
12100 break;
12101 case OPC_MUL_PS:
12102 check_ps(ctx);
12103 {
12104 TCGv_i64 fp0 = tcg_temp_new_i64();
12105 TCGv_i64 fp1 = tcg_temp_new_i64();
12106
12107 gen_load_fpr64(ctx, fp0, fs);
12108 gen_load_fpr64(ctx, fp1, ft);
12109 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
12110 tcg_temp_free_i64(fp1);
12111 gen_store_fpr64(ctx, fp0, fd);
12112 tcg_temp_free_i64(fp0);
12113 }
12114 break;
12115 case OPC_ABS_PS:
12116 check_ps(ctx);
12117 {
12118 TCGv_i64 fp0 = tcg_temp_new_i64();
12119
12120 gen_load_fpr64(ctx, fp0, fs);
12121 gen_helper_float_abs_ps(fp0, fp0);
12122 gen_store_fpr64(ctx, fp0, fd);
12123 tcg_temp_free_i64(fp0);
12124 }
12125 break;
12126 case OPC_MOV_PS:
12127 check_ps(ctx);
12128 {
12129 TCGv_i64 fp0 = tcg_temp_new_i64();
12130
12131 gen_load_fpr64(ctx, fp0, fs);
12132 gen_store_fpr64(ctx, fp0, fd);
12133 tcg_temp_free_i64(fp0);
12134 }
12135 break;
12136 case OPC_NEG_PS:
12137 check_ps(ctx);
12138 {
12139 TCGv_i64 fp0 = tcg_temp_new_i64();
12140
12141 gen_load_fpr64(ctx, fp0, fs);
12142 gen_helper_float_chs_ps(fp0, fp0);
12143 gen_store_fpr64(ctx, fp0, fd);
12144 tcg_temp_free_i64(fp0);
12145 }
12146 break;
12147 case OPC_MOVCF_PS:
12148 check_ps(ctx);
12149 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
12150 break;
12151 case OPC_MOVZ_PS:
12152 check_ps(ctx);
12153 {
12154 TCGLabel *l1 = gen_new_label();
12155 TCGv_i64 fp0;
12156
12157 if (ft != 0) {
12158 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
12159 }
12160 fp0 = tcg_temp_new_i64();
12161 gen_load_fpr64(ctx, fp0, fs);
12162 gen_store_fpr64(ctx, fp0, fd);
12163 tcg_temp_free_i64(fp0);
12164 gen_set_label(l1);
12165 }
12166 break;
12167 case OPC_MOVN_PS:
12168 check_ps(ctx);
12169 {
12170 TCGLabel *l1 = gen_new_label();
12171 TCGv_i64 fp0;
12172
12173 if (ft != 0) {
12174 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12175 fp0 = tcg_temp_new_i64();
12176 gen_load_fpr64(ctx, fp0, fs);
12177 gen_store_fpr64(ctx, fp0, fd);
12178 tcg_temp_free_i64(fp0);
12179 gen_set_label(l1);
12180 }
12181 }
12182 break;
12183 case OPC_ADDR_PS:
12184 check_ps(ctx);
12185 {
12186 TCGv_i64 fp0 = tcg_temp_new_i64();
12187 TCGv_i64 fp1 = tcg_temp_new_i64();
12188
12189 gen_load_fpr64(ctx, fp0, ft);
12190 gen_load_fpr64(ctx, fp1, fs);
12191 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
12192 tcg_temp_free_i64(fp1);
12193 gen_store_fpr64(ctx, fp0, fd);
12194 tcg_temp_free_i64(fp0);
12195 }
12196 break;
12197 case OPC_MULR_PS:
12198 check_ps(ctx);
12199 {
12200 TCGv_i64 fp0 = tcg_temp_new_i64();
12201 TCGv_i64 fp1 = tcg_temp_new_i64();
12202
12203 gen_load_fpr64(ctx, fp0, ft);
12204 gen_load_fpr64(ctx, fp1, fs);
12205 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
12206 tcg_temp_free_i64(fp1);
12207 gen_store_fpr64(ctx, fp0, fd);
12208 tcg_temp_free_i64(fp0);
12209 }
12210 break;
12211 case OPC_RECIP2_PS:
12212 check_ps(ctx);
12213 {
12214 TCGv_i64 fp0 = tcg_temp_new_i64();
12215 TCGv_i64 fp1 = tcg_temp_new_i64();
12216
12217 gen_load_fpr64(ctx, fp0, fs);
12218 gen_load_fpr64(ctx, fp1, ft);
12219 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
12220 tcg_temp_free_i64(fp1);
12221 gen_store_fpr64(ctx, fp0, fd);
12222 tcg_temp_free_i64(fp0);
12223 }
12224 break;
12225 case OPC_RECIP1_PS:
12226 check_ps(ctx);
12227 {
12228 TCGv_i64 fp0 = tcg_temp_new_i64();
12229
12230 gen_load_fpr64(ctx, fp0, fs);
12231 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
12232 gen_store_fpr64(ctx, fp0, fd);
12233 tcg_temp_free_i64(fp0);
12234 }
12235 break;
12236 case OPC_RSQRT1_PS:
12237 check_ps(ctx);
12238 {
12239 TCGv_i64 fp0 = tcg_temp_new_i64();
12240
12241 gen_load_fpr64(ctx, fp0, fs);
12242 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
12243 gen_store_fpr64(ctx, fp0, fd);
12244 tcg_temp_free_i64(fp0);
12245 }
12246 break;
12247 case OPC_RSQRT2_PS:
12248 check_ps(ctx);
12249 {
12250 TCGv_i64 fp0 = tcg_temp_new_i64();
12251 TCGv_i64 fp1 = tcg_temp_new_i64();
12252
12253 gen_load_fpr64(ctx, fp0, fs);
12254 gen_load_fpr64(ctx, fp1, ft);
12255 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
12256 tcg_temp_free_i64(fp1);
12257 gen_store_fpr64(ctx, fp0, fd);
12258 tcg_temp_free_i64(fp0);
12259 }
12260 break;
12261 case OPC_CVT_S_PU:
12262 check_cp1_64bitmode(ctx);
12263 {
12264 TCGv_i32 fp0 = tcg_temp_new_i32();
12265
12266 gen_load_fpr32h(ctx, fp0, fs);
12267 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
12268 gen_store_fpr32(ctx, fp0, fd);
12269 tcg_temp_free_i32(fp0);
12270 }
12271 break;
12272 case OPC_CVT_PW_PS:
12273 check_ps(ctx);
12274 {
12275 TCGv_i64 fp0 = tcg_temp_new_i64();
12276
12277 gen_load_fpr64(ctx, fp0, fs);
12278 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
12279 gen_store_fpr64(ctx, fp0, fd);
12280 tcg_temp_free_i64(fp0);
12281 }
12282 break;
12283 case OPC_CVT_S_PL:
12284 check_cp1_64bitmode(ctx);
12285 {
12286 TCGv_i32 fp0 = tcg_temp_new_i32();
12287
12288 gen_load_fpr32(ctx, fp0, fs);
12289 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
12290 gen_store_fpr32(ctx, fp0, fd);
12291 tcg_temp_free_i32(fp0);
12292 }
12293 break;
12294 case OPC_PLL_PS:
12295 check_ps(ctx);
12296 {
12297 TCGv_i32 fp0 = tcg_temp_new_i32();
12298 TCGv_i32 fp1 = tcg_temp_new_i32();
12299
12300 gen_load_fpr32(ctx, fp0, fs);
12301 gen_load_fpr32(ctx, fp1, ft);
12302 gen_store_fpr32h(ctx, fp0, fd);
12303 gen_store_fpr32(ctx, fp1, fd);
12304 tcg_temp_free_i32(fp0);
12305 tcg_temp_free_i32(fp1);
12306 }
12307 break;
12308 case OPC_PLU_PS:
12309 check_ps(ctx);
12310 {
12311 TCGv_i32 fp0 = tcg_temp_new_i32();
12312 TCGv_i32 fp1 = tcg_temp_new_i32();
12313
12314 gen_load_fpr32(ctx, fp0, fs);
12315 gen_load_fpr32h(ctx, fp1, ft);
12316 gen_store_fpr32(ctx, fp1, fd);
12317 gen_store_fpr32h(ctx, fp0, fd);
12318 tcg_temp_free_i32(fp0);
12319 tcg_temp_free_i32(fp1);
12320 }
12321 break;
12322 case OPC_PUL_PS:
12323 check_ps(ctx);
12324 {
12325 TCGv_i32 fp0 = tcg_temp_new_i32();
12326 TCGv_i32 fp1 = tcg_temp_new_i32();
12327
12328 gen_load_fpr32h(ctx, fp0, fs);
12329 gen_load_fpr32(ctx, fp1, ft);
12330 gen_store_fpr32(ctx, fp1, fd);
12331 gen_store_fpr32h(ctx, fp0, fd);
12332 tcg_temp_free_i32(fp0);
12333 tcg_temp_free_i32(fp1);
12334 }
12335 break;
12336 case OPC_PUU_PS:
12337 check_ps(ctx);
12338 {
12339 TCGv_i32 fp0 = tcg_temp_new_i32();
12340 TCGv_i32 fp1 = tcg_temp_new_i32();
12341
12342 gen_load_fpr32h(ctx, fp0, fs);
12343 gen_load_fpr32h(ctx, fp1, ft);
12344 gen_store_fpr32(ctx, fp1, fd);
12345 gen_store_fpr32h(ctx, fp0, fd);
12346 tcg_temp_free_i32(fp0);
12347 tcg_temp_free_i32(fp1);
12348 }
12349 break;
12350 case OPC_CMP_F_PS:
12351 case OPC_CMP_UN_PS:
12352 case OPC_CMP_EQ_PS:
12353 case OPC_CMP_UEQ_PS:
12354 case OPC_CMP_OLT_PS:
12355 case OPC_CMP_ULT_PS:
12356 case OPC_CMP_OLE_PS:
12357 case OPC_CMP_ULE_PS:
12358 case OPC_CMP_SF_PS:
12359 case OPC_CMP_NGLE_PS:
12360 case OPC_CMP_SEQ_PS:
12361 case OPC_CMP_NGL_PS:
12362 case OPC_CMP_LT_PS:
12363 case OPC_CMP_NGE_PS:
12364 case OPC_CMP_LE_PS:
12365 case OPC_CMP_NGT_PS:
12366 if (ctx->opcode & (1 << 6)) {
12367 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
12368 } else {
12369 gen_cmp_ps(ctx, func-48, ft, fs, cc);
12370 }
12371 break;
12372 default:
12373 MIPS_INVAL("farith");
12374 generate_exception_end(ctx, EXCP_RI);
12375 return;
12376 }
12377 }
12378
12379 /* Coprocessor 3 (FPU) */
12380 static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
12381 int fd, int fs, int base, int index)
12382 {
12383 TCGv t0 = tcg_temp_new();
12384
12385 if (base == 0) {
12386 gen_load_gpr(t0, index);
12387 } else if (index == 0) {
12388 gen_load_gpr(t0, base);
12389 } else {
12390 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
12391 }
12392 /* Don't do NOP if destination is zero: we must perform the actual
12393 memory access. */
12394 switch (opc) {
12395 case OPC_LWXC1:
12396 check_cop1x(ctx);
12397 {
12398 TCGv_i32 fp0 = tcg_temp_new_i32();
12399
12400 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
12401 tcg_gen_trunc_tl_i32(fp0, t0);
12402 gen_store_fpr32(ctx, fp0, fd);
12403 tcg_temp_free_i32(fp0);
12404 }
12405 break;
12406 case OPC_LDXC1:
12407 check_cop1x(ctx);
12408 check_cp1_registers(ctx, fd);
12409 {
12410 TCGv_i64 fp0 = tcg_temp_new_i64();
12411 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12412 gen_store_fpr64(ctx, fp0, fd);
12413 tcg_temp_free_i64(fp0);
12414 }
12415 break;
12416 case OPC_LUXC1:
12417 check_cp1_64bitmode(ctx);
12418 tcg_gen_andi_tl(t0, t0, ~0x7);
12419 {
12420 TCGv_i64 fp0 = tcg_temp_new_i64();
12421
12422 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12423 gen_store_fpr64(ctx, fp0, fd);
12424 tcg_temp_free_i64(fp0);
12425 }
12426 break;
12427 case OPC_SWXC1:
12428 check_cop1x(ctx);
12429 {
12430 TCGv_i32 fp0 = tcg_temp_new_i32();
12431 gen_load_fpr32(ctx, fp0, fs);
12432 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
12433 tcg_temp_free_i32(fp0);
12434 }
12435 break;
12436 case OPC_SDXC1:
12437 check_cop1x(ctx);
12438 check_cp1_registers(ctx, fs);
12439 {
12440 TCGv_i64 fp0 = tcg_temp_new_i64();
12441 gen_load_fpr64(ctx, fp0, fs);
12442 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12443 tcg_temp_free_i64(fp0);
12444 }
12445 break;
12446 case OPC_SUXC1:
12447 check_cp1_64bitmode(ctx);
12448 tcg_gen_andi_tl(t0, t0, ~0x7);
12449 {
12450 TCGv_i64 fp0 = tcg_temp_new_i64();
12451 gen_load_fpr64(ctx, fp0, fs);
12452 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12453 tcg_temp_free_i64(fp0);
12454 }
12455 break;
12456 }
12457 tcg_temp_free(t0);
12458 }
12459
12460 static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
12461 int fd, int fr, int fs, int ft)
12462 {
12463 switch (opc) {
12464 case OPC_ALNV_PS:
12465 check_ps(ctx);
12466 {
12467 TCGv t0 = tcg_temp_local_new();
12468 TCGv_i32 fp = tcg_temp_new_i32();
12469 TCGv_i32 fph = tcg_temp_new_i32();
12470 TCGLabel *l1 = gen_new_label();
12471 TCGLabel *l2 = gen_new_label();
12472
12473 gen_load_gpr(t0, fr);
12474 tcg_gen_andi_tl(t0, t0, 0x7);
12475
12476 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
12477 gen_load_fpr32(ctx, fp, fs);
12478 gen_load_fpr32h(ctx, fph, fs);
12479 gen_store_fpr32(ctx, fp, fd);
12480 gen_store_fpr32h(ctx, fph, fd);
12481 tcg_gen_br(l2);
12482 gen_set_label(l1);
12483 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
12484 tcg_temp_free(t0);
12485 #ifdef TARGET_WORDS_BIGENDIAN
12486 gen_load_fpr32(ctx, fp, fs);
12487 gen_load_fpr32h(ctx, fph, ft);
12488 gen_store_fpr32h(ctx, fp, fd);
12489 gen_store_fpr32(ctx, fph, fd);
12490 #else
12491 gen_load_fpr32h(ctx, fph, fs);
12492 gen_load_fpr32(ctx, fp, ft);
12493 gen_store_fpr32(ctx, fph, fd);
12494 gen_store_fpr32h(ctx, fp, fd);
12495 #endif
12496 gen_set_label(l2);
12497 tcg_temp_free_i32(fp);
12498 tcg_temp_free_i32(fph);
12499 }
12500 break;
12501 case OPC_MADD_S:
12502 check_cop1x(ctx);
12503 {
12504 TCGv_i32 fp0 = tcg_temp_new_i32();
12505 TCGv_i32 fp1 = tcg_temp_new_i32();
12506 TCGv_i32 fp2 = tcg_temp_new_i32();
12507
12508 gen_load_fpr32(ctx, fp0, fs);
12509 gen_load_fpr32(ctx, fp1, ft);
12510 gen_load_fpr32(ctx, fp2, fr);
12511 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
12512 tcg_temp_free_i32(fp0);
12513 tcg_temp_free_i32(fp1);
12514 gen_store_fpr32(ctx, fp2, fd);
12515 tcg_temp_free_i32(fp2);
12516 }
12517 break;
12518 case OPC_MADD_D:
12519 check_cop1x(ctx);
12520 check_cp1_registers(ctx, fd | fs | ft | fr);
12521 {
12522 TCGv_i64 fp0 = tcg_temp_new_i64();
12523 TCGv_i64 fp1 = tcg_temp_new_i64();
12524 TCGv_i64 fp2 = tcg_temp_new_i64();
12525
12526 gen_load_fpr64(ctx, fp0, fs);
12527 gen_load_fpr64(ctx, fp1, ft);
12528 gen_load_fpr64(ctx, fp2, fr);
12529 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
12530 tcg_temp_free_i64(fp0);
12531 tcg_temp_free_i64(fp1);
12532 gen_store_fpr64(ctx, fp2, fd);
12533 tcg_temp_free_i64(fp2);
12534 }
12535 break;
12536 case OPC_MADD_PS:
12537 check_ps(ctx);
12538 {
12539 TCGv_i64 fp0 = tcg_temp_new_i64();
12540 TCGv_i64 fp1 = tcg_temp_new_i64();
12541 TCGv_i64 fp2 = tcg_temp_new_i64();
12542
12543 gen_load_fpr64(ctx, fp0, fs);
12544 gen_load_fpr64(ctx, fp1, ft);
12545 gen_load_fpr64(ctx, fp2, fr);
12546 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
12547 tcg_temp_free_i64(fp0);
12548 tcg_temp_free_i64(fp1);
12549 gen_store_fpr64(ctx, fp2, fd);
12550 tcg_temp_free_i64(fp2);
12551 }
12552 break;
12553 case OPC_MSUB_S:
12554 check_cop1x(ctx);
12555 {
12556 TCGv_i32 fp0 = tcg_temp_new_i32();
12557 TCGv_i32 fp1 = tcg_temp_new_i32();
12558 TCGv_i32 fp2 = tcg_temp_new_i32();
12559
12560 gen_load_fpr32(ctx, fp0, fs);
12561 gen_load_fpr32(ctx, fp1, ft);
12562 gen_load_fpr32(ctx, fp2, fr);
12563 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
12564 tcg_temp_free_i32(fp0);
12565 tcg_temp_free_i32(fp1);
12566 gen_store_fpr32(ctx, fp2, fd);
12567 tcg_temp_free_i32(fp2);
12568 }
12569 break;
12570 case OPC_MSUB_D:
12571 check_cop1x(ctx);
12572 check_cp1_registers(ctx, fd | fs | ft | fr);
12573 {
12574 TCGv_i64 fp0 = tcg_temp_new_i64();
12575 TCGv_i64 fp1 = tcg_temp_new_i64();
12576 TCGv_i64 fp2 = tcg_temp_new_i64();
12577
12578 gen_load_fpr64(ctx, fp0, fs);
12579 gen_load_fpr64(ctx, fp1, ft);
12580 gen_load_fpr64(ctx, fp2, fr);
12581 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
12582 tcg_temp_free_i64(fp0);
12583 tcg_temp_free_i64(fp1);
12584 gen_store_fpr64(ctx, fp2, fd);
12585 tcg_temp_free_i64(fp2);
12586 }
12587 break;
12588 case OPC_MSUB_PS:
12589 check_ps(ctx);
12590 {
12591 TCGv_i64 fp0 = tcg_temp_new_i64();
12592 TCGv_i64 fp1 = tcg_temp_new_i64();
12593 TCGv_i64 fp2 = tcg_temp_new_i64();
12594
12595 gen_load_fpr64(ctx, fp0, fs);
12596 gen_load_fpr64(ctx, fp1, ft);
12597 gen_load_fpr64(ctx, fp2, fr);
12598 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
12599 tcg_temp_free_i64(fp0);
12600 tcg_temp_free_i64(fp1);
12601 gen_store_fpr64(ctx, fp2, fd);
12602 tcg_temp_free_i64(fp2);
12603 }
12604 break;
12605 case OPC_NMADD_S:
12606 check_cop1x(ctx);
12607 {
12608 TCGv_i32 fp0 = tcg_temp_new_i32();
12609 TCGv_i32 fp1 = tcg_temp_new_i32();
12610 TCGv_i32 fp2 = tcg_temp_new_i32();
12611
12612 gen_load_fpr32(ctx, fp0, fs);
12613 gen_load_fpr32(ctx, fp1, ft);
12614 gen_load_fpr32(ctx, fp2, fr);
12615 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
12616 tcg_temp_free_i32(fp0);
12617 tcg_temp_free_i32(fp1);
12618 gen_store_fpr32(ctx, fp2, fd);
12619 tcg_temp_free_i32(fp2);
12620 }
12621 break;
12622 case OPC_NMADD_D:
12623 check_cop1x(ctx);
12624 check_cp1_registers(ctx, fd | fs | ft | fr);
12625 {
12626 TCGv_i64 fp0 = tcg_temp_new_i64();
12627 TCGv_i64 fp1 = tcg_temp_new_i64();
12628 TCGv_i64 fp2 = tcg_temp_new_i64();
12629
12630 gen_load_fpr64(ctx, fp0, fs);
12631 gen_load_fpr64(ctx, fp1, ft);
12632 gen_load_fpr64(ctx, fp2, fr);
12633 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
12634 tcg_temp_free_i64(fp0);
12635 tcg_temp_free_i64(fp1);
12636 gen_store_fpr64(ctx, fp2, fd);
12637 tcg_temp_free_i64(fp2);
12638 }
12639 break;
12640 case OPC_NMADD_PS:
12641 check_ps(ctx);
12642 {
12643 TCGv_i64 fp0 = tcg_temp_new_i64();
12644 TCGv_i64 fp1 = tcg_temp_new_i64();
12645 TCGv_i64 fp2 = tcg_temp_new_i64();
12646
12647 gen_load_fpr64(ctx, fp0, fs);
12648 gen_load_fpr64(ctx, fp1, ft);
12649 gen_load_fpr64(ctx, fp2, fr);
12650 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
12651 tcg_temp_free_i64(fp0);
12652 tcg_temp_free_i64(fp1);
12653 gen_store_fpr64(ctx, fp2, fd);
12654 tcg_temp_free_i64(fp2);
12655 }
12656 break;
12657 case OPC_NMSUB_S:
12658 check_cop1x(ctx);
12659 {
12660 TCGv_i32 fp0 = tcg_temp_new_i32();
12661 TCGv_i32 fp1 = tcg_temp_new_i32();
12662 TCGv_i32 fp2 = tcg_temp_new_i32();
12663
12664 gen_load_fpr32(ctx, fp0, fs);
12665 gen_load_fpr32(ctx, fp1, ft);
12666 gen_load_fpr32(ctx, fp2, fr);
12667 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
12668 tcg_temp_free_i32(fp0);
12669 tcg_temp_free_i32(fp1);
12670 gen_store_fpr32(ctx, fp2, fd);
12671 tcg_temp_free_i32(fp2);
12672 }
12673 break;
12674 case OPC_NMSUB_D:
12675 check_cop1x(ctx);
12676 check_cp1_registers(ctx, fd | fs | ft | fr);
12677 {
12678 TCGv_i64 fp0 = tcg_temp_new_i64();
12679 TCGv_i64 fp1 = tcg_temp_new_i64();
12680 TCGv_i64 fp2 = tcg_temp_new_i64();
12681
12682 gen_load_fpr64(ctx, fp0, fs);
12683 gen_load_fpr64(ctx, fp1, ft);
12684 gen_load_fpr64(ctx, fp2, fr);
12685 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
12686 tcg_temp_free_i64(fp0);
12687 tcg_temp_free_i64(fp1);
12688 gen_store_fpr64(ctx, fp2, fd);
12689 tcg_temp_free_i64(fp2);
12690 }
12691 break;
12692 case OPC_NMSUB_PS:
12693 check_ps(ctx);
12694 {
12695 TCGv_i64 fp0 = tcg_temp_new_i64();
12696 TCGv_i64 fp1 = tcg_temp_new_i64();
12697 TCGv_i64 fp2 = tcg_temp_new_i64();
12698
12699 gen_load_fpr64(ctx, fp0, fs);
12700 gen_load_fpr64(ctx, fp1, ft);
12701 gen_load_fpr64(ctx, fp2, fr);
12702 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
12703 tcg_temp_free_i64(fp0);
12704 tcg_temp_free_i64(fp1);
12705 gen_store_fpr64(ctx, fp2, fd);
12706 tcg_temp_free_i64(fp2);
12707 }
12708 break;
12709 default:
12710 MIPS_INVAL("flt3_arith");
12711 generate_exception_end(ctx, EXCP_RI);
12712 return;
12713 }
12714 }
12715
12716 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
12717 {
12718 TCGv t0;
12719
12720 #if !defined(CONFIG_USER_ONLY)
12721 /* The Linux kernel will emulate rdhwr if it's not supported natively.
12722 Therefore only check the ISA in system mode. */
12723 check_insn(ctx, ISA_MIPS32R2);
12724 #endif
12725 t0 = tcg_temp_new();
12726
12727 switch (rd) {
12728 case 0:
12729 gen_helper_rdhwr_cpunum(t0, cpu_env);
12730 gen_store_gpr(t0, rt);
12731 break;
12732 case 1:
12733 gen_helper_rdhwr_synci_step(t0, cpu_env);
12734 gen_store_gpr(t0, rt);
12735 break;
12736 case 2:
12737 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12738 gen_io_start();
12739 }
12740 gen_helper_rdhwr_cc(t0, cpu_env);
12741 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12742 gen_io_end();
12743 }
12744 gen_store_gpr(t0, rt);
12745 /* Break the TB to be able to take timer interrupts immediately
12746 after reading count. DISAS_STOP isn't sufficient, we need to ensure
12747 we break completely out of translated code. */
12748 gen_save_pc(ctx->base.pc_next + 4);
12749 ctx->base.is_jmp = DISAS_EXIT;
12750 break;
12751 case 3:
12752 gen_helper_rdhwr_ccres(t0, cpu_env);
12753 gen_store_gpr(t0, rt);
12754 break;
12755 case 4:
12756 check_insn(ctx, ISA_MIPS32R6);
12757 if (sel != 0) {
12758 /* Performance counter registers are not implemented other than
12759 * control register 0.
12760 */
12761 generate_exception(ctx, EXCP_RI);
12762 }
12763 gen_helper_rdhwr_performance(t0, cpu_env);
12764 gen_store_gpr(t0, rt);
12765 break;
12766 case 5:
12767 check_insn(ctx, ISA_MIPS32R6);
12768 gen_helper_rdhwr_xnp(t0, cpu_env);
12769 gen_store_gpr(t0, rt);
12770 break;
12771 case 29:
12772 #if defined(CONFIG_USER_ONLY)
12773 tcg_gen_ld_tl(t0, cpu_env,
12774 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12775 gen_store_gpr(t0, rt);
12776 break;
12777 #else
12778 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
12779 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
12780 tcg_gen_ld_tl(t0, cpu_env,
12781 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12782 gen_store_gpr(t0, rt);
12783 } else {
12784 generate_exception_end(ctx, EXCP_RI);
12785 }
12786 break;
12787 #endif
12788 default: /* Invalid */
12789 MIPS_INVAL("rdhwr");
12790 generate_exception_end(ctx, EXCP_RI);
12791 break;
12792 }
12793 tcg_temp_free(t0);
12794 }
12795
12796 static inline void clear_branch_hflags(DisasContext *ctx)
12797 {
12798 ctx->hflags &= ~MIPS_HFLAG_BMASK;
12799 if (ctx->base.is_jmp == DISAS_NEXT) {
12800 save_cpu_state(ctx, 0);
12801 } else {
12802 /* it is not safe to save ctx->hflags as hflags may be changed
12803 in execution time by the instruction in delay / forbidden slot. */
12804 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
12805 }
12806 }
12807
12808 static void gen_branch(DisasContext *ctx, int insn_bytes)
12809 {
12810 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12811 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
12812 /* Branches completion */
12813 clear_branch_hflags(ctx);
12814 ctx->base.is_jmp = DISAS_NORETURN;
12815 /* FIXME: Need to clear can_do_io. */
12816 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
12817 case MIPS_HFLAG_FBNSLOT:
12818 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
12819 break;
12820 case MIPS_HFLAG_B:
12821 /* unconditional branch */
12822 if (proc_hflags & MIPS_HFLAG_BX) {
12823 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
12824 }
12825 gen_goto_tb(ctx, 0, ctx->btarget);
12826 break;
12827 case MIPS_HFLAG_BL:
12828 /* blikely taken case */
12829 gen_goto_tb(ctx, 0, ctx->btarget);
12830 break;
12831 case MIPS_HFLAG_BC:
12832 /* Conditional branch */
12833 {
12834 TCGLabel *l1 = gen_new_label();
12835
12836 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
12837 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
12838 gen_set_label(l1);
12839 gen_goto_tb(ctx, 0, ctx->btarget);
12840 }
12841 break;
12842 case MIPS_HFLAG_BR:
12843 /* unconditional branch to register */
12844 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
12845 TCGv t0 = tcg_temp_new();
12846 TCGv_i32 t1 = tcg_temp_new_i32();
12847
12848 tcg_gen_andi_tl(t0, btarget, 0x1);
12849 tcg_gen_trunc_tl_i32(t1, t0);
12850 tcg_temp_free(t0);
12851 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
12852 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
12853 tcg_gen_or_i32(hflags, hflags, t1);
12854 tcg_temp_free_i32(t1);
12855
12856 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
12857 } else {
12858 tcg_gen_mov_tl(cpu_PC, btarget);
12859 }
12860 if (ctx->base.singlestep_enabled) {
12861 save_cpu_state(ctx, 0);
12862 gen_helper_raise_exception_debug(cpu_env);
12863 }
12864 tcg_gen_lookup_and_goto_ptr();
12865 break;
12866 default:
12867 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
12868 abort();
12869 }
12870 }
12871 }
12872
12873 /* Compact Branches */
12874 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
12875 int rs, int rt, int32_t offset)
12876 {
12877 int bcond_compute = 0;
12878 TCGv t0 = tcg_temp_new();
12879 TCGv t1 = tcg_temp_new();
12880 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
12881
12882 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12883 #ifdef MIPS_DEBUG_DISAS
12884 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
12885 "\n", ctx->base.pc_next);
12886 #endif
12887 generate_exception_end(ctx, EXCP_RI);
12888 goto out;
12889 }
12890
12891 /* Load needed operands and calculate btarget */
12892 switch (opc) {
12893 /* compact branch */
12894 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12895 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12896 gen_load_gpr(t0, rs);
12897 gen_load_gpr(t1, rt);
12898 bcond_compute = 1;
12899 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12900 if (rs <= rt && rs == 0) {
12901 /* OPC_BEQZALC, OPC_BNEZALC */
12902 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12903 }
12904 break;
12905 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12906 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12907 gen_load_gpr(t0, rs);
12908 gen_load_gpr(t1, rt);
12909 bcond_compute = 1;
12910 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12911 break;
12912 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12913 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12914 if (rs == 0 || rs == rt) {
12915 /* OPC_BLEZALC, OPC_BGEZALC */
12916 /* OPC_BGTZALC, OPC_BLTZALC */
12917 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12918 }
12919 gen_load_gpr(t0, rs);
12920 gen_load_gpr(t1, rt);
12921 bcond_compute = 1;
12922 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12923 break;
12924 case OPC_BC:
12925 case OPC_BALC:
12926 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12927 break;
12928 case OPC_BEQZC:
12929 case OPC_BNEZC:
12930 if (rs != 0) {
12931 /* OPC_BEQZC, OPC_BNEZC */
12932 gen_load_gpr(t0, rs);
12933 bcond_compute = 1;
12934 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12935 } else {
12936 /* OPC_JIC, OPC_JIALC */
12937 TCGv tbase = tcg_temp_new();
12938 TCGv toffset = tcg_temp_new();
12939
12940 gen_load_gpr(tbase, rt);
12941 tcg_gen_movi_tl(toffset, offset);
12942 gen_op_addr_add(ctx, btarget, tbase, toffset);
12943 tcg_temp_free(tbase);
12944 tcg_temp_free(toffset);
12945 }
12946 break;
12947 default:
12948 MIPS_INVAL("Compact branch/jump");
12949 generate_exception_end(ctx, EXCP_RI);
12950 goto out;
12951 }
12952
12953 if (bcond_compute == 0) {
12954 /* Uncoditional compact branch */
12955 switch (opc) {
12956 case OPC_JIALC:
12957 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12958 /* Fallthrough */
12959 case OPC_JIC:
12960 ctx->hflags |= MIPS_HFLAG_BR;
12961 break;
12962 case OPC_BALC:
12963 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12964 /* Fallthrough */
12965 case OPC_BC:
12966 ctx->hflags |= MIPS_HFLAG_B;
12967 break;
12968 default:
12969 MIPS_INVAL("Compact branch/jump");
12970 generate_exception_end(ctx, EXCP_RI);
12971 goto out;
12972 }
12973
12974 /* Generating branch here as compact branches don't have delay slot */
12975 gen_branch(ctx, 4);
12976 } else {
12977 /* Conditional compact branch */
12978 TCGLabel *fs = gen_new_label();
12979 save_cpu_state(ctx, 0);
12980
12981 switch (opc) {
12982 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12983 if (rs == 0 && rt != 0) {
12984 /* OPC_BLEZALC */
12985 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12986 } else if (rs != 0 && rt != 0 && rs == rt) {
12987 /* OPC_BGEZALC */
12988 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12989 } else {
12990 /* OPC_BGEUC */
12991 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
12992 }
12993 break;
12994 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12995 if (rs == 0 && rt != 0) {
12996 /* OPC_BGTZALC */
12997 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12998 } else if (rs != 0 && rt != 0 && rs == rt) {
12999 /* OPC_BLTZALC */
13000 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13001 } else {
13002 /* OPC_BLTUC */
13003 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
13004 }
13005 break;
13006 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13007 if (rs == 0 && rt != 0) {
13008 /* OPC_BLEZC */
13009 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13010 } else if (rs != 0 && rt != 0 && rs == rt) {
13011 /* OPC_BGEZC */
13012 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13013 } else {
13014 /* OPC_BGEC */
13015 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
13016 }
13017 break;
13018 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13019 if (rs == 0 && rt != 0) {
13020 /* OPC_BGTZC */
13021 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13022 } else if (rs != 0 && rt != 0 && rs == rt) {
13023 /* OPC_BLTZC */
13024 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13025 } else {
13026 /* OPC_BLTC */
13027 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
13028 }
13029 break;
13030 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13031 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13032 if (rs >= rt) {
13033 /* OPC_BOVC, OPC_BNVC */
13034 TCGv t2 = tcg_temp_new();
13035 TCGv t3 = tcg_temp_new();
13036 TCGv t4 = tcg_temp_new();
13037 TCGv input_overflow = tcg_temp_new();
13038
13039 gen_load_gpr(t0, rs);
13040 gen_load_gpr(t1, rt);
13041 tcg_gen_ext32s_tl(t2, t0);
13042 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
13043 tcg_gen_ext32s_tl(t3, t1);
13044 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
13045 tcg_gen_or_tl(input_overflow, input_overflow, t4);
13046
13047 tcg_gen_add_tl(t4, t2, t3);
13048 tcg_gen_ext32s_tl(t4, t4);
13049 tcg_gen_xor_tl(t2, t2, t3);
13050 tcg_gen_xor_tl(t3, t4, t3);
13051 tcg_gen_andc_tl(t2, t3, t2);
13052 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
13053 tcg_gen_or_tl(t4, t4, input_overflow);
13054 if (opc == OPC_BOVC) {
13055 /* OPC_BOVC */
13056 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
13057 } else {
13058 /* OPC_BNVC */
13059 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
13060 }
13061 tcg_temp_free(input_overflow);
13062 tcg_temp_free(t4);
13063 tcg_temp_free(t3);
13064 tcg_temp_free(t2);
13065 } else if (rs < rt && rs == 0) {
13066 /* OPC_BEQZALC, OPC_BNEZALC */
13067 if (opc == OPC_BEQZALC) {
13068 /* OPC_BEQZALC */
13069 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
13070 } else {
13071 /* OPC_BNEZALC */
13072 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
13073 }
13074 } else {
13075 /* OPC_BEQC, OPC_BNEC */
13076 if (opc == OPC_BEQC) {
13077 /* OPC_BEQC */
13078 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
13079 } else {
13080 /* OPC_BNEC */
13081 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
13082 }
13083 }
13084 break;
13085 case OPC_BEQZC:
13086 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
13087 break;
13088 case OPC_BNEZC:
13089 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
13090 break;
13091 default:
13092 MIPS_INVAL("Compact conditional branch/jump");
13093 generate_exception_end(ctx, EXCP_RI);
13094 goto out;
13095 }
13096
13097 /* Generating branch here as compact branches don't have delay slot */
13098 gen_goto_tb(ctx, 1, ctx->btarget);
13099 gen_set_label(fs);
13100
13101 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
13102 }
13103
13104 out:
13105 tcg_temp_free(t0);
13106 tcg_temp_free(t1);
13107 }
13108
13109 /* ISA extensions (ASEs) */
13110 /* MIPS16 extension to MIPS32 */
13111
13112 /* MIPS16 major opcodes */
13113 enum {
13114 M16_OPC_ADDIUSP = 0x00,
13115 M16_OPC_ADDIUPC = 0x01,
13116 M16_OPC_B = 0x02,
13117 M16_OPC_JAL = 0x03,
13118 M16_OPC_BEQZ = 0x04,
13119 M16_OPC_BNEQZ = 0x05,
13120 M16_OPC_SHIFT = 0x06,
13121 M16_OPC_LD = 0x07,
13122 M16_OPC_RRIA = 0x08,
13123 M16_OPC_ADDIU8 = 0x09,
13124 M16_OPC_SLTI = 0x0a,
13125 M16_OPC_SLTIU = 0x0b,
13126 M16_OPC_I8 = 0x0c,
13127 M16_OPC_LI = 0x0d,
13128 M16_OPC_CMPI = 0x0e,
13129 M16_OPC_SD = 0x0f,
13130 M16_OPC_LB = 0x10,
13131 M16_OPC_LH = 0x11,
13132 M16_OPC_LWSP = 0x12,
13133 M16_OPC_LW = 0x13,
13134 M16_OPC_LBU = 0x14,
13135 M16_OPC_LHU = 0x15,
13136 M16_OPC_LWPC = 0x16,
13137 M16_OPC_LWU = 0x17,
13138 M16_OPC_SB = 0x18,
13139 M16_OPC_SH = 0x19,
13140 M16_OPC_SWSP = 0x1a,
13141 M16_OPC_SW = 0x1b,
13142 M16_OPC_RRR = 0x1c,
13143 M16_OPC_RR = 0x1d,
13144 M16_OPC_EXTEND = 0x1e,
13145 M16_OPC_I64 = 0x1f
13146 };
13147
13148 /* I8 funct field */
13149 enum {
13150 I8_BTEQZ = 0x0,
13151 I8_BTNEZ = 0x1,
13152 I8_SWRASP = 0x2,
13153 I8_ADJSP = 0x3,
13154 I8_SVRS = 0x4,
13155 I8_MOV32R = 0x5,
13156 I8_MOVR32 = 0x7
13157 };
13158
13159 /* RRR f field */
13160 enum {
13161 RRR_DADDU = 0x0,
13162 RRR_ADDU = 0x1,
13163 RRR_DSUBU = 0x2,
13164 RRR_SUBU = 0x3
13165 };
13166
13167 /* RR funct field */
13168 enum {
13169 RR_JR = 0x00,
13170 RR_SDBBP = 0x01,
13171 RR_SLT = 0x02,
13172 RR_SLTU = 0x03,
13173 RR_SLLV = 0x04,
13174 RR_BREAK = 0x05,
13175 RR_SRLV = 0x06,
13176 RR_SRAV = 0x07,
13177 RR_DSRL = 0x08,
13178 RR_CMP = 0x0a,
13179 RR_NEG = 0x0b,
13180 RR_AND = 0x0c,
13181 RR_OR = 0x0d,
13182 RR_XOR = 0x0e,
13183 RR_NOT = 0x0f,
13184 RR_MFHI = 0x10,
13185 RR_CNVT = 0x11,
13186 RR_MFLO = 0x12,
13187 RR_DSRA = 0x13,
13188 RR_DSLLV = 0x14,
13189 RR_DSRLV = 0x16,
13190 RR_DSRAV = 0x17,
13191 RR_MULT = 0x18,
13192 RR_MULTU = 0x19,
13193 RR_DIV = 0x1a,
13194 RR_DIVU = 0x1b,
13195 RR_DMULT = 0x1c,
13196 RR_DMULTU = 0x1d,
13197 RR_DDIV = 0x1e,
13198 RR_DDIVU = 0x1f
13199 };
13200
13201 /* I64 funct field */
13202 enum {
13203 I64_LDSP = 0x0,
13204 I64_SDSP = 0x1,
13205 I64_SDRASP = 0x2,
13206 I64_DADJSP = 0x3,
13207 I64_LDPC = 0x4,
13208 I64_DADDIU5 = 0x5,
13209 I64_DADDIUPC = 0x6,
13210 I64_DADDIUSP = 0x7
13211 };
13212
13213 /* RR ry field for CNVT */
13214 enum {
13215 RR_RY_CNVT_ZEB = 0x0,
13216 RR_RY_CNVT_ZEH = 0x1,
13217 RR_RY_CNVT_ZEW = 0x2,
13218 RR_RY_CNVT_SEB = 0x4,
13219 RR_RY_CNVT_SEH = 0x5,
13220 RR_RY_CNVT_SEW = 0x6,
13221 };
13222
13223 static int xlat(int r)
13224 {
13225 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
13226
13227 return map[r];
13228 }
13229
13230 static void gen_mips16_save(DisasContext *ctx,
13231 int xsregs, int aregs,
13232 int do_ra, int do_s0, int do_s1,
13233 int framesize)
13234 {
13235 TCGv t0 = tcg_temp_new();
13236 TCGv t1 = tcg_temp_new();
13237 TCGv t2 = tcg_temp_new();
13238 int args, astatic;
13239
13240 switch (aregs) {
13241 case 0:
13242 case 1:
13243 case 2:
13244 case 3:
13245 case 11:
13246 args = 0;
13247 break;
13248 case 4:
13249 case 5:
13250 case 6:
13251 case 7:
13252 args = 1;
13253 break;
13254 case 8:
13255 case 9:
13256 case 10:
13257 args = 2;
13258 break;
13259 case 12:
13260 case 13:
13261 args = 3;
13262 break;
13263 case 14:
13264 args = 4;
13265 break;
13266 default:
13267 generate_exception_end(ctx, EXCP_RI);
13268 return;
13269 }
13270
13271 switch (args) {
13272 case 4:
13273 gen_base_offset_addr(ctx, t0, 29, 12);
13274 gen_load_gpr(t1, 7);
13275 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13276 /* Fall through */
13277 case 3:
13278 gen_base_offset_addr(ctx, t0, 29, 8);
13279 gen_load_gpr(t1, 6);
13280 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13281 /* Fall through */
13282 case 2:
13283 gen_base_offset_addr(ctx, t0, 29, 4);
13284 gen_load_gpr(t1, 5);
13285 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13286 /* Fall through */
13287 case 1:
13288 gen_base_offset_addr(ctx, t0, 29, 0);
13289 gen_load_gpr(t1, 4);
13290 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13291 }
13292
13293 gen_load_gpr(t0, 29);
13294
13295 #define DECR_AND_STORE(reg) do { \
13296 tcg_gen_movi_tl(t2, -4); \
13297 gen_op_addr_add(ctx, t0, t0, t2); \
13298 gen_load_gpr(t1, reg); \
13299 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
13300 } while (0)
13301
13302 if (do_ra) {
13303 DECR_AND_STORE(31);
13304 }
13305
13306 switch (xsregs) {
13307 case 7:
13308 DECR_AND_STORE(30);
13309 /* Fall through */
13310 case 6:
13311 DECR_AND_STORE(23);
13312 /* Fall through */
13313 case 5:
13314 DECR_AND_STORE(22);
13315 /* Fall through */
13316 case 4:
13317 DECR_AND_STORE(21);
13318 /* Fall through */
13319 case 3:
13320 DECR_AND_STORE(20);
13321 /* Fall through */
13322 case 2:
13323 DECR_AND_STORE(19);
13324 /* Fall through */
13325 case 1:
13326 DECR_AND_STORE(18);
13327 }
13328
13329 if (do_s1) {
13330 DECR_AND_STORE(17);
13331 }
13332 if (do_s0) {
13333 DECR_AND_STORE(16);
13334 }
13335
13336 switch (aregs) {
13337 case 0:
13338 case 4:
13339 case 8:
13340 case 12:
13341 case 14:
13342 astatic = 0;
13343 break;
13344 case 1:
13345 case 5:
13346 case 9:
13347 case 13:
13348 astatic = 1;
13349 break;
13350 case 2:
13351 case 6:
13352 case 10:
13353 astatic = 2;
13354 break;
13355 case 3:
13356 case 7:
13357 astatic = 3;
13358 break;
13359 case 11:
13360 astatic = 4;
13361 break;
13362 default:
13363 generate_exception_end(ctx, EXCP_RI);
13364 return;
13365 }
13366
13367 if (astatic > 0) {
13368 DECR_AND_STORE(7);
13369 if (astatic > 1) {
13370 DECR_AND_STORE(6);
13371 if (astatic > 2) {
13372 DECR_AND_STORE(5);
13373 if (astatic > 3) {
13374 DECR_AND_STORE(4);
13375 }
13376 }
13377 }
13378 }
13379 #undef DECR_AND_STORE
13380
13381 tcg_gen_movi_tl(t2, -framesize);
13382 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13383 tcg_temp_free(t0);
13384 tcg_temp_free(t1);
13385 tcg_temp_free(t2);
13386 }
13387
13388 static void gen_mips16_restore(DisasContext *ctx,
13389 int xsregs, int aregs,
13390 int do_ra, int do_s0, int do_s1,
13391 int framesize)
13392 {
13393 int astatic;
13394 TCGv t0 = tcg_temp_new();
13395 TCGv t1 = tcg_temp_new();
13396 TCGv t2 = tcg_temp_new();
13397
13398 tcg_gen_movi_tl(t2, framesize);
13399 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
13400
13401 #define DECR_AND_LOAD(reg) do { \
13402 tcg_gen_movi_tl(t2, -4); \
13403 gen_op_addr_add(ctx, t0, t0, t2); \
13404 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
13405 gen_store_gpr(t1, reg); \
13406 } while (0)
13407
13408 if (do_ra) {
13409 DECR_AND_LOAD(31);
13410 }
13411
13412 switch (xsregs) {
13413 case 7:
13414 DECR_AND_LOAD(30);
13415 /* Fall through */
13416 case 6:
13417 DECR_AND_LOAD(23);
13418 /* Fall through */
13419 case 5:
13420 DECR_AND_LOAD(22);
13421 /* Fall through */
13422 case 4:
13423 DECR_AND_LOAD(21);
13424 /* Fall through */
13425 case 3:
13426 DECR_AND_LOAD(20);
13427 /* Fall through */
13428 case 2:
13429 DECR_AND_LOAD(19);
13430 /* Fall through */
13431 case 1:
13432 DECR_AND_LOAD(18);
13433 }
13434
13435 if (do_s1) {
13436 DECR_AND_LOAD(17);
13437 }
13438 if (do_s0) {
13439 DECR_AND_LOAD(16);
13440 }
13441
13442 switch (aregs) {
13443 case 0:
13444 case 4:
13445 case 8:
13446 case 12:
13447 case 14:
13448 astatic = 0;
13449 break;
13450 case 1:
13451 case 5:
13452 case 9:
13453 case 13:
13454 astatic = 1;
13455 break;
13456 case 2:
13457 case 6:
13458 case 10:
13459 astatic = 2;
13460 break;
13461 case 3:
13462 case 7:
13463 astatic = 3;
13464 break;
13465 case 11:
13466 astatic = 4;
13467 break;
13468 default:
13469 generate_exception_end(ctx, EXCP_RI);
13470 return;
13471 }
13472
13473 if (astatic > 0) {
13474 DECR_AND_LOAD(7);
13475 if (astatic > 1) {
13476 DECR_AND_LOAD(6);
13477 if (astatic > 2) {
13478 DECR_AND_LOAD(5);
13479 if (astatic > 3) {
13480 DECR_AND_LOAD(4);
13481 }
13482 }
13483 }
13484 }
13485 #undef DECR_AND_LOAD
13486
13487 tcg_gen_movi_tl(t2, framesize);
13488 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13489 tcg_temp_free(t0);
13490 tcg_temp_free(t1);
13491 tcg_temp_free(t2);
13492 }
13493
13494 static void gen_addiupc(DisasContext *ctx, int rx, int imm,
13495 int is_64_bit, int extended)
13496 {
13497 TCGv t0;
13498
13499 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13500 generate_exception_end(ctx, EXCP_RI);
13501 return;
13502 }
13503
13504 t0 = tcg_temp_new();
13505
13506 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
13507 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
13508 if (!is_64_bit) {
13509 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13510 }
13511
13512 tcg_temp_free(t0);
13513 }
13514
13515 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
13516 int16_t offset)
13517 {
13518 TCGv_i32 t0 = tcg_const_i32(op);
13519 TCGv t1 = tcg_temp_new();
13520 gen_base_offset_addr(ctx, t1, base, offset);
13521 gen_helper_cache(cpu_env, t1, t0);
13522 }
13523
13524 #if defined(TARGET_MIPS64)
13525 static void decode_i64_mips16(DisasContext *ctx,
13526 int ry, int funct, int16_t offset,
13527 int extended)
13528 {
13529 switch (funct) {
13530 case I64_LDSP:
13531 check_insn(ctx, ISA_MIPS3);
13532 check_mips_64(ctx);
13533 offset = extended ? offset : offset << 3;
13534 gen_ld(ctx, OPC_LD, ry, 29, offset);
13535 break;
13536 case I64_SDSP:
13537 check_insn(ctx, ISA_MIPS3);
13538 check_mips_64(ctx);
13539 offset = extended ? offset : offset << 3;
13540 gen_st(ctx, OPC_SD, ry, 29, offset);
13541 break;
13542 case I64_SDRASP:
13543 check_insn(ctx, ISA_MIPS3);
13544 check_mips_64(ctx);
13545 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
13546 gen_st(ctx, OPC_SD, 31, 29, offset);
13547 break;
13548 case I64_DADJSP:
13549 check_insn(ctx, ISA_MIPS3);
13550 check_mips_64(ctx);
13551 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
13552 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
13553 break;
13554 case I64_LDPC:
13555 check_insn(ctx, ISA_MIPS3);
13556 check_mips_64(ctx);
13557 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13558 generate_exception_end(ctx, EXCP_RI);
13559 } else {
13560 offset = extended ? offset : offset << 3;
13561 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
13562 }
13563 break;
13564 case I64_DADDIU5:
13565 check_insn(ctx, ISA_MIPS3);
13566 check_mips_64(ctx);
13567 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
13568 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
13569 break;
13570 case I64_DADDIUPC:
13571 check_insn(ctx, ISA_MIPS3);
13572 check_mips_64(ctx);
13573 offset = extended ? offset : offset << 2;
13574 gen_addiupc(ctx, ry, offset, 1, extended);
13575 break;
13576 case I64_DADDIUSP:
13577 check_insn(ctx, ISA_MIPS3);
13578 check_mips_64(ctx);
13579 offset = extended ? offset : offset << 2;
13580 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
13581 break;
13582 }
13583 }
13584 #endif
13585
13586 static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
13587 {
13588 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
13589 int op, rx, ry, funct, sa;
13590 int16_t imm, offset;
13591
13592 ctx->opcode = (ctx->opcode << 16) | extend;
13593 op = (ctx->opcode >> 11) & 0x1f;
13594 sa = (ctx->opcode >> 22) & 0x1f;
13595 funct = (ctx->opcode >> 8) & 0x7;
13596 rx = xlat((ctx->opcode >> 8) & 0x7);
13597 ry = xlat((ctx->opcode >> 5) & 0x7);
13598 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
13599 | ((ctx->opcode >> 21) & 0x3f) << 5
13600 | (ctx->opcode & 0x1f));
13601
13602 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
13603 counterparts. */
13604 switch (op) {
13605 case M16_OPC_ADDIUSP:
13606 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13607 break;
13608 case M16_OPC_ADDIUPC:
13609 gen_addiupc(ctx, rx, imm, 0, 1);
13610 break;
13611 case M16_OPC_B:
13612 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
13613 /* No delay slot, so just process as a normal instruction */
13614 break;
13615 case M16_OPC_BEQZ:
13616 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
13617 /* No delay slot, so just process as a normal instruction */
13618 break;
13619 case M16_OPC_BNEQZ:
13620 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
13621 /* No delay slot, so just process as a normal instruction */
13622 break;
13623 case M16_OPC_SHIFT:
13624 switch (ctx->opcode & 0x3) {
13625 case 0x0:
13626 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13627 break;
13628 case 0x1:
13629 #if defined(TARGET_MIPS64)
13630 check_mips_64(ctx);
13631 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13632 #else
13633 generate_exception_end(ctx, EXCP_RI);
13634 #endif
13635 break;
13636 case 0x2:
13637 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13638 break;
13639 case 0x3:
13640 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13641 break;
13642 }
13643 break;
13644 #if defined(TARGET_MIPS64)
13645 case M16_OPC_LD:
13646 check_insn(ctx, ISA_MIPS3);
13647 check_mips_64(ctx);
13648 gen_ld(ctx, OPC_LD, ry, rx, offset);
13649 break;
13650 #endif
13651 case M16_OPC_RRIA:
13652 imm = ctx->opcode & 0xf;
13653 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
13654 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
13655 imm = (int16_t) (imm << 1) >> 1;
13656 if ((ctx->opcode >> 4) & 0x1) {
13657 #if defined(TARGET_MIPS64)
13658 check_mips_64(ctx);
13659 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13660 #else
13661 generate_exception_end(ctx, EXCP_RI);
13662 #endif
13663 } else {
13664 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13665 }
13666 break;
13667 case M16_OPC_ADDIU8:
13668 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13669 break;
13670 case M16_OPC_SLTI:
13671 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13672 break;
13673 case M16_OPC_SLTIU:
13674 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13675 break;
13676 case M16_OPC_I8:
13677 switch (funct) {
13678 case I8_BTEQZ:
13679 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
13680 break;
13681 case I8_BTNEZ:
13682 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
13683 break;
13684 case I8_SWRASP:
13685 gen_st(ctx, OPC_SW, 31, 29, imm);
13686 break;
13687 case I8_ADJSP:
13688 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
13689 break;
13690 case I8_SVRS:
13691 check_insn(ctx, ISA_MIPS32);
13692 {
13693 int xsregs = (ctx->opcode >> 24) & 0x7;
13694 int aregs = (ctx->opcode >> 16) & 0xf;
13695 int do_ra = (ctx->opcode >> 6) & 0x1;
13696 int do_s0 = (ctx->opcode >> 5) & 0x1;
13697 int do_s1 = (ctx->opcode >> 4) & 0x1;
13698 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
13699 | (ctx->opcode & 0xf)) << 3;
13700
13701 if (ctx->opcode & (1 << 7)) {
13702 gen_mips16_save(ctx, xsregs, aregs,
13703 do_ra, do_s0, do_s1,
13704 framesize);
13705 } else {
13706 gen_mips16_restore(ctx, xsregs, aregs,
13707 do_ra, do_s0, do_s1,
13708 framesize);
13709 }
13710 }
13711 break;
13712 default:
13713 generate_exception_end(ctx, EXCP_RI);
13714 break;
13715 }
13716 break;
13717 case M16_OPC_LI:
13718 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
13719 break;
13720 case M16_OPC_CMPI:
13721 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
13722 break;
13723 #if defined(TARGET_MIPS64)
13724 case M16_OPC_SD:
13725 check_insn(ctx, ISA_MIPS3);
13726 check_mips_64(ctx);
13727 gen_st(ctx, OPC_SD, ry, rx, offset);
13728 break;
13729 #endif
13730 case M16_OPC_LB:
13731 gen_ld(ctx, OPC_LB, ry, rx, offset);
13732 break;
13733 case M16_OPC_LH:
13734 gen_ld(ctx, OPC_LH, ry, rx, offset);
13735 break;
13736 case M16_OPC_LWSP:
13737 gen_ld(ctx, OPC_LW, rx, 29, offset);
13738 break;
13739 case M16_OPC_LW:
13740 gen_ld(ctx, OPC_LW, ry, rx, offset);
13741 break;
13742 case M16_OPC_LBU:
13743 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13744 break;
13745 case M16_OPC_LHU:
13746 gen_ld(ctx, OPC_LHU, ry, rx, offset);
13747 break;
13748 case M16_OPC_LWPC:
13749 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
13750 break;
13751 #if defined(TARGET_MIPS64)
13752 case M16_OPC_LWU:
13753 check_insn(ctx, ISA_MIPS3);
13754 check_mips_64(ctx);
13755 gen_ld(ctx, OPC_LWU, ry, rx, offset);
13756 break;
13757 #endif
13758 case M16_OPC_SB:
13759 gen_st(ctx, OPC_SB, ry, rx, offset);
13760 break;
13761 case M16_OPC_SH:
13762 gen_st(ctx, OPC_SH, ry, rx, offset);
13763 break;
13764 case M16_OPC_SWSP:
13765 gen_st(ctx, OPC_SW, rx, 29, offset);
13766 break;
13767 case M16_OPC_SW:
13768 gen_st(ctx, OPC_SW, ry, rx, offset);
13769 break;
13770 #if defined(TARGET_MIPS64)
13771 case M16_OPC_I64:
13772 decode_i64_mips16(ctx, ry, funct, offset, 1);
13773 break;
13774 #endif
13775 default:
13776 generate_exception_end(ctx, EXCP_RI);
13777 break;
13778 }
13779
13780 return 4;
13781 }
13782
13783 static inline bool is_uhi(int sdbbp_code)
13784 {
13785 #ifdef CONFIG_USER_ONLY
13786 return false;
13787 #else
13788 return semihosting_enabled() && sdbbp_code == 1;
13789 #endif
13790 }
13791
13792 #ifdef CONFIG_USER_ONLY
13793 /* The above should dead-code away any calls to this..*/
13794 static inline void gen_helper_do_semihosting(void *env)
13795 {
13796 g_assert_not_reached();
13797 }
13798 #endif
13799
13800 static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
13801 {
13802 int rx, ry;
13803 int sa;
13804 int op, cnvt_op, op1, offset;
13805 int funct;
13806 int n_bytes;
13807
13808 op = (ctx->opcode >> 11) & 0x1f;
13809 sa = (ctx->opcode >> 2) & 0x7;
13810 sa = sa == 0 ? 8 : sa;
13811 rx = xlat((ctx->opcode >> 8) & 0x7);
13812 cnvt_op = (ctx->opcode >> 5) & 0x7;
13813 ry = xlat((ctx->opcode >> 5) & 0x7);
13814 op1 = offset = ctx->opcode & 0x1f;
13815
13816 n_bytes = 2;
13817
13818 switch (op) {
13819 case M16_OPC_ADDIUSP:
13820 {
13821 int16_t imm = ((uint8_t) ctx->opcode) << 2;
13822
13823 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13824 }
13825 break;
13826 case M16_OPC_ADDIUPC:
13827 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
13828 break;
13829 case M16_OPC_B:
13830 offset = (ctx->opcode & 0x7ff) << 1;
13831 offset = (int16_t)(offset << 4) >> 4;
13832 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
13833 /* No delay slot, so just process as a normal instruction */
13834 break;
13835 case M16_OPC_JAL:
13836 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
13837 offset = (((ctx->opcode & 0x1f) << 21)
13838 | ((ctx->opcode >> 5) & 0x1f) << 16
13839 | offset) << 2;
13840 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
13841 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
13842 n_bytes = 4;
13843 break;
13844 case M16_OPC_BEQZ:
13845 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
13846 ((int8_t)ctx->opcode) << 1, 0);
13847 /* No delay slot, so just process as a normal instruction */
13848 break;
13849 case M16_OPC_BNEQZ:
13850 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
13851 ((int8_t)ctx->opcode) << 1, 0);
13852 /* No delay slot, so just process as a normal instruction */
13853 break;
13854 case M16_OPC_SHIFT:
13855 switch (ctx->opcode & 0x3) {
13856 case 0x0:
13857 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13858 break;
13859 case 0x1:
13860 #if defined(TARGET_MIPS64)
13861 check_insn(ctx, ISA_MIPS3);
13862 check_mips_64(ctx);
13863 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13864 #else
13865 generate_exception_end(ctx, EXCP_RI);
13866 #endif
13867 break;
13868 case 0x2:
13869 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13870 break;
13871 case 0x3:
13872 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13873 break;
13874 }
13875 break;
13876 #if defined(TARGET_MIPS64)
13877 case M16_OPC_LD:
13878 check_insn(ctx, ISA_MIPS3);
13879 check_mips_64(ctx);
13880 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
13881 break;
13882 #endif
13883 case M16_OPC_RRIA:
13884 {
13885 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
13886
13887 if ((ctx->opcode >> 4) & 1) {
13888 #if defined(TARGET_MIPS64)
13889 check_insn(ctx, ISA_MIPS3);
13890 check_mips_64(ctx);
13891 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13892 #else
13893 generate_exception_end(ctx, EXCP_RI);
13894 #endif
13895 } else {
13896 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13897 }
13898 }
13899 break;
13900 case M16_OPC_ADDIU8:
13901 {
13902 int16_t imm = (int8_t) ctx->opcode;
13903
13904 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13905 }
13906 break;
13907 case M16_OPC_SLTI:
13908 {
13909 int16_t imm = (uint8_t) ctx->opcode;
13910 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13911 }
13912 break;
13913 case M16_OPC_SLTIU:
13914 {
13915 int16_t imm = (uint8_t) ctx->opcode;
13916 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13917 }
13918 break;
13919 case M16_OPC_I8:
13920 {
13921 int reg32;
13922
13923 funct = (ctx->opcode >> 8) & 0x7;
13924 switch (funct) {
13925 case I8_BTEQZ:
13926 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
13927 ((int8_t)ctx->opcode) << 1, 0);
13928 break;
13929 case I8_BTNEZ:
13930 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
13931 ((int8_t)ctx->opcode) << 1, 0);
13932 break;
13933 case I8_SWRASP:
13934 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
13935 break;
13936 case I8_ADJSP:
13937 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
13938 ((int8_t)ctx->opcode) << 3);
13939 break;
13940 case I8_SVRS:
13941 check_insn(ctx, ISA_MIPS32);
13942 {
13943 int do_ra = ctx->opcode & (1 << 6);
13944 int do_s0 = ctx->opcode & (1 << 5);
13945 int do_s1 = ctx->opcode & (1 << 4);
13946 int framesize = ctx->opcode & 0xf;
13947
13948 if (framesize == 0) {
13949 framesize = 128;
13950 } else {
13951 framesize = framesize << 3;
13952 }
13953
13954 if (ctx->opcode & (1 << 7)) {
13955 gen_mips16_save(ctx, 0, 0,
13956 do_ra, do_s0, do_s1, framesize);
13957 } else {
13958 gen_mips16_restore(ctx, 0, 0,
13959 do_ra, do_s0, do_s1, framesize);
13960 }
13961 }
13962 break;
13963 case I8_MOV32R:
13964 {
13965 int rz = xlat(ctx->opcode & 0x7);
13966
13967 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
13968 ((ctx->opcode >> 5) & 0x7);
13969 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
13970 }
13971 break;
13972 case I8_MOVR32:
13973 reg32 = ctx->opcode & 0x1f;
13974 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
13975 break;
13976 default:
13977 generate_exception_end(ctx, EXCP_RI);
13978 break;
13979 }
13980 }
13981 break;
13982 case M16_OPC_LI:
13983 {
13984 int16_t imm = (uint8_t) ctx->opcode;
13985
13986 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
13987 }
13988 break;
13989 case M16_OPC_CMPI:
13990 {
13991 int16_t imm = (uint8_t) ctx->opcode;
13992 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
13993 }
13994 break;
13995 #if defined(TARGET_MIPS64)
13996 case M16_OPC_SD:
13997 check_insn(ctx, ISA_MIPS3);
13998 check_mips_64(ctx);
13999 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
14000 break;
14001 #endif
14002 case M16_OPC_LB:
14003 gen_ld(ctx, OPC_LB, ry, rx, offset);
14004 break;
14005 case M16_OPC_LH:
14006 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
14007 break;
14008 case M16_OPC_LWSP:
14009 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14010 break;
14011 case M16_OPC_LW:
14012 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
14013 break;
14014 case M16_OPC_LBU:
14015 gen_ld(ctx, OPC_LBU, ry, rx, offset);
14016 break;
14017 case M16_OPC_LHU:
14018 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
14019 break;
14020 case M16_OPC_LWPC:
14021 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
14022 break;
14023 #if defined(TARGET_MIPS64)
14024 case M16_OPC_LWU:
14025 check_insn(ctx, ISA_MIPS3);
14026 check_mips_64(ctx);
14027 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
14028 break;
14029 #endif
14030 case M16_OPC_SB:
14031 gen_st(ctx, OPC_SB, ry, rx, offset);
14032 break;
14033 case M16_OPC_SH:
14034 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
14035 break;
14036 case M16_OPC_SWSP:
14037 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14038 break;
14039 case M16_OPC_SW:
14040 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
14041 break;
14042 case M16_OPC_RRR:
14043 {
14044 int rz = xlat((ctx->opcode >> 2) & 0x7);
14045 int mips32_op;
14046
14047 switch (ctx->opcode & 0x3) {
14048 case RRR_ADDU:
14049 mips32_op = OPC_ADDU;
14050 break;
14051 case RRR_SUBU:
14052 mips32_op = OPC_SUBU;
14053 break;
14054 #if defined(TARGET_MIPS64)
14055 case RRR_DADDU:
14056 mips32_op = OPC_DADDU;
14057 check_insn(ctx, ISA_MIPS3);
14058 check_mips_64(ctx);
14059 break;
14060 case RRR_DSUBU:
14061 mips32_op = OPC_DSUBU;
14062 check_insn(ctx, ISA_MIPS3);
14063 check_mips_64(ctx);
14064 break;
14065 #endif
14066 default:
14067 generate_exception_end(ctx, EXCP_RI);
14068 goto done;
14069 }
14070
14071 gen_arith(ctx, mips32_op, rz, rx, ry);
14072 done:
14073 ;
14074 }
14075 break;
14076 case M16_OPC_RR:
14077 switch (op1) {
14078 case RR_JR:
14079 {
14080 int nd = (ctx->opcode >> 7) & 0x1;
14081 int link = (ctx->opcode >> 6) & 0x1;
14082 int ra = (ctx->opcode >> 5) & 0x1;
14083
14084 if (nd) {
14085 check_insn(ctx, ISA_MIPS32);
14086 }
14087
14088 if (link) {
14089 op = OPC_JALR;
14090 } else {
14091 op = OPC_JR;
14092 }
14093
14094 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
14095 (nd ? 0 : 2));
14096 }
14097 break;
14098 case RR_SDBBP:
14099 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
14100 gen_helper_do_semihosting(cpu_env);
14101 } else {
14102 /* XXX: not clear which exception should be raised
14103 * when in debug mode...
14104 */
14105 check_insn(ctx, ISA_MIPS32);
14106 generate_exception_end(ctx, EXCP_DBp);
14107 }
14108 break;
14109 case RR_SLT:
14110 gen_slt(ctx, OPC_SLT, 24, rx, ry);
14111 break;
14112 case RR_SLTU:
14113 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
14114 break;
14115 case RR_BREAK:
14116 generate_exception_end(ctx, EXCP_BREAK);
14117 break;
14118 case RR_SLLV:
14119 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
14120 break;
14121 case RR_SRLV:
14122 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
14123 break;
14124 case RR_SRAV:
14125 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
14126 break;
14127 #if defined(TARGET_MIPS64)
14128 case RR_DSRL:
14129 check_insn(ctx, ISA_MIPS3);
14130 check_mips_64(ctx);
14131 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
14132 break;
14133 #endif
14134 case RR_CMP:
14135 gen_logic(ctx, OPC_XOR, 24, rx, ry);
14136 break;
14137 case RR_NEG:
14138 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
14139 break;
14140 case RR_AND:
14141 gen_logic(ctx, OPC_AND, rx, rx, ry);
14142 break;
14143 case RR_OR:
14144 gen_logic(ctx, OPC_OR, rx, rx, ry);
14145 break;
14146 case RR_XOR:
14147 gen_logic(ctx, OPC_XOR, rx, rx, ry);
14148 break;
14149 case RR_NOT:
14150 gen_logic(ctx, OPC_NOR, rx, ry, 0);
14151 break;
14152 case RR_MFHI:
14153 gen_HILO(ctx, OPC_MFHI, 0, rx);
14154 break;
14155 case RR_CNVT:
14156 check_insn(ctx, ISA_MIPS32);
14157 switch (cnvt_op) {
14158 case RR_RY_CNVT_ZEB:
14159 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14160 break;
14161 case RR_RY_CNVT_ZEH:
14162 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14163 break;
14164 case RR_RY_CNVT_SEB:
14165 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14166 break;
14167 case RR_RY_CNVT_SEH:
14168 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14169 break;
14170 #if defined (TARGET_MIPS64)
14171 case RR_RY_CNVT_ZEW:
14172 check_insn(ctx, ISA_MIPS64);
14173 check_mips_64(ctx);
14174 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14175 break;
14176 case RR_RY_CNVT_SEW:
14177 check_insn(ctx, ISA_MIPS64);
14178 check_mips_64(ctx);
14179 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14180 break;
14181 #endif
14182 default:
14183 generate_exception_end(ctx, EXCP_RI);
14184 break;
14185 }
14186 break;
14187 case RR_MFLO:
14188 gen_HILO(ctx, OPC_MFLO, 0, rx);
14189 break;
14190 #if defined(TARGET_MIPS64)
14191 case RR_DSRA:
14192 check_insn(ctx, ISA_MIPS3);
14193 check_mips_64(ctx);
14194 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
14195 break;
14196 case RR_DSLLV:
14197 check_insn(ctx, ISA_MIPS3);
14198 check_mips_64(ctx);
14199 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
14200 break;
14201 case RR_DSRLV:
14202 check_insn(ctx, ISA_MIPS3);
14203 check_mips_64(ctx);
14204 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
14205 break;
14206 case RR_DSRAV:
14207 check_insn(ctx, ISA_MIPS3);
14208 check_mips_64(ctx);
14209 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
14210 break;
14211 #endif
14212 case RR_MULT:
14213 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
14214 break;
14215 case RR_MULTU:
14216 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
14217 break;
14218 case RR_DIV:
14219 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
14220 break;
14221 case RR_DIVU:
14222 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
14223 break;
14224 #if defined(TARGET_MIPS64)
14225 case RR_DMULT:
14226 check_insn(ctx, ISA_MIPS3);
14227 check_mips_64(ctx);
14228 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
14229 break;
14230 case RR_DMULTU:
14231 check_insn(ctx, ISA_MIPS3);
14232 check_mips_64(ctx);
14233 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
14234 break;
14235 case RR_DDIV:
14236 check_insn(ctx, ISA_MIPS3);
14237 check_mips_64(ctx);
14238 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
14239 break;
14240 case RR_DDIVU:
14241 check_insn(ctx, ISA_MIPS3);
14242 check_mips_64(ctx);
14243 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
14244 break;
14245 #endif
14246 default:
14247 generate_exception_end(ctx, EXCP_RI);
14248 break;
14249 }
14250 break;
14251 case M16_OPC_EXTEND:
14252 decode_extended_mips16_opc(env, ctx);
14253 n_bytes = 4;
14254 break;
14255 #if defined(TARGET_MIPS64)
14256 case M16_OPC_I64:
14257 funct = (ctx->opcode >> 8) & 0x7;
14258 decode_i64_mips16(ctx, ry, funct, offset, 0);
14259 break;
14260 #endif
14261 default:
14262 generate_exception_end(ctx, EXCP_RI);
14263 break;
14264 }
14265
14266 return n_bytes;
14267 }
14268
14269 /* microMIPS extension to MIPS32/MIPS64 */
14270
14271 /*
14272 * microMIPS32/microMIPS64 major opcodes
14273 *
14274 * 1. MIPS Architecture for Programmers Volume II-B:
14275 * The microMIPS32 Instruction Set (Revision 3.05)
14276 *
14277 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
14278 *
14279 * 2. MIPS Architecture For Programmers Volume II-A:
14280 * The MIPS64 Instruction Set (Revision 3.51)
14281 */
14282
14283 enum {
14284 POOL32A = 0x00,
14285 POOL16A = 0x01,
14286 LBU16 = 0x02,
14287 MOVE16 = 0x03,
14288 ADDI32 = 0x04,
14289 R6_LUI = 0x04,
14290 AUI = 0x04,
14291 LBU32 = 0x05,
14292 SB32 = 0x06,
14293 LB32 = 0x07,
14294
14295 POOL32B = 0x08,
14296 POOL16B = 0x09,
14297 LHU16 = 0x0a,
14298 ANDI16 = 0x0b,
14299 ADDIU32 = 0x0c,
14300 LHU32 = 0x0d,
14301 SH32 = 0x0e,
14302 LH32 = 0x0f,
14303
14304 POOL32I = 0x10,
14305 POOL16C = 0x11,
14306 LWSP16 = 0x12,
14307 POOL16D = 0x13,
14308 ORI32 = 0x14,
14309 POOL32F = 0x15,
14310 POOL32S = 0x16, /* MIPS64 */
14311 DADDIU32 = 0x17, /* MIPS64 */
14312
14313 POOL32C = 0x18,
14314 LWGP16 = 0x19,
14315 LW16 = 0x1a,
14316 POOL16E = 0x1b,
14317 XORI32 = 0x1c,
14318 JALS32 = 0x1d,
14319 BOVC = 0x1d,
14320 BEQC = 0x1d,
14321 BEQZALC = 0x1d,
14322 ADDIUPC = 0x1e,
14323 PCREL = 0x1e,
14324 BNVC = 0x1f,
14325 BNEC = 0x1f,
14326 BNEZALC = 0x1f,
14327
14328 R6_BEQZC = 0x20,
14329 JIC = 0x20,
14330 POOL16F = 0x21,
14331 SB16 = 0x22,
14332 BEQZ16 = 0x23,
14333 BEQZC16 = 0x23,
14334 SLTI32 = 0x24,
14335 BEQ32 = 0x25,
14336 BC = 0x25,
14337 SWC132 = 0x26,
14338 LWC132 = 0x27,
14339
14340 /* 0x29 is reserved */
14341 RES_29 = 0x29,
14342 R6_BNEZC = 0x28,
14343 JIALC = 0x28,
14344 SH16 = 0x2a,
14345 BNEZ16 = 0x2b,
14346 BNEZC16 = 0x2b,
14347 SLTIU32 = 0x2c,
14348 BNE32 = 0x2d,
14349 BALC = 0x2d,
14350 SDC132 = 0x2e,
14351 LDC132 = 0x2f,
14352
14353 /* 0x31 is reserved */
14354 RES_31 = 0x31,
14355 BLEZALC = 0x30,
14356 BGEZALC = 0x30,
14357 BGEUC = 0x30,
14358 SWSP16 = 0x32,
14359 B16 = 0x33,
14360 BC16 = 0x33,
14361 ANDI32 = 0x34,
14362 J32 = 0x35,
14363 BGTZC = 0x35,
14364 BLTZC = 0x35,
14365 BLTC = 0x35,
14366 SD32 = 0x36, /* MIPS64 */
14367 LD32 = 0x37, /* MIPS64 */
14368
14369 /* 0x39 is reserved */
14370 RES_39 = 0x39,
14371 BGTZALC = 0x38,
14372 BLTZALC = 0x38,
14373 BLTUC = 0x38,
14374 SW16 = 0x3a,
14375 LI16 = 0x3b,
14376 JALX32 = 0x3c,
14377 JAL32 = 0x3d,
14378 BLEZC = 0x3d,
14379 BGEZC = 0x3d,
14380 BGEC = 0x3d,
14381 SW32 = 0x3e,
14382 LW32 = 0x3f
14383 };
14384
14385 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
14386 enum {
14387 ADDIUPC_00 = 0x00,
14388 ADDIUPC_01 = 0x01,
14389 ADDIUPC_02 = 0x02,
14390 ADDIUPC_03 = 0x03,
14391 ADDIUPC_04 = 0x04,
14392 ADDIUPC_05 = 0x05,
14393 ADDIUPC_06 = 0x06,
14394 ADDIUPC_07 = 0x07,
14395 AUIPC = 0x1e,
14396 ALUIPC = 0x1f,
14397 LWPC_08 = 0x08,
14398 LWPC_09 = 0x09,
14399 LWPC_0A = 0x0A,
14400 LWPC_0B = 0x0B,
14401 LWPC_0C = 0x0C,
14402 LWPC_0D = 0x0D,
14403 LWPC_0E = 0x0E,
14404 LWPC_0F = 0x0F,
14405 };
14406
14407 /* POOL32A encoding of minor opcode field */
14408
14409 enum {
14410 /* These opcodes are distinguished only by bits 9..6; those bits are
14411 * what are recorded below. */
14412 SLL32 = 0x0,
14413 SRL32 = 0x1,
14414 SRA = 0x2,
14415 ROTR = 0x3,
14416 SELEQZ = 0x5,
14417 SELNEZ = 0x6,
14418 R6_RDHWR = 0x7,
14419
14420 SLLV = 0x0,
14421 SRLV = 0x1,
14422 SRAV = 0x2,
14423 ROTRV = 0x3,
14424 ADD = 0x4,
14425 ADDU32 = 0x5,
14426 SUB = 0x6,
14427 SUBU32 = 0x7,
14428 MUL = 0x8,
14429 AND = 0x9,
14430 OR32 = 0xa,
14431 NOR = 0xb,
14432 XOR32 = 0xc,
14433 SLT = 0xd,
14434 SLTU = 0xe,
14435
14436 MOVN = 0x0,
14437 R6_MUL = 0x0,
14438 MOVZ = 0x1,
14439 MUH = 0x1,
14440 MULU = 0x2,
14441 MUHU = 0x3,
14442 LWXS = 0x4,
14443 R6_DIV = 0x4,
14444 MOD = 0x5,
14445 R6_DIVU = 0x6,
14446 MODU = 0x7,
14447
14448 /* The following can be distinguished by their lower 6 bits. */
14449 BREAK32 = 0x07,
14450 INS = 0x0c,
14451 LSA = 0x0f,
14452 ALIGN = 0x1f,
14453 EXT = 0x2c,
14454 POOL32AXF = 0x3c,
14455 SIGRIE = 0x3f
14456 };
14457
14458 /* POOL32AXF encoding of minor opcode field extension */
14459
14460 /*
14461 * 1. MIPS Architecture for Programmers Volume II-B:
14462 * The microMIPS32 Instruction Set (Revision 3.05)
14463 *
14464 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
14465 *
14466 * 2. MIPS Architecture for Programmers VolumeIV-e:
14467 * The MIPS DSP Application-Specific Extension
14468 * to the microMIPS32 Architecture (Revision 2.34)
14469 *
14470 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
14471 */
14472
14473 enum {
14474 /* bits 11..6 */
14475 TEQ = 0x00,
14476 TGE = 0x08,
14477 TGEU = 0x10,
14478 TLT = 0x20,
14479 TLTU = 0x28,
14480 TNE = 0x30,
14481
14482 MFC0 = 0x03,
14483 MTC0 = 0x0b,
14484
14485 /* begin of microMIPS32 DSP */
14486
14487 /* bits 13..12 for 0x01 */
14488 MFHI_ACC = 0x0,
14489 MFLO_ACC = 0x1,
14490 MTHI_ACC = 0x2,
14491 MTLO_ACC = 0x3,
14492
14493 /* bits 13..12 for 0x2a */
14494 MADD_ACC = 0x0,
14495 MADDU_ACC = 0x1,
14496 MSUB_ACC = 0x2,
14497 MSUBU_ACC = 0x3,
14498
14499 /* bits 13..12 for 0x32 */
14500 MULT_ACC = 0x0,
14501 MULTU_ACC = 0x1,
14502
14503 /* end of microMIPS32 DSP */
14504
14505 /* bits 15..12 for 0x2c */
14506 BITSWAP = 0x0,
14507 SEB = 0x2,
14508 SEH = 0x3,
14509 CLO = 0x4,
14510 CLZ = 0x5,
14511 RDHWR = 0x6,
14512 WSBH = 0x7,
14513 MULT = 0x8,
14514 MULTU = 0x9,
14515 DIV = 0xa,
14516 DIVU = 0xb,
14517 MADD = 0xc,
14518 MADDU = 0xd,
14519 MSUB = 0xe,
14520 MSUBU = 0xf,
14521
14522 /* bits 15..12 for 0x34 */
14523 MFC2 = 0x4,
14524 MTC2 = 0x5,
14525 MFHC2 = 0x8,
14526 MTHC2 = 0x9,
14527 CFC2 = 0xc,
14528 CTC2 = 0xd,
14529
14530 /* bits 15..12 for 0x3c */
14531 JALR = 0x0,
14532 JR = 0x0, /* alias */
14533 JALRC = 0x0,
14534 JRC = 0x0,
14535 JALR_HB = 0x1,
14536 JALRC_HB = 0x1,
14537 JALRS = 0x4,
14538 JALRS_HB = 0x5,
14539
14540 /* bits 15..12 for 0x05 */
14541 RDPGPR = 0xe,
14542 WRPGPR = 0xf,
14543
14544 /* bits 15..12 for 0x0d */
14545 TLBP = 0x0,
14546 TLBR = 0x1,
14547 TLBWI = 0x2,
14548 TLBWR = 0x3,
14549 TLBINV = 0x4,
14550 TLBINVF = 0x5,
14551 WAIT = 0x9,
14552 IRET = 0xd,
14553 DERET = 0xe,
14554 ERET = 0xf,
14555
14556 /* bits 15..12 for 0x15 */
14557 DMT = 0x0,
14558 DVPE = 0x1,
14559 EMT = 0x2,
14560 EVPE = 0x3,
14561
14562 /* bits 15..12 for 0x1d */
14563 DI = 0x4,
14564 EI = 0x5,
14565
14566 /* bits 15..12 for 0x2d */
14567 SYNC = 0x6,
14568 SYSCALL = 0x8,
14569 SDBBP = 0xd,
14570
14571 /* bits 15..12 for 0x35 */
14572 MFHI32 = 0x0,
14573 MFLO32 = 0x1,
14574 MTHI32 = 0x2,
14575 MTLO32 = 0x3,
14576 };
14577
14578 /* POOL32B encoding of minor opcode field (bits 15..12) */
14579
14580 enum {
14581 LWC2 = 0x0,
14582 LWP = 0x1,
14583 LDP = 0x4,
14584 LWM32 = 0x5,
14585 CACHE = 0x6,
14586 LDM = 0x7,
14587 SWC2 = 0x8,
14588 SWP = 0x9,
14589 SDP = 0xc,
14590 SWM32 = 0xd,
14591 SDM = 0xf
14592 };
14593
14594 /* POOL32C encoding of minor opcode field (bits 15..12) */
14595
14596 enum {
14597 LWL = 0x0,
14598 SWL = 0x8,
14599 LWR = 0x1,
14600 SWR = 0x9,
14601 PREF = 0x2,
14602 ST_EVA = 0xa,
14603 LL = 0x3,
14604 SC = 0xb,
14605 LDL = 0x4,
14606 SDL = 0xc,
14607 LDR = 0x5,
14608 SDR = 0xd,
14609 LD_EVA = 0x6,
14610 LWU = 0xe,
14611 LLD = 0x7,
14612 SCD = 0xf
14613 };
14614
14615 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
14616
14617 enum {
14618 LBUE = 0x0,
14619 LHUE = 0x1,
14620 LWLE = 0x2,
14621 LWRE = 0x3,
14622 LBE = 0x4,
14623 LHE = 0x5,
14624 LLE = 0x6,
14625 LWE = 0x7,
14626 };
14627
14628 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
14629
14630 enum {
14631 SWLE = 0x0,
14632 SWRE = 0x1,
14633 PREFE = 0x2,
14634 CACHEE = 0x3,
14635 SBE = 0x4,
14636 SHE = 0x5,
14637 SCE = 0x6,
14638 SWE = 0x7,
14639 };
14640
14641 /* POOL32F encoding of minor opcode field (bits 5..0) */
14642
14643 enum {
14644 /* These are the bit 7..6 values */
14645 ADD_FMT = 0x0,
14646
14647 SUB_FMT = 0x1,
14648
14649 MUL_FMT = 0x2,
14650
14651 DIV_FMT = 0x3,
14652
14653 /* These are the bit 8..6 values */
14654 MOVN_FMT = 0x0,
14655 RSQRT2_FMT = 0x0,
14656 MOVF_FMT = 0x0,
14657 RINT_FMT = 0x0,
14658 SELNEZ_FMT = 0x0,
14659
14660 MOVZ_FMT = 0x1,
14661 LWXC1 = 0x1,
14662 MOVT_FMT = 0x1,
14663 CLASS_FMT = 0x1,
14664 SELEQZ_FMT = 0x1,
14665
14666 PLL_PS = 0x2,
14667 SWXC1 = 0x2,
14668 SEL_FMT = 0x2,
14669
14670 PLU_PS = 0x3,
14671 LDXC1 = 0x3,
14672
14673 MOVN_FMT_04 = 0x4,
14674 PUL_PS = 0x4,
14675 SDXC1 = 0x4,
14676 RECIP2_FMT = 0x4,
14677
14678 MOVZ_FMT_05 = 0x05,
14679 PUU_PS = 0x5,
14680 LUXC1 = 0x5,
14681
14682 CVT_PS_S = 0x6,
14683 SUXC1 = 0x6,
14684 ADDR_PS = 0x6,
14685 PREFX = 0x6,
14686 MADDF_FMT = 0x6,
14687
14688 MULR_PS = 0x7,
14689 MSUBF_FMT = 0x7,
14690
14691 MADD_S = 0x01,
14692 MADD_D = 0x09,
14693 MADD_PS = 0x11,
14694 ALNV_PS = 0x19,
14695 MSUB_S = 0x21,
14696 MSUB_D = 0x29,
14697 MSUB_PS = 0x31,
14698
14699 NMADD_S = 0x02,
14700 NMADD_D = 0x0a,
14701 NMADD_PS = 0x12,
14702 NMSUB_S = 0x22,
14703 NMSUB_D = 0x2a,
14704 NMSUB_PS = 0x32,
14705
14706 MIN_FMT = 0x3,
14707 MAX_FMT = 0xb,
14708 MINA_FMT = 0x23,
14709 MAXA_FMT = 0x2b,
14710 POOL32FXF = 0x3b,
14711
14712 CABS_COND_FMT = 0x1c, /* MIPS3D */
14713 C_COND_FMT = 0x3c,
14714
14715 CMP_CONDN_S = 0x5,
14716 CMP_CONDN_D = 0x15
14717 };
14718
14719 /* POOL32Fxf encoding of minor opcode extension field */
14720
14721 enum {
14722 CVT_L = 0x04,
14723 RSQRT_FMT = 0x08,
14724 FLOOR_L = 0x0c,
14725 CVT_PW_PS = 0x1c,
14726 CVT_W = 0x24,
14727 SQRT_FMT = 0x28,
14728 FLOOR_W = 0x2c,
14729 CVT_PS_PW = 0x3c,
14730 CFC1 = 0x40,
14731 RECIP_FMT = 0x48,
14732 CEIL_L = 0x4c,
14733 CTC1 = 0x60,
14734 CEIL_W = 0x6c,
14735 MFC1 = 0x80,
14736 CVT_S_PL = 0x84,
14737 TRUNC_L = 0x8c,
14738 MTC1 = 0xa0,
14739 CVT_S_PU = 0xa4,
14740 TRUNC_W = 0xac,
14741 MFHC1 = 0xc0,
14742 ROUND_L = 0xcc,
14743 MTHC1 = 0xe0,
14744 ROUND_W = 0xec,
14745
14746 MOV_FMT = 0x01,
14747 MOVF = 0x05,
14748 ABS_FMT = 0x0d,
14749 RSQRT1_FMT = 0x1d,
14750 MOVT = 0x25,
14751 NEG_FMT = 0x2d,
14752 CVT_D = 0x4d,
14753 RECIP1_FMT = 0x5d,
14754 CVT_S = 0x6d
14755 };
14756
14757 /* POOL32I encoding of minor opcode field (bits 25..21) */
14758
14759 enum {
14760 BLTZ = 0x00,
14761 BLTZAL = 0x01,
14762 BGEZ = 0x02,
14763 BGEZAL = 0x03,
14764 BLEZ = 0x04,
14765 BNEZC = 0x05,
14766 BGTZ = 0x06,
14767 BEQZC = 0x07,
14768 TLTI = 0x08,
14769 BC1EQZC = 0x08,
14770 TGEI = 0x09,
14771 BC1NEZC = 0x09,
14772 TLTIU = 0x0a,
14773 BC2EQZC = 0x0a,
14774 TGEIU = 0x0b,
14775 BC2NEZC = 0x0a,
14776 TNEI = 0x0c,
14777 R6_SYNCI = 0x0c,
14778 LUI = 0x0d,
14779 TEQI = 0x0e,
14780 SYNCI = 0x10,
14781 BLTZALS = 0x11,
14782 BGEZALS = 0x13,
14783 BC2F = 0x14,
14784 BC2T = 0x15,
14785 BPOSGE64 = 0x1a,
14786 BPOSGE32 = 0x1b,
14787 /* These overlap and are distinguished by bit16 of the instruction */
14788 BC1F = 0x1c,
14789 BC1T = 0x1d,
14790 BC1ANY2F = 0x1c,
14791 BC1ANY2T = 0x1d,
14792 BC1ANY4F = 0x1e,
14793 BC1ANY4T = 0x1f
14794 };
14795
14796 /* POOL16A encoding of minor opcode field */
14797
14798 enum {
14799 ADDU16 = 0x0,
14800 SUBU16 = 0x1
14801 };
14802
14803 /* POOL16B encoding of minor opcode field */
14804
14805 enum {
14806 SLL16 = 0x0,
14807 SRL16 = 0x1
14808 };
14809
14810 /* POOL16C encoding of minor opcode field */
14811
14812 enum {
14813 NOT16 = 0x00,
14814 XOR16 = 0x04,
14815 AND16 = 0x08,
14816 OR16 = 0x0c,
14817 LWM16 = 0x10,
14818 SWM16 = 0x14,
14819 JR16 = 0x18,
14820 JRC16 = 0x1a,
14821 JALR16 = 0x1c,
14822 JALR16S = 0x1e,
14823 MFHI16 = 0x20,
14824 MFLO16 = 0x24,
14825 BREAK16 = 0x28,
14826 SDBBP16 = 0x2c,
14827 JRADDIUSP = 0x30
14828 };
14829
14830 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
14831
14832 enum {
14833 R6_NOT16 = 0x00,
14834 R6_AND16 = 0x01,
14835 R6_LWM16 = 0x02,
14836 R6_JRC16 = 0x03,
14837 MOVEP = 0x04,
14838 MOVEP_05 = 0x05,
14839 MOVEP_06 = 0x06,
14840 MOVEP_07 = 0x07,
14841 R6_XOR16 = 0x08,
14842 R6_OR16 = 0x09,
14843 R6_SWM16 = 0x0a,
14844 JALRC16 = 0x0b,
14845 MOVEP_0C = 0x0c,
14846 MOVEP_0D = 0x0d,
14847 MOVEP_0E = 0x0e,
14848 MOVEP_0F = 0x0f,
14849 JRCADDIUSP = 0x13,
14850 R6_BREAK16 = 0x1b,
14851 R6_SDBBP16 = 0x3b
14852 };
14853
14854 /* POOL16D encoding of minor opcode field */
14855
14856 enum {
14857 ADDIUS5 = 0x0,
14858 ADDIUSP = 0x1
14859 };
14860
14861 /* POOL16E encoding of minor opcode field */
14862
14863 enum {
14864 ADDIUR2 = 0x0,
14865 ADDIUR1SP = 0x1
14866 };
14867
14868 static int mmreg(int r)
14869 {
14870 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
14871
14872 return map[r];
14873 }
14874
14875 /* Used for 16-bit store instructions. */
14876 static int mmreg2(int r)
14877 {
14878 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
14879
14880 return map[r];
14881 }
14882
14883 #define uMIPS_RD(op) ((op >> 7) & 0x7)
14884 #define uMIPS_RS(op) ((op >> 4) & 0x7)
14885 #define uMIPS_RS2(op) uMIPS_RS(op)
14886 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
14887 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
14888 #define uMIPS_RS5(op) (op & 0x1f)
14889
14890 /* Signed immediate */
14891 #define SIMM(op, start, width) \
14892 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
14893 << (32-width)) \
14894 >> (32-width))
14895 /* Zero-extended immediate */
14896 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
14897
14898 static void gen_addiur1sp(DisasContext *ctx)
14899 {
14900 int rd = mmreg(uMIPS_RD(ctx->opcode));
14901
14902 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
14903 }
14904
14905 static void gen_addiur2(DisasContext *ctx)
14906 {
14907 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
14908 int rd = mmreg(uMIPS_RD(ctx->opcode));
14909 int rs = mmreg(uMIPS_RS(ctx->opcode));
14910
14911 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
14912 }
14913
14914 static void gen_addiusp(DisasContext *ctx)
14915 {
14916 int encoded = ZIMM(ctx->opcode, 1, 9);
14917 int decoded;
14918
14919 if (encoded <= 1) {
14920 decoded = 256 + encoded;
14921 } else if (encoded <= 255) {
14922 decoded = encoded;
14923 } else if (encoded <= 509) {
14924 decoded = encoded - 512;
14925 } else {
14926 decoded = encoded - 768;
14927 }
14928
14929 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
14930 }
14931
14932 static void gen_addius5(DisasContext *ctx)
14933 {
14934 int imm = SIMM(ctx->opcode, 1, 4);
14935 int rd = (ctx->opcode >> 5) & 0x1f;
14936
14937 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
14938 }
14939
14940 static void gen_andi16(DisasContext *ctx)
14941 {
14942 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
14943 31, 32, 63, 64, 255, 32768, 65535 };
14944 int rd = mmreg(uMIPS_RD(ctx->opcode));
14945 int rs = mmreg(uMIPS_RS(ctx->opcode));
14946 int encoded = ZIMM(ctx->opcode, 0, 4);
14947
14948 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
14949 }
14950
14951 static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist,
14952 int base, int16_t offset)
14953 {
14954 TCGv t0, t1;
14955 TCGv_i32 t2;
14956
14957 if (ctx->hflags & MIPS_HFLAG_BMASK) {
14958 generate_exception_end(ctx, EXCP_RI);
14959 return;
14960 }
14961
14962 t0 = tcg_temp_new();
14963
14964 gen_base_offset_addr(ctx, t0, base, offset);
14965
14966 t1 = tcg_const_tl(reglist);
14967 t2 = tcg_const_i32(ctx->mem_idx);
14968
14969 save_cpu_state(ctx, 1);
14970 switch (opc) {
14971 case LWM32:
14972 gen_helper_lwm(cpu_env, t0, t1, t2);
14973 break;
14974 case SWM32:
14975 gen_helper_swm(cpu_env, t0, t1, t2);
14976 break;
14977 #ifdef TARGET_MIPS64
14978 case LDM:
14979 gen_helper_ldm(cpu_env, t0, t1, t2);
14980 break;
14981 case SDM:
14982 gen_helper_sdm(cpu_env, t0, t1, t2);
14983 break;
14984 #endif
14985 }
14986 tcg_temp_free(t0);
14987 tcg_temp_free(t1);
14988 tcg_temp_free_i32(t2);
14989 }
14990
14991
14992 static void gen_pool16c_insn(DisasContext *ctx)
14993 {
14994 int rd = mmreg((ctx->opcode >> 3) & 0x7);
14995 int rs = mmreg(ctx->opcode & 0x7);
14996
14997 switch (((ctx->opcode) >> 4) & 0x3f) {
14998 case NOT16 + 0:
14999 case NOT16 + 1:
15000 case NOT16 + 2:
15001 case NOT16 + 3:
15002 gen_logic(ctx, OPC_NOR, rd, rs, 0);
15003 break;
15004 case XOR16 + 0:
15005 case XOR16 + 1:
15006 case XOR16 + 2:
15007 case XOR16 + 3:
15008 gen_logic(ctx, OPC_XOR, rd, rd, rs);
15009 break;
15010 case AND16 + 0:
15011 case AND16 + 1:
15012 case AND16 + 2:
15013 case AND16 + 3:
15014 gen_logic(ctx, OPC_AND, rd, rd, rs);
15015 break;
15016 case OR16 + 0:
15017 case OR16 + 1:
15018 case OR16 + 2:
15019 case OR16 + 3:
15020 gen_logic(ctx, OPC_OR, rd, rd, rs);
15021 break;
15022 case LWM16 + 0:
15023 case LWM16 + 1:
15024 case LWM16 + 2:
15025 case LWM16 + 3:
15026 {
15027 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15028 int offset = ZIMM(ctx->opcode, 0, 4);
15029
15030 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
15031 29, offset << 2);
15032 }
15033 break;
15034 case SWM16 + 0:
15035 case SWM16 + 1:
15036 case SWM16 + 2:
15037 case SWM16 + 3:
15038 {
15039 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15040 int offset = ZIMM(ctx->opcode, 0, 4);
15041
15042 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
15043 29, offset << 2);
15044 }
15045 break;
15046 case JR16 + 0:
15047 case JR16 + 1:
15048 {
15049 int reg = ctx->opcode & 0x1f;
15050
15051 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
15052 }
15053 break;
15054 case JRC16 + 0:
15055 case JRC16 + 1:
15056 {
15057 int reg = ctx->opcode & 0x1f;
15058 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
15059 /* Let normal delay slot handling in our caller take us
15060 to the branch target. */
15061 }
15062 break;
15063 case JALR16 + 0:
15064 case JALR16 + 1:
15065 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
15066 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15067 break;
15068 case JALR16S + 0:
15069 case JALR16S + 1:
15070 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
15071 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15072 break;
15073 case MFHI16 + 0:
15074 case MFHI16 + 1:
15075 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
15076 break;
15077 case MFLO16 + 0:
15078 case MFLO16 + 1:
15079 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
15080 break;
15081 case BREAK16:
15082 generate_exception_end(ctx, EXCP_BREAK);
15083 break;
15084 case SDBBP16:
15085 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
15086 gen_helper_do_semihosting(cpu_env);
15087 } else {
15088 /* XXX: not clear which exception should be raised
15089 * when in debug mode...
15090 */
15091 check_insn(ctx, ISA_MIPS32);
15092 generate_exception_end(ctx, EXCP_DBp);
15093 }
15094 break;
15095 case JRADDIUSP + 0:
15096 case JRADDIUSP + 1:
15097 {
15098 int imm = ZIMM(ctx->opcode, 0, 5);
15099 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15100 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15101 /* Let normal delay slot handling in our caller take us
15102 to the branch target. */
15103 }
15104 break;
15105 default:
15106 generate_exception_end(ctx, EXCP_RI);
15107 break;
15108 }
15109 }
15110
15111 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
15112 int enc_rs)
15113 {
15114 int rd, rs, re, rt;
15115 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
15116 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
15117 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
15118 rd = rd_enc[enc_dest];
15119 re = re_enc[enc_dest];
15120 rs = rs_rt_enc[enc_rs];
15121 rt = rs_rt_enc[enc_rt];
15122 if (rs) {
15123 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
15124 } else {
15125 tcg_gen_movi_tl(cpu_gpr[rd], 0);
15126 }
15127 if (rt) {
15128 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
15129 } else {
15130 tcg_gen_movi_tl(cpu_gpr[re], 0);
15131 }
15132 }
15133
15134 static void gen_pool16c_r6_insn(DisasContext *ctx)
15135 {
15136 int rt = mmreg((ctx->opcode >> 7) & 0x7);
15137 int rs = mmreg((ctx->opcode >> 4) & 0x7);
15138
15139 switch (ctx->opcode & 0xf) {
15140 case R6_NOT16:
15141 gen_logic(ctx, OPC_NOR, rt, rs, 0);
15142 break;
15143 case R6_AND16:
15144 gen_logic(ctx, OPC_AND, rt, rt, rs);
15145 break;
15146 case R6_LWM16:
15147 {
15148 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15149 int offset = extract32(ctx->opcode, 4, 4);
15150 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
15151 }
15152 break;
15153 case R6_JRC16: /* JRCADDIUSP */
15154 if ((ctx->opcode >> 4) & 1) {
15155 /* JRCADDIUSP */
15156 int imm = extract32(ctx->opcode, 5, 5);
15157 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15158 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15159 } else {
15160 /* JRC16 */
15161 rs = extract32(ctx->opcode, 5, 5);
15162 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
15163 }
15164 break;
15165 case MOVEP:
15166 case MOVEP_05:
15167 case MOVEP_06:
15168 case MOVEP_07:
15169 case MOVEP_0C:
15170 case MOVEP_0D:
15171 case MOVEP_0E:
15172 case MOVEP_0F:
15173 {
15174 int enc_dest = uMIPS_RD(ctx->opcode);
15175 int enc_rt = uMIPS_RS2(ctx->opcode);
15176 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
15177 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15178 }
15179 break;
15180 case R6_XOR16:
15181 gen_logic(ctx, OPC_XOR, rt, rt, rs);
15182 break;
15183 case R6_OR16:
15184 gen_logic(ctx, OPC_OR, rt, rt, rs);
15185 break;
15186 case R6_SWM16:
15187 {
15188 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15189 int offset = extract32(ctx->opcode, 4, 4);
15190 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
15191 }
15192 break;
15193 case JALRC16: /* BREAK16, SDBBP16 */
15194 switch (ctx->opcode & 0x3f) {
15195 case JALRC16:
15196 case JALRC16 + 0x20:
15197 /* JALRC16 */
15198 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
15199 31, 0, 0);
15200 break;
15201 case R6_BREAK16:
15202 /* BREAK16 */
15203 generate_exception(ctx, EXCP_BREAK);
15204 break;
15205 case R6_SDBBP16:
15206 /* SDBBP16 */
15207 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
15208 gen_helper_do_semihosting(cpu_env);
15209 } else {
15210 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15211 generate_exception(ctx, EXCP_RI);
15212 } else {
15213 generate_exception(ctx, EXCP_DBp);
15214 }
15215 }
15216 break;
15217 }
15218 break;
15219 default:
15220 generate_exception(ctx, EXCP_RI);
15221 break;
15222 }
15223 }
15224
15225 static void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
15226 {
15227 TCGv t0 = tcg_temp_new();
15228 TCGv t1 = tcg_temp_new();
15229
15230 gen_load_gpr(t0, base);
15231
15232 if (index != 0) {
15233 gen_load_gpr(t1, index);
15234 tcg_gen_shli_tl(t1, t1, 2);
15235 gen_op_addr_add(ctx, t0, t1, t0);
15236 }
15237
15238 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15239 gen_store_gpr(t1, rd);
15240
15241 tcg_temp_free(t0);
15242 tcg_temp_free(t1);
15243 }
15244
15245 static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd,
15246 int base, int16_t offset)
15247 {
15248 TCGv t0, t1;
15249
15250 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
15251 generate_exception_end(ctx, EXCP_RI);
15252 return;
15253 }
15254
15255 t0 = tcg_temp_new();
15256 t1 = tcg_temp_new();
15257
15258 gen_base_offset_addr(ctx, t0, base, offset);
15259
15260 switch (opc) {
15261 case LWP:
15262 if (rd == base) {
15263 generate_exception_end(ctx, EXCP_RI);
15264 return;
15265 }
15266 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15267 gen_store_gpr(t1, rd);
15268 tcg_gen_movi_tl(t1, 4);
15269 gen_op_addr_add(ctx, t0, t0, t1);
15270 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15271 gen_store_gpr(t1, rd + 1);
15272 break;
15273 case SWP:
15274 gen_load_gpr(t1, rd);
15275 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15276 tcg_gen_movi_tl(t1, 4);
15277 gen_op_addr_add(ctx, t0, t0, t1);
15278 gen_load_gpr(t1, rd + 1);
15279 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15280 break;
15281 #ifdef TARGET_MIPS64
15282 case LDP:
15283 if (rd == base) {
15284 generate_exception_end(ctx, EXCP_RI);
15285 return;
15286 }
15287 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15288 gen_store_gpr(t1, rd);
15289 tcg_gen_movi_tl(t1, 8);
15290 gen_op_addr_add(ctx, t0, t0, t1);
15291 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15292 gen_store_gpr(t1, rd + 1);
15293 break;
15294 case SDP:
15295 gen_load_gpr(t1, rd);
15296 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15297 tcg_gen_movi_tl(t1, 8);
15298 gen_op_addr_add(ctx, t0, t0, t1);
15299 gen_load_gpr(t1, rd + 1);
15300 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15301 break;
15302 #endif
15303 }
15304 tcg_temp_free(t0);
15305 tcg_temp_free(t1);
15306 }
15307
15308 static void gen_sync(int stype)
15309 {
15310 TCGBar tcg_mo = TCG_BAR_SC;
15311
15312 switch (stype) {
15313 case 0x4: /* SYNC_WMB */
15314 tcg_mo |= TCG_MO_ST_ST;
15315 break;
15316 case 0x10: /* SYNC_MB */
15317 tcg_mo |= TCG_MO_ALL;
15318 break;
15319 case 0x11: /* SYNC_ACQUIRE */
15320 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
15321 break;
15322 case 0x12: /* SYNC_RELEASE */
15323 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
15324 break;
15325 case 0x13: /* SYNC_RMB */
15326 tcg_mo |= TCG_MO_LD_LD;
15327 break;
15328 default:
15329 tcg_mo |= TCG_MO_ALL;
15330 break;
15331 }
15332
15333 tcg_gen_mb(tcg_mo);
15334 }
15335
15336 static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
15337 {
15338 int extension = (ctx->opcode >> 6) & 0x3f;
15339 int minor = (ctx->opcode >> 12) & 0xf;
15340 uint32_t mips32_op;
15341
15342 switch (extension) {
15343 case TEQ:
15344 mips32_op = OPC_TEQ;
15345 goto do_trap;
15346 case TGE:
15347 mips32_op = OPC_TGE;
15348 goto do_trap;
15349 case TGEU:
15350 mips32_op = OPC_TGEU;
15351 goto do_trap;
15352 case TLT:
15353 mips32_op = OPC_TLT;
15354 goto do_trap;
15355 case TLTU:
15356 mips32_op = OPC_TLTU;
15357 goto do_trap;
15358 case TNE:
15359 mips32_op = OPC_TNE;
15360 do_trap:
15361 gen_trap(ctx, mips32_op, rs, rt, -1);
15362 break;
15363 #ifndef CONFIG_USER_ONLY
15364 case MFC0:
15365 case MFC0 + 32:
15366 check_cp0_enabled(ctx);
15367 if (rt == 0) {
15368 /* Treat as NOP. */
15369 break;
15370 }
15371 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
15372 break;
15373 case MTC0:
15374 case MTC0 + 32:
15375 check_cp0_enabled(ctx);
15376 {
15377 TCGv t0 = tcg_temp_new();
15378
15379 gen_load_gpr(t0, rt);
15380 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
15381 tcg_temp_free(t0);
15382 }
15383 break;
15384 #endif
15385 case 0x2a:
15386 switch (minor & 3) {
15387 case MADD_ACC:
15388 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
15389 break;
15390 case MADDU_ACC:
15391 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
15392 break;
15393 case MSUB_ACC:
15394 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
15395 break;
15396 case MSUBU_ACC:
15397 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
15398 break;
15399 default:
15400 goto pool32axf_invalid;
15401 }
15402 break;
15403 case 0x32:
15404 switch (minor & 3) {
15405 case MULT_ACC:
15406 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
15407 break;
15408 case MULTU_ACC:
15409 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
15410 break;
15411 default:
15412 goto pool32axf_invalid;
15413 }
15414 break;
15415 case 0x2c:
15416 switch (minor) {
15417 case BITSWAP:
15418 check_insn(ctx, ISA_MIPS32R6);
15419 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
15420 break;
15421 case SEB:
15422 gen_bshfl(ctx, OPC_SEB, rs, rt);
15423 break;
15424 case SEH:
15425 gen_bshfl(ctx, OPC_SEH, rs, rt);
15426 break;
15427 case CLO:
15428 mips32_op = OPC_CLO;
15429 goto do_cl;
15430 case CLZ:
15431 mips32_op = OPC_CLZ;
15432 do_cl:
15433 check_insn(ctx, ISA_MIPS32);
15434 gen_cl(ctx, mips32_op, rt, rs);
15435 break;
15436 case RDHWR:
15437 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15438 gen_rdhwr(ctx, rt, rs, 0);
15439 break;
15440 case WSBH:
15441 gen_bshfl(ctx, OPC_WSBH, rs, rt);
15442 break;
15443 case MULT:
15444 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15445 mips32_op = OPC_MULT;
15446 goto do_mul;
15447 case MULTU:
15448 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15449 mips32_op = OPC_MULTU;
15450 goto do_mul;
15451 case DIV:
15452 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15453 mips32_op = OPC_DIV;
15454 goto do_div;
15455 case DIVU:
15456 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15457 mips32_op = OPC_DIVU;
15458 goto do_div;
15459 do_div:
15460 check_insn(ctx, ISA_MIPS32);
15461 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15462 break;
15463 case MADD:
15464 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15465 mips32_op = OPC_MADD;
15466 goto do_mul;
15467 case MADDU:
15468 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15469 mips32_op = OPC_MADDU;
15470 goto do_mul;
15471 case MSUB:
15472 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15473 mips32_op = OPC_MSUB;
15474 goto do_mul;
15475 case MSUBU:
15476 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15477 mips32_op = OPC_MSUBU;
15478 do_mul:
15479 check_insn(ctx, ISA_MIPS32);
15480 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15481 break;
15482 default:
15483 goto pool32axf_invalid;
15484 }
15485 break;
15486 case 0x34:
15487 switch (minor) {
15488 case MFC2:
15489 case MTC2:
15490 case MFHC2:
15491 case MTHC2:
15492 case CFC2:
15493 case CTC2:
15494 generate_exception_err(ctx, EXCP_CpU, 2);
15495 break;
15496 default:
15497 goto pool32axf_invalid;
15498 }
15499 break;
15500 case 0x3c:
15501 switch (minor) {
15502 case JALR: /* JALRC */
15503 case JALR_HB: /* JALRC_HB */
15504 if (ctx->insn_flags & ISA_MIPS32R6) {
15505 /* JALRC, JALRC_HB */
15506 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
15507 } else {
15508 /* JALR, JALR_HB */
15509 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
15510 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15511 }
15512 break;
15513 case JALRS:
15514 case JALRS_HB:
15515 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15516 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
15517 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15518 break;
15519 default:
15520 goto pool32axf_invalid;
15521 }
15522 break;
15523 case 0x05:
15524 switch (minor) {
15525 case RDPGPR:
15526 check_cp0_enabled(ctx);
15527 check_insn(ctx, ISA_MIPS32R2);
15528 gen_load_srsgpr(rs, rt);
15529 break;
15530 case WRPGPR:
15531 check_cp0_enabled(ctx);
15532 check_insn(ctx, ISA_MIPS32R2);
15533 gen_store_srsgpr(rs, rt);
15534 break;
15535 default:
15536 goto pool32axf_invalid;
15537 }
15538 break;
15539 #ifndef CONFIG_USER_ONLY
15540 case 0x0d:
15541 switch (minor) {
15542 case TLBP:
15543 mips32_op = OPC_TLBP;
15544 goto do_cp0;
15545 case TLBR:
15546 mips32_op = OPC_TLBR;
15547 goto do_cp0;
15548 case TLBWI:
15549 mips32_op = OPC_TLBWI;
15550 goto do_cp0;
15551 case TLBWR:
15552 mips32_op = OPC_TLBWR;
15553 goto do_cp0;
15554 case TLBINV:
15555 mips32_op = OPC_TLBINV;
15556 goto do_cp0;
15557 case TLBINVF:
15558 mips32_op = OPC_TLBINVF;
15559 goto do_cp0;
15560 case WAIT:
15561 mips32_op = OPC_WAIT;
15562 goto do_cp0;
15563 case DERET:
15564 mips32_op = OPC_DERET;
15565 goto do_cp0;
15566 case ERET:
15567 mips32_op = OPC_ERET;
15568 do_cp0:
15569 gen_cp0(env, ctx, mips32_op, rt, rs);
15570 break;
15571 default:
15572 goto pool32axf_invalid;
15573 }
15574 break;
15575 case 0x1d:
15576 switch (minor) {
15577 case DI:
15578 check_cp0_enabled(ctx);
15579 {
15580 TCGv t0 = tcg_temp_new();
15581
15582 save_cpu_state(ctx, 1);
15583 gen_helper_di(t0, cpu_env);
15584 gen_store_gpr(t0, rs);
15585 /* Stop translation as we may have switched the execution mode */
15586 ctx->base.is_jmp = DISAS_STOP;
15587 tcg_temp_free(t0);
15588 }
15589 break;
15590 case EI:
15591 check_cp0_enabled(ctx);
15592 {
15593 TCGv t0 = tcg_temp_new();
15594
15595 save_cpu_state(ctx, 1);
15596 gen_helper_ei(t0, cpu_env);
15597 gen_store_gpr(t0, rs);
15598 /* DISAS_STOP isn't sufficient, we need to ensure we break out
15599 of translated code to check for pending interrupts. */
15600 gen_save_pc(ctx->base.pc_next + 4);
15601 ctx->base.is_jmp = DISAS_EXIT;
15602 tcg_temp_free(t0);
15603 }
15604 break;
15605 default:
15606 goto pool32axf_invalid;
15607 }
15608 break;
15609 #endif
15610 case 0x2d:
15611 switch (minor) {
15612 case SYNC:
15613 gen_sync(extract32(ctx->opcode, 16, 5));
15614 break;
15615 case SYSCALL:
15616 generate_exception_end(ctx, EXCP_SYSCALL);
15617 break;
15618 case SDBBP:
15619 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
15620 gen_helper_do_semihosting(cpu_env);
15621 } else {
15622 check_insn(ctx, ISA_MIPS32);
15623 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15624 generate_exception_end(ctx, EXCP_RI);
15625 } else {
15626 generate_exception_end(ctx, EXCP_DBp);
15627 }
15628 }
15629 break;
15630 default:
15631 goto pool32axf_invalid;
15632 }
15633 break;
15634 case 0x01:
15635 switch (minor & 3) {
15636 case MFHI_ACC:
15637 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
15638 break;
15639 case MFLO_ACC:
15640 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
15641 break;
15642 case MTHI_ACC:
15643 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
15644 break;
15645 case MTLO_ACC:
15646 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
15647 break;
15648 default:
15649 goto pool32axf_invalid;
15650 }
15651 break;
15652 case 0x35:
15653 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15654 switch (minor) {
15655 case MFHI32:
15656 gen_HILO(ctx, OPC_MFHI, 0, rs);
15657 break;
15658 case MFLO32:
15659 gen_HILO(ctx, OPC_MFLO, 0, rs);
15660 break;
15661 case MTHI32:
15662 gen_HILO(ctx, OPC_MTHI, 0, rs);
15663 break;
15664 case MTLO32:
15665 gen_HILO(ctx, OPC_MTLO, 0, rs);
15666 break;
15667 default:
15668 goto pool32axf_invalid;
15669 }
15670 break;
15671 default:
15672 pool32axf_invalid:
15673 MIPS_INVAL("pool32axf");
15674 generate_exception_end(ctx, EXCP_RI);
15675 break;
15676 }
15677 }
15678
15679 /* Values for microMIPS fmt field. Variable-width, depending on which
15680 formats the instruction supports. */
15681
15682 enum {
15683 FMT_SD_S = 0,
15684 FMT_SD_D = 1,
15685
15686 FMT_SDPS_S = 0,
15687 FMT_SDPS_D = 1,
15688 FMT_SDPS_PS = 2,
15689
15690 FMT_SWL_S = 0,
15691 FMT_SWL_W = 1,
15692 FMT_SWL_L = 2,
15693
15694 FMT_DWL_D = 0,
15695 FMT_DWL_W = 1,
15696 FMT_DWL_L = 2
15697 };
15698
15699 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
15700 {
15701 int extension = (ctx->opcode >> 6) & 0x3ff;
15702 uint32_t mips32_op;
15703
15704 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
15705 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
15706 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
15707
15708 switch (extension) {
15709 case FLOAT_1BIT_FMT(CFC1, 0):
15710 mips32_op = OPC_CFC1;
15711 goto do_cp1;
15712 case FLOAT_1BIT_FMT(CTC1, 0):
15713 mips32_op = OPC_CTC1;
15714 goto do_cp1;
15715 case FLOAT_1BIT_FMT(MFC1, 0):
15716 mips32_op = OPC_MFC1;
15717 goto do_cp1;
15718 case FLOAT_1BIT_FMT(MTC1, 0):
15719 mips32_op = OPC_MTC1;
15720 goto do_cp1;
15721 case FLOAT_1BIT_FMT(MFHC1, 0):
15722 mips32_op = OPC_MFHC1;
15723 goto do_cp1;
15724 case FLOAT_1BIT_FMT(MTHC1, 0):
15725 mips32_op = OPC_MTHC1;
15726 do_cp1:
15727 gen_cp1(ctx, mips32_op, rt, rs);
15728 break;
15729
15730 /* Reciprocal square root */
15731 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
15732 mips32_op = OPC_RSQRT_S;
15733 goto do_unaryfp;
15734 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
15735 mips32_op = OPC_RSQRT_D;
15736 goto do_unaryfp;
15737
15738 /* Square root */
15739 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
15740 mips32_op = OPC_SQRT_S;
15741 goto do_unaryfp;
15742 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
15743 mips32_op = OPC_SQRT_D;
15744 goto do_unaryfp;
15745
15746 /* Reciprocal */
15747 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
15748 mips32_op = OPC_RECIP_S;
15749 goto do_unaryfp;
15750 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
15751 mips32_op = OPC_RECIP_D;
15752 goto do_unaryfp;
15753
15754 /* Floor */
15755 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
15756 mips32_op = OPC_FLOOR_L_S;
15757 goto do_unaryfp;
15758 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
15759 mips32_op = OPC_FLOOR_L_D;
15760 goto do_unaryfp;
15761 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
15762 mips32_op = OPC_FLOOR_W_S;
15763 goto do_unaryfp;
15764 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
15765 mips32_op = OPC_FLOOR_W_D;
15766 goto do_unaryfp;
15767
15768 /* Ceiling */
15769 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
15770 mips32_op = OPC_CEIL_L_S;
15771 goto do_unaryfp;
15772 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
15773 mips32_op = OPC_CEIL_L_D;
15774 goto do_unaryfp;
15775 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
15776 mips32_op = OPC_CEIL_W_S;
15777 goto do_unaryfp;
15778 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
15779 mips32_op = OPC_CEIL_W_D;
15780 goto do_unaryfp;
15781
15782 /* Truncation */
15783 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
15784 mips32_op = OPC_TRUNC_L_S;
15785 goto do_unaryfp;
15786 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
15787 mips32_op = OPC_TRUNC_L_D;
15788 goto do_unaryfp;
15789 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
15790 mips32_op = OPC_TRUNC_W_S;
15791 goto do_unaryfp;
15792 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
15793 mips32_op = OPC_TRUNC_W_D;
15794 goto do_unaryfp;
15795
15796 /* Round */
15797 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
15798 mips32_op = OPC_ROUND_L_S;
15799 goto do_unaryfp;
15800 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
15801 mips32_op = OPC_ROUND_L_D;
15802 goto do_unaryfp;
15803 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
15804 mips32_op = OPC_ROUND_W_S;
15805 goto do_unaryfp;
15806 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
15807 mips32_op = OPC_ROUND_W_D;
15808 goto do_unaryfp;
15809
15810 /* Integer to floating-point conversion */
15811 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
15812 mips32_op = OPC_CVT_L_S;
15813 goto do_unaryfp;
15814 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
15815 mips32_op = OPC_CVT_L_D;
15816 goto do_unaryfp;
15817 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
15818 mips32_op = OPC_CVT_W_S;
15819 goto do_unaryfp;
15820 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
15821 mips32_op = OPC_CVT_W_D;
15822 goto do_unaryfp;
15823
15824 /* Paired-foo conversions */
15825 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
15826 mips32_op = OPC_CVT_S_PL;
15827 goto do_unaryfp;
15828 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
15829 mips32_op = OPC_CVT_S_PU;
15830 goto do_unaryfp;
15831 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
15832 mips32_op = OPC_CVT_PW_PS;
15833 goto do_unaryfp;
15834 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
15835 mips32_op = OPC_CVT_PS_PW;
15836 goto do_unaryfp;
15837
15838 /* Floating-point moves */
15839 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
15840 mips32_op = OPC_MOV_S;
15841 goto do_unaryfp;
15842 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
15843 mips32_op = OPC_MOV_D;
15844 goto do_unaryfp;
15845 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
15846 mips32_op = OPC_MOV_PS;
15847 goto do_unaryfp;
15848
15849 /* Absolute value */
15850 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
15851 mips32_op = OPC_ABS_S;
15852 goto do_unaryfp;
15853 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
15854 mips32_op = OPC_ABS_D;
15855 goto do_unaryfp;
15856 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
15857 mips32_op = OPC_ABS_PS;
15858 goto do_unaryfp;
15859
15860 /* Negation */
15861 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
15862 mips32_op = OPC_NEG_S;
15863 goto do_unaryfp;
15864 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
15865 mips32_op = OPC_NEG_D;
15866 goto do_unaryfp;
15867 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
15868 mips32_op = OPC_NEG_PS;
15869 goto do_unaryfp;
15870
15871 /* Reciprocal square root step */
15872 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
15873 mips32_op = OPC_RSQRT1_S;
15874 goto do_unaryfp;
15875 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
15876 mips32_op = OPC_RSQRT1_D;
15877 goto do_unaryfp;
15878 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
15879 mips32_op = OPC_RSQRT1_PS;
15880 goto do_unaryfp;
15881
15882 /* Reciprocal step */
15883 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
15884 mips32_op = OPC_RECIP1_S;
15885 goto do_unaryfp;
15886 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
15887 mips32_op = OPC_RECIP1_S;
15888 goto do_unaryfp;
15889 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
15890 mips32_op = OPC_RECIP1_PS;
15891 goto do_unaryfp;
15892
15893 /* Conversions from double */
15894 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
15895 mips32_op = OPC_CVT_D_S;
15896 goto do_unaryfp;
15897 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
15898 mips32_op = OPC_CVT_D_W;
15899 goto do_unaryfp;
15900 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
15901 mips32_op = OPC_CVT_D_L;
15902 goto do_unaryfp;
15903
15904 /* Conversions from single */
15905 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
15906 mips32_op = OPC_CVT_S_D;
15907 goto do_unaryfp;
15908 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
15909 mips32_op = OPC_CVT_S_W;
15910 goto do_unaryfp;
15911 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
15912 mips32_op = OPC_CVT_S_L;
15913 do_unaryfp:
15914 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
15915 break;
15916
15917 /* Conditional moves on floating-point codes */
15918 case COND_FLOAT_MOV(MOVT, 0):
15919 case COND_FLOAT_MOV(MOVT, 1):
15920 case COND_FLOAT_MOV(MOVT, 2):
15921 case COND_FLOAT_MOV(MOVT, 3):
15922 case COND_FLOAT_MOV(MOVT, 4):
15923 case COND_FLOAT_MOV(MOVT, 5):
15924 case COND_FLOAT_MOV(MOVT, 6):
15925 case COND_FLOAT_MOV(MOVT, 7):
15926 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15927 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
15928 break;
15929 case COND_FLOAT_MOV(MOVF, 0):
15930 case COND_FLOAT_MOV(MOVF, 1):
15931 case COND_FLOAT_MOV(MOVF, 2):
15932 case COND_FLOAT_MOV(MOVF, 3):
15933 case COND_FLOAT_MOV(MOVF, 4):
15934 case COND_FLOAT_MOV(MOVF, 5):
15935 case COND_FLOAT_MOV(MOVF, 6):
15936 case COND_FLOAT_MOV(MOVF, 7):
15937 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15938 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
15939 break;
15940 default:
15941 MIPS_INVAL("pool32fxf");
15942 generate_exception_end(ctx, EXCP_RI);
15943 break;
15944 }
15945 }
15946
15947 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
15948 {
15949 int32_t offset;
15950 uint16_t insn;
15951 int rt, rs, rd, rr;
15952 int16_t imm;
15953 uint32_t op, minor, minor2, mips32_op;
15954 uint32_t cond, fmt, cc;
15955
15956 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
15957 ctx->opcode = (ctx->opcode << 16) | insn;
15958
15959 rt = (ctx->opcode >> 21) & 0x1f;
15960 rs = (ctx->opcode >> 16) & 0x1f;
15961 rd = (ctx->opcode >> 11) & 0x1f;
15962 rr = (ctx->opcode >> 6) & 0x1f;
15963 imm = (int16_t) ctx->opcode;
15964
15965 op = (ctx->opcode >> 26) & 0x3f;
15966 switch (op) {
15967 case POOL32A:
15968 minor = ctx->opcode & 0x3f;
15969 switch (minor) {
15970 case 0x00:
15971 minor = (ctx->opcode >> 6) & 0xf;
15972 switch (minor) {
15973 case SLL32:
15974 mips32_op = OPC_SLL;
15975 goto do_shifti;
15976 case SRA:
15977 mips32_op = OPC_SRA;
15978 goto do_shifti;
15979 case SRL32:
15980 mips32_op = OPC_SRL;
15981 goto do_shifti;
15982 case ROTR:
15983 mips32_op = OPC_ROTR;
15984 do_shifti:
15985 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
15986 break;
15987 case SELEQZ:
15988 check_insn(ctx, ISA_MIPS32R6);
15989 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
15990 break;
15991 case SELNEZ:
15992 check_insn(ctx, ISA_MIPS32R6);
15993 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
15994 break;
15995 case R6_RDHWR:
15996 check_insn(ctx, ISA_MIPS32R6);
15997 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
15998 break;
15999 default:
16000 goto pool32a_invalid;
16001 }
16002 break;
16003 case 0x10:
16004 minor = (ctx->opcode >> 6) & 0xf;
16005 switch (minor) {
16006 /* Arithmetic */
16007 case ADD:
16008 mips32_op = OPC_ADD;
16009 goto do_arith;
16010 case ADDU32:
16011 mips32_op = OPC_ADDU;
16012 goto do_arith;
16013 case SUB:
16014 mips32_op = OPC_SUB;
16015 goto do_arith;
16016 case SUBU32:
16017 mips32_op = OPC_SUBU;
16018 goto do_arith;
16019 case MUL:
16020 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16021 mips32_op = OPC_MUL;
16022 do_arith:
16023 gen_arith(ctx, mips32_op, rd, rs, rt);
16024 break;
16025 /* Shifts */
16026 case SLLV:
16027 mips32_op = OPC_SLLV;
16028 goto do_shift;
16029 case SRLV:
16030 mips32_op = OPC_SRLV;
16031 goto do_shift;
16032 case SRAV:
16033 mips32_op = OPC_SRAV;
16034 goto do_shift;
16035 case ROTRV:
16036 mips32_op = OPC_ROTRV;
16037 do_shift:
16038 gen_shift(ctx, mips32_op, rd, rs, rt);
16039 break;
16040 /* Logical operations */
16041 case AND:
16042 mips32_op = OPC_AND;
16043 goto do_logic;
16044 case OR32:
16045 mips32_op = OPC_OR;
16046 goto do_logic;
16047 case NOR:
16048 mips32_op = OPC_NOR;
16049 goto do_logic;
16050 case XOR32:
16051 mips32_op = OPC_XOR;
16052 do_logic:
16053 gen_logic(ctx, mips32_op, rd, rs, rt);
16054 break;
16055 /* Set less than */
16056 case SLT:
16057 mips32_op = OPC_SLT;
16058 goto do_slt;
16059 case SLTU:
16060 mips32_op = OPC_SLTU;
16061 do_slt:
16062 gen_slt(ctx, mips32_op, rd, rs, rt);
16063 break;
16064 default:
16065 goto pool32a_invalid;
16066 }
16067 break;
16068 case 0x18:
16069 minor = (ctx->opcode >> 6) & 0xf;
16070 switch (minor) {
16071 /* Conditional moves */
16072 case MOVN: /* MUL */
16073 if (ctx->insn_flags & ISA_MIPS32R6) {
16074 /* MUL */
16075 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
16076 } else {
16077 /* MOVN */
16078 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
16079 }
16080 break;
16081 case MOVZ: /* MUH */
16082 if (ctx->insn_flags & ISA_MIPS32R6) {
16083 /* MUH */
16084 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
16085 } else {
16086 /* MOVZ */
16087 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
16088 }
16089 break;
16090 case MULU:
16091 check_insn(ctx, ISA_MIPS32R6);
16092 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
16093 break;
16094 case MUHU:
16095 check_insn(ctx, ISA_MIPS32R6);
16096 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
16097 break;
16098 case LWXS: /* DIV */
16099 if (ctx->insn_flags & ISA_MIPS32R6) {
16100 /* DIV */
16101 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
16102 } else {
16103 /* LWXS */
16104 gen_ldxs(ctx, rs, rt, rd);
16105 }
16106 break;
16107 case MOD:
16108 check_insn(ctx, ISA_MIPS32R6);
16109 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
16110 break;
16111 case R6_DIVU:
16112 check_insn(ctx, ISA_MIPS32R6);
16113 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
16114 break;
16115 case MODU:
16116 check_insn(ctx, ISA_MIPS32R6);
16117 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
16118 break;
16119 default:
16120 goto pool32a_invalid;
16121 }
16122 break;
16123 case INS:
16124 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
16125 return;
16126 case LSA:
16127 check_insn(ctx, ISA_MIPS32R6);
16128 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
16129 extract32(ctx->opcode, 9, 2));
16130 break;
16131 case ALIGN:
16132 check_insn(ctx, ISA_MIPS32R6);
16133 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
16134 break;
16135 case EXT:
16136 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
16137 return;
16138 case POOL32AXF:
16139 gen_pool32axf(env, ctx, rt, rs);
16140 break;
16141 case BREAK32:
16142 generate_exception_end(ctx, EXCP_BREAK);
16143 break;
16144 case SIGRIE:
16145 check_insn(ctx, ISA_MIPS32R6);
16146 generate_exception_end(ctx, EXCP_RI);
16147 break;
16148 default:
16149 pool32a_invalid:
16150 MIPS_INVAL("pool32a");
16151 generate_exception_end(ctx, EXCP_RI);
16152 break;
16153 }
16154 break;
16155 case POOL32B:
16156 minor = (ctx->opcode >> 12) & 0xf;
16157 switch (minor) {
16158 case CACHE:
16159 check_cp0_enabled(ctx);
16160 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16161 gen_cache_operation(ctx, rt, rs, imm);
16162 }
16163 break;
16164 case LWC2:
16165 case SWC2:
16166 /* COP2: Not implemented. */
16167 generate_exception_err(ctx, EXCP_CpU, 2);
16168 break;
16169 #ifdef TARGET_MIPS64
16170 case LDP:
16171 case SDP:
16172 check_insn(ctx, ISA_MIPS3);
16173 check_mips_64(ctx);
16174 #endif
16175 /* fall through */
16176 case LWP:
16177 case SWP:
16178 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16179 break;
16180 #ifdef TARGET_MIPS64
16181 case LDM:
16182 case SDM:
16183 check_insn(ctx, ISA_MIPS3);
16184 check_mips_64(ctx);
16185 #endif
16186 /* fall through */
16187 case LWM32:
16188 case SWM32:
16189 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16190 break;
16191 default:
16192 MIPS_INVAL("pool32b");
16193 generate_exception_end(ctx, EXCP_RI);
16194 break;
16195 }
16196 break;
16197 case POOL32F:
16198 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
16199 minor = ctx->opcode & 0x3f;
16200 check_cp1_enabled(ctx);
16201 switch (minor) {
16202 case ALNV_PS:
16203 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16204 mips32_op = OPC_ALNV_PS;
16205 goto do_madd;
16206 case MADD_S:
16207 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16208 mips32_op = OPC_MADD_S;
16209 goto do_madd;
16210 case MADD_D:
16211 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16212 mips32_op = OPC_MADD_D;
16213 goto do_madd;
16214 case MADD_PS:
16215 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16216 mips32_op = OPC_MADD_PS;
16217 goto do_madd;
16218 case MSUB_S:
16219 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16220 mips32_op = OPC_MSUB_S;
16221 goto do_madd;
16222 case MSUB_D:
16223 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16224 mips32_op = OPC_MSUB_D;
16225 goto do_madd;
16226 case MSUB_PS:
16227 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16228 mips32_op = OPC_MSUB_PS;
16229 goto do_madd;
16230 case NMADD_S:
16231 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16232 mips32_op = OPC_NMADD_S;
16233 goto do_madd;
16234 case NMADD_D:
16235 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16236 mips32_op = OPC_NMADD_D;
16237 goto do_madd;
16238 case NMADD_PS:
16239 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16240 mips32_op = OPC_NMADD_PS;
16241 goto do_madd;
16242 case NMSUB_S:
16243 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16244 mips32_op = OPC_NMSUB_S;
16245 goto do_madd;
16246 case NMSUB_D:
16247 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16248 mips32_op = OPC_NMSUB_D;
16249 goto do_madd;
16250 case NMSUB_PS:
16251 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16252 mips32_op = OPC_NMSUB_PS;
16253 do_madd:
16254 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
16255 break;
16256 case CABS_COND_FMT:
16257 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16258 cond = (ctx->opcode >> 6) & 0xf;
16259 cc = (ctx->opcode >> 13) & 0x7;
16260 fmt = (ctx->opcode >> 10) & 0x3;
16261 switch (fmt) {
16262 case 0x0:
16263 gen_cmpabs_s(ctx, cond, rt, rs, cc);
16264 break;
16265 case 0x1:
16266 gen_cmpabs_d(ctx, cond, rt, rs, cc);
16267 break;
16268 case 0x2:
16269 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
16270 break;
16271 default:
16272 goto pool32f_invalid;
16273 }
16274 break;
16275 case C_COND_FMT:
16276 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16277 cond = (ctx->opcode >> 6) & 0xf;
16278 cc = (ctx->opcode >> 13) & 0x7;
16279 fmt = (ctx->opcode >> 10) & 0x3;
16280 switch (fmt) {
16281 case 0x0:
16282 gen_cmp_s(ctx, cond, rt, rs, cc);
16283 break;
16284 case 0x1:
16285 gen_cmp_d(ctx, cond, rt, rs, cc);
16286 break;
16287 case 0x2:
16288 gen_cmp_ps(ctx, cond, rt, rs, cc);
16289 break;
16290 default:
16291 goto pool32f_invalid;
16292 }
16293 break;
16294 case CMP_CONDN_S:
16295 check_insn(ctx, ISA_MIPS32R6);
16296 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16297 break;
16298 case CMP_CONDN_D:
16299 check_insn(ctx, ISA_MIPS32R6);
16300 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16301 break;
16302 case POOL32FXF:
16303 gen_pool32fxf(ctx, rt, rs);
16304 break;
16305 case 0x00:
16306 /* PLL foo */
16307 switch ((ctx->opcode >> 6) & 0x7) {
16308 case PLL_PS:
16309 mips32_op = OPC_PLL_PS;
16310 goto do_ps;
16311 case PLU_PS:
16312 mips32_op = OPC_PLU_PS;
16313 goto do_ps;
16314 case PUL_PS:
16315 mips32_op = OPC_PUL_PS;
16316 goto do_ps;
16317 case PUU_PS:
16318 mips32_op = OPC_PUU_PS;
16319 goto do_ps;
16320 case CVT_PS_S:
16321 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16322 mips32_op = OPC_CVT_PS_S;
16323 do_ps:
16324 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16325 break;
16326 default:
16327 goto pool32f_invalid;
16328 }
16329 break;
16330 case MIN_FMT:
16331 check_insn(ctx, ISA_MIPS32R6);
16332 switch ((ctx->opcode >> 9) & 0x3) {
16333 case FMT_SDPS_S:
16334 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
16335 break;
16336 case FMT_SDPS_D:
16337 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
16338 break;
16339 default:
16340 goto pool32f_invalid;
16341 }
16342 break;
16343 case 0x08:
16344 /* [LS][WDU]XC1 */
16345 switch ((ctx->opcode >> 6) & 0x7) {
16346 case LWXC1:
16347 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16348 mips32_op = OPC_LWXC1;
16349 goto do_ldst_cp1;
16350 case SWXC1:
16351 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16352 mips32_op = OPC_SWXC1;
16353 goto do_ldst_cp1;
16354 case LDXC1:
16355 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16356 mips32_op = OPC_LDXC1;
16357 goto do_ldst_cp1;
16358 case SDXC1:
16359 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16360 mips32_op = OPC_SDXC1;
16361 goto do_ldst_cp1;
16362 case LUXC1:
16363 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16364 mips32_op = OPC_LUXC1;
16365 goto do_ldst_cp1;
16366 case SUXC1:
16367 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16368 mips32_op = OPC_SUXC1;
16369 do_ldst_cp1:
16370 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
16371 break;
16372 default:
16373 goto pool32f_invalid;
16374 }
16375 break;
16376 case MAX_FMT:
16377 check_insn(ctx, ISA_MIPS32R6);
16378 switch ((ctx->opcode >> 9) & 0x3) {
16379 case FMT_SDPS_S:
16380 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
16381 break;
16382 case FMT_SDPS_D:
16383 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
16384 break;
16385 default:
16386 goto pool32f_invalid;
16387 }
16388 break;
16389 case 0x18:
16390 /* 3D insns */
16391 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16392 fmt = (ctx->opcode >> 9) & 0x3;
16393 switch ((ctx->opcode >> 6) & 0x7) {
16394 case RSQRT2_FMT:
16395 switch (fmt) {
16396 case FMT_SDPS_S:
16397 mips32_op = OPC_RSQRT2_S;
16398 goto do_3d;
16399 case FMT_SDPS_D:
16400 mips32_op = OPC_RSQRT2_D;
16401 goto do_3d;
16402 case FMT_SDPS_PS:
16403 mips32_op = OPC_RSQRT2_PS;
16404 goto do_3d;
16405 default:
16406 goto pool32f_invalid;
16407 }
16408 break;
16409 case RECIP2_FMT:
16410 switch (fmt) {
16411 case FMT_SDPS_S:
16412 mips32_op = OPC_RECIP2_S;
16413 goto do_3d;
16414 case FMT_SDPS_D:
16415 mips32_op = OPC_RECIP2_D;
16416 goto do_3d;
16417 case FMT_SDPS_PS:
16418 mips32_op = OPC_RECIP2_PS;
16419 goto do_3d;
16420 default:
16421 goto pool32f_invalid;
16422 }
16423 break;
16424 case ADDR_PS:
16425 mips32_op = OPC_ADDR_PS;
16426 goto do_3d;
16427 case MULR_PS:
16428 mips32_op = OPC_MULR_PS;
16429 do_3d:
16430 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16431 break;
16432 default:
16433 goto pool32f_invalid;
16434 }
16435 break;
16436 case 0x20:
16437 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
16438 cc = (ctx->opcode >> 13) & 0x7;
16439 fmt = (ctx->opcode >> 9) & 0x3;
16440 switch ((ctx->opcode >> 6) & 0x7) {
16441 case MOVF_FMT: /* RINT_FMT */
16442 if (ctx->insn_flags & ISA_MIPS32R6) {
16443 /* RINT_FMT */
16444 switch (fmt) {
16445 case FMT_SDPS_S:
16446 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
16447 break;
16448 case FMT_SDPS_D:
16449 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
16450 break;
16451 default:
16452 goto pool32f_invalid;
16453 }
16454 } else {
16455 /* MOVF_FMT */
16456 switch (fmt) {
16457 case FMT_SDPS_S:
16458 gen_movcf_s(ctx, rs, rt, cc, 0);
16459 break;
16460 case FMT_SDPS_D:
16461 gen_movcf_d(ctx, rs, rt, cc, 0);
16462 break;
16463 case FMT_SDPS_PS:
16464 check_ps(ctx);
16465 gen_movcf_ps(ctx, rs, rt, cc, 0);
16466 break;
16467 default:
16468 goto pool32f_invalid;
16469 }
16470 }
16471 break;
16472 case MOVT_FMT: /* CLASS_FMT */
16473 if (ctx->insn_flags & ISA_MIPS32R6) {
16474 /* CLASS_FMT */
16475 switch (fmt) {
16476 case FMT_SDPS_S:
16477 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
16478 break;
16479 case FMT_SDPS_D:
16480 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
16481 break;
16482 default:
16483 goto pool32f_invalid;
16484 }
16485 } else {
16486 /* MOVT_FMT */
16487 switch (fmt) {
16488 case FMT_SDPS_S:
16489 gen_movcf_s(ctx, rs, rt, cc, 1);
16490 break;
16491 case FMT_SDPS_D:
16492 gen_movcf_d(ctx, rs, rt, cc, 1);
16493 break;
16494 case FMT_SDPS_PS:
16495 check_ps(ctx);
16496 gen_movcf_ps(ctx, rs, rt, cc, 1);
16497 break;
16498 default:
16499 goto pool32f_invalid;
16500 }
16501 }
16502 break;
16503 case PREFX:
16504 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16505 break;
16506 default:
16507 goto pool32f_invalid;
16508 }
16509 break;
16510 #define FINSN_3ARG_SDPS(prfx) \
16511 switch ((ctx->opcode >> 8) & 0x3) { \
16512 case FMT_SDPS_S: \
16513 mips32_op = OPC_##prfx##_S; \
16514 goto do_fpop; \
16515 case FMT_SDPS_D: \
16516 mips32_op = OPC_##prfx##_D; \
16517 goto do_fpop; \
16518 case FMT_SDPS_PS: \
16519 check_ps(ctx); \
16520 mips32_op = OPC_##prfx##_PS; \
16521 goto do_fpop; \
16522 default: \
16523 goto pool32f_invalid; \
16524 }
16525 case MINA_FMT:
16526 check_insn(ctx, ISA_MIPS32R6);
16527 switch ((ctx->opcode >> 9) & 0x3) {
16528 case FMT_SDPS_S:
16529 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
16530 break;
16531 case FMT_SDPS_D:
16532 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
16533 break;
16534 default:
16535 goto pool32f_invalid;
16536 }
16537 break;
16538 case MAXA_FMT:
16539 check_insn(ctx, ISA_MIPS32R6);
16540 switch ((ctx->opcode >> 9) & 0x3) {
16541 case FMT_SDPS_S:
16542 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
16543 break;
16544 case FMT_SDPS_D:
16545 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
16546 break;
16547 default:
16548 goto pool32f_invalid;
16549 }
16550 break;
16551 case 0x30:
16552 /* regular FP ops */
16553 switch ((ctx->opcode >> 6) & 0x3) {
16554 case ADD_FMT:
16555 FINSN_3ARG_SDPS(ADD);
16556 break;
16557 case SUB_FMT:
16558 FINSN_3ARG_SDPS(SUB);
16559 break;
16560 case MUL_FMT:
16561 FINSN_3ARG_SDPS(MUL);
16562 break;
16563 case DIV_FMT:
16564 fmt = (ctx->opcode >> 8) & 0x3;
16565 if (fmt == 1) {
16566 mips32_op = OPC_DIV_D;
16567 } else if (fmt == 0) {
16568 mips32_op = OPC_DIV_S;
16569 } else {
16570 goto pool32f_invalid;
16571 }
16572 goto do_fpop;
16573 default:
16574 goto pool32f_invalid;
16575 }
16576 break;
16577 case 0x38:
16578 /* cmovs */
16579 switch ((ctx->opcode >> 6) & 0x7) {
16580 case MOVN_FMT: /* SELEQZ_FMT */
16581 if (ctx->insn_flags & ISA_MIPS32R6) {
16582 /* SELEQZ_FMT */
16583 switch ((ctx->opcode >> 9) & 0x3) {
16584 case FMT_SDPS_S:
16585 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
16586 break;
16587 case FMT_SDPS_D:
16588 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
16589 break;
16590 default:
16591 goto pool32f_invalid;
16592 }
16593 } else {
16594 /* MOVN_FMT */
16595 FINSN_3ARG_SDPS(MOVN);
16596 }
16597 break;
16598 case MOVN_FMT_04:
16599 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16600 FINSN_3ARG_SDPS(MOVN);
16601 break;
16602 case MOVZ_FMT: /* SELNEZ_FMT */
16603 if (ctx->insn_flags & ISA_MIPS32R6) {
16604 /* SELNEZ_FMT */
16605 switch ((ctx->opcode >> 9) & 0x3) {
16606 case FMT_SDPS_S:
16607 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
16608 break;
16609 case FMT_SDPS_D:
16610 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
16611 break;
16612 default:
16613 goto pool32f_invalid;
16614 }
16615 } else {
16616 /* MOVZ_FMT */
16617 FINSN_3ARG_SDPS(MOVZ);
16618 }
16619 break;
16620 case MOVZ_FMT_05:
16621 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16622 FINSN_3ARG_SDPS(MOVZ);
16623 break;
16624 case SEL_FMT:
16625 check_insn(ctx, ISA_MIPS32R6);
16626 switch ((ctx->opcode >> 9) & 0x3) {
16627 case FMT_SDPS_S:
16628 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
16629 break;
16630 case FMT_SDPS_D:
16631 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
16632 break;
16633 default:
16634 goto pool32f_invalid;
16635 }
16636 break;
16637 case MADDF_FMT:
16638 check_insn(ctx, ISA_MIPS32R6);
16639 switch ((ctx->opcode >> 9) & 0x3) {
16640 case FMT_SDPS_S:
16641 mips32_op = OPC_MADDF_S;
16642 goto do_fpop;
16643 case FMT_SDPS_D:
16644 mips32_op = OPC_MADDF_D;
16645 goto do_fpop;
16646 default:
16647 goto pool32f_invalid;
16648 }
16649 break;
16650 case MSUBF_FMT:
16651 check_insn(ctx, ISA_MIPS32R6);
16652 switch ((ctx->opcode >> 9) & 0x3) {
16653 case FMT_SDPS_S:
16654 mips32_op = OPC_MSUBF_S;
16655 goto do_fpop;
16656 case FMT_SDPS_D:
16657 mips32_op = OPC_MSUBF_D;
16658 goto do_fpop;
16659 default:
16660 goto pool32f_invalid;
16661 }
16662 break;
16663 default:
16664 goto pool32f_invalid;
16665 }
16666 break;
16667 do_fpop:
16668 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16669 break;
16670 default:
16671 pool32f_invalid:
16672 MIPS_INVAL("pool32f");
16673 generate_exception_end(ctx, EXCP_RI);
16674 break;
16675 }
16676 } else {
16677 generate_exception_err(ctx, EXCP_CpU, 1);
16678 }
16679 break;
16680 case POOL32I:
16681 minor = (ctx->opcode >> 21) & 0x1f;
16682 switch (minor) {
16683 case BLTZ:
16684 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16685 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
16686 break;
16687 case BLTZAL:
16688 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16689 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
16690 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16691 break;
16692 case BLTZALS:
16693 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16694 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
16695 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16696 break;
16697 case BGEZ:
16698 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16699 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
16700 break;
16701 case BGEZAL:
16702 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16703 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
16704 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16705 break;
16706 case BGEZALS:
16707 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16708 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
16709 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16710 break;
16711 case BLEZ:
16712 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16713 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
16714 break;
16715 case BGTZ:
16716 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16717 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
16718 break;
16719
16720 /* Traps */
16721 case TLTI: /* BC1EQZC */
16722 if (ctx->insn_flags & ISA_MIPS32R6) {
16723 /* BC1EQZC */
16724 check_cp1_enabled(ctx);
16725 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
16726 } else {
16727 /* TLTI */
16728 mips32_op = OPC_TLTI;
16729 goto do_trapi;
16730 }
16731 break;
16732 case TGEI: /* BC1NEZC */
16733 if (ctx->insn_flags & ISA_MIPS32R6) {
16734 /* BC1NEZC */
16735 check_cp1_enabled(ctx);
16736 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
16737 } else {
16738 /* TGEI */
16739 mips32_op = OPC_TGEI;
16740 goto do_trapi;
16741 }
16742 break;
16743 case TLTIU:
16744 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16745 mips32_op = OPC_TLTIU;
16746 goto do_trapi;
16747 case TGEIU:
16748 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16749 mips32_op = OPC_TGEIU;
16750 goto do_trapi;
16751 case TNEI: /* SYNCI */
16752 if (ctx->insn_flags & ISA_MIPS32R6) {
16753 /* SYNCI */
16754 /* Break the TB to be able to sync copied instructions
16755 immediately */
16756 ctx->base.is_jmp = DISAS_STOP;
16757 } else {
16758 /* TNEI */
16759 mips32_op = OPC_TNEI;
16760 goto do_trapi;
16761 }
16762 break;
16763 case TEQI:
16764 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16765 mips32_op = OPC_TEQI;
16766 do_trapi:
16767 gen_trap(ctx, mips32_op, rs, -1, imm);
16768 break;
16769
16770 case BNEZC:
16771 case BEQZC:
16772 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16773 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
16774 4, rs, 0, imm << 1, 0);
16775 /* Compact branches don't have a delay slot, so just let
16776 the normal delay slot handling take us to the branch
16777 target. */
16778 break;
16779 case LUI:
16780 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16781 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
16782 break;
16783 case SYNCI:
16784 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16785 /* Break the TB to be able to sync copied instructions
16786 immediately */
16787 ctx->base.is_jmp = DISAS_STOP;
16788 break;
16789 case BC2F:
16790 case BC2T:
16791 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16792 /* COP2: Not implemented. */
16793 generate_exception_err(ctx, EXCP_CpU, 2);
16794 break;
16795 case BC1F:
16796 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16797 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
16798 goto do_cp1branch;
16799 case BC1T:
16800 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16801 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
16802 goto do_cp1branch;
16803 case BC1ANY4F:
16804 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16805 mips32_op = OPC_BC1FANY4;
16806 goto do_cp1mips3d;
16807 case BC1ANY4T:
16808 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16809 mips32_op = OPC_BC1TANY4;
16810 do_cp1mips3d:
16811 check_cop1x(ctx);
16812 check_insn(ctx, ASE_MIPS3D);
16813 /* Fall through */
16814 do_cp1branch:
16815 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16816 check_cp1_enabled(ctx);
16817 gen_compute_branch1(ctx, mips32_op,
16818 (ctx->opcode >> 18) & 0x7, imm << 1);
16819 } else {
16820 generate_exception_err(ctx, EXCP_CpU, 1);
16821 }
16822 break;
16823 case BPOSGE64:
16824 case BPOSGE32:
16825 /* MIPS DSP: not implemented */
16826 /* Fall through */
16827 default:
16828 MIPS_INVAL("pool32i");
16829 generate_exception_end(ctx, EXCP_RI);
16830 break;
16831 }
16832 break;
16833 case POOL32C:
16834 minor = (ctx->opcode >> 12) & 0xf;
16835 offset = sextract32(ctx->opcode, 0,
16836 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
16837 switch (minor) {
16838 case LWL:
16839 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16840 mips32_op = OPC_LWL;
16841 goto do_ld_lr;
16842 case SWL:
16843 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16844 mips32_op = OPC_SWL;
16845 goto do_st_lr;
16846 case LWR:
16847 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16848 mips32_op = OPC_LWR;
16849 goto do_ld_lr;
16850 case SWR:
16851 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16852 mips32_op = OPC_SWR;
16853 goto do_st_lr;
16854 #if defined(TARGET_MIPS64)
16855 case LDL:
16856 check_insn(ctx, ISA_MIPS3);
16857 check_mips_64(ctx);
16858 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16859 mips32_op = OPC_LDL;
16860 goto do_ld_lr;
16861 case SDL:
16862 check_insn(ctx, ISA_MIPS3);
16863 check_mips_64(ctx);
16864 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16865 mips32_op = OPC_SDL;
16866 goto do_st_lr;
16867 case LDR:
16868 check_insn(ctx, ISA_MIPS3);
16869 check_mips_64(ctx);
16870 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16871 mips32_op = OPC_LDR;
16872 goto do_ld_lr;
16873 case SDR:
16874 check_insn(ctx, ISA_MIPS3);
16875 check_mips_64(ctx);
16876 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16877 mips32_op = OPC_SDR;
16878 goto do_st_lr;
16879 case LWU:
16880 check_insn(ctx, ISA_MIPS3);
16881 check_mips_64(ctx);
16882 mips32_op = OPC_LWU;
16883 goto do_ld_lr;
16884 case LLD:
16885 check_insn(ctx, ISA_MIPS3);
16886 check_mips_64(ctx);
16887 mips32_op = OPC_LLD;
16888 goto do_ld_lr;
16889 #endif
16890 case LL:
16891 mips32_op = OPC_LL;
16892 goto do_ld_lr;
16893 do_ld_lr:
16894 gen_ld(ctx, mips32_op, rt, rs, offset);
16895 break;
16896 do_st_lr:
16897 gen_st(ctx, mips32_op, rt, rs, offset);
16898 break;
16899 case SC:
16900 gen_st_cond(ctx, rt, rs, offset, MO_TESL, false);
16901 break;
16902 #if defined(TARGET_MIPS64)
16903 case SCD:
16904 check_insn(ctx, ISA_MIPS3);
16905 check_mips_64(ctx);
16906 gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false);
16907 break;
16908 #endif
16909 case LD_EVA:
16910 if (!ctx->eva) {
16911 MIPS_INVAL("pool32c ld-eva");
16912 generate_exception_end(ctx, EXCP_RI);
16913 break;
16914 }
16915 check_cp0_enabled(ctx);
16916
16917 minor2 = (ctx->opcode >> 9) & 0x7;
16918 offset = sextract32(ctx->opcode, 0, 9);
16919 switch (minor2) {
16920 case LBUE:
16921 mips32_op = OPC_LBUE;
16922 goto do_ld_lr;
16923 case LHUE:
16924 mips32_op = OPC_LHUE;
16925 goto do_ld_lr;
16926 case LWLE:
16927 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16928 mips32_op = OPC_LWLE;
16929 goto do_ld_lr;
16930 case LWRE:
16931 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16932 mips32_op = OPC_LWRE;
16933 goto do_ld_lr;
16934 case LBE:
16935 mips32_op = OPC_LBE;
16936 goto do_ld_lr;
16937 case LHE:
16938 mips32_op = OPC_LHE;
16939 goto do_ld_lr;
16940 case LLE:
16941 mips32_op = OPC_LLE;
16942 goto do_ld_lr;
16943 case LWE:
16944 mips32_op = OPC_LWE;
16945 goto do_ld_lr;
16946 };
16947 break;
16948 case ST_EVA:
16949 if (!ctx->eva) {
16950 MIPS_INVAL("pool32c st-eva");
16951 generate_exception_end(ctx, EXCP_RI);
16952 break;
16953 }
16954 check_cp0_enabled(ctx);
16955
16956 minor2 = (ctx->opcode >> 9) & 0x7;
16957 offset = sextract32(ctx->opcode, 0, 9);
16958 switch (minor2) {
16959 case SWLE:
16960 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16961 mips32_op = OPC_SWLE;
16962 goto do_st_lr;
16963 case SWRE:
16964 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16965 mips32_op = OPC_SWRE;
16966 goto do_st_lr;
16967 case PREFE:
16968 /* Treat as no-op */
16969 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16970 /* hint codes 24-31 are reserved and signal RI */
16971 generate_exception(ctx, EXCP_RI);
16972 }
16973 break;
16974 case CACHEE:
16975 /* Treat as no-op */
16976 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16977 gen_cache_operation(ctx, rt, rs, offset);
16978 }
16979 break;
16980 case SBE:
16981 mips32_op = OPC_SBE;
16982 goto do_st_lr;
16983 case SHE:
16984 mips32_op = OPC_SHE;
16985 goto do_st_lr;
16986 case SCE:
16987 gen_st_cond(ctx, rt, rs, offset, MO_TESL, true);
16988 break;
16989 case SWE:
16990 mips32_op = OPC_SWE;
16991 goto do_st_lr;
16992 };
16993 break;
16994 case PREF:
16995 /* Treat as no-op */
16996 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16997 /* hint codes 24-31 are reserved and signal RI */
16998 generate_exception(ctx, EXCP_RI);
16999 }
17000 break;
17001 default:
17002 MIPS_INVAL("pool32c");
17003 generate_exception_end(ctx, EXCP_RI);
17004 break;
17005 }
17006 break;
17007 case ADDI32: /* AUI, LUI */
17008 if (ctx->insn_flags & ISA_MIPS32R6) {
17009 /* AUI, LUI */
17010 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
17011 } else {
17012 /* ADDI32 */
17013 mips32_op = OPC_ADDI;
17014 goto do_addi;
17015 }
17016 break;
17017 case ADDIU32:
17018 mips32_op = OPC_ADDIU;
17019 do_addi:
17020 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
17021 break;
17022
17023 /* Logical operations */
17024 case ORI32:
17025 mips32_op = OPC_ORI;
17026 goto do_logici;
17027 case XORI32:
17028 mips32_op = OPC_XORI;
17029 goto do_logici;
17030 case ANDI32:
17031 mips32_op = OPC_ANDI;
17032 do_logici:
17033 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
17034 break;
17035
17036 /* Set less than immediate */
17037 case SLTI32:
17038 mips32_op = OPC_SLTI;
17039 goto do_slti;
17040 case SLTIU32:
17041 mips32_op = OPC_SLTIU;
17042 do_slti:
17043 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
17044 break;
17045 case JALX32:
17046 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17047 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
17048 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
17049 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17050 break;
17051 case JALS32: /* BOVC, BEQC, BEQZALC */
17052 if (ctx->insn_flags & ISA_MIPS32R6) {
17053 if (rs >= rt) {
17054 /* BOVC */
17055 mips32_op = OPC_BOVC;
17056 } else if (rs < rt && rs == 0) {
17057 /* BEQZALC */
17058 mips32_op = OPC_BEQZALC;
17059 } else {
17060 /* BEQC */
17061 mips32_op = OPC_BEQC;
17062 }
17063 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17064 } else {
17065 /* JALS32 */
17066 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
17067 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
17068 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17069 }
17070 break;
17071 case BEQ32: /* BC */
17072 if (ctx->insn_flags & ISA_MIPS32R6) {
17073 /* BC */
17074 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
17075 sextract32(ctx->opcode << 1, 0, 27));
17076 } else {
17077 /* BEQ32 */
17078 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
17079 }
17080 break;
17081 case BNE32: /* BALC */
17082 if (ctx->insn_flags & ISA_MIPS32R6) {
17083 /* BALC */
17084 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
17085 sextract32(ctx->opcode << 1, 0, 27));
17086 } else {
17087 /* BNE32 */
17088 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
17089 }
17090 break;
17091 case J32: /* BGTZC, BLTZC, BLTC */
17092 if (ctx->insn_flags & ISA_MIPS32R6) {
17093 if (rs == 0 && rt != 0) {
17094 /* BGTZC */
17095 mips32_op = OPC_BGTZC;
17096 } else if (rs != 0 && rt != 0 && rs == rt) {
17097 /* BLTZC */
17098 mips32_op = OPC_BLTZC;
17099 } else {
17100 /* BLTC */
17101 mips32_op = OPC_BLTC;
17102 }
17103 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17104 } else {
17105 /* J32 */
17106 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
17107 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17108 }
17109 break;
17110 case JAL32: /* BLEZC, BGEZC, BGEC */
17111 if (ctx->insn_flags & ISA_MIPS32R6) {
17112 if (rs == 0 && rt != 0) {
17113 /* BLEZC */
17114 mips32_op = OPC_BLEZC;
17115 } else if (rs != 0 && rt != 0 && rs == rt) {
17116 /* BGEZC */
17117 mips32_op = OPC_BGEZC;
17118 } else {
17119 /* BGEC */
17120 mips32_op = OPC_BGEC;
17121 }
17122 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17123 } else {
17124 /* JAL32 */
17125 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
17126 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17127 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17128 }
17129 break;
17130 /* Floating point (COP1) */
17131 case LWC132:
17132 mips32_op = OPC_LWC1;
17133 goto do_cop1;
17134 case LDC132:
17135 mips32_op = OPC_LDC1;
17136 goto do_cop1;
17137 case SWC132:
17138 mips32_op = OPC_SWC1;
17139 goto do_cop1;
17140 case SDC132:
17141 mips32_op = OPC_SDC1;
17142 do_cop1:
17143 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
17144 break;
17145 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17146 if (ctx->insn_flags & ISA_MIPS32R6) {
17147 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17148 switch ((ctx->opcode >> 16) & 0x1f) {
17149 case ADDIUPC_00:
17150 case ADDIUPC_01:
17151 case ADDIUPC_02:
17152 case ADDIUPC_03:
17153 case ADDIUPC_04:
17154 case ADDIUPC_05:
17155 case ADDIUPC_06:
17156 case ADDIUPC_07:
17157 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
17158 break;
17159 case AUIPC:
17160 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
17161 break;
17162 case ALUIPC:
17163 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
17164 break;
17165 case LWPC_08:
17166 case LWPC_09:
17167 case LWPC_0A:
17168 case LWPC_0B:
17169 case LWPC_0C:
17170 case LWPC_0D:
17171 case LWPC_0E:
17172 case LWPC_0F:
17173 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
17174 break;
17175 default:
17176 generate_exception(ctx, EXCP_RI);
17177 break;
17178 }
17179 } else {
17180 /* ADDIUPC */
17181 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
17182 offset = SIMM(ctx->opcode, 0, 23) << 2;
17183
17184 gen_addiupc(ctx, reg, offset, 0, 0);
17185 }
17186 break;
17187 case BNVC: /* BNEC, BNEZALC */
17188 check_insn(ctx, ISA_MIPS32R6);
17189 if (rs >= rt) {
17190 /* BNVC */
17191 mips32_op = OPC_BNVC;
17192 } else if (rs < rt && rs == 0) {
17193 /* BNEZALC */
17194 mips32_op = OPC_BNEZALC;
17195 } else {
17196 /* BNEC */
17197 mips32_op = OPC_BNEC;
17198 }
17199 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17200 break;
17201 case R6_BNEZC: /* JIALC */
17202 check_insn(ctx, ISA_MIPS32R6);
17203 if (rt != 0) {
17204 /* BNEZC */
17205 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
17206 sextract32(ctx->opcode << 1, 0, 22));
17207 } else {
17208 /* JIALC */
17209 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
17210 }
17211 break;
17212 case R6_BEQZC: /* JIC */
17213 check_insn(ctx, ISA_MIPS32R6);
17214 if (rt != 0) {
17215 /* BEQZC */
17216 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
17217 sextract32(ctx->opcode << 1, 0, 22));
17218 } else {
17219 /* JIC */
17220 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
17221 }
17222 break;
17223 case BLEZALC: /* BGEZALC, BGEUC */
17224 check_insn(ctx, ISA_MIPS32R6);
17225 if (rs == 0 && rt != 0) {
17226 /* BLEZALC */
17227 mips32_op = OPC_BLEZALC;
17228 } else if (rs != 0 && rt != 0 && rs == rt) {
17229 /* BGEZALC */
17230 mips32_op = OPC_BGEZALC;
17231 } else {
17232 /* BGEUC */
17233 mips32_op = OPC_BGEUC;
17234 }
17235 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17236 break;
17237 case BGTZALC: /* BLTZALC, BLTUC */
17238 check_insn(ctx, ISA_MIPS32R6);
17239 if (rs == 0 && rt != 0) {
17240 /* BGTZALC */
17241 mips32_op = OPC_BGTZALC;
17242 } else if (rs != 0 && rt != 0 && rs == rt) {
17243 /* BLTZALC */
17244 mips32_op = OPC_BLTZALC;
17245 } else {
17246 /* BLTUC */
17247 mips32_op = OPC_BLTUC;
17248 }
17249 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17250 break;
17251 /* Loads and stores */
17252 case LB32:
17253 mips32_op = OPC_LB;
17254 goto do_ld;
17255 case LBU32:
17256 mips32_op = OPC_LBU;
17257 goto do_ld;
17258 case LH32:
17259 mips32_op = OPC_LH;
17260 goto do_ld;
17261 case LHU32:
17262 mips32_op = OPC_LHU;
17263 goto do_ld;
17264 case LW32:
17265 mips32_op = OPC_LW;
17266 goto do_ld;
17267 #ifdef TARGET_MIPS64
17268 case LD32:
17269 check_insn(ctx, ISA_MIPS3);
17270 check_mips_64(ctx);
17271 mips32_op = OPC_LD;
17272 goto do_ld;
17273 case SD32:
17274 check_insn(ctx, ISA_MIPS3);
17275 check_mips_64(ctx);
17276 mips32_op = OPC_SD;
17277 goto do_st;
17278 #endif
17279 case SB32:
17280 mips32_op = OPC_SB;
17281 goto do_st;
17282 case SH32:
17283 mips32_op = OPC_SH;
17284 goto do_st;
17285 case SW32:
17286 mips32_op = OPC_SW;
17287 goto do_st;
17288 do_ld:
17289 gen_ld(ctx, mips32_op, rt, rs, imm);
17290 break;
17291 do_st:
17292 gen_st(ctx, mips32_op, rt, rs, imm);
17293 break;
17294 default:
17295 generate_exception_end(ctx, EXCP_RI);
17296 break;
17297 }
17298 }
17299
17300 static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx)
17301 {
17302 uint32_t op;
17303
17304 /* make sure instructions are on a halfword boundary */
17305 if (ctx->base.pc_next & 0x1) {
17306 env->CP0_BadVAddr = ctx->base.pc_next;
17307 generate_exception_end(ctx, EXCP_AdEL);
17308 return 2;
17309 }
17310
17311 op = (ctx->opcode >> 10) & 0x3f;
17312 /* Enforce properly-sized instructions in a delay slot */
17313 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
17314 switch (op & 0x7) { /* MSB-3..MSB-5 */
17315 case 0:
17316 /* POOL32A, POOL32B, POOL32I, POOL32C */
17317 case 4:
17318 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
17319 case 5:
17320 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
17321 case 6:
17322 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
17323 case 7:
17324 /* LB32, LH32, LWC132, LDC132, LW32 */
17325 if (ctx->hflags & MIPS_HFLAG_BDS16) {
17326 generate_exception_end(ctx, EXCP_RI);
17327 return 2;
17328 }
17329 break;
17330 case 1:
17331 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
17332 case 2:
17333 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
17334 case 3:
17335 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
17336 if (ctx->hflags & MIPS_HFLAG_BDS32) {
17337 generate_exception_end(ctx, EXCP_RI);
17338 return 2;
17339 }
17340 break;
17341 }
17342 }
17343
17344 switch (op) {
17345 case POOL16A:
17346 {
17347 int rd = mmreg(uMIPS_RD(ctx->opcode));
17348 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
17349 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
17350 uint32_t opc = 0;
17351
17352 switch (ctx->opcode & 0x1) {
17353 case ADDU16:
17354 opc = OPC_ADDU;
17355 break;
17356 case SUBU16:
17357 opc = OPC_SUBU;
17358 break;
17359 }
17360 if (ctx->insn_flags & ISA_MIPS32R6) {
17361 /* In the Release 6 the register number location in
17362 * the instruction encoding has changed.
17363 */
17364 gen_arith(ctx, opc, rs1, rd, rs2);
17365 } else {
17366 gen_arith(ctx, opc, rd, rs1, rs2);
17367 }
17368 }
17369 break;
17370 case POOL16B:
17371 {
17372 int rd = mmreg(uMIPS_RD(ctx->opcode));
17373 int rs = mmreg(uMIPS_RS(ctx->opcode));
17374 int amount = (ctx->opcode >> 1) & 0x7;
17375 uint32_t opc = 0;
17376 amount = amount == 0 ? 8 : amount;
17377
17378 switch (ctx->opcode & 0x1) {
17379 case SLL16:
17380 opc = OPC_SLL;
17381 break;
17382 case SRL16:
17383 opc = OPC_SRL;
17384 break;
17385 }
17386
17387 gen_shift_imm(ctx, opc, rd, rs, amount);
17388 }
17389 break;
17390 case POOL16C:
17391 if (ctx->insn_flags & ISA_MIPS32R6) {
17392 gen_pool16c_r6_insn(ctx);
17393 } else {
17394 gen_pool16c_insn(ctx);
17395 }
17396 break;
17397 case LWGP16:
17398 {
17399 int rd = mmreg(uMIPS_RD(ctx->opcode));
17400 int rb = 28; /* GP */
17401 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
17402
17403 gen_ld(ctx, OPC_LW, rd, rb, offset);
17404 }
17405 break;
17406 case POOL16F:
17407 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17408 if (ctx->opcode & 1) {
17409 generate_exception_end(ctx, EXCP_RI);
17410 } else {
17411 /* MOVEP */
17412 int enc_dest = uMIPS_RD(ctx->opcode);
17413 int enc_rt = uMIPS_RS2(ctx->opcode);
17414 int enc_rs = uMIPS_RS1(ctx->opcode);
17415 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
17416 }
17417 break;
17418 case LBU16:
17419 {
17420 int rd = mmreg(uMIPS_RD(ctx->opcode));
17421 int rb = mmreg(uMIPS_RS(ctx->opcode));
17422 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17423 offset = (offset == 0xf ? -1 : offset);
17424
17425 gen_ld(ctx, OPC_LBU, rd, rb, offset);
17426 }
17427 break;
17428 case LHU16:
17429 {
17430 int rd = mmreg(uMIPS_RD(ctx->opcode));
17431 int rb = mmreg(uMIPS_RS(ctx->opcode));
17432 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17433
17434 gen_ld(ctx, OPC_LHU, rd, rb, offset);
17435 }
17436 break;
17437 case LWSP16:
17438 {
17439 int rd = (ctx->opcode >> 5) & 0x1f;
17440 int rb = 29; /* SP */
17441 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17442
17443 gen_ld(ctx, OPC_LW, rd, rb, offset);
17444 }
17445 break;
17446 case LW16:
17447 {
17448 int rd = mmreg(uMIPS_RD(ctx->opcode));
17449 int rb = mmreg(uMIPS_RS(ctx->opcode));
17450 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17451
17452 gen_ld(ctx, OPC_LW, rd, rb, offset);
17453 }
17454 break;
17455 case SB16:
17456 {
17457 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17458 int rb = mmreg(uMIPS_RS(ctx->opcode));
17459 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17460
17461 gen_st(ctx, OPC_SB, rd, rb, offset);
17462 }
17463 break;
17464 case SH16:
17465 {
17466 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17467 int rb = mmreg(uMIPS_RS(ctx->opcode));
17468 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17469
17470 gen_st(ctx, OPC_SH, rd, rb, offset);
17471 }
17472 break;
17473 case SWSP16:
17474 {
17475 int rd = (ctx->opcode >> 5) & 0x1f;
17476 int rb = 29; /* SP */
17477 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17478
17479 gen_st(ctx, OPC_SW, rd, rb, offset);
17480 }
17481 break;
17482 case SW16:
17483 {
17484 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17485 int rb = mmreg(uMIPS_RS(ctx->opcode));
17486 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17487
17488 gen_st(ctx, OPC_SW, rd, rb, offset);
17489 }
17490 break;
17491 case MOVE16:
17492 {
17493 int rd = uMIPS_RD5(ctx->opcode);
17494 int rs = uMIPS_RS5(ctx->opcode);
17495
17496 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
17497 }
17498 break;
17499 case ANDI16:
17500 gen_andi16(ctx);
17501 break;
17502 case POOL16D:
17503 switch (ctx->opcode & 0x1) {
17504 case ADDIUS5:
17505 gen_addius5(ctx);
17506 break;
17507 case ADDIUSP:
17508 gen_addiusp(ctx);
17509 break;
17510 }
17511 break;
17512 case POOL16E:
17513 switch (ctx->opcode & 0x1) {
17514 case ADDIUR2:
17515 gen_addiur2(ctx);
17516 break;
17517 case ADDIUR1SP:
17518 gen_addiur1sp(ctx);
17519 break;
17520 }
17521 break;
17522 case B16: /* BC16 */
17523 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
17524 sextract32(ctx->opcode, 0, 10) << 1,
17525 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17526 break;
17527 case BNEZ16: /* BNEZC16 */
17528 case BEQZ16: /* BEQZC16 */
17529 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
17530 mmreg(uMIPS_RD(ctx->opcode)),
17531 0, sextract32(ctx->opcode, 0, 7) << 1,
17532 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17533
17534 break;
17535 case LI16:
17536 {
17537 int reg = mmreg(uMIPS_RD(ctx->opcode));
17538 int imm = ZIMM(ctx->opcode, 0, 7);
17539
17540 imm = (imm == 0x7f ? -1 : imm);
17541 tcg_gen_movi_tl(cpu_gpr[reg], imm);
17542 }
17543 break;
17544 case RES_29:
17545 case RES_31:
17546 case RES_39:
17547 generate_exception_end(ctx, EXCP_RI);
17548 break;
17549 default:
17550 decode_micromips32_opc(env, ctx);
17551 return 4;
17552 }
17553
17554 return 2;
17555 }
17556
17557 /*
17558 *
17559 * nanoMIPS opcodes
17560 *
17561 */
17562
17563 /* MAJOR, P16, and P32 pools opcodes */
17564 enum {
17565 NM_P_ADDIU = 0x00,
17566 NM_ADDIUPC = 0x01,
17567 NM_MOVE_BALC = 0x02,
17568 NM_P16_MV = 0x04,
17569 NM_LW16 = 0x05,
17570 NM_BC16 = 0x06,
17571 NM_P16_SR = 0x07,
17572
17573 NM_POOL32A = 0x08,
17574 NM_P_BAL = 0x0a,
17575 NM_P16_SHIFT = 0x0c,
17576 NM_LWSP16 = 0x0d,
17577 NM_BALC16 = 0x0e,
17578 NM_P16_4X4 = 0x0f,
17579
17580 NM_P_GP_W = 0x10,
17581 NM_P_GP_BH = 0x11,
17582 NM_P_J = 0x12,
17583 NM_P16C = 0x14,
17584 NM_LWGP16 = 0x15,
17585 NM_P16_LB = 0x17,
17586
17587 NM_P48I = 0x18,
17588 NM_P16_A1 = 0x1c,
17589 NM_LW4X4 = 0x1d,
17590 NM_P16_LH = 0x1f,
17591
17592 NM_P_U12 = 0x20,
17593 NM_P_LS_U12 = 0x21,
17594 NM_P_BR1 = 0x22,
17595 NM_P16_A2 = 0x24,
17596 NM_SW16 = 0x25,
17597 NM_BEQZC16 = 0x26,
17598
17599 NM_POOL32F = 0x28,
17600 NM_P_LS_S9 = 0x29,
17601 NM_P_BR2 = 0x2a,
17602
17603 NM_P16_ADDU = 0x2c,
17604 NM_SWSP16 = 0x2d,
17605 NM_BNEZC16 = 0x2e,
17606 NM_MOVEP = 0x2f,
17607
17608 NM_POOL32S = 0x30,
17609 NM_P_BRI = 0x32,
17610 NM_LI16 = 0x34,
17611 NM_SWGP16 = 0x35,
17612 NM_P16_BR = 0x36,
17613
17614 NM_P_LUI = 0x38,
17615 NM_ANDI16 = 0x3c,
17616 NM_SW4X4 = 0x3d,
17617 NM_MOVEPREV = 0x3f,
17618 };
17619
17620 /* POOL32A instruction pool */
17621 enum {
17622 NM_POOL32A0 = 0x00,
17623 NM_SPECIAL2 = 0x01,
17624 NM_COP2_1 = 0x02,
17625 NM_UDI = 0x03,
17626 NM_POOL32A5 = 0x05,
17627 NM_POOL32A7 = 0x07,
17628 };
17629
17630 /* P.GP.W instruction pool */
17631 enum {
17632 NM_ADDIUGP_W = 0x00,
17633 NM_LWGP = 0x02,
17634 NM_SWGP = 0x03,
17635 };
17636
17637 /* P48I instruction pool */
17638 enum {
17639 NM_LI48 = 0x00,
17640 NM_ADDIU48 = 0x01,
17641 NM_ADDIUGP48 = 0x02,
17642 NM_ADDIUPC48 = 0x03,
17643 NM_LWPC48 = 0x0b,
17644 NM_SWPC48 = 0x0f,
17645 };
17646
17647 /* P.U12 instruction pool */
17648 enum {
17649 NM_ORI = 0x00,
17650 NM_XORI = 0x01,
17651 NM_ANDI = 0x02,
17652 NM_P_SR = 0x03,
17653 NM_SLTI = 0x04,
17654 NM_SLTIU = 0x05,
17655 NM_SEQI = 0x06,
17656 NM_ADDIUNEG = 0x08,
17657 NM_P_SHIFT = 0x0c,
17658 NM_P_ROTX = 0x0d,
17659 NM_P_INS = 0x0e,
17660 NM_P_EXT = 0x0f,
17661 };
17662
17663 /* POOL32F instruction pool */
17664 enum {
17665 NM_POOL32F_0 = 0x00,
17666 NM_POOL32F_3 = 0x03,
17667 NM_POOL32F_5 = 0x05,
17668 };
17669
17670 /* POOL32S instruction pool */
17671 enum {
17672 NM_POOL32S_0 = 0x00,
17673 NM_POOL32S_4 = 0x04,
17674 };
17675
17676 /* P.LUI instruction pool */
17677 enum {
17678 NM_LUI = 0x00,
17679 NM_ALUIPC = 0x01,
17680 };
17681
17682 /* P.GP.BH instruction pool */
17683 enum {
17684 NM_LBGP = 0x00,
17685 NM_SBGP = 0x01,
17686 NM_LBUGP = 0x02,
17687 NM_ADDIUGP_B = 0x03,
17688 NM_P_GP_LH = 0x04,
17689 NM_P_GP_SH = 0x05,
17690 NM_P_GP_CP1 = 0x06,
17691 };
17692
17693 /* P.LS.U12 instruction pool */
17694 enum {
17695 NM_LB = 0x00,
17696 NM_SB = 0x01,
17697 NM_LBU = 0x02,
17698 NM_P_PREFU12 = 0x03,
17699 NM_LH = 0x04,
17700 NM_SH = 0x05,
17701 NM_LHU = 0x06,
17702 NM_LWU = 0x07,
17703 NM_LW = 0x08,
17704 NM_SW = 0x09,
17705 NM_LWC1 = 0x0a,
17706 NM_SWC1 = 0x0b,
17707 NM_LDC1 = 0x0e,
17708 NM_SDC1 = 0x0f,
17709 };
17710
17711 /* P.LS.S9 instruction pool */
17712 enum {
17713 NM_P_LS_S0 = 0x00,
17714 NM_P_LS_S1 = 0x01,
17715 NM_P_LS_E0 = 0x02,
17716 NM_P_LS_WM = 0x04,
17717 NM_P_LS_UAWM = 0x05,
17718 };
17719
17720 /* P.BAL instruction pool */
17721 enum {
17722 NM_BC = 0x00,
17723 NM_BALC = 0x01,
17724 };
17725
17726 /* P.J instruction pool */
17727 enum {
17728 NM_JALRC = 0x00,
17729 NM_JALRC_HB = 0x01,
17730 NM_P_BALRSC = 0x08,
17731 };
17732
17733 /* P.BR1 instruction pool */
17734 enum {
17735 NM_BEQC = 0x00,
17736 NM_P_BR3A = 0x01,
17737 NM_BGEC = 0x02,
17738 NM_BGEUC = 0x03,
17739 };
17740
17741 /* P.BR2 instruction pool */
17742 enum {
17743 NM_BNEC = 0x00,
17744 NM_BLTC = 0x02,
17745 NM_BLTUC = 0x03,
17746 };
17747
17748 /* P.BRI instruction pool */
17749 enum {
17750 NM_BEQIC = 0x00,
17751 NM_BBEQZC = 0x01,
17752 NM_BGEIC = 0x02,
17753 NM_BGEIUC = 0x03,
17754 NM_BNEIC = 0x04,
17755 NM_BBNEZC = 0x05,
17756 NM_BLTIC = 0x06,
17757 NM_BLTIUC = 0x07,
17758 };
17759
17760 /* P16.SHIFT instruction pool */
17761 enum {
17762 NM_SLL16 = 0x00,
17763 NM_SRL16 = 0x01,
17764 };
17765
17766 /* POOL16C instruction pool */
17767 enum {
17768 NM_POOL16C_0 = 0x00,
17769 NM_LWXS16 = 0x01,
17770 };
17771
17772 /* P16.A1 instruction pool */
17773 enum {
17774 NM_ADDIUR1SP = 0x01,
17775 };
17776
17777 /* P16.A2 instruction pool */
17778 enum {
17779 NM_ADDIUR2 = 0x00,
17780 NM_P_ADDIURS5 = 0x01,
17781 };
17782
17783 /* P16.ADDU instruction pool */
17784 enum {
17785 NM_ADDU16 = 0x00,
17786 NM_SUBU16 = 0x01,
17787 };
17788
17789 /* P16.SR instruction pool */
17790 enum {
17791 NM_SAVE16 = 0x00,
17792 NM_RESTORE_JRC16 = 0x01,
17793 };
17794
17795 /* P16.4X4 instruction pool */
17796 enum {
17797 NM_ADDU4X4 = 0x00,
17798 NM_MUL4X4 = 0x01,
17799 };
17800
17801 /* P16.LB instruction pool */
17802 enum {
17803 NM_LB16 = 0x00,
17804 NM_SB16 = 0x01,
17805 NM_LBU16 = 0x02,
17806 };
17807
17808 /* P16.LH instruction pool */
17809 enum {
17810 NM_LH16 = 0x00,
17811 NM_SH16 = 0x01,
17812 NM_LHU16 = 0x02,
17813 };
17814
17815 /* P.RI instruction pool */
17816 enum {
17817 NM_SIGRIE = 0x00,
17818 NM_P_SYSCALL = 0x01,
17819 NM_BREAK = 0x02,
17820 NM_SDBBP = 0x03,
17821 };
17822
17823 /* POOL32A0 instruction pool */
17824 enum {
17825 NM_P_TRAP = 0x00,
17826 NM_SEB = 0x01,
17827 NM_SLLV = 0x02,
17828 NM_MUL = 0x03,
17829 NM_MFC0 = 0x06,
17830 NM_MFHC0 = 0x07,
17831 NM_SEH = 0x09,
17832 NM_SRLV = 0x0a,
17833 NM_MUH = 0x0b,
17834 NM_MTC0 = 0x0e,
17835 NM_MTHC0 = 0x0f,
17836 NM_SRAV = 0x12,
17837 NM_MULU = 0x13,
17838 NM_ROTRV = 0x1a,
17839 NM_MUHU = 0x1b,
17840 NM_ADD = 0x22,
17841 NM_DIV = 0x23,
17842 NM_ADDU = 0x2a,
17843 NM_MOD = 0x2b,
17844 NM_SUB = 0x32,
17845 NM_DIVU = 0x33,
17846 NM_RDHWR = 0x38,
17847 NM_SUBU = 0x3a,
17848 NM_MODU = 0x3b,
17849 NM_P_CMOVE = 0x42,
17850 NM_FORK = 0x45,
17851 NM_MFTR = 0x46,
17852 NM_MFHTR = 0x47,
17853 NM_AND = 0x4a,
17854 NM_YIELD = 0x4d,
17855 NM_MTTR = 0x4e,
17856 NM_MTHTR = 0x4f,
17857 NM_OR = 0x52,
17858 NM_D_E_MT_VPE = 0x56,
17859 NM_NOR = 0x5a,
17860 NM_XOR = 0x62,
17861 NM_SLT = 0x6a,
17862 NM_P_SLTU = 0x72,
17863 NM_SOV = 0x7a,
17864 };
17865
17866 /* CRC32 instruction pool */
17867 enum {
17868 NM_CRC32B = 0x00,
17869 NM_CRC32H = 0x01,
17870 NM_CRC32W = 0x02,
17871 NM_CRC32CB = 0x04,
17872 NM_CRC32CH = 0x05,
17873 NM_CRC32CW = 0x06,
17874 };
17875
17876 /* POOL32A5 instruction pool */
17877 enum {
17878 NM_CMP_EQ_PH = 0x00,
17879 NM_CMP_LT_PH = 0x08,
17880 NM_CMP_LE_PH = 0x10,
17881 NM_CMPGU_EQ_QB = 0x18,
17882 NM_CMPGU_LT_QB = 0x20,
17883 NM_CMPGU_LE_QB = 0x28,
17884 NM_CMPGDU_EQ_QB = 0x30,
17885 NM_CMPGDU_LT_QB = 0x38,
17886 NM_CMPGDU_LE_QB = 0x40,
17887 NM_CMPU_EQ_QB = 0x48,
17888 NM_CMPU_LT_QB = 0x50,
17889 NM_CMPU_LE_QB = 0x58,
17890 NM_ADDQ_S_W = 0x60,
17891 NM_SUBQ_S_W = 0x68,
17892 NM_ADDSC = 0x70,
17893 NM_ADDWC = 0x78,
17894
17895 NM_ADDQ_S_PH = 0x01,
17896 NM_ADDQH_R_PH = 0x09,
17897 NM_ADDQH_R_W = 0x11,
17898 NM_ADDU_S_QB = 0x19,
17899 NM_ADDU_S_PH = 0x21,
17900 NM_ADDUH_R_QB = 0x29,
17901 NM_SHRAV_R_PH = 0x31,
17902 NM_SHRAV_R_QB = 0x39,
17903 NM_SUBQ_S_PH = 0x41,
17904 NM_SUBQH_R_PH = 0x49,
17905 NM_SUBQH_R_W = 0x51,
17906 NM_SUBU_S_QB = 0x59,
17907 NM_SUBU_S_PH = 0x61,
17908 NM_SUBUH_R_QB = 0x69,
17909 NM_SHLLV_S_PH = 0x71,
17910 NM_PRECR_SRA_R_PH_W = 0x79,
17911
17912 NM_MULEU_S_PH_QBL = 0x12,
17913 NM_MULEU_S_PH_QBR = 0x1a,
17914 NM_MULQ_RS_PH = 0x22,
17915 NM_MULQ_S_PH = 0x2a,
17916 NM_MULQ_RS_W = 0x32,
17917 NM_MULQ_S_W = 0x3a,
17918 NM_APPEND = 0x42,
17919 NM_MODSUB = 0x52,
17920 NM_SHRAV_R_W = 0x5a,
17921 NM_SHRLV_PH = 0x62,
17922 NM_SHRLV_QB = 0x6a,
17923 NM_SHLLV_QB = 0x72,
17924 NM_SHLLV_S_W = 0x7a,
17925
17926 NM_SHILO = 0x03,
17927
17928 NM_MULEQ_S_W_PHL = 0x04,
17929 NM_MULEQ_S_W_PHR = 0x0c,
17930
17931 NM_MUL_S_PH = 0x05,
17932 NM_PRECR_QB_PH = 0x0d,
17933 NM_PRECRQ_QB_PH = 0x15,
17934 NM_PRECRQ_PH_W = 0x1d,
17935 NM_PRECRQ_RS_PH_W = 0x25,
17936 NM_PRECRQU_S_QB_PH = 0x2d,
17937 NM_PACKRL_PH = 0x35,
17938 NM_PICK_QB = 0x3d,
17939 NM_PICK_PH = 0x45,
17940
17941 NM_SHRA_R_W = 0x5e,
17942 NM_SHRA_R_PH = 0x66,
17943 NM_SHLL_S_PH = 0x76,
17944 NM_SHLL_S_W = 0x7e,
17945
17946 NM_REPL_PH = 0x07
17947 };
17948
17949 /* POOL32A7 instruction pool */
17950 enum {
17951 NM_P_LSX = 0x00,
17952 NM_LSA = 0x01,
17953 NM_EXTW = 0x03,
17954 NM_POOL32AXF = 0x07,
17955 };
17956
17957 /* P.SR instruction pool */
17958 enum {
17959 NM_PP_SR = 0x00,
17960 NM_P_SR_F = 0x01,
17961 };
17962
17963 /* P.SHIFT instruction pool */
17964 enum {
17965 NM_P_SLL = 0x00,
17966 NM_SRL = 0x02,
17967 NM_SRA = 0x04,
17968 NM_ROTR = 0x06,
17969 };
17970
17971 /* P.ROTX instruction pool */
17972 enum {
17973 NM_ROTX = 0x00,
17974 };
17975
17976 /* P.INS instruction pool */
17977 enum {
17978 NM_INS = 0x00,
17979 };
17980
17981 /* P.EXT instruction pool */
17982 enum {
17983 NM_EXT = 0x00,
17984 };
17985
17986 /* POOL32F_0 (fmt) instruction pool */
17987 enum {
17988 NM_RINT_S = 0x04,
17989 NM_RINT_D = 0x44,
17990 NM_ADD_S = 0x06,
17991 NM_SELEQZ_S = 0x07,
17992 NM_SELEQZ_D = 0x47,
17993 NM_CLASS_S = 0x0c,
17994 NM_CLASS_D = 0x4c,
17995 NM_SUB_S = 0x0e,
17996 NM_SELNEZ_S = 0x0f,
17997 NM_SELNEZ_D = 0x4f,
17998 NM_MUL_S = 0x16,
17999 NM_SEL_S = 0x17,
18000 NM_SEL_D = 0x57,
18001 NM_DIV_S = 0x1e,
18002 NM_ADD_D = 0x26,
18003 NM_SUB_D = 0x2e,
18004 NM_MUL_D = 0x36,
18005 NM_MADDF_S = 0x37,
18006 NM_MADDF_D = 0x77,
18007 NM_DIV_D = 0x3e,
18008 NM_MSUBF_S = 0x3f,
18009 NM_MSUBF_D = 0x7f,
18010 };
18011
18012 /* POOL32F_3 instruction pool */
18013 enum {
18014 NM_MIN_FMT = 0x00,
18015 NM_MAX_FMT = 0x01,
18016 NM_MINA_FMT = 0x04,
18017 NM_MAXA_FMT = 0x05,
18018 NM_POOL32FXF = 0x07,
18019 };
18020
18021 /* POOL32F_5 instruction pool */
18022 enum {
18023 NM_CMP_CONDN_S = 0x00,
18024 NM_CMP_CONDN_D = 0x02,
18025 };
18026
18027 /* P.GP.LH instruction pool */
18028 enum {
18029 NM_LHGP = 0x00,
18030 NM_LHUGP = 0x01,
18031 };
18032
18033 /* P.GP.SH instruction pool */
18034 enum {
18035 NM_SHGP = 0x00,
18036 };
18037
18038 /* P.GP.CP1 instruction pool */
18039 enum {
18040 NM_LWC1GP = 0x00,
18041 NM_SWC1GP = 0x01,
18042 NM_LDC1GP = 0x02,
18043 NM_SDC1GP = 0x03,
18044 };
18045
18046 /* P.LS.S0 instruction pool */
18047 enum {
18048 NM_LBS9 = 0x00,
18049 NM_LHS9 = 0x04,
18050 NM_LWS9 = 0x08,
18051 NM_LDS9 = 0x0c,
18052
18053 NM_SBS9 = 0x01,
18054 NM_SHS9 = 0x05,
18055 NM_SWS9 = 0x09,
18056 NM_SDS9 = 0x0d,
18057
18058 NM_LBUS9 = 0x02,
18059 NM_LHUS9 = 0x06,
18060 NM_LWC1S9 = 0x0a,
18061 NM_LDC1S9 = 0x0e,
18062
18063 NM_P_PREFS9 = 0x03,
18064 NM_LWUS9 = 0x07,
18065 NM_SWC1S9 = 0x0b,
18066 NM_SDC1S9 = 0x0f,
18067 };
18068
18069 /* P.LS.S1 instruction pool */
18070 enum {
18071 NM_ASET_ACLR = 0x02,
18072 NM_UALH = 0x04,
18073 NM_UASH = 0x05,
18074 NM_CACHE = 0x07,
18075 NM_P_LL = 0x0a,
18076 NM_P_SC = 0x0b,
18077 };
18078
18079 /* P.LS.E0 instruction pool */
18080 enum {
18081 NM_LBE = 0x00,
18082 NM_SBE = 0x01,
18083 NM_LBUE = 0x02,
18084 NM_P_PREFE = 0x03,
18085 NM_LHE = 0x04,
18086 NM_SHE = 0x05,
18087 NM_LHUE = 0x06,
18088 NM_CACHEE = 0x07,
18089 NM_LWE = 0x08,
18090 NM_SWE = 0x09,
18091 NM_P_LLE = 0x0a,
18092 NM_P_SCE = 0x0b,
18093 };
18094
18095 /* P.PREFE instruction pool */
18096 enum {
18097 NM_SYNCIE = 0x00,
18098 NM_PREFE = 0x01,
18099 };
18100
18101 /* P.LLE instruction pool */
18102 enum {
18103 NM_LLE = 0x00,
18104 NM_LLWPE = 0x01,
18105 };
18106
18107 /* P.SCE instruction pool */
18108 enum {
18109 NM_SCE = 0x00,
18110 NM_SCWPE = 0x01,
18111 };
18112
18113 /* P.LS.WM instruction pool */
18114 enum {
18115 NM_LWM = 0x00,
18116 NM_SWM = 0x01,
18117 };
18118
18119 /* P.LS.UAWM instruction pool */
18120 enum {
18121 NM_UALWM = 0x00,
18122 NM_UASWM = 0x01,
18123 };
18124
18125 /* P.BR3A instruction pool */
18126 enum {
18127 NM_BC1EQZC = 0x00,
18128 NM_BC1NEZC = 0x01,
18129 NM_BC2EQZC = 0x02,
18130 NM_BC2NEZC = 0x03,
18131 NM_BPOSGE32C = 0x04,
18132 };
18133
18134 /* P16.RI instruction pool */
18135 enum {
18136 NM_P16_SYSCALL = 0x01,
18137 NM_BREAK16 = 0x02,
18138 NM_SDBBP16 = 0x03,
18139 };
18140
18141 /* POOL16C_0 instruction pool */
18142 enum {
18143 NM_POOL16C_00 = 0x00,
18144 };
18145
18146 /* P16.JRC instruction pool */
18147 enum {
18148 NM_JRC = 0x00,
18149 NM_JALRC16 = 0x01,
18150 };
18151
18152 /* P.SYSCALL instruction pool */
18153 enum {
18154 NM_SYSCALL = 0x00,
18155 NM_HYPCALL = 0x01,
18156 };
18157
18158 /* P.TRAP instruction pool */
18159 enum {
18160 NM_TEQ = 0x00,
18161 NM_TNE = 0x01,
18162 };
18163
18164 /* P.CMOVE instruction pool */
18165 enum {
18166 NM_MOVZ = 0x00,
18167 NM_MOVN = 0x01,
18168 };
18169
18170 /* POOL32Axf instruction pool */
18171 enum {
18172 NM_POOL32AXF_1 = 0x01,
18173 NM_POOL32AXF_2 = 0x02,
18174 NM_POOL32AXF_4 = 0x04,
18175 NM_POOL32AXF_5 = 0x05,
18176 NM_POOL32AXF_7 = 0x07,
18177 };
18178
18179 /* POOL32Axf_1 instruction pool */
18180 enum {
18181 NM_POOL32AXF_1_0 = 0x00,
18182 NM_POOL32AXF_1_1 = 0x01,
18183 NM_POOL32AXF_1_3 = 0x03,
18184 NM_POOL32AXF_1_4 = 0x04,
18185 NM_POOL32AXF_1_5 = 0x05,
18186 NM_POOL32AXF_1_7 = 0x07,
18187 };
18188
18189 /* POOL32Axf_2 instruction pool */
18190 enum {
18191 NM_POOL32AXF_2_0_7 = 0x00,
18192 NM_POOL32AXF_2_8_15 = 0x01,
18193 NM_POOL32AXF_2_16_23 = 0x02,
18194 NM_POOL32AXF_2_24_31 = 0x03,
18195 };
18196
18197 /* POOL32Axf_7 instruction pool */
18198 enum {
18199 NM_SHRA_R_QB = 0x0,
18200 NM_SHRL_PH = 0x1,
18201 NM_REPL_QB = 0x2,
18202 };
18203
18204 /* POOL32Axf_1_0 instruction pool */
18205 enum {
18206 NM_MFHI = 0x0,
18207 NM_MFLO = 0x1,
18208 NM_MTHI = 0x2,
18209 NM_MTLO = 0x3,
18210 };
18211
18212 /* POOL32Axf_1_1 instruction pool */
18213 enum {
18214 NM_MTHLIP = 0x0,
18215 NM_SHILOV = 0x1,
18216 };
18217
18218 /* POOL32Axf_1_3 instruction pool */
18219 enum {
18220 NM_RDDSP = 0x0,
18221 NM_WRDSP = 0x1,
18222 NM_EXTP = 0x2,
18223 NM_EXTPDP = 0x3,
18224 };
18225
18226 /* POOL32Axf_1_4 instruction pool */
18227 enum {
18228 NM_SHLL_QB = 0x0,
18229 NM_SHRL_QB = 0x1,
18230 };
18231
18232 /* POOL32Axf_1_5 instruction pool */
18233 enum {
18234 NM_MAQ_S_W_PHR = 0x0,
18235 NM_MAQ_S_W_PHL = 0x1,
18236 NM_MAQ_SA_W_PHR = 0x2,
18237 NM_MAQ_SA_W_PHL = 0x3,
18238 };
18239
18240 /* POOL32Axf_1_7 instruction pool */
18241 enum {
18242 NM_EXTR_W = 0x0,
18243 NM_EXTR_R_W = 0x1,
18244 NM_EXTR_RS_W = 0x2,
18245 NM_EXTR_S_H = 0x3,
18246 };
18247
18248 /* POOL32Axf_2_0_7 instruction pool */
18249 enum {
18250 NM_DPA_W_PH = 0x0,
18251 NM_DPAQ_S_W_PH = 0x1,
18252 NM_DPS_W_PH = 0x2,
18253 NM_DPSQ_S_W_PH = 0x3,
18254 NM_BALIGN = 0x4,
18255 NM_MADD = 0x5,
18256 NM_MULT = 0x6,
18257 NM_EXTRV_W = 0x7,
18258 };
18259
18260 /* POOL32Axf_2_8_15 instruction pool */
18261 enum {
18262 NM_DPAX_W_PH = 0x0,
18263 NM_DPAQ_SA_L_W = 0x1,
18264 NM_DPSX_W_PH = 0x2,
18265 NM_DPSQ_SA_L_W = 0x3,
18266 NM_MADDU = 0x5,
18267 NM_MULTU = 0x6,
18268 NM_EXTRV_R_W = 0x7,
18269 };
18270
18271 /* POOL32Axf_2_16_23 instruction pool */
18272 enum {
18273 NM_DPAU_H_QBL = 0x0,
18274 NM_DPAQX_S_W_PH = 0x1,
18275 NM_DPSU_H_QBL = 0x2,
18276 NM_DPSQX_S_W_PH = 0x3,
18277 NM_EXTPV = 0x4,
18278 NM_MSUB = 0x5,
18279 NM_MULSA_W_PH = 0x6,
18280 NM_EXTRV_RS_W = 0x7,
18281 };
18282
18283 /* POOL32Axf_2_24_31 instruction pool */
18284 enum {
18285 NM_DPAU_H_QBR = 0x0,
18286 NM_DPAQX_SA_W_PH = 0x1,
18287 NM_DPSU_H_QBR = 0x2,
18288 NM_DPSQX_SA_W_PH = 0x3,
18289 NM_EXTPDPV = 0x4,
18290 NM_MSUBU = 0x5,
18291 NM_MULSAQ_S_W_PH = 0x6,
18292 NM_EXTRV_S_H = 0x7,
18293 };
18294
18295 /* POOL32Axf_{4, 5} instruction pool */
18296 enum {
18297 NM_CLO = 0x25,
18298 NM_CLZ = 0x2d,
18299
18300 NM_TLBP = 0x01,
18301 NM_TLBR = 0x09,
18302 NM_TLBWI = 0x11,
18303 NM_TLBWR = 0x19,
18304 NM_TLBINV = 0x03,
18305 NM_TLBINVF = 0x0b,
18306 NM_DI = 0x23,
18307 NM_EI = 0x2b,
18308 NM_RDPGPR = 0x70,
18309 NM_WRPGPR = 0x78,
18310 NM_WAIT = 0x61,
18311 NM_DERET = 0x71,
18312 NM_ERETX = 0x79,
18313
18314 /* nanoMIPS DSP instructions */
18315 NM_ABSQ_S_QB = 0x00,
18316 NM_ABSQ_S_PH = 0x08,
18317 NM_ABSQ_S_W = 0x10,
18318 NM_PRECEQ_W_PHL = 0x28,
18319 NM_PRECEQ_W_PHR = 0x30,
18320 NM_PRECEQU_PH_QBL = 0x38,
18321 NM_PRECEQU_PH_QBR = 0x48,
18322 NM_PRECEU_PH_QBL = 0x58,
18323 NM_PRECEU_PH_QBR = 0x68,
18324 NM_PRECEQU_PH_QBLA = 0x39,
18325 NM_PRECEQU_PH_QBRA = 0x49,
18326 NM_PRECEU_PH_QBLA = 0x59,
18327 NM_PRECEU_PH_QBRA = 0x69,
18328 NM_REPLV_PH = 0x01,
18329 NM_REPLV_QB = 0x09,
18330 NM_BITREV = 0x18,
18331 NM_INSV = 0x20,
18332 NM_RADDU_W_QB = 0x78,
18333
18334 NM_BITSWAP = 0x05,
18335 NM_WSBH = 0x3d,
18336 };
18337
18338 /* PP.SR instruction pool */
18339 enum {
18340 NM_SAVE = 0x00,
18341 NM_RESTORE = 0x02,
18342 NM_RESTORE_JRC = 0x03,
18343 };
18344
18345 /* P.SR.F instruction pool */
18346 enum {
18347 NM_SAVEF = 0x00,
18348 NM_RESTOREF = 0x01,
18349 };
18350
18351 /* P16.SYSCALL instruction pool */
18352 enum {
18353 NM_SYSCALL16 = 0x00,
18354 NM_HYPCALL16 = 0x01,
18355 };
18356
18357 /* POOL16C_00 instruction pool */
18358 enum {
18359 NM_NOT16 = 0x00,
18360 NM_XOR16 = 0x01,
18361 NM_AND16 = 0x02,
18362 NM_OR16 = 0x03,
18363 };
18364
18365 /* PP.LSX and PP.LSXS instruction pool */
18366 enum {
18367 NM_LBX = 0x00,
18368 NM_LHX = 0x04,
18369 NM_LWX = 0x08,
18370 NM_LDX = 0x0c,
18371
18372 NM_SBX = 0x01,
18373 NM_SHX = 0x05,
18374 NM_SWX = 0x09,
18375 NM_SDX = 0x0d,
18376
18377 NM_LBUX = 0x02,
18378 NM_LHUX = 0x06,
18379 NM_LWC1X = 0x0a,
18380 NM_LDC1X = 0x0e,
18381
18382 NM_LWUX = 0x07,
18383 NM_SWC1X = 0x0b,
18384 NM_SDC1X = 0x0f,
18385
18386 NM_LHXS = 0x04,
18387 NM_LWXS = 0x08,
18388 NM_LDXS = 0x0c,
18389
18390 NM_SHXS = 0x05,
18391 NM_SWXS = 0x09,
18392 NM_SDXS = 0x0d,
18393
18394 NM_LHUXS = 0x06,
18395 NM_LWC1XS = 0x0a,
18396 NM_LDC1XS = 0x0e,
18397
18398 NM_LWUXS = 0x07,
18399 NM_SWC1XS = 0x0b,
18400 NM_SDC1XS = 0x0f,
18401 };
18402
18403 /* ERETx instruction pool */
18404 enum {
18405 NM_ERET = 0x00,
18406 NM_ERETNC = 0x01,
18407 };
18408
18409 /* POOL32FxF_{0, 1} insturction pool */
18410 enum {
18411 NM_CFC1 = 0x40,
18412 NM_CTC1 = 0x60,
18413 NM_MFC1 = 0x80,
18414 NM_MTC1 = 0xa0,
18415 NM_MFHC1 = 0xc0,
18416 NM_MTHC1 = 0xe0,
18417
18418 NM_CVT_S_PL = 0x84,
18419 NM_CVT_S_PU = 0xa4,
18420
18421 NM_CVT_L_S = 0x004,
18422 NM_CVT_L_D = 0x104,
18423 NM_CVT_W_S = 0x024,
18424 NM_CVT_W_D = 0x124,
18425
18426 NM_RSQRT_S = 0x008,
18427 NM_RSQRT_D = 0x108,
18428
18429 NM_SQRT_S = 0x028,
18430 NM_SQRT_D = 0x128,
18431
18432 NM_RECIP_S = 0x048,
18433 NM_RECIP_D = 0x148,
18434
18435 NM_FLOOR_L_S = 0x00c,
18436 NM_FLOOR_L_D = 0x10c,
18437
18438 NM_FLOOR_W_S = 0x02c,
18439 NM_FLOOR_W_D = 0x12c,
18440
18441 NM_CEIL_L_S = 0x04c,
18442 NM_CEIL_L_D = 0x14c,
18443 NM_CEIL_W_S = 0x06c,
18444 NM_CEIL_W_D = 0x16c,
18445 NM_TRUNC_L_S = 0x08c,
18446 NM_TRUNC_L_D = 0x18c,
18447 NM_TRUNC_W_S = 0x0ac,
18448 NM_TRUNC_W_D = 0x1ac,
18449 NM_ROUND_L_S = 0x0cc,
18450 NM_ROUND_L_D = 0x1cc,
18451 NM_ROUND_W_S = 0x0ec,
18452 NM_ROUND_W_D = 0x1ec,
18453
18454 NM_MOV_S = 0x01,
18455 NM_MOV_D = 0x81,
18456 NM_ABS_S = 0x0d,
18457 NM_ABS_D = 0x8d,
18458 NM_NEG_S = 0x2d,
18459 NM_NEG_D = 0xad,
18460 NM_CVT_D_S = 0x04d,
18461 NM_CVT_D_W = 0x0cd,
18462 NM_CVT_D_L = 0x14d,
18463 NM_CVT_S_D = 0x06d,
18464 NM_CVT_S_W = 0x0ed,
18465 NM_CVT_S_L = 0x16d,
18466 };
18467
18468 /* P.LL instruction pool */
18469 enum {
18470 NM_LL = 0x00,
18471 NM_LLWP = 0x01,
18472 };
18473
18474 /* P.SC instruction pool */
18475 enum {
18476 NM_SC = 0x00,
18477 NM_SCWP = 0x01,
18478 };
18479
18480 /* P.DVP instruction pool */
18481 enum {
18482 NM_DVP = 0x00,
18483 NM_EVP = 0x01,
18484 };
18485
18486
18487 /*
18488 *
18489 * nanoMIPS decoding engine
18490 *
18491 */
18492
18493
18494 /* extraction utilities */
18495
18496 #define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7)
18497 #define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7)
18498 #define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7)
18499 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18500 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18501
18502 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
18503 static inline int decode_gpr_gpr3(int r)
18504 {
18505 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
18506
18507 return map[r & 0x7];
18508 }
18509
18510 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
18511 static inline int decode_gpr_gpr3_src_store(int r)
18512 {
18513 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
18514
18515 return map[r & 0x7];
18516 }
18517
18518 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
18519 static inline int decode_gpr_gpr4(int r)
18520 {
18521 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
18522 16, 17, 18, 19, 20, 21, 22, 23 };
18523
18524 return map[r & 0xf];
18525 }
18526
18527 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
18528 static inline int decode_gpr_gpr4_zero(int r)
18529 {
18530 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
18531 16, 17, 18, 19, 20, 21, 22, 23 };
18532
18533 return map[r & 0xf];
18534 }
18535
18536
18537 static void gen_adjust_sp(DisasContext *ctx, int u)
18538 {
18539 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
18540 }
18541
18542 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
18543 uint8_t gp, uint16_t u)
18544 {
18545 int counter = 0;
18546 TCGv va = tcg_temp_new();
18547 TCGv t0 = tcg_temp_new();
18548
18549 while (counter != count) {
18550 bool use_gp = gp && (counter == count - 1);
18551 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18552 int this_offset = -((counter + 1) << 2);
18553 gen_base_offset_addr(ctx, va, 29, this_offset);
18554 gen_load_gpr(t0, this_rt);
18555 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
18556 (MO_TEUL | ctx->default_tcg_memop_mask));
18557 counter++;
18558 }
18559
18560 /* adjust stack pointer */
18561 gen_adjust_sp(ctx, -u);
18562
18563 tcg_temp_free(t0);
18564 tcg_temp_free(va);
18565 }
18566
18567 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
18568 uint8_t gp, uint16_t u)
18569 {
18570 int counter = 0;
18571 TCGv va = tcg_temp_new();
18572 TCGv t0 = tcg_temp_new();
18573
18574 while (counter != count) {
18575 bool use_gp = gp && (counter == count - 1);
18576 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18577 int this_offset = u - ((counter + 1) << 2);
18578 gen_base_offset_addr(ctx, va, 29, this_offset);
18579 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
18580 ctx->default_tcg_memop_mask);
18581 tcg_gen_ext32s_tl(t0, t0);
18582 gen_store_gpr(t0, this_rt);
18583 counter++;
18584 }
18585
18586 /* adjust stack pointer */
18587 gen_adjust_sp(ctx, u);
18588
18589 tcg_temp_free(t0);
18590 tcg_temp_free(va);
18591 }
18592
18593 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
18594 {
18595 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
18596 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
18597
18598 switch (extract32(ctx->opcode, 2, 2)) {
18599 case NM_NOT16:
18600 gen_logic(ctx, OPC_NOR, rt, rs, 0);
18601 break;
18602 case NM_AND16:
18603 gen_logic(ctx, OPC_AND, rt, rt, rs);
18604 break;
18605 case NM_XOR16:
18606 gen_logic(ctx, OPC_XOR, rt, rt, rs);
18607 break;
18608 case NM_OR16:
18609 gen_logic(ctx, OPC_OR, rt, rt, rs);
18610 break;
18611 }
18612 }
18613
18614 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18615 {
18616 int rt = extract32(ctx->opcode, 21, 5);
18617 int rs = extract32(ctx->opcode, 16, 5);
18618 int rd = extract32(ctx->opcode, 11, 5);
18619
18620 switch (extract32(ctx->opcode, 3, 7)) {
18621 case NM_P_TRAP:
18622 switch (extract32(ctx->opcode, 10, 1)) {
18623 case NM_TEQ:
18624 check_nms(ctx);
18625 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
18626 break;
18627 case NM_TNE:
18628 check_nms(ctx);
18629 gen_trap(ctx, OPC_TNE, rs, rt, -1);
18630 break;
18631 }
18632 break;
18633 case NM_RDHWR:
18634 check_nms(ctx);
18635 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
18636 break;
18637 case NM_SEB:
18638 check_nms(ctx);
18639 gen_bshfl(ctx, OPC_SEB, rs, rt);
18640 break;
18641 case NM_SEH:
18642 gen_bshfl(ctx, OPC_SEH, rs, rt);
18643 break;
18644 case NM_SLLV:
18645 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
18646 break;
18647 case NM_SRLV:
18648 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
18649 break;
18650 case NM_SRAV:
18651 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
18652 break;
18653 case NM_ROTRV:
18654 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
18655 break;
18656 case NM_ADD:
18657 gen_arith(ctx, OPC_ADD, rd, rs, rt);
18658 break;
18659 case NM_ADDU:
18660 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
18661 break;
18662 case NM_SUB:
18663 check_nms(ctx);
18664 gen_arith(ctx, OPC_SUB, rd, rs, rt);
18665 break;
18666 case NM_SUBU:
18667 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
18668 break;
18669 case NM_P_CMOVE:
18670 switch (extract32(ctx->opcode, 10, 1)) {
18671 case NM_MOVZ:
18672 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
18673 break;
18674 case NM_MOVN:
18675 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
18676 break;
18677 }
18678 break;
18679 case NM_AND:
18680 gen_logic(ctx, OPC_AND, rd, rs, rt);
18681 break;
18682 case NM_OR:
18683 gen_logic(ctx, OPC_OR, rd, rs, rt);
18684 break;
18685 case NM_NOR:
18686 gen_logic(ctx, OPC_NOR, rd, rs, rt);
18687 break;
18688 case NM_XOR:
18689 gen_logic(ctx, OPC_XOR, rd, rs, rt);
18690 break;
18691 case NM_SLT:
18692 gen_slt(ctx, OPC_SLT, rd, rs, rt);
18693 break;
18694 case NM_P_SLTU:
18695 if (rd == 0) {
18696 /* P_DVP */
18697 #ifndef CONFIG_USER_ONLY
18698 TCGv t0 = tcg_temp_new();
18699 switch (extract32(ctx->opcode, 10, 1)) {
18700 case NM_DVP:
18701 if (ctx->vp) {
18702 check_cp0_enabled(ctx);
18703 gen_helper_dvp(t0, cpu_env);
18704 gen_store_gpr(t0, rt);
18705 }
18706 break;
18707 case NM_EVP:
18708 if (ctx->vp) {
18709 check_cp0_enabled(ctx);
18710 gen_helper_evp(t0, cpu_env);
18711 gen_store_gpr(t0, rt);
18712 }
18713 break;
18714 }
18715 tcg_temp_free(t0);
18716 #endif
18717 } else {
18718 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
18719 }
18720 break;
18721 case NM_SOV:
18722 {
18723 TCGv t0 = tcg_temp_new();
18724 TCGv t1 = tcg_temp_new();
18725 TCGv t2 = tcg_temp_new();
18726
18727 gen_load_gpr(t1, rs);
18728 gen_load_gpr(t2, rt);
18729 tcg_gen_add_tl(t0, t1, t2);
18730 tcg_gen_ext32s_tl(t0, t0);
18731 tcg_gen_xor_tl(t1, t1, t2);
18732 tcg_gen_xor_tl(t2, t0, t2);
18733 tcg_gen_andc_tl(t1, t2, t1);
18734
18735 /* operands of same sign, result different sign */
18736 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
18737 gen_store_gpr(t0, rd);
18738
18739 tcg_temp_free(t0);
18740 tcg_temp_free(t1);
18741 tcg_temp_free(t2);
18742 }
18743 break;
18744 case NM_MUL:
18745 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
18746 break;
18747 case NM_MUH:
18748 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
18749 break;
18750 case NM_MULU:
18751 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
18752 break;
18753 case NM_MUHU:
18754 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
18755 break;
18756 case NM_DIV:
18757 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
18758 break;
18759 case NM_MOD:
18760 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
18761 break;
18762 case NM_DIVU:
18763 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
18764 break;
18765 case NM_MODU:
18766 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
18767 break;
18768 #ifndef CONFIG_USER_ONLY
18769 case NM_MFC0:
18770 check_cp0_enabled(ctx);
18771 if (rt == 0) {
18772 /* Treat as NOP. */
18773 break;
18774 }
18775 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
18776 break;
18777 case NM_MTC0:
18778 check_cp0_enabled(ctx);
18779 {
18780 TCGv t0 = tcg_temp_new();
18781
18782 gen_load_gpr(t0, rt);
18783 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
18784 tcg_temp_free(t0);
18785 }
18786 break;
18787 case NM_D_E_MT_VPE:
18788 {
18789 uint8_t sc = extract32(ctx->opcode, 10, 1);
18790 TCGv t0 = tcg_temp_new();
18791
18792 switch (sc) {
18793 case 0:
18794 if (rs == 1) {
18795 /* DMT */
18796 check_cp0_mt(ctx);
18797 gen_helper_dmt(t0);
18798 gen_store_gpr(t0, rt);
18799 } else if (rs == 0) {
18800 /* DVPE */
18801 check_cp0_mt(ctx);
18802 gen_helper_dvpe(t0, cpu_env);
18803 gen_store_gpr(t0, rt);
18804 } else {
18805 generate_exception_end(ctx, EXCP_RI);
18806 }
18807 break;
18808 case 1:
18809 if (rs == 1) {
18810 /* EMT */
18811 check_cp0_mt(ctx);
18812 gen_helper_emt(t0);
18813 gen_store_gpr(t0, rt);
18814 } else if (rs == 0) {
18815 /* EVPE */
18816 check_cp0_mt(ctx);
18817 gen_helper_evpe(t0, cpu_env);
18818 gen_store_gpr(t0, rt);
18819 } else {
18820 generate_exception_end(ctx, EXCP_RI);
18821 }
18822 break;
18823 }
18824
18825 tcg_temp_free(t0);
18826 }
18827 break;
18828 case NM_FORK:
18829 check_mt(ctx);
18830 {
18831 TCGv t0 = tcg_temp_new();
18832 TCGv t1 = tcg_temp_new();
18833
18834 gen_load_gpr(t0, rt);
18835 gen_load_gpr(t1, rs);
18836 gen_helper_fork(t0, t1);
18837 tcg_temp_free(t0);
18838 tcg_temp_free(t1);
18839 }
18840 break;
18841 case NM_MFTR:
18842 case NM_MFHTR:
18843 check_cp0_enabled(ctx);
18844 if (rd == 0) {
18845 /* Treat as NOP. */
18846 return;
18847 }
18848 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18849 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18850 break;
18851 case NM_MTTR:
18852 case NM_MTHTR:
18853 check_cp0_enabled(ctx);
18854 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18855 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18856 break;
18857 case NM_YIELD:
18858 check_mt(ctx);
18859 {
18860 TCGv t0 = tcg_temp_new();
18861
18862 gen_load_gpr(t0, rs);
18863 gen_helper_yield(t0, cpu_env, t0);
18864 gen_store_gpr(t0, rt);
18865 tcg_temp_free(t0);
18866 }
18867 break;
18868 #endif
18869 default:
18870 generate_exception_end(ctx, EXCP_RI);
18871 break;
18872 }
18873 }
18874
18875 /* dsp */
18876 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
18877 int ret, int v1, int v2)
18878 {
18879 TCGv_i32 t0;
18880 TCGv v0_t;
18881 TCGv v1_t;
18882
18883 t0 = tcg_temp_new_i32();
18884
18885 v0_t = tcg_temp_new();
18886 v1_t = tcg_temp_new();
18887
18888 tcg_gen_movi_i32(t0, v2 >> 3);
18889
18890 gen_load_gpr(v0_t, ret);
18891 gen_load_gpr(v1_t, v1);
18892
18893 switch (opc) {
18894 case NM_MAQ_S_W_PHR:
18895 check_dsp(ctx);
18896 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
18897 break;
18898 case NM_MAQ_S_W_PHL:
18899 check_dsp(ctx);
18900 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
18901 break;
18902 case NM_MAQ_SA_W_PHR:
18903 check_dsp(ctx);
18904 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
18905 break;
18906 case NM_MAQ_SA_W_PHL:
18907 check_dsp(ctx);
18908 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
18909 break;
18910 default:
18911 generate_exception_end(ctx, EXCP_RI);
18912 break;
18913 }
18914
18915 tcg_temp_free_i32(t0);
18916
18917 tcg_temp_free(v0_t);
18918 tcg_temp_free(v1_t);
18919 }
18920
18921
18922 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
18923 int ret, int v1, int v2)
18924 {
18925 int16_t imm;
18926 TCGv t0 = tcg_temp_new();
18927 TCGv t1 = tcg_temp_new();
18928 TCGv v0_t = tcg_temp_new();
18929
18930 gen_load_gpr(v0_t, v1);
18931
18932 switch (opc) {
18933 case NM_POOL32AXF_1_0:
18934 check_dsp(ctx);
18935 switch (extract32(ctx->opcode, 12, 2)) {
18936 case NM_MFHI:
18937 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
18938 break;
18939 case NM_MFLO:
18940 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
18941 break;
18942 case NM_MTHI:
18943 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
18944 break;
18945 case NM_MTLO:
18946 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
18947 break;
18948 }
18949 break;
18950 case NM_POOL32AXF_1_1:
18951 check_dsp(ctx);
18952 switch (extract32(ctx->opcode, 12, 2)) {
18953 case NM_MTHLIP:
18954 tcg_gen_movi_tl(t0, v2);
18955 gen_helper_mthlip(t0, v0_t, cpu_env);
18956 break;
18957 case NM_SHILOV:
18958 tcg_gen_movi_tl(t0, v2 >> 3);
18959 gen_helper_shilo(t0, v0_t, cpu_env);
18960 break;
18961 default:
18962 generate_exception_end(ctx, EXCP_RI);
18963 break;
18964 }
18965 break;
18966 case NM_POOL32AXF_1_3:
18967 check_dsp(ctx);
18968 imm = extract32(ctx->opcode, 14, 7);
18969 switch (extract32(ctx->opcode, 12, 2)) {
18970 case NM_RDDSP:
18971 tcg_gen_movi_tl(t0, imm);
18972 gen_helper_rddsp(t0, t0, cpu_env);
18973 gen_store_gpr(t0, ret);
18974 break;
18975 case NM_WRDSP:
18976 gen_load_gpr(t0, ret);
18977 tcg_gen_movi_tl(t1, imm);
18978 gen_helper_wrdsp(t0, t1, cpu_env);
18979 break;
18980 case NM_EXTP:
18981 tcg_gen_movi_tl(t0, v2 >> 3);
18982 tcg_gen_movi_tl(t1, v1);
18983 gen_helper_extp(t0, t0, t1, cpu_env);
18984 gen_store_gpr(t0, ret);
18985 break;
18986 case NM_EXTPDP:
18987 tcg_gen_movi_tl(t0, v2 >> 3);
18988 tcg_gen_movi_tl(t1, v1);
18989 gen_helper_extpdp(t0, t0, t1, cpu_env);
18990 gen_store_gpr(t0, ret);
18991 break;
18992 }
18993 break;
18994 case NM_POOL32AXF_1_4:
18995 check_dsp(ctx);
18996 tcg_gen_movi_tl(t0, v2 >> 2);
18997 switch (extract32(ctx->opcode, 12, 1)) {
18998 case NM_SHLL_QB:
18999 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
19000 gen_store_gpr(t0, ret);
19001 break;
19002 case NM_SHRL_QB:
19003 gen_helper_shrl_qb(t0, t0, v0_t);
19004 gen_store_gpr(t0, ret);
19005 break;
19006 }
19007 break;
19008 case NM_POOL32AXF_1_5:
19009 opc = extract32(ctx->opcode, 12, 2);
19010 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
19011 break;
19012 case NM_POOL32AXF_1_7:
19013 check_dsp(ctx);
19014 tcg_gen_movi_tl(t0, v2 >> 3);
19015 tcg_gen_movi_tl(t1, v1);
19016 switch (extract32(ctx->opcode, 12, 2)) {
19017 case NM_EXTR_W:
19018 gen_helper_extr_w(t0, t0, t1, cpu_env);
19019 gen_store_gpr(t0, ret);
19020 break;
19021 case NM_EXTR_R_W:
19022 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
19023 gen_store_gpr(t0, ret);
19024 break;
19025 case NM_EXTR_RS_W:
19026 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
19027 gen_store_gpr(t0, ret);
19028 break;
19029 case NM_EXTR_S_H:
19030 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
19031 gen_store_gpr(t0, ret);
19032 break;
19033 }
19034 break;
19035 default:
19036 generate_exception_end(ctx, EXCP_RI);
19037 break;
19038 }
19039
19040 tcg_temp_free(t0);
19041 tcg_temp_free(t1);
19042 tcg_temp_free(v0_t);
19043 }
19044
19045 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
19046 TCGv v0, TCGv v1, int rd)
19047 {
19048 TCGv_i32 t0;
19049
19050 t0 = tcg_temp_new_i32();
19051
19052 tcg_gen_movi_i32(t0, rd >> 3);
19053
19054 switch (opc) {
19055 case NM_POOL32AXF_2_0_7:
19056 switch (extract32(ctx->opcode, 9, 3)) {
19057 case NM_DPA_W_PH:
19058 check_dsp_r2(ctx);
19059 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
19060 break;
19061 case NM_DPAQ_S_W_PH:
19062 check_dsp(ctx);
19063 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
19064 break;
19065 case NM_DPS_W_PH:
19066 check_dsp_r2(ctx);
19067 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
19068 break;
19069 case NM_DPSQ_S_W_PH:
19070 check_dsp(ctx);
19071 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
19072 break;
19073 default:
19074 generate_exception_end(ctx, EXCP_RI);
19075 break;
19076 }
19077 break;
19078 case NM_POOL32AXF_2_8_15:
19079 switch (extract32(ctx->opcode, 9, 3)) {
19080 case NM_DPAX_W_PH:
19081 check_dsp_r2(ctx);
19082 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
19083 break;
19084 case NM_DPAQ_SA_L_W:
19085 check_dsp(ctx);
19086 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
19087 break;
19088 case NM_DPSX_W_PH:
19089 check_dsp_r2(ctx);
19090 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
19091 break;
19092 case NM_DPSQ_SA_L_W:
19093 check_dsp(ctx);
19094 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
19095 break;
19096 default:
19097 generate_exception_end(ctx, EXCP_RI);
19098 break;
19099 }
19100 break;
19101 case NM_POOL32AXF_2_16_23:
19102 switch (extract32(ctx->opcode, 9, 3)) {
19103 case NM_DPAU_H_QBL:
19104 check_dsp(ctx);
19105 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
19106 break;
19107 case NM_DPAQX_S_W_PH:
19108 check_dsp_r2(ctx);
19109 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
19110 break;
19111 case NM_DPSU_H_QBL:
19112 check_dsp(ctx);
19113 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
19114 break;
19115 case NM_DPSQX_S_W_PH:
19116 check_dsp_r2(ctx);
19117 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
19118 break;
19119 case NM_MULSA_W_PH:
19120 check_dsp_r2(ctx);
19121 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
19122 break;
19123 default:
19124 generate_exception_end(ctx, EXCP_RI);
19125 break;
19126 }
19127 break;
19128 case NM_POOL32AXF_2_24_31:
19129 switch (extract32(ctx->opcode, 9, 3)) {
19130 case NM_DPAU_H_QBR:
19131 check_dsp(ctx);
19132 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
19133 break;
19134 case NM_DPAQX_SA_W_PH:
19135 check_dsp_r2(ctx);
19136 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
19137 break;
19138 case NM_DPSU_H_QBR:
19139 check_dsp(ctx);
19140 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
19141 break;
19142 case NM_DPSQX_SA_W_PH:
19143 check_dsp_r2(ctx);
19144 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
19145 break;
19146 case NM_MULSAQ_S_W_PH:
19147 check_dsp(ctx);
19148 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
19149 break;
19150 default:
19151 generate_exception_end(ctx, EXCP_RI);
19152 break;
19153 }
19154 break;
19155 default:
19156 generate_exception_end(ctx, EXCP_RI);
19157 break;
19158 }
19159
19160 tcg_temp_free_i32(t0);
19161 }
19162
19163 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
19164 int rt, int rs, int rd)
19165 {
19166 int ret = rt;
19167 TCGv t0 = tcg_temp_new();
19168 TCGv t1 = tcg_temp_new();
19169 TCGv v0_t = tcg_temp_new();
19170 TCGv v1_t = tcg_temp_new();
19171
19172 gen_load_gpr(v0_t, rt);
19173 gen_load_gpr(v1_t, rs);
19174
19175 switch (opc) {
19176 case NM_POOL32AXF_2_0_7:
19177 switch (extract32(ctx->opcode, 9, 3)) {
19178 case NM_DPA_W_PH:
19179 case NM_DPAQ_S_W_PH:
19180 case NM_DPS_W_PH:
19181 case NM_DPSQ_S_W_PH:
19182 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19183 break;
19184 case NM_BALIGN:
19185 check_dsp_r2(ctx);
19186 if (rt != 0) {
19187 gen_load_gpr(t0, rs);
19188 rd &= 3;
19189 if (rd != 0 && rd != 2) {
19190 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
19191 tcg_gen_ext32u_tl(t0, t0);
19192 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
19193 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19194 }
19195 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
19196 }
19197 break;
19198 case NM_MADD:
19199 check_dsp(ctx);
19200 {
19201 int acc = extract32(ctx->opcode, 14, 2);
19202 TCGv_i64 t2 = tcg_temp_new_i64();
19203 TCGv_i64 t3 = tcg_temp_new_i64();
19204
19205 gen_load_gpr(t0, rt);
19206 gen_load_gpr(t1, rs);
19207 tcg_gen_ext_tl_i64(t2, t0);
19208 tcg_gen_ext_tl_i64(t3, t1);
19209 tcg_gen_mul_i64(t2, t2, t3);
19210 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19211 tcg_gen_add_i64(t2, t2, t3);
19212 tcg_temp_free_i64(t3);
19213 gen_move_low32(cpu_LO[acc], t2);
19214 gen_move_high32(cpu_HI[acc], t2);
19215 tcg_temp_free_i64(t2);
19216 }
19217 break;
19218 case NM_MULT:
19219 check_dsp(ctx);
19220 {
19221 int acc = extract32(ctx->opcode, 14, 2);
19222 TCGv_i32 t2 = tcg_temp_new_i32();
19223 TCGv_i32 t3 = tcg_temp_new_i32();
19224
19225 gen_load_gpr(t0, rs);
19226 gen_load_gpr(t1, rt);
19227 tcg_gen_trunc_tl_i32(t2, t0);
19228 tcg_gen_trunc_tl_i32(t3, t1);
19229 tcg_gen_muls2_i32(t2, t3, t2, t3);
19230 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19231 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19232 tcg_temp_free_i32(t2);
19233 tcg_temp_free_i32(t3);
19234 }
19235 break;
19236 case NM_EXTRV_W:
19237 check_dsp(ctx);
19238 gen_load_gpr(v1_t, rs);
19239 tcg_gen_movi_tl(t0, rd >> 3);
19240 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
19241 gen_store_gpr(t0, ret);
19242 break;
19243 }
19244 break;
19245 case NM_POOL32AXF_2_8_15:
19246 switch (extract32(ctx->opcode, 9, 3)) {
19247 case NM_DPAX_W_PH:
19248 case NM_DPAQ_SA_L_W:
19249 case NM_DPSX_W_PH:
19250 case NM_DPSQ_SA_L_W:
19251 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19252 break;
19253 case NM_MADDU:
19254 check_dsp(ctx);
19255 {
19256 int acc = extract32(ctx->opcode, 14, 2);
19257 TCGv_i64 t2 = tcg_temp_new_i64();
19258 TCGv_i64 t3 = tcg_temp_new_i64();
19259
19260 gen_load_gpr(t0, rs);
19261 gen_load_gpr(t1, rt);
19262 tcg_gen_ext32u_tl(t0, t0);
19263 tcg_gen_ext32u_tl(t1, t1);
19264 tcg_gen_extu_tl_i64(t2, t0);
19265 tcg_gen_extu_tl_i64(t3, t1);
19266 tcg_gen_mul_i64(t2, t2, t3);
19267 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19268 tcg_gen_add_i64(t2, t2, t3);
19269 tcg_temp_free_i64(t3);
19270 gen_move_low32(cpu_LO[acc], t2);
19271 gen_move_high32(cpu_HI[acc], t2);
19272 tcg_temp_free_i64(t2);
19273 }
19274 break;
19275 case NM_MULTU:
19276 check_dsp(ctx);
19277 {
19278 int acc = extract32(ctx->opcode, 14, 2);
19279 TCGv_i32 t2 = tcg_temp_new_i32();
19280 TCGv_i32 t3 = tcg_temp_new_i32();
19281
19282 gen_load_gpr(t0, rs);
19283 gen_load_gpr(t1, rt);
19284 tcg_gen_trunc_tl_i32(t2, t0);
19285 tcg_gen_trunc_tl_i32(t3, t1);
19286 tcg_gen_mulu2_i32(t2, t3, t2, t3);
19287 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19288 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19289 tcg_temp_free_i32(t2);
19290 tcg_temp_free_i32(t3);
19291 }
19292 break;
19293 case NM_EXTRV_R_W:
19294 check_dsp(ctx);
19295 tcg_gen_movi_tl(t0, rd >> 3);
19296 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
19297 gen_store_gpr(t0, ret);
19298 break;
19299 default:
19300 generate_exception_end(ctx, EXCP_RI);
19301 break;
19302 }
19303 break;
19304 case NM_POOL32AXF_2_16_23:
19305 switch (extract32(ctx->opcode, 9, 3)) {
19306 case NM_DPAU_H_QBL:
19307 case NM_DPAQX_S_W_PH:
19308 case NM_DPSU_H_QBL:
19309 case NM_DPSQX_S_W_PH:
19310 case NM_MULSA_W_PH:
19311 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19312 break;
19313 case NM_EXTPV:
19314 check_dsp(ctx);
19315 tcg_gen_movi_tl(t0, rd >> 3);
19316 gen_helper_extp(t0, t0, v1_t, cpu_env);
19317 gen_store_gpr(t0, ret);
19318 break;
19319 case NM_MSUB:
19320 check_dsp(ctx);
19321 {
19322 int acc = extract32(ctx->opcode, 14, 2);
19323 TCGv_i64 t2 = tcg_temp_new_i64();
19324 TCGv_i64 t3 = tcg_temp_new_i64();
19325
19326 gen_load_gpr(t0, rs);
19327 gen_load_gpr(t1, rt);
19328 tcg_gen_ext_tl_i64(t2, t0);
19329 tcg_gen_ext_tl_i64(t3, t1);
19330 tcg_gen_mul_i64(t2, t2, t3);
19331 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19332 tcg_gen_sub_i64(t2, t3, t2);
19333 tcg_temp_free_i64(t3);
19334 gen_move_low32(cpu_LO[acc], t2);
19335 gen_move_high32(cpu_HI[acc], t2);
19336 tcg_temp_free_i64(t2);
19337 }
19338 break;
19339 case NM_EXTRV_RS_W:
19340 check_dsp(ctx);
19341 tcg_gen_movi_tl(t0, rd >> 3);
19342 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
19343 gen_store_gpr(t0, ret);
19344 break;
19345 }
19346 break;
19347 case NM_POOL32AXF_2_24_31:
19348 switch (extract32(ctx->opcode, 9, 3)) {
19349 case NM_DPAU_H_QBR:
19350 case NM_DPAQX_SA_W_PH:
19351 case NM_DPSU_H_QBR:
19352 case NM_DPSQX_SA_W_PH:
19353 case NM_MULSAQ_S_W_PH:
19354 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19355 break;
19356 case NM_EXTPDPV:
19357 check_dsp(ctx);
19358 tcg_gen_movi_tl(t0, rd >> 3);
19359 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
19360 gen_store_gpr(t0, ret);
19361 break;
19362 case NM_MSUBU:
19363 check_dsp(ctx);
19364 {
19365 int acc = extract32(ctx->opcode, 14, 2);
19366 TCGv_i64 t2 = tcg_temp_new_i64();
19367 TCGv_i64 t3 = tcg_temp_new_i64();
19368
19369 gen_load_gpr(t0, rs);
19370 gen_load_gpr(t1, rt);
19371 tcg_gen_ext32u_tl(t0, t0);
19372 tcg_gen_ext32u_tl(t1, t1);
19373 tcg_gen_extu_tl_i64(t2, t0);
19374 tcg_gen_extu_tl_i64(t3, t1);
19375 tcg_gen_mul_i64(t2, t2, t3);
19376 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19377 tcg_gen_sub_i64(t2, t3, t2);
19378 tcg_temp_free_i64(t3);
19379 gen_move_low32(cpu_LO[acc], t2);
19380 gen_move_high32(cpu_HI[acc], t2);
19381 tcg_temp_free_i64(t2);
19382 }
19383 break;
19384 case NM_EXTRV_S_H:
19385 check_dsp(ctx);
19386 tcg_gen_movi_tl(t0, rd >> 3);
19387 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
19388 gen_store_gpr(t0, ret);
19389 break;
19390 }
19391 break;
19392 default:
19393 generate_exception_end(ctx, EXCP_RI);
19394 break;
19395 }
19396
19397 tcg_temp_free(t0);
19398 tcg_temp_free(t1);
19399
19400 tcg_temp_free(v0_t);
19401 tcg_temp_free(v1_t);
19402 }
19403
19404 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
19405 int rt, int rs)
19406 {
19407 int ret = rt;
19408 TCGv t0 = tcg_temp_new();
19409 TCGv v0_t = tcg_temp_new();
19410
19411 gen_load_gpr(v0_t, rs);
19412
19413 switch (opc) {
19414 case NM_ABSQ_S_QB:
19415 check_dsp_r2(ctx);
19416 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
19417 gen_store_gpr(v0_t, ret);
19418 break;
19419 case NM_ABSQ_S_PH:
19420 check_dsp(ctx);
19421 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
19422 gen_store_gpr(v0_t, ret);
19423 break;
19424 case NM_ABSQ_S_W:
19425 check_dsp(ctx);
19426 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
19427 gen_store_gpr(v0_t, ret);
19428 break;
19429 case NM_PRECEQ_W_PHL:
19430 check_dsp(ctx);
19431 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
19432 tcg_gen_ext32s_tl(v0_t, v0_t);
19433 gen_store_gpr(v0_t, ret);
19434 break;
19435 case NM_PRECEQ_W_PHR:
19436 check_dsp(ctx);
19437 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
19438 tcg_gen_shli_tl(v0_t, v0_t, 16);
19439 tcg_gen_ext32s_tl(v0_t, v0_t);
19440 gen_store_gpr(v0_t, ret);
19441 break;
19442 case NM_PRECEQU_PH_QBL:
19443 check_dsp(ctx);
19444 gen_helper_precequ_ph_qbl(v0_t, v0_t);
19445 gen_store_gpr(v0_t, ret);
19446 break;
19447 case NM_PRECEQU_PH_QBR:
19448 check_dsp(ctx);
19449 gen_helper_precequ_ph_qbr(v0_t, v0_t);
19450 gen_store_gpr(v0_t, ret);
19451 break;
19452 case NM_PRECEQU_PH_QBLA:
19453 check_dsp(ctx);
19454 gen_helper_precequ_ph_qbla(v0_t, v0_t);
19455 gen_store_gpr(v0_t, ret);
19456 break;
19457 case NM_PRECEQU_PH_QBRA:
19458 check_dsp(ctx);
19459 gen_helper_precequ_ph_qbra(v0_t, v0_t);
19460 gen_store_gpr(v0_t, ret);
19461 break;
19462 case NM_PRECEU_PH_QBL:
19463 check_dsp(ctx);
19464 gen_helper_preceu_ph_qbl(v0_t, v0_t);
19465 gen_store_gpr(v0_t, ret);
19466 break;
19467 case NM_PRECEU_PH_QBR:
19468 check_dsp(ctx);
19469 gen_helper_preceu_ph_qbr(v0_t, v0_t);
19470 gen_store_gpr(v0_t, ret);
19471 break;
19472 case NM_PRECEU_PH_QBLA:
19473 check_dsp(ctx);
19474 gen_helper_preceu_ph_qbla(v0_t, v0_t);
19475 gen_store_gpr(v0_t, ret);
19476 break;
19477 case NM_PRECEU_PH_QBRA:
19478 check_dsp(ctx);
19479 gen_helper_preceu_ph_qbra(v0_t, v0_t);
19480 gen_store_gpr(v0_t, ret);
19481 break;
19482 case NM_REPLV_PH:
19483 check_dsp(ctx);
19484 tcg_gen_ext16u_tl(v0_t, v0_t);
19485 tcg_gen_shli_tl(t0, v0_t, 16);
19486 tcg_gen_or_tl(v0_t, v0_t, t0);
19487 tcg_gen_ext32s_tl(v0_t, v0_t);
19488 gen_store_gpr(v0_t, ret);
19489 break;
19490 case NM_REPLV_QB:
19491 check_dsp(ctx);
19492 tcg_gen_ext8u_tl(v0_t, v0_t);
19493 tcg_gen_shli_tl(t0, v0_t, 8);
19494 tcg_gen_or_tl(v0_t, v0_t, t0);
19495 tcg_gen_shli_tl(t0, v0_t, 16);
19496 tcg_gen_or_tl(v0_t, v0_t, t0);
19497 tcg_gen_ext32s_tl(v0_t, v0_t);
19498 gen_store_gpr(v0_t, ret);
19499 break;
19500 case NM_BITREV:
19501 check_dsp(ctx);
19502 gen_helper_bitrev(v0_t, v0_t);
19503 gen_store_gpr(v0_t, ret);
19504 break;
19505 case NM_INSV:
19506 check_dsp(ctx);
19507 {
19508 TCGv tv0 = tcg_temp_new();
19509
19510 gen_load_gpr(tv0, rt);
19511 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
19512 gen_store_gpr(v0_t, ret);
19513 tcg_temp_free(tv0);
19514 }
19515 break;
19516 case NM_RADDU_W_QB:
19517 check_dsp(ctx);
19518 gen_helper_raddu_w_qb(v0_t, v0_t);
19519 gen_store_gpr(v0_t, ret);
19520 break;
19521 case NM_BITSWAP:
19522 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
19523 break;
19524 case NM_CLO:
19525 check_nms(ctx);
19526 gen_cl(ctx, OPC_CLO, ret, rs);
19527 break;
19528 case NM_CLZ:
19529 check_nms(ctx);
19530 gen_cl(ctx, OPC_CLZ, ret, rs);
19531 break;
19532 case NM_WSBH:
19533 gen_bshfl(ctx, OPC_WSBH, ret, rs);
19534 break;
19535 default:
19536 generate_exception_end(ctx, EXCP_RI);
19537 break;
19538 }
19539
19540 tcg_temp_free(v0_t);
19541 tcg_temp_free(t0);
19542 }
19543
19544 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
19545 int rt, int rs, int rd)
19546 {
19547 TCGv t0 = tcg_temp_new();
19548 TCGv rs_t = tcg_temp_new();
19549
19550 gen_load_gpr(rs_t, rs);
19551
19552 switch (opc) {
19553 case NM_SHRA_R_QB:
19554 check_dsp_r2(ctx);
19555 tcg_gen_movi_tl(t0, rd >> 2);
19556 switch (extract32(ctx->opcode, 12, 1)) {
19557 case 0:
19558 /* NM_SHRA_QB */
19559 gen_helper_shra_qb(t0, t0, rs_t);
19560 gen_store_gpr(t0, rt);
19561 break;
19562 case 1:
19563 /* NM_SHRA_R_QB */
19564 gen_helper_shra_r_qb(t0, t0, rs_t);
19565 gen_store_gpr(t0, rt);
19566 break;
19567 }
19568 break;
19569 case NM_SHRL_PH:
19570 check_dsp_r2(ctx);
19571 tcg_gen_movi_tl(t0, rd >> 1);
19572 gen_helper_shrl_ph(t0, t0, rs_t);
19573 gen_store_gpr(t0, rt);
19574 break;
19575 case NM_REPL_QB:
19576 check_dsp(ctx);
19577 {
19578 int16_t imm;
19579 target_long result;
19580 imm = extract32(ctx->opcode, 13, 8);
19581 result = (uint32_t)imm << 24 |
19582 (uint32_t)imm << 16 |
19583 (uint32_t)imm << 8 |
19584 (uint32_t)imm;
19585 result = (int32_t)result;
19586 tcg_gen_movi_tl(t0, result);
19587 gen_store_gpr(t0, rt);
19588 }
19589 break;
19590 default:
19591 generate_exception_end(ctx, EXCP_RI);
19592 break;
19593 }
19594 tcg_temp_free(t0);
19595 tcg_temp_free(rs_t);
19596 }
19597
19598
19599 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19600 {
19601 int rt = extract32(ctx->opcode, 21, 5);
19602 int rs = extract32(ctx->opcode, 16, 5);
19603 int rd = extract32(ctx->opcode, 11, 5);
19604
19605 switch (extract32(ctx->opcode, 6, 3)) {
19606 case NM_POOL32AXF_1:
19607 {
19608 int32_t op1 = extract32(ctx->opcode, 9, 3);
19609 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
19610 }
19611 break;
19612 case NM_POOL32AXF_2:
19613 {
19614 int32_t op1 = extract32(ctx->opcode, 12, 2);
19615 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
19616 }
19617 break;
19618 case NM_POOL32AXF_4:
19619 {
19620 int32_t op1 = extract32(ctx->opcode, 9, 7);
19621 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
19622 }
19623 break;
19624 case NM_POOL32AXF_5:
19625 switch (extract32(ctx->opcode, 9, 7)) {
19626 #ifndef CONFIG_USER_ONLY
19627 case NM_TLBP:
19628 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
19629 break;
19630 case NM_TLBR:
19631 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
19632 break;
19633 case NM_TLBWI:
19634 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
19635 break;
19636 case NM_TLBWR:
19637 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
19638 break;
19639 case NM_TLBINV:
19640 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
19641 break;
19642 case NM_TLBINVF:
19643 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
19644 break;
19645 case NM_DI:
19646 check_cp0_enabled(ctx);
19647 {
19648 TCGv t0 = tcg_temp_new();
19649
19650 save_cpu_state(ctx, 1);
19651 gen_helper_di(t0, cpu_env);
19652 gen_store_gpr(t0, rt);
19653 /* Stop translation as we may have switched the execution mode */
19654 ctx->base.is_jmp = DISAS_STOP;
19655 tcg_temp_free(t0);
19656 }
19657 break;
19658 case NM_EI:
19659 check_cp0_enabled(ctx);
19660 {
19661 TCGv t0 = tcg_temp_new();
19662
19663 save_cpu_state(ctx, 1);
19664 gen_helper_ei(t0, cpu_env);
19665 gen_store_gpr(t0, rt);
19666 /* Stop translation as we may have switched the execution mode */
19667 ctx->base.is_jmp = DISAS_STOP;
19668 tcg_temp_free(t0);
19669 }
19670 break;
19671 case NM_RDPGPR:
19672 gen_load_srsgpr(rs, rt);
19673 break;
19674 case NM_WRPGPR:
19675 gen_store_srsgpr(rs, rt);
19676 break;
19677 case NM_WAIT:
19678 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
19679 break;
19680 case NM_DERET:
19681 gen_cp0(env, ctx, OPC_DERET, 0, 0);
19682 break;
19683 case NM_ERETX:
19684 gen_cp0(env, ctx, OPC_ERET, 0, 0);
19685 break;
19686 #endif
19687 default:
19688 generate_exception_end(ctx, EXCP_RI);
19689 break;
19690 }
19691 break;
19692 case NM_POOL32AXF_7:
19693 {
19694 int32_t op1 = extract32(ctx->opcode, 9, 3);
19695 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
19696 }
19697 break;
19698 default:
19699 generate_exception_end(ctx, EXCP_RI);
19700 break;
19701 }
19702 }
19703
19704 /* Immediate Value Compact Branches */
19705 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
19706 int rt, int32_t imm, int32_t offset)
19707 {
19708 TCGCond cond;
19709 int bcond_compute = 0;
19710 TCGv t0 = tcg_temp_new();
19711 TCGv t1 = tcg_temp_new();
19712
19713 gen_load_gpr(t0, rt);
19714 tcg_gen_movi_tl(t1, imm);
19715 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19716
19717 /* Load needed operands and calculate btarget */
19718 switch (opc) {
19719 case NM_BEQIC:
19720 if (rt == 0 && imm == 0) {
19721 /* Unconditional branch */
19722 } else if (rt == 0 && imm != 0) {
19723 /* Treat as NOP */
19724 goto out;
19725 } else {
19726 bcond_compute = 1;
19727 cond = TCG_COND_EQ;
19728 }
19729 break;
19730 case NM_BBEQZC:
19731 case NM_BBNEZC:
19732 check_nms(ctx);
19733 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
19734 generate_exception_end(ctx, EXCP_RI);
19735 goto out;
19736 } else if (rt == 0 && opc == NM_BBEQZC) {
19737 /* Unconditional branch */
19738 } else if (rt == 0 && opc == NM_BBNEZC) {
19739 /* Treat as NOP */
19740 goto out;
19741 } else {
19742 tcg_gen_shri_tl(t0, t0, imm);
19743 tcg_gen_andi_tl(t0, t0, 1);
19744 tcg_gen_movi_tl(t1, 0);
19745 bcond_compute = 1;
19746 if (opc == NM_BBEQZC) {
19747 cond = TCG_COND_EQ;
19748 } else {
19749 cond = TCG_COND_NE;
19750 }
19751 }
19752 break;
19753 case NM_BNEIC:
19754 if (rt == 0 && imm == 0) {
19755 /* Treat as NOP */
19756 goto out;
19757 } else if (rt == 0 && imm != 0) {
19758 /* Unconditional branch */
19759 } else {
19760 bcond_compute = 1;
19761 cond = TCG_COND_NE;
19762 }
19763 break;
19764 case NM_BGEIC:
19765 if (rt == 0 && imm == 0) {
19766 /* Unconditional branch */
19767 } else {
19768 bcond_compute = 1;
19769 cond = TCG_COND_GE;
19770 }
19771 break;
19772 case NM_BLTIC:
19773 bcond_compute = 1;
19774 cond = TCG_COND_LT;
19775 break;
19776 case NM_BGEIUC:
19777 if (rt == 0 && imm == 0) {
19778 /* Unconditional branch */
19779 } else {
19780 bcond_compute = 1;
19781 cond = TCG_COND_GEU;
19782 }
19783 break;
19784 case NM_BLTIUC:
19785 bcond_compute = 1;
19786 cond = TCG_COND_LTU;
19787 break;
19788 default:
19789 MIPS_INVAL("Immediate Value Compact branch");
19790 generate_exception_end(ctx, EXCP_RI);
19791 goto out;
19792 }
19793
19794 /* branch completion */
19795 clear_branch_hflags(ctx);
19796 ctx->base.is_jmp = DISAS_NORETURN;
19797
19798 if (bcond_compute == 0) {
19799 /* Uncoditional compact branch */
19800 gen_goto_tb(ctx, 0, ctx->btarget);
19801 } else {
19802 /* Conditional compact branch */
19803 TCGLabel *fs = gen_new_label();
19804
19805 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
19806
19807 gen_goto_tb(ctx, 1, ctx->btarget);
19808 gen_set_label(fs);
19809
19810 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19811 }
19812
19813 out:
19814 tcg_temp_free(t0);
19815 tcg_temp_free(t1);
19816 }
19817
19818 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
19819 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
19820 int rt)
19821 {
19822 TCGv t0 = tcg_temp_new();
19823 TCGv t1 = tcg_temp_new();
19824
19825 /* load rs */
19826 gen_load_gpr(t0, rs);
19827
19828 /* link */
19829 if (rt != 0) {
19830 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
19831 }
19832
19833 /* calculate btarget */
19834 tcg_gen_shli_tl(t0, t0, 1);
19835 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
19836 gen_op_addr_add(ctx, btarget, t1, t0);
19837
19838 /* branch completion */
19839 clear_branch_hflags(ctx);
19840 ctx->base.is_jmp = DISAS_NORETURN;
19841
19842 /* unconditional branch to register */
19843 tcg_gen_mov_tl(cpu_PC, btarget);
19844 tcg_gen_lookup_and_goto_ptr();
19845
19846 tcg_temp_free(t0);
19847 tcg_temp_free(t1);
19848 }
19849
19850 /* nanoMIPS Branches */
19851 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
19852 int rs, int rt, int32_t offset)
19853 {
19854 int bcond_compute = 0;
19855 TCGv t0 = tcg_temp_new();
19856 TCGv t1 = tcg_temp_new();
19857
19858 /* Load needed operands and calculate btarget */
19859 switch (opc) {
19860 /* compact branch */
19861 case OPC_BGEC:
19862 case OPC_BLTC:
19863 gen_load_gpr(t0, rs);
19864 gen_load_gpr(t1, rt);
19865 bcond_compute = 1;
19866 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19867 break;
19868 case OPC_BGEUC:
19869 case OPC_BLTUC:
19870 if (rs == 0 || rs == rt) {
19871 /* OPC_BLEZALC, OPC_BGEZALC */
19872 /* OPC_BGTZALC, OPC_BLTZALC */
19873 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
19874 }
19875 gen_load_gpr(t0, rs);
19876 gen_load_gpr(t1, rt);
19877 bcond_compute = 1;
19878 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19879 break;
19880 case OPC_BC:
19881 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19882 break;
19883 case OPC_BEQZC:
19884 if (rs != 0) {
19885 /* OPC_BEQZC, OPC_BNEZC */
19886 gen_load_gpr(t0, rs);
19887 bcond_compute = 1;
19888 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19889 } else {
19890 /* OPC_JIC, OPC_JIALC */
19891 TCGv tbase = tcg_temp_new();
19892 TCGv toffset = tcg_temp_new();
19893
19894 gen_load_gpr(tbase, rt);
19895 tcg_gen_movi_tl(toffset, offset);
19896 gen_op_addr_add(ctx, btarget, tbase, toffset);
19897 tcg_temp_free(tbase);
19898 tcg_temp_free(toffset);
19899 }
19900 break;
19901 default:
19902 MIPS_INVAL("Compact branch/jump");
19903 generate_exception_end(ctx, EXCP_RI);
19904 goto out;
19905 }
19906
19907 if (bcond_compute == 0) {
19908 /* Uncoditional compact branch */
19909 switch (opc) {
19910 case OPC_BC:
19911 gen_goto_tb(ctx, 0, ctx->btarget);
19912 break;
19913 default:
19914 MIPS_INVAL("Compact branch/jump");
19915 generate_exception_end(ctx, EXCP_RI);
19916 goto out;
19917 }
19918 } else {
19919 /* Conditional compact branch */
19920 TCGLabel *fs = gen_new_label();
19921
19922 switch (opc) {
19923 case OPC_BGEUC:
19924 if (rs == 0 && rt != 0) {
19925 /* OPC_BLEZALC */
19926 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19927 } else if (rs != 0 && rt != 0 && rs == rt) {
19928 /* OPC_BGEZALC */
19929 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19930 } else {
19931 /* OPC_BGEUC */
19932 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
19933 }
19934 break;
19935 case OPC_BLTUC:
19936 if (rs == 0 && rt != 0) {
19937 /* OPC_BGTZALC */
19938 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19939 } else if (rs != 0 && rt != 0 && rs == rt) {
19940 /* OPC_BLTZALC */
19941 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19942 } else {
19943 /* OPC_BLTUC */
19944 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
19945 }
19946 break;
19947 case OPC_BGEC:
19948 if (rs == 0 && rt != 0) {
19949 /* OPC_BLEZC */
19950 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19951 } else if (rs != 0 && rt != 0 && rs == rt) {
19952 /* OPC_BGEZC */
19953 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19954 } else {
19955 /* OPC_BGEC */
19956 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
19957 }
19958 break;
19959 case OPC_BLTC:
19960 if (rs == 0 && rt != 0) {
19961 /* OPC_BGTZC */
19962 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19963 } else if (rs != 0 && rt != 0 && rs == rt) {
19964 /* OPC_BLTZC */
19965 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19966 } else {
19967 /* OPC_BLTC */
19968 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
19969 }
19970 break;
19971 case OPC_BEQZC:
19972 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
19973 break;
19974 default:
19975 MIPS_INVAL("Compact conditional branch/jump");
19976 generate_exception_end(ctx, EXCP_RI);
19977 goto out;
19978 }
19979
19980 /* branch completion */
19981 clear_branch_hflags(ctx);
19982 ctx->base.is_jmp = DISAS_NORETURN;
19983
19984 /* Generating branch here as compact branches don't have delay slot */
19985 gen_goto_tb(ctx, 1, ctx->btarget);
19986 gen_set_label(fs);
19987
19988 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19989 }
19990
19991 out:
19992 tcg_temp_free(t0);
19993 tcg_temp_free(t1);
19994 }
19995
19996
19997 /* nanoMIPS CP1 Branches */
19998 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
19999 int32_t ft, int32_t offset)
20000 {
20001 target_ulong btarget;
20002 TCGv_i64 t0 = tcg_temp_new_i64();
20003
20004 gen_load_fpr64(ctx, t0, ft);
20005 tcg_gen_andi_i64(t0, t0, 1);
20006
20007 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20008
20009 switch (op) {
20010 case NM_BC1EQZC:
20011 tcg_gen_xori_i64(t0, t0, 1);
20012 ctx->hflags |= MIPS_HFLAG_BC;
20013 break;
20014 case NM_BC1NEZC:
20015 /* t0 already set */
20016 ctx->hflags |= MIPS_HFLAG_BC;
20017 break;
20018 default:
20019 MIPS_INVAL("cp1 cond branch");
20020 generate_exception_end(ctx, EXCP_RI);
20021 goto out;
20022 }
20023
20024 tcg_gen_trunc_i64_tl(bcond, t0);
20025
20026 ctx->btarget = btarget;
20027
20028 out:
20029 tcg_temp_free_i64(t0);
20030 }
20031
20032
20033 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
20034 {
20035 TCGv t0, t1;
20036 t0 = tcg_temp_new();
20037 t1 = tcg_temp_new();
20038
20039 gen_load_gpr(t0, rs);
20040 gen_load_gpr(t1, rt);
20041
20042 if ((extract32(ctx->opcode, 6, 1)) == 1) {
20043 /* PP.LSXS instructions require shifting */
20044 switch (extract32(ctx->opcode, 7, 4)) {
20045 case NM_SHXS:
20046 check_nms(ctx);
20047 case NM_LHXS:
20048 case NM_LHUXS:
20049 tcg_gen_shli_tl(t0, t0, 1);
20050 break;
20051 case NM_SWXS:
20052 check_nms(ctx);
20053 case NM_LWXS:
20054 case NM_LWC1XS:
20055 case NM_SWC1XS:
20056 tcg_gen_shli_tl(t0, t0, 2);
20057 break;
20058 case NM_LDC1XS:
20059 case NM_SDC1XS:
20060 tcg_gen_shli_tl(t0, t0, 3);
20061 break;
20062 }
20063 }
20064 gen_op_addr_add(ctx, t0, t0, t1);
20065
20066 switch (extract32(ctx->opcode, 7, 4)) {
20067 case NM_LBX:
20068 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20069 MO_SB);
20070 gen_store_gpr(t0, rd);
20071 break;
20072 case NM_LHX:
20073 /*case NM_LHXS:*/
20074 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20075 MO_TESW);
20076 gen_store_gpr(t0, rd);
20077 break;
20078 case NM_LWX:
20079 /*case NM_LWXS:*/
20080 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20081 MO_TESL);
20082 gen_store_gpr(t0, rd);
20083 break;
20084 case NM_LBUX:
20085 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20086 MO_UB);
20087 gen_store_gpr(t0, rd);
20088 break;
20089 case NM_LHUX:
20090 /*case NM_LHUXS:*/
20091 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20092 MO_TEUW);
20093 gen_store_gpr(t0, rd);
20094 break;
20095 case NM_SBX:
20096 check_nms(ctx);
20097 gen_load_gpr(t1, rd);
20098 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20099 MO_8);
20100 break;
20101 case NM_SHX:
20102 /*case NM_SHXS:*/
20103 check_nms(ctx);
20104 gen_load_gpr(t1, rd);
20105 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20106 MO_TEUW);
20107 break;
20108 case NM_SWX:
20109 /*case NM_SWXS:*/
20110 check_nms(ctx);
20111 gen_load_gpr(t1, rd);
20112 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20113 MO_TEUL);
20114 break;
20115 case NM_LWC1X:
20116 /*case NM_LWC1XS:*/
20117 case NM_LDC1X:
20118 /*case NM_LDC1XS:*/
20119 case NM_SWC1X:
20120 /*case NM_SWC1XS:*/
20121 case NM_SDC1X:
20122 /*case NM_SDC1XS:*/
20123 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
20124 check_cp1_enabled(ctx);
20125 switch (extract32(ctx->opcode, 7, 4)) {
20126 case NM_LWC1X:
20127 /*case NM_LWC1XS:*/
20128 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
20129 break;
20130 case NM_LDC1X:
20131 /*case NM_LDC1XS:*/
20132 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
20133 break;
20134 case NM_SWC1X:
20135 /*case NM_SWC1XS:*/
20136 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
20137 break;
20138 case NM_SDC1X:
20139 /*case NM_SDC1XS:*/
20140 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
20141 break;
20142 }
20143 } else {
20144 generate_exception_err(ctx, EXCP_CpU, 1);
20145 }
20146 break;
20147 default:
20148 generate_exception_end(ctx, EXCP_RI);
20149 break;
20150 }
20151
20152 tcg_temp_free(t0);
20153 tcg_temp_free(t1);
20154 }
20155
20156 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
20157 {
20158 int rt, rs, rd;
20159
20160 rt = extract32(ctx->opcode, 21, 5);
20161 rs = extract32(ctx->opcode, 16, 5);
20162 rd = extract32(ctx->opcode, 11, 5);
20163
20164 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
20165 generate_exception_end(ctx, EXCP_RI);
20166 return;
20167 }
20168 check_cp1_enabled(ctx);
20169 switch (extract32(ctx->opcode, 0, 3)) {
20170 case NM_POOL32F_0:
20171 switch (extract32(ctx->opcode, 3, 7)) {
20172 case NM_RINT_S:
20173 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
20174 break;
20175 case NM_RINT_D:
20176 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
20177 break;
20178 case NM_CLASS_S:
20179 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
20180 break;
20181 case NM_CLASS_D:
20182 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
20183 break;
20184 case NM_ADD_S:
20185 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
20186 break;
20187 case NM_ADD_D:
20188 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
20189 break;
20190 case NM_SUB_S:
20191 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
20192 break;
20193 case NM_SUB_D:
20194 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
20195 break;
20196 case NM_MUL_S:
20197 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
20198 break;
20199 case NM_MUL_D:
20200 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
20201 break;
20202 case NM_DIV_S:
20203 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
20204 break;
20205 case NM_DIV_D:
20206 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
20207 break;
20208 case NM_SELEQZ_S:
20209 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
20210 break;
20211 case NM_SELEQZ_D:
20212 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
20213 break;
20214 case NM_SELNEZ_S:
20215 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
20216 break;
20217 case NM_SELNEZ_D:
20218 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
20219 break;
20220 case NM_SEL_S:
20221 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
20222 break;
20223 case NM_SEL_D:
20224 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
20225 break;
20226 case NM_MADDF_S:
20227 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
20228 break;
20229 case NM_MADDF_D:
20230 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
20231 break;
20232 case NM_MSUBF_S:
20233 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
20234 break;
20235 case NM_MSUBF_D:
20236 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
20237 break;
20238 default:
20239 generate_exception_end(ctx, EXCP_RI);
20240 break;
20241 }
20242 break;
20243 case NM_POOL32F_3:
20244 switch (extract32(ctx->opcode, 3, 3)) {
20245 case NM_MIN_FMT:
20246 switch (extract32(ctx->opcode, 9, 1)) {
20247 case FMT_SDPS_S:
20248 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
20249 break;
20250 case FMT_SDPS_D:
20251 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
20252 break;
20253 }
20254 break;
20255 case NM_MAX_FMT:
20256 switch (extract32(ctx->opcode, 9, 1)) {
20257 case FMT_SDPS_S:
20258 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
20259 break;
20260 case FMT_SDPS_D:
20261 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
20262 break;
20263 }
20264 break;
20265 case NM_MINA_FMT:
20266 switch (extract32(ctx->opcode, 9, 1)) {
20267 case FMT_SDPS_S:
20268 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
20269 break;
20270 case FMT_SDPS_D:
20271 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
20272 break;
20273 }
20274 break;
20275 case NM_MAXA_FMT:
20276 switch (extract32(ctx->opcode, 9, 1)) {
20277 case FMT_SDPS_S:
20278 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
20279 break;
20280 case FMT_SDPS_D:
20281 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
20282 break;
20283 }
20284 break;
20285 case NM_POOL32FXF:
20286 switch (extract32(ctx->opcode, 6, 8)) {
20287 case NM_CFC1:
20288 gen_cp1(ctx, OPC_CFC1, rt, rs);
20289 break;
20290 case NM_CTC1:
20291 gen_cp1(ctx, OPC_CTC1, rt, rs);
20292 break;
20293 case NM_MFC1:
20294 gen_cp1(ctx, OPC_MFC1, rt, rs);
20295 break;
20296 case NM_MTC1:
20297 gen_cp1(ctx, OPC_MTC1, rt, rs);
20298 break;
20299 case NM_MFHC1:
20300 gen_cp1(ctx, OPC_MFHC1, rt, rs);
20301 break;
20302 case NM_MTHC1:
20303 gen_cp1(ctx, OPC_MTHC1, rt, rs);
20304 break;
20305 case NM_CVT_S_PL:
20306 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
20307 break;
20308 case NM_CVT_S_PU:
20309 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
20310 break;
20311 default:
20312 switch (extract32(ctx->opcode, 6, 9)) {
20313 case NM_CVT_L_S:
20314 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
20315 break;
20316 case NM_CVT_L_D:
20317 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
20318 break;
20319 case NM_CVT_W_S:
20320 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
20321 break;
20322 case NM_CVT_W_D:
20323 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
20324 break;
20325 case NM_RSQRT_S:
20326 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
20327 break;
20328 case NM_RSQRT_D:
20329 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
20330 break;
20331 case NM_SQRT_S:
20332 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
20333 break;
20334 case NM_SQRT_D:
20335 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
20336 break;
20337 case NM_RECIP_S:
20338 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
20339 break;
20340 case NM_RECIP_D:
20341 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
20342 break;
20343 case NM_FLOOR_L_S:
20344 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
20345 break;
20346 case NM_FLOOR_L_D:
20347 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
20348 break;
20349 case NM_FLOOR_W_S:
20350 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
20351 break;
20352 case NM_FLOOR_W_D:
20353 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
20354 break;
20355 case NM_CEIL_L_S:
20356 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
20357 break;
20358 case NM_CEIL_L_D:
20359 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
20360 break;
20361 case NM_CEIL_W_S:
20362 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
20363 break;
20364 case NM_CEIL_W_D:
20365 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
20366 break;
20367 case NM_TRUNC_L_S:
20368 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
20369 break;
20370 case NM_TRUNC_L_D:
20371 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
20372 break;
20373 case NM_TRUNC_W_S:
20374 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
20375 break;
20376 case NM_TRUNC_W_D:
20377 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
20378 break;
20379 case NM_ROUND_L_S:
20380 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
20381 break;
20382 case NM_ROUND_L_D:
20383 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
20384 break;
20385 case NM_ROUND_W_S:
20386 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
20387 break;
20388 case NM_ROUND_W_D:
20389 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
20390 break;
20391 case NM_MOV_S:
20392 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
20393 break;
20394 case NM_MOV_D:
20395 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
20396 break;
20397 case NM_ABS_S:
20398 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
20399 break;
20400 case NM_ABS_D:
20401 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
20402 break;
20403 case NM_NEG_S:
20404 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
20405 break;
20406 case NM_NEG_D:
20407 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
20408 break;
20409 case NM_CVT_D_S:
20410 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
20411 break;
20412 case NM_CVT_D_W:
20413 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
20414 break;
20415 case NM_CVT_D_L:
20416 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
20417 break;
20418 case NM_CVT_S_D:
20419 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
20420 break;
20421 case NM_CVT_S_W:
20422 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
20423 break;
20424 case NM_CVT_S_L:
20425 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
20426 break;
20427 default:
20428 generate_exception_end(ctx, EXCP_RI);
20429 break;
20430 }
20431 break;
20432 }
20433 break;
20434 }
20435 break;
20436 case NM_POOL32F_5:
20437 switch (extract32(ctx->opcode, 3, 3)) {
20438 case NM_CMP_CONDN_S:
20439 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20440 break;
20441 case NM_CMP_CONDN_D:
20442 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20443 break;
20444 default:
20445 generate_exception_end(ctx, EXCP_RI);
20446 break;
20447 }
20448 break;
20449 default:
20450 generate_exception_end(ctx, EXCP_RI);
20451 break;
20452 }
20453 }
20454
20455 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
20456 int rd, int rs, int rt)
20457 {
20458 int ret = rd;
20459 TCGv t0 = tcg_temp_new();
20460 TCGv v1_t = tcg_temp_new();
20461 TCGv v2_t = tcg_temp_new();
20462
20463 gen_load_gpr(v1_t, rs);
20464 gen_load_gpr(v2_t, rt);
20465
20466 switch (opc) {
20467 case NM_CMP_EQ_PH:
20468 check_dsp(ctx);
20469 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
20470 break;
20471 case NM_CMP_LT_PH:
20472 check_dsp(ctx);
20473 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
20474 break;
20475 case NM_CMP_LE_PH:
20476 check_dsp(ctx);
20477 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
20478 break;
20479 case NM_CMPU_EQ_QB:
20480 check_dsp(ctx);
20481 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
20482 break;
20483 case NM_CMPU_LT_QB:
20484 check_dsp(ctx);
20485 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
20486 break;
20487 case NM_CMPU_LE_QB:
20488 check_dsp(ctx);
20489 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
20490 break;
20491 case NM_CMPGU_EQ_QB:
20492 check_dsp(ctx);
20493 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20494 gen_store_gpr(v1_t, ret);
20495 break;
20496 case NM_CMPGU_LT_QB:
20497 check_dsp(ctx);
20498 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20499 gen_store_gpr(v1_t, ret);
20500 break;
20501 case NM_CMPGU_LE_QB:
20502 check_dsp(ctx);
20503 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20504 gen_store_gpr(v1_t, ret);
20505 break;
20506 case NM_CMPGDU_EQ_QB:
20507 check_dsp_r2(ctx);
20508 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20509 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20510 gen_store_gpr(v1_t, ret);
20511 break;
20512 case NM_CMPGDU_LT_QB:
20513 check_dsp_r2(ctx);
20514 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20515 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20516 gen_store_gpr(v1_t, ret);
20517 break;
20518 case NM_CMPGDU_LE_QB:
20519 check_dsp_r2(ctx);
20520 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20521 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20522 gen_store_gpr(v1_t, ret);
20523 break;
20524 case NM_PACKRL_PH:
20525 check_dsp(ctx);
20526 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
20527 gen_store_gpr(v1_t, ret);
20528 break;
20529 case NM_PICK_QB:
20530 check_dsp(ctx);
20531 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
20532 gen_store_gpr(v1_t, ret);
20533 break;
20534 case NM_PICK_PH:
20535 check_dsp(ctx);
20536 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
20537 gen_store_gpr(v1_t, ret);
20538 break;
20539 case NM_ADDQ_S_W:
20540 check_dsp(ctx);
20541 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
20542 gen_store_gpr(v1_t, ret);
20543 break;
20544 case NM_SUBQ_S_W:
20545 check_dsp(ctx);
20546 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
20547 gen_store_gpr(v1_t, ret);
20548 break;
20549 case NM_ADDSC:
20550 check_dsp(ctx);
20551 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
20552 gen_store_gpr(v1_t, ret);
20553 break;
20554 case NM_ADDWC:
20555 check_dsp(ctx);
20556 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
20557 gen_store_gpr(v1_t, ret);
20558 break;
20559 case NM_ADDQ_S_PH:
20560 check_dsp(ctx);
20561 switch (extract32(ctx->opcode, 10, 1)) {
20562 case 0:
20563 /* ADDQ_PH */
20564 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
20565 gen_store_gpr(v1_t, ret);
20566 break;
20567 case 1:
20568 /* ADDQ_S_PH */
20569 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20570 gen_store_gpr(v1_t, ret);
20571 break;
20572 }
20573 break;
20574 case NM_ADDQH_R_PH:
20575 check_dsp_r2(ctx);
20576 switch (extract32(ctx->opcode, 10, 1)) {
20577 case 0:
20578 /* ADDQH_PH */
20579 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
20580 gen_store_gpr(v1_t, ret);
20581 break;
20582 case 1:
20583 /* ADDQH_R_PH */
20584 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
20585 gen_store_gpr(v1_t, ret);
20586 break;
20587 }
20588 break;
20589 case NM_ADDQH_R_W:
20590 check_dsp_r2(ctx);
20591 switch (extract32(ctx->opcode, 10, 1)) {
20592 case 0:
20593 /* ADDQH_W */
20594 gen_helper_addqh_w(v1_t, v1_t, v2_t);
20595 gen_store_gpr(v1_t, ret);
20596 break;
20597 case 1:
20598 /* ADDQH_R_W */
20599 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
20600 gen_store_gpr(v1_t, ret);
20601 break;
20602 }
20603 break;
20604 case NM_ADDU_S_QB:
20605 check_dsp(ctx);
20606 switch (extract32(ctx->opcode, 10, 1)) {
20607 case 0:
20608 /* ADDU_QB */
20609 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
20610 gen_store_gpr(v1_t, ret);
20611 break;
20612 case 1:
20613 /* ADDU_S_QB */
20614 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20615 gen_store_gpr(v1_t, ret);
20616 break;
20617 }
20618 break;
20619 case NM_ADDU_S_PH:
20620 check_dsp_r2(ctx);
20621 switch (extract32(ctx->opcode, 10, 1)) {
20622 case 0:
20623 /* ADDU_PH */
20624 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
20625 gen_store_gpr(v1_t, ret);
20626 break;
20627 case 1:
20628 /* ADDU_S_PH */
20629 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20630 gen_store_gpr(v1_t, ret);
20631 break;
20632 }
20633 break;
20634 case NM_ADDUH_R_QB:
20635 check_dsp_r2(ctx);
20636 switch (extract32(ctx->opcode, 10, 1)) {
20637 case 0:
20638 /* ADDUH_QB */
20639 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
20640 gen_store_gpr(v1_t, ret);
20641 break;
20642 case 1:
20643 /* ADDUH_R_QB */
20644 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
20645 gen_store_gpr(v1_t, ret);
20646 break;
20647 }
20648 break;
20649 case NM_SHRAV_R_PH:
20650 check_dsp(ctx);
20651 switch (extract32(ctx->opcode, 10, 1)) {
20652 case 0:
20653 /* SHRAV_PH */
20654 gen_helper_shra_ph(v1_t, v1_t, v2_t);
20655 gen_store_gpr(v1_t, ret);
20656 break;
20657 case 1:
20658 /* SHRAV_R_PH */
20659 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
20660 gen_store_gpr(v1_t, ret);
20661 break;
20662 }
20663 break;
20664 case NM_SHRAV_R_QB:
20665 check_dsp_r2(ctx);
20666 switch (extract32(ctx->opcode, 10, 1)) {
20667 case 0:
20668 /* SHRAV_QB */
20669 gen_helper_shra_qb(v1_t, v1_t, v2_t);
20670 gen_store_gpr(v1_t, ret);
20671 break;
20672 case 1:
20673 /* SHRAV_R_QB */
20674 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
20675 gen_store_gpr(v1_t, ret);
20676 break;
20677 }
20678 break;
20679 case NM_SUBQ_S_PH:
20680 check_dsp(ctx);
20681 switch (extract32(ctx->opcode, 10, 1)) {
20682 case 0:
20683 /* SUBQ_PH */
20684 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
20685 gen_store_gpr(v1_t, ret);
20686 break;
20687 case 1:
20688 /* SUBQ_S_PH */
20689 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20690 gen_store_gpr(v1_t, ret);
20691 break;
20692 }
20693 break;
20694 case NM_SUBQH_R_PH:
20695 check_dsp_r2(ctx);
20696 switch (extract32(ctx->opcode, 10, 1)) {
20697 case 0:
20698 /* SUBQH_PH */
20699 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
20700 gen_store_gpr(v1_t, ret);
20701 break;
20702 case 1:
20703 /* SUBQH_R_PH */
20704 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
20705 gen_store_gpr(v1_t, ret);
20706 break;
20707 }
20708 break;
20709 case NM_SUBQH_R_W:
20710 check_dsp_r2(ctx);
20711 switch (extract32(ctx->opcode, 10, 1)) {
20712 case 0:
20713 /* SUBQH_W */
20714 gen_helper_subqh_w(v1_t, v1_t, v2_t);
20715 gen_store_gpr(v1_t, ret);
20716 break;
20717 case 1:
20718 /* SUBQH_R_W */
20719 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
20720 gen_store_gpr(v1_t, ret);
20721 break;
20722 }
20723 break;
20724 case NM_SUBU_S_QB:
20725 check_dsp(ctx);
20726 switch (extract32(ctx->opcode, 10, 1)) {
20727 case 0:
20728 /* SUBU_QB */
20729 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
20730 gen_store_gpr(v1_t, ret);
20731 break;
20732 case 1:
20733 /* SUBU_S_QB */
20734 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20735 gen_store_gpr(v1_t, ret);
20736 break;
20737 }
20738 break;
20739 case NM_SUBU_S_PH:
20740 check_dsp_r2(ctx);
20741 switch (extract32(ctx->opcode, 10, 1)) {
20742 case 0:
20743 /* SUBU_PH */
20744 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
20745 gen_store_gpr(v1_t, ret);
20746 break;
20747 case 1:
20748 /* SUBU_S_PH */
20749 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20750 gen_store_gpr(v1_t, ret);
20751 break;
20752 }
20753 break;
20754 case NM_SUBUH_R_QB:
20755 check_dsp_r2(ctx);
20756 switch (extract32(ctx->opcode, 10, 1)) {
20757 case 0:
20758 /* SUBUH_QB */
20759 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
20760 gen_store_gpr(v1_t, ret);
20761 break;
20762 case 1:
20763 /* SUBUH_R_QB */
20764 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
20765 gen_store_gpr(v1_t, ret);
20766 break;
20767 }
20768 break;
20769 case NM_SHLLV_S_PH:
20770 check_dsp(ctx);
20771 switch (extract32(ctx->opcode, 10, 1)) {
20772 case 0:
20773 /* SHLLV_PH */
20774 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
20775 gen_store_gpr(v1_t, ret);
20776 break;
20777 case 1:
20778 /* SHLLV_S_PH */
20779 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
20780 gen_store_gpr(v1_t, ret);
20781 break;
20782 }
20783 break;
20784 case NM_PRECR_SRA_R_PH_W:
20785 check_dsp_r2(ctx);
20786 switch (extract32(ctx->opcode, 10, 1)) {
20787 case 0:
20788 /* PRECR_SRA_PH_W */
20789 {
20790 TCGv_i32 sa_t = tcg_const_i32(rd);
20791 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
20792 cpu_gpr[rt]);
20793 gen_store_gpr(v1_t, rt);
20794 tcg_temp_free_i32(sa_t);
20795 }
20796 break;
20797 case 1:
20798 /* PRECR_SRA_R_PH_W */
20799 {
20800 TCGv_i32 sa_t = tcg_const_i32(rd);
20801 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
20802 cpu_gpr[rt]);
20803 gen_store_gpr(v1_t, rt);
20804 tcg_temp_free_i32(sa_t);
20805 }
20806 break;
20807 }
20808 break;
20809 case NM_MULEU_S_PH_QBL:
20810 check_dsp(ctx);
20811 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
20812 gen_store_gpr(v1_t, ret);
20813 break;
20814 case NM_MULEU_S_PH_QBR:
20815 check_dsp(ctx);
20816 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
20817 gen_store_gpr(v1_t, ret);
20818 break;
20819 case NM_MULQ_RS_PH:
20820 check_dsp(ctx);
20821 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
20822 gen_store_gpr(v1_t, ret);
20823 break;
20824 case NM_MULQ_S_PH:
20825 check_dsp_r2(ctx);
20826 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20827 gen_store_gpr(v1_t, ret);
20828 break;
20829 case NM_MULQ_RS_W:
20830 check_dsp_r2(ctx);
20831 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
20832 gen_store_gpr(v1_t, ret);
20833 break;
20834 case NM_MULQ_S_W:
20835 check_dsp_r2(ctx);
20836 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
20837 gen_store_gpr(v1_t, ret);
20838 break;
20839 case NM_APPEND:
20840 check_dsp_r2(ctx);
20841 gen_load_gpr(t0, rs);
20842 if (rd != 0) {
20843 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
20844 }
20845 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20846 break;
20847 case NM_MODSUB:
20848 check_dsp(ctx);
20849 gen_helper_modsub(v1_t, v1_t, v2_t);
20850 gen_store_gpr(v1_t, ret);
20851 break;
20852 case NM_SHRAV_R_W:
20853 check_dsp(ctx);
20854 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
20855 gen_store_gpr(v1_t, ret);
20856 break;
20857 case NM_SHRLV_PH:
20858 check_dsp_r2(ctx);
20859 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
20860 gen_store_gpr(v1_t, ret);
20861 break;
20862 case NM_SHRLV_QB:
20863 check_dsp(ctx);
20864 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
20865 gen_store_gpr(v1_t, ret);
20866 break;
20867 case NM_SHLLV_QB:
20868 check_dsp(ctx);
20869 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
20870 gen_store_gpr(v1_t, ret);
20871 break;
20872 case NM_SHLLV_S_W:
20873 check_dsp(ctx);
20874 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
20875 gen_store_gpr(v1_t, ret);
20876 break;
20877 case NM_SHILO:
20878 check_dsp(ctx);
20879 {
20880 TCGv tv0 = tcg_temp_new();
20881 TCGv tv1 = tcg_temp_new();
20882 int16_t imm = extract32(ctx->opcode, 16, 7);
20883
20884 tcg_gen_movi_tl(tv0, rd >> 3);
20885 tcg_gen_movi_tl(tv1, imm);
20886 gen_helper_shilo(tv0, tv1, cpu_env);
20887 }
20888 break;
20889 case NM_MULEQ_S_W_PHL:
20890 check_dsp(ctx);
20891 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
20892 gen_store_gpr(v1_t, ret);
20893 break;
20894 case NM_MULEQ_S_W_PHR:
20895 check_dsp(ctx);
20896 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
20897 gen_store_gpr(v1_t, ret);
20898 break;
20899 case NM_MUL_S_PH:
20900 check_dsp_r2(ctx);
20901 switch (extract32(ctx->opcode, 10, 1)) {
20902 case 0:
20903 /* MUL_PH */
20904 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
20905 gen_store_gpr(v1_t, ret);
20906 break;
20907 case 1:
20908 /* MUL_S_PH */
20909 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
20910 gen_store_gpr(v1_t, ret);
20911 break;
20912 }
20913 break;
20914 case NM_PRECR_QB_PH:
20915 check_dsp_r2(ctx);
20916 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
20917 gen_store_gpr(v1_t, ret);
20918 break;
20919 case NM_PRECRQ_QB_PH:
20920 check_dsp(ctx);
20921 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
20922 gen_store_gpr(v1_t, ret);
20923 break;
20924 case NM_PRECRQ_PH_W:
20925 check_dsp(ctx);
20926 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
20927 gen_store_gpr(v1_t, ret);
20928 break;
20929 case NM_PRECRQ_RS_PH_W:
20930 check_dsp(ctx);
20931 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
20932 gen_store_gpr(v1_t, ret);
20933 break;
20934 case NM_PRECRQU_S_QB_PH:
20935 check_dsp(ctx);
20936 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
20937 gen_store_gpr(v1_t, ret);
20938 break;
20939 case NM_SHRA_R_W:
20940 check_dsp(ctx);
20941 tcg_gen_movi_tl(t0, rd);
20942 gen_helper_shra_r_w(v1_t, t0, v1_t);
20943 gen_store_gpr(v1_t, rt);
20944 break;
20945 case NM_SHRA_R_PH:
20946 check_dsp(ctx);
20947 tcg_gen_movi_tl(t0, rd >> 1);
20948 switch (extract32(ctx->opcode, 10, 1)) {
20949 case 0:
20950 /* SHRA_PH */
20951 gen_helper_shra_ph(v1_t, t0, v1_t);
20952 gen_store_gpr(v1_t, rt);
20953 break;
20954 case 1:
20955 /* SHRA_R_PH */
20956 gen_helper_shra_r_ph(v1_t, t0, v1_t);
20957 gen_store_gpr(v1_t, rt);
20958 break;
20959 }
20960 break;
20961 case NM_SHLL_S_PH:
20962 check_dsp(ctx);
20963 tcg_gen_movi_tl(t0, rd >> 1);
20964 switch (extract32(ctx->opcode, 10, 2)) {
20965 case 0:
20966 /* SHLL_PH */
20967 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
20968 gen_store_gpr(v1_t, rt);
20969 break;
20970 case 2:
20971 /* SHLL_S_PH */
20972 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
20973 gen_store_gpr(v1_t, rt);
20974 break;
20975 default:
20976 generate_exception_end(ctx, EXCP_RI);
20977 break;
20978 }
20979 break;
20980 case NM_SHLL_S_W:
20981 check_dsp(ctx);
20982 tcg_gen_movi_tl(t0, rd);
20983 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
20984 gen_store_gpr(v1_t, rt);
20985 break;
20986 case NM_REPL_PH:
20987 check_dsp(ctx);
20988 {
20989 int16_t imm;
20990 imm = sextract32(ctx->opcode, 11, 11);
20991 imm = (int16_t)(imm << 6) >> 6;
20992 if (rt != 0) {
20993 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
20994 }
20995 }
20996 break;
20997 default:
20998 generate_exception_end(ctx, EXCP_RI);
20999 break;
21000 }
21001 }
21002
21003 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
21004 {
21005 uint16_t insn;
21006 uint32_t op;
21007 int rt, rs, rd;
21008 int offset;
21009 int imm;
21010
21011 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
21012 ctx->opcode = (ctx->opcode << 16) | insn;
21013
21014 rt = extract32(ctx->opcode, 21, 5);
21015 rs = extract32(ctx->opcode, 16, 5);
21016 rd = extract32(ctx->opcode, 11, 5);
21017
21018 op = extract32(ctx->opcode, 26, 6);
21019 switch (op) {
21020 case NM_P_ADDIU:
21021 if (rt == 0) {
21022 /* P.RI */
21023 switch (extract32(ctx->opcode, 19, 2)) {
21024 case NM_SIGRIE:
21025 default:
21026 generate_exception_end(ctx, EXCP_RI);
21027 break;
21028 case NM_P_SYSCALL:
21029 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
21030 generate_exception_end(ctx, EXCP_SYSCALL);
21031 } else {
21032 generate_exception_end(ctx, EXCP_RI);
21033 }
21034 break;
21035 case NM_BREAK:
21036 generate_exception_end(ctx, EXCP_BREAK);
21037 break;
21038 case NM_SDBBP:
21039 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
21040 gen_helper_do_semihosting(cpu_env);
21041 } else {
21042 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21043 generate_exception_end(ctx, EXCP_RI);
21044 } else {
21045 generate_exception_end(ctx, EXCP_DBp);
21046 }
21047 }
21048 break;
21049 }
21050 } else {
21051 /* NM_ADDIU */
21052 imm = extract32(ctx->opcode, 0, 16);
21053 if (rs != 0) {
21054 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
21055 } else {
21056 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21057 }
21058 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21059 }
21060 break;
21061 case NM_ADDIUPC:
21062 if (rt != 0) {
21063 offset = sextract32(ctx->opcode, 0, 1) << 21 |
21064 extract32(ctx->opcode, 1, 20) << 1;
21065 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
21066 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21067 }
21068 break;
21069 case NM_POOL32A:
21070 switch (ctx->opcode & 0x07) {
21071 case NM_POOL32A0:
21072 gen_pool32a0_nanomips_insn(env, ctx);
21073 break;
21074 case NM_POOL32A5:
21075 {
21076 int32_t op1 = extract32(ctx->opcode, 3, 7);
21077 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
21078 }
21079 break;
21080 case NM_POOL32A7:
21081 switch (extract32(ctx->opcode, 3, 3)) {
21082 case NM_P_LSX:
21083 gen_p_lsx(ctx, rd, rs, rt);
21084 break;
21085 case NM_LSA:
21086 /* In nanoMIPS, the shift field directly encodes the shift
21087 * amount, meaning that the supported shift values are in
21088 * the range 0 to 3 (instead of 1 to 4 in MIPSR6). */
21089 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
21090 extract32(ctx->opcode, 9, 2) - 1);
21091 break;
21092 case NM_EXTW:
21093 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
21094 break;
21095 case NM_POOL32AXF:
21096 gen_pool32axf_nanomips_insn(env, ctx);
21097 break;
21098 default:
21099 generate_exception_end(ctx, EXCP_RI);
21100 break;
21101 }
21102 break;
21103 default:
21104 generate_exception_end(ctx, EXCP_RI);
21105 break;
21106 }
21107 break;
21108 case NM_P_GP_W:
21109 switch (ctx->opcode & 0x03) {
21110 case NM_ADDIUGP_W:
21111 if (rt != 0) {
21112 offset = extract32(ctx->opcode, 0, 21);
21113 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
21114 }
21115 break;
21116 case NM_LWGP:
21117 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21118 break;
21119 case NM_SWGP:
21120 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21121 break;
21122 default:
21123 generate_exception_end(ctx, EXCP_RI);
21124 break;
21125 }
21126 break;
21127 case NM_P48I:
21128 {
21129 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
21130 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
21131 switch (extract32(ctx->opcode, 16, 5)) {
21132 case NM_LI48:
21133 check_nms(ctx);
21134 if (rt != 0) {
21135 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
21136 }
21137 break;
21138 case NM_ADDIU48:
21139 check_nms(ctx);
21140 if (rt != 0) {
21141 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
21142 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21143 }
21144 break;
21145 case NM_ADDIUGP48:
21146 check_nms(ctx);
21147 if (rt != 0) {
21148 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
21149 }
21150 break;
21151 case NM_ADDIUPC48:
21152 check_nms(ctx);
21153 if (rt != 0) {
21154 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21155 addr_off);
21156
21157 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21158 }
21159 break;
21160 case NM_LWPC48:
21161 check_nms(ctx);
21162 if (rt != 0) {
21163 TCGv t0;
21164 t0 = tcg_temp_new();
21165
21166 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21167 addr_off);
21168
21169 tcg_gen_movi_tl(t0, addr);
21170 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
21171 tcg_temp_free(t0);
21172 }
21173 break;
21174 case NM_SWPC48:
21175 check_nms(ctx);
21176 {
21177 TCGv t0, t1;
21178 t0 = tcg_temp_new();
21179 t1 = tcg_temp_new();
21180
21181 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21182 addr_off);
21183
21184 tcg_gen_movi_tl(t0, addr);
21185 gen_load_gpr(t1, rt);
21186
21187 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
21188
21189 tcg_temp_free(t0);
21190 tcg_temp_free(t1);
21191 }
21192 break;
21193 default:
21194 generate_exception_end(ctx, EXCP_RI);
21195 break;
21196 }
21197 return 6;
21198 }
21199 case NM_P_U12:
21200 switch (extract32(ctx->opcode, 12, 4)) {
21201 case NM_ORI:
21202 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
21203 break;
21204 case NM_XORI:
21205 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
21206 break;
21207 case NM_ANDI:
21208 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
21209 break;
21210 case NM_P_SR:
21211 switch (extract32(ctx->opcode, 20, 1)) {
21212 case NM_PP_SR:
21213 switch (ctx->opcode & 3) {
21214 case NM_SAVE:
21215 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
21216 extract32(ctx->opcode, 2, 1),
21217 extract32(ctx->opcode, 3, 9) << 3);
21218 break;
21219 case NM_RESTORE:
21220 case NM_RESTORE_JRC:
21221 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
21222 extract32(ctx->opcode, 2, 1),
21223 extract32(ctx->opcode, 3, 9) << 3);
21224 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
21225 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21226 }
21227 break;
21228 default:
21229 generate_exception_end(ctx, EXCP_RI);
21230 break;
21231 }
21232 break;
21233 case NM_P_SR_F:
21234 generate_exception_end(ctx, EXCP_RI);
21235 break;
21236 }
21237 break;
21238 case NM_SLTI:
21239 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
21240 break;
21241 case NM_SLTIU:
21242 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
21243 break;
21244 case NM_SEQI:
21245 {
21246 TCGv t0 = tcg_temp_new();
21247
21248 imm = extract32(ctx->opcode, 0, 12);
21249 gen_load_gpr(t0, rs);
21250 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
21251 gen_store_gpr(t0, rt);
21252
21253 tcg_temp_free(t0);
21254 }
21255 break;
21256 case NM_ADDIUNEG:
21257 imm = (int16_t) extract32(ctx->opcode, 0, 12);
21258 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
21259 break;
21260 case NM_P_SHIFT:
21261 {
21262 int shift = extract32(ctx->opcode, 0, 5);
21263 switch (extract32(ctx->opcode, 5, 4)) {
21264 case NM_P_SLL:
21265 if (rt == 0 && shift == 0) {
21266 /* NOP */
21267 } else if (rt == 0 && shift == 3) {
21268 /* EHB - treat as NOP */
21269 } else if (rt == 0 && shift == 5) {
21270 /* PAUSE - treat as NOP */
21271 } else if (rt == 0 && shift == 6) {
21272 /* SYNC */
21273 gen_sync(extract32(ctx->opcode, 16, 5));
21274 } else {
21275 /* SLL */
21276 gen_shift_imm(ctx, OPC_SLL, rt, rs,
21277 extract32(ctx->opcode, 0, 5));
21278 }
21279 break;
21280 case NM_SRL:
21281 gen_shift_imm(ctx, OPC_SRL, rt, rs,
21282 extract32(ctx->opcode, 0, 5));
21283 break;
21284 case NM_SRA:
21285 gen_shift_imm(ctx, OPC_SRA, rt, rs,
21286 extract32(ctx->opcode, 0, 5));
21287 break;
21288 case NM_ROTR:
21289 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
21290 extract32(ctx->opcode, 0, 5));
21291 break;
21292 }
21293 }
21294 break;
21295 case NM_P_ROTX:
21296 check_nms(ctx);
21297 if (rt != 0) {
21298 TCGv t0 = tcg_temp_new();
21299 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
21300 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
21301 << 1);
21302 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
21303
21304 gen_load_gpr(t0, rs);
21305 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
21306 tcg_temp_free(t0);
21307
21308 tcg_temp_free_i32(shift);
21309 tcg_temp_free_i32(shiftx);
21310 tcg_temp_free_i32(stripe);
21311 }
21312 break;
21313 case NM_P_INS:
21314 switch (((ctx->opcode >> 10) & 2) |
21315 (extract32(ctx->opcode, 5, 1))) {
21316 case NM_INS:
21317 check_nms(ctx);
21318 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
21319 extract32(ctx->opcode, 6, 5));
21320 break;
21321 default:
21322 generate_exception_end(ctx, EXCP_RI);
21323 break;
21324 }
21325 break;
21326 case NM_P_EXT:
21327 switch (((ctx->opcode >> 10) & 2) |
21328 (extract32(ctx->opcode, 5, 1))) {
21329 case NM_EXT:
21330 check_nms(ctx);
21331 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
21332 extract32(ctx->opcode, 6, 5));
21333 break;
21334 default:
21335 generate_exception_end(ctx, EXCP_RI);
21336 break;
21337 }
21338 break;
21339 default:
21340 generate_exception_end(ctx, EXCP_RI);
21341 break;
21342 }
21343 break;
21344 case NM_POOL32F:
21345 gen_pool32f_nanomips_insn(ctx);
21346 break;
21347 case NM_POOL32S:
21348 break;
21349 case NM_P_LUI:
21350 switch (extract32(ctx->opcode, 1, 1)) {
21351 case NM_LUI:
21352 if (rt != 0) {
21353 tcg_gen_movi_tl(cpu_gpr[rt],
21354 sextract32(ctx->opcode, 0, 1) << 31 |
21355 extract32(ctx->opcode, 2, 10) << 21 |
21356 extract32(ctx->opcode, 12, 9) << 12);
21357 }
21358 break;
21359 case NM_ALUIPC:
21360 if (rt != 0) {
21361 offset = sextract32(ctx->opcode, 0, 1) << 31 |
21362 extract32(ctx->opcode, 2, 10) << 21 |
21363 extract32(ctx->opcode, 12, 9) << 12;
21364 target_long addr;
21365 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
21366 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21367 }
21368 break;
21369 }
21370 break;
21371 case NM_P_GP_BH:
21372 {
21373 uint32_t u = extract32(ctx->opcode, 0, 18);
21374
21375 switch (extract32(ctx->opcode, 18, 3)) {
21376 case NM_LBGP:
21377 gen_ld(ctx, OPC_LB, rt, 28, u);
21378 break;
21379 case NM_SBGP:
21380 gen_st(ctx, OPC_SB, rt, 28, u);
21381 break;
21382 case NM_LBUGP:
21383 gen_ld(ctx, OPC_LBU, rt, 28, u);
21384 break;
21385 case NM_ADDIUGP_B:
21386 if (rt != 0) {
21387 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
21388 }
21389 break;
21390 case NM_P_GP_LH:
21391 u &= ~1;
21392 switch (ctx->opcode & 1) {
21393 case NM_LHGP:
21394 gen_ld(ctx, OPC_LH, rt, 28, u);
21395 break;
21396 case NM_LHUGP:
21397 gen_ld(ctx, OPC_LHU, rt, 28, u);
21398 break;
21399 }
21400 break;
21401 case NM_P_GP_SH:
21402 u &= ~1;
21403 switch (ctx->opcode & 1) {
21404 case NM_SHGP:
21405 gen_st(ctx, OPC_SH, rt, 28, u);
21406 break;
21407 default:
21408 generate_exception_end(ctx, EXCP_RI);
21409 break;
21410 }
21411 break;
21412 case NM_P_GP_CP1:
21413 u &= ~0x3;
21414 switch (ctx->opcode & 0x3) {
21415 case NM_LWC1GP:
21416 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
21417 break;
21418 case NM_LDC1GP:
21419 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
21420 break;
21421 case NM_SWC1GP:
21422 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
21423 break;
21424 case NM_SDC1GP:
21425 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
21426 break;
21427 }
21428 break;
21429 default:
21430 generate_exception_end(ctx, EXCP_RI);
21431 break;
21432 }
21433 }
21434 break;
21435 case NM_P_LS_U12:
21436 {
21437 uint32_t u = extract32(ctx->opcode, 0, 12);
21438
21439 switch (extract32(ctx->opcode, 12, 4)) {
21440 case NM_P_PREFU12:
21441 if (rt == 31) {
21442 /* SYNCI */
21443 /* Break the TB to be able to sync copied instructions
21444 immediately */
21445 ctx->base.is_jmp = DISAS_STOP;
21446 } else {
21447 /* PREF */
21448 /* Treat as NOP. */
21449 }
21450 break;
21451 case NM_LB:
21452 gen_ld(ctx, OPC_LB, rt, rs, u);
21453 break;
21454 case NM_LH:
21455 gen_ld(ctx, OPC_LH, rt, rs, u);
21456 break;
21457 case NM_LW:
21458 gen_ld(ctx, OPC_LW, rt, rs, u);
21459 break;
21460 case NM_LBU:
21461 gen_ld(ctx, OPC_LBU, rt, rs, u);
21462 break;
21463 case NM_LHU:
21464 gen_ld(ctx, OPC_LHU, rt, rs, u);
21465 break;
21466 case NM_SB:
21467 gen_st(ctx, OPC_SB, rt, rs, u);
21468 break;
21469 case NM_SH:
21470 gen_st(ctx, OPC_SH, rt, rs, u);
21471 break;
21472 case NM_SW:
21473 gen_st(ctx, OPC_SW, rt, rs, u);
21474 break;
21475 case NM_LWC1:
21476 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
21477 break;
21478 case NM_LDC1:
21479 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
21480 break;
21481 case NM_SWC1:
21482 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
21483 break;
21484 case NM_SDC1:
21485 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
21486 break;
21487 default:
21488 generate_exception_end(ctx, EXCP_RI);
21489 break;
21490 }
21491 }
21492 break;
21493 case NM_P_LS_S9:
21494 {
21495 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
21496 extract32(ctx->opcode, 0, 8);
21497
21498 switch (extract32(ctx->opcode, 8, 3)) {
21499 case NM_P_LS_S0:
21500 switch (extract32(ctx->opcode, 11, 4)) {
21501 case NM_LBS9:
21502 gen_ld(ctx, OPC_LB, rt, rs, s);
21503 break;
21504 case NM_LHS9:
21505 gen_ld(ctx, OPC_LH, rt, rs, s);
21506 break;
21507 case NM_LWS9:
21508 gen_ld(ctx, OPC_LW, rt, rs, s);
21509 break;
21510 case NM_LBUS9:
21511 gen_ld(ctx, OPC_LBU, rt, rs, s);
21512 break;
21513 case NM_LHUS9:
21514 gen_ld(ctx, OPC_LHU, rt, rs, s);
21515 break;
21516 case NM_SBS9:
21517 gen_st(ctx, OPC_SB, rt, rs, s);
21518 break;
21519 case NM_SHS9:
21520 gen_st(ctx, OPC_SH, rt, rs, s);
21521 break;
21522 case NM_SWS9:
21523 gen_st(ctx, OPC_SW, rt, rs, s);
21524 break;
21525 case NM_LWC1S9:
21526 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
21527 break;
21528 case NM_LDC1S9:
21529 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
21530 break;
21531 case NM_SWC1S9:
21532 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
21533 break;
21534 case NM_SDC1S9:
21535 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
21536 break;
21537 case NM_P_PREFS9:
21538 if (rt == 31) {
21539 /* SYNCI */
21540 /* Break the TB to be able to sync copied instructions
21541 immediately */
21542 ctx->base.is_jmp = DISAS_STOP;
21543 } else {
21544 /* PREF */
21545 /* Treat as NOP. */
21546 }
21547 break;
21548 default:
21549 generate_exception_end(ctx, EXCP_RI);
21550 break;
21551 }
21552 break;
21553 case NM_P_LS_S1:
21554 switch (extract32(ctx->opcode, 11, 4)) {
21555 case NM_UALH:
21556 case NM_UASH:
21557 check_nms(ctx);
21558 {
21559 TCGv t0 = tcg_temp_new();
21560 TCGv t1 = tcg_temp_new();
21561
21562 gen_base_offset_addr(ctx, t0, rs, s);
21563
21564 switch (extract32(ctx->opcode, 11, 4)) {
21565 case NM_UALH:
21566 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
21567 MO_UNALN);
21568 gen_store_gpr(t0, rt);
21569 break;
21570 case NM_UASH:
21571 gen_load_gpr(t1, rt);
21572 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
21573 MO_UNALN);
21574 break;
21575 }
21576 tcg_temp_free(t0);
21577 tcg_temp_free(t1);
21578 }
21579 break;
21580 case NM_P_LL:
21581 switch (ctx->opcode & 0x03) {
21582 case NM_LL:
21583 gen_ld(ctx, OPC_LL, rt, rs, s);
21584 break;
21585 case NM_LLWP:
21586 check_xnp(ctx);
21587 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21588 break;
21589 }
21590 break;
21591 case NM_P_SC:
21592 switch (ctx->opcode & 0x03) {
21593 case NM_SC:
21594 gen_st_cond(ctx, rt, rs, s, MO_TESL, false);
21595 break;
21596 case NM_SCWP:
21597 check_xnp(ctx);
21598 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21599 false);
21600 break;
21601 }
21602 break;
21603 case NM_CACHE:
21604 check_cp0_enabled(ctx);
21605 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
21606 gen_cache_operation(ctx, rt, rs, s);
21607 }
21608 break;
21609 }
21610 break;
21611 case NM_P_LS_E0:
21612 switch (extract32(ctx->opcode, 11, 4)) {
21613 case NM_LBE:
21614 check_eva(ctx);
21615 check_cp0_enabled(ctx);
21616 gen_ld(ctx, OPC_LBE, rt, rs, s);
21617 break;
21618 case NM_SBE:
21619 check_eva(ctx);
21620 check_cp0_enabled(ctx);
21621 gen_st(ctx, OPC_SBE, rt, rs, s);
21622 break;
21623 case NM_LBUE:
21624 check_eva(ctx);
21625 check_cp0_enabled(ctx);
21626 gen_ld(ctx, OPC_LBUE, rt, rs, s);
21627 break;
21628 case NM_P_PREFE:
21629 if (rt == 31) {
21630 /* case NM_SYNCIE */
21631 check_eva(ctx);
21632 check_cp0_enabled(ctx);
21633 /* Break the TB to be able to sync copied instructions
21634 immediately */
21635 ctx->base.is_jmp = DISAS_STOP;
21636 } else {
21637 /* case NM_PREFE */
21638 check_eva(ctx);
21639 check_cp0_enabled(ctx);
21640 /* Treat as NOP. */
21641 }
21642 break;
21643 case NM_LHE:
21644 check_eva(ctx);
21645 check_cp0_enabled(ctx);
21646 gen_ld(ctx, OPC_LHE, rt, rs, s);
21647 break;
21648 case NM_SHE:
21649 check_eva(ctx);
21650 check_cp0_enabled(ctx);
21651 gen_st(ctx, OPC_SHE, rt, rs, s);
21652 break;
21653 case NM_LHUE:
21654 check_eva(ctx);
21655 check_cp0_enabled(ctx);
21656 gen_ld(ctx, OPC_LHUE, rt, rs, s);
21657 break;
21658 case NM_CACHEE:
21659 check_nms_dl_il_sl_tl_l2c(ctx);
21660 gen_cache_operation(ctx, rt, rs, s);
21661 break;
21662 case NM_LWE:
21663 check_eva(ctx);
21664 check_cp0_enabled(ctx);
21665 gen_ld(ctx, OPC_LWE, rt, rs, s);
21666 break;
21667 case NM_SWE:
21668 check_eva(ctx);
21669 check_cp0_enabled(ctx);
21670 gen_st(ctx, OPC_SWE, rt, rs, s);
21671 break;
21672 case NM_P_LLE:
21673 switch (extract32(ctx->opcode, 2, 2)) {
21674 case NM_LLE:
21675 check_xnp(ctx);
21676 check_eva(ctx);
21677 check_cp0_enabled(ctx);
21678 gen_ld(ctx, OPC_LLE, rt, rs, s);
21679 break;
21680 case NM_LLWPE:
21681 check_xnp(ctx);
21682 check_eva(ctx);
21683 check_cp0_enabled(ctx);
21684 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21685 break;
21686 default:
21687 generate_exception_end(ctx, EXCP_RI);
21688 break;
21689 }
21690 break;
21691 case NM_P_SCE:
21692 switch (extract32(ctx->opcode, 2, 2)) {
21693 case NM_SCE:
21694 check_xnp(ctx);
21695 check_eva(ctx);
21696 check_cp0_enabled(ctx);
21697 gen_st_cond(ctx, rt, rs, s, MO_TESL, true);
21698 break;
21699 case NM_SCWPE:
21700 check_xnp(ctx);
21701 check_eva(ctx);
21702 check_cp0_enabled(ctx);
21703 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21704 true);
21705 break;
21706 default:
21707 generate_exception_end(ctx, EXCP_RI);
21708 break;
21709 }
21710 break;
21711 }
21712 break;
21713 case NM_P_LS_WM:
21714 case NM_P_LS_UAWM:
21715 check_nms(ctx);
21716 {
21717 int count = extract32(ctx->opcode, 12, 3);
21718 int counter = 0;
21719
21720 offset = sextract32(ctx->opcode, 15, 1) << 8 |
21721 extract32(ctx->opcode, 0, 8);
21722 TCGv va = tcg_temp_new();
21723 TCGv t1 = tcg_temp_new();
21724 TCGMemOp memop = (extract32(ctx->opcode, 8, 3)) ==
21725 NM_P_LS_UAWM ? MO_UNALN : 0;
21726
21727 count = (count == 0) ? 8 : count;
21728 while (counter != count) {
21729 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
21730 int this_offset = offset + (counter << 2);
21731
21732 gen_base_offset_addr(ctx, va, rs, this_offset);
21733
21734 switch (extract32(ctx->opcode, 11, 1)) {
21735 case NM_LWM:
21736 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
21737 memop | MO_TESL);
21738 gen_store_gpr(t1, this_rt);
21739 if ((this_rt == rs) &&
21740 (counter != (count - 1))) {
21741 /* UNPREDICTABLE */
21742 }
21743 break;
21744 case NM_SWM:
21745 this_rt = (rt == 0) ? 0 : this_rt;
21746 gen_load_gpr(t1, this_rt);
21747 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
21748 memop | MO_TEUL);
21749 break;
21750 }
21751 counter++;
21752 }
21753 tcg_temp_free(va);
21754 tcg_temp_free(t1);
21755 }
21756 break;
21757 default:
21758 generate_exception_end(ctx, EXCP_RI);
21759 break;
21760 }
21761 }
21762 break;
21763 case NM_MOVE_BALC:
21764 check_nms(ctx);
21765 {
21766 TCGv t0 = tcg_temp_new();
21767 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
21768 extract32(ctx->opcode, 1, 20) << 1;
21769 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
21770 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
21771 extract32(ctx->opcode, 21, 3));
21772 gen_load_gpr(t0, rt);
21773 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21774 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21775 tcg_temp_free(t0);
21776 }
21777 break;
21778 case NM_P_BAL:
21779 {
21780 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
21781 extract32(ctx->opcode, 1, 24) << 1;
21782
21783 if ((extract32(ctx->opcode, 25, 1)) == 0) {
21784 /* BC */
21785 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
21786 } else {
21787 /* BALC */
21788 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21789 }
21790 }
21791 break;
21792 case NM_P_J:
21793 switch (extract32(ctx->opcode, 12, 4)) {
21794 case NM_JALRC:
21795 case NM_JALRC_HB:
21796 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
21797 break;
21798 case NM_P_BALRSC:
21799 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
21800 break;
21801 default:
21802 generate_exception_end(ctx, EXCP_RI);
21803 break;
21804 }
21805 break;
21806 case NM_P_BR1:
21807 {
21808 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21809 extract32(ctx->opcode, 1, 13) << 1;
21810 switch (extract32(ctx->opcode, 14, 2)) {
21811 case NM_BEQC:
21812 check_nms(ctx);
21813 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
21814 break;
21815 case NM_P_BR3A:
21816 s = sextract32(ctx->opcode, 0, 1) << 14 |
21817 extract32(ctx->opcode, 1, 13) << 1;
21818 check_cp1_enabled(ctx);
21819 switch (extract32(ctx->opcode, 16, 5)) {
21820 case NM_BC1EQZC:
21821 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
21822 break;
21823 case NM_BC1NEZC:
21824 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
21825 break;
21826 case NM_BPOSGE32C:
21827 check_dsp_r3(ctx);
21828 {
21829 int32_t imm = extract32(ctx->opcode, 1, 13) |
21830 extract32(ctx->opcode, 0, 1) << 13;
21831
21832 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
21833 imm);
21834 }
21835 break;
21836 default:
21837 generate_exception_end(ctx, EXCP_RI);
21838 break;
21839 }
21840 break;
21841 case NM_BGEC:
21842 if (rs == rt) {
21843 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
21844 } else {
21845 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
21846 }
21847 break;
21848 case NM_BGEUC:
21849 if (rs == rt || rt == 0) {
21850 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
21851 } else if (rs == 0) {
21852 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
21853 } else {
21854 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
21855 }
21856 break;
21857 }
21858 }
21859 break;
21860 case NM_P_BR2:
21861 {
21862 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21863 extract32(ctx->opcode, 1, 13) << 1;
21864 switch (extract32(ctx->opcode, 14, 2)) {
21865 case NM_BNEC:
21866 check_nms(ctx);
21867 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
21868 break;
21869 case NM_BLTC:
21870 if (rs != 0 && rt != 0 && rs == rt) {
21871 /* NOP */
21872 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21873 } else {
21874 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
21875 }
21876 break;
21877 case NM_BLTUC:
21878 if (rs == 0 || rs == rt) {
21879 /* NOP */
21880 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21881 } else {
21882 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
21883 }
21884 break;
21885 default:
21886 generate_exception_end(ctx, EXCP_RI);
21887 break;
21888 }
21889 }
21890 break;
21891 case NM_P_BRI:
21892 {
21893 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
21894 extract32(ctx->opcode, 1, 10) << 1;
21895 uint32_t u = extract32(ctx->opcode, 11, 7);
21896
21897 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
21898 rt, u, s);
21899 }
21900 break;
21901 default:
21902 generate_exception_end(ctx, EXCP_RI);
21903 break;
21904 }
21905 return 4;
21906 }
21907
21908 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
21909 {
21910 uint32_t op;
21911 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
21912 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
21913 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode));
21914 int offset;
21915 int imm;
21916
21917 /* make sure instructions are on a halfword boundary */
21918 if (ctx->base.pc_next & 0x1) {
21919 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
21920 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
21921 tcg_temp_free(tmp);
21922 generate_exception_end(ctx, EXCP_AdEL);
21923 return 2;
21924 }
21925
21926 op = extract32(ctx->opcode, 10, 6);
21927 switch (op) {
21928 case NM_P16_MV:
21929 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21930 if (rt != 0) {
21931 /* MOVE */
21932 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
21933 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
21934 } else {
21935 /* P16.RI */
21936 switch (extract32(ctx->opcode, 3, 2)) {
21937 case NM_P16_SYSCALL:
21938 if (extract32(ctx->opcode, 2, 1) == 0) {
21939 generate_exception_end(ctx, EXCP_SYSCALL);
21940 } else {
21941 generate_exception_end(ctx, EXCP_RI);
21942 }
21943 break;
21944 case NM_BREAK16:
21945 generate_exception_end(ctx, EXCP_BREAK);
21946 break;
21947 case NM_SDBBP16:
21948 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
21949 gen_helper_do_semihosting(cpu_env);
21950 } else {
21951 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21952 generate_exception_end(ctx, EXCP_RI);
21953 } else {
21954 generate_exception_end(ctx, EXCP_DBp);
21955 }
21956 }
21957 break;
21958 default:
21959 generate_exception_end(ctx, EXCP_RI);
21960 break;
21961 }
21962 }
21963 break;
21964 case NM_P16_SHIFT:
21965 {
21966 int shift = extract32(ctx->opcode, 0, 3);
21967 uint32_t opc = 0;
21968 shift = (shift == 0) ? 8 : shift;
21969
21970 switch (extract32(ctx->opcode, 3, 1)) {
21971 case NM_SLL16:
21972 opc = OPC_SLL;
21973 break;
21974 case NM_SRL16:
21975 opc = OPC_SRL;
21976 break;
21977 }
21978 gen_shift_imm(ctx, opc, rt, rs, shift);
21979 }
21980 break;
21981 case NM_P16C:
21982 switch (ctx->opcode & 1) {
21983 case NM_POOL16C_0:
21984 gen_pool16c_nanomips_insn(ctx);
21985 break;
21986 case NM_LWXS16:
21987 gen_ldxs(ctx, rt, rs, rd);
21988 break;
21989 }
21990 break;
21991 case NM_P16_A1:
21992 switch (extract32(ctx->opcode, 6, 1)) {
21993 case NM_ADDIUR1SP:
21994 imm = extract32(ctx->opcode, 0, 6) << 2;
21995 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
21996 break;
21997 default:
21998 generate_exception_end(ctx, EXCP_RI);
21999 break;
22000 }
22001 break;
22002 case NM_P16_A2:
22003 switch (extract32(ctx->opcode, 3, 1)) {
22004 case NM_ADDIUR2:
22005 imm = extract32(ctx->opcode, 0, 3) << 2;
22006 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
22007 break;
22008 case NM_P_ADDIURS5:
22009 rt = extract32(ctx->opcode, 5, 5);
22010 if (rt != 0) {
22011 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
22012 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
22013 (extract32(ctx->opcode, 0, 3));
22014 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
22015 }
22016 break;
22017 }
22018 break;
22019 case NM_P16_ADDU:
22020 switch (ctx->opcode & 0x1) {
22021 case NM_ADDU16:
22022 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
22023 break;
22024 case NM_SUBU16:
22025 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
22026 break;
22027 }
22028 break;
22029 case NM_P16_4X4:
22030 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22031 extract32(ctx->opcode, 5, 3);
22032 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22033 extract32(ctx->opcode, 0, 3);
22034 rt = decode_gpr_gpr4(rt);
22035 rs = decode_gpr_gpr4(rs);
22036 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
22037 (extract32(ctx->opcode, 3, 1))) {
22038 case NM_ADDU4X4:
22039 check_nms(ctx);
22040 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
22041 break;
22042 case NM_MUL4X4:
22043 check_nms(ctx);
22044 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
22045 break;
22046 default:
22047 generate_exception_end(ctx, EXCP_RI);
22048 break;
22049 }
22050 break;
22051 case NM_LI16:
22052 {
22053 int imm = extract32(ctx->opcode, 0, 7);
22054 imm = (imm == 0x7f ? -1 : imm);
22055 if (rt != 0) {
22056 tcg_gen_movi_tl(cpu_gpr[rt], imm);
22057 }
22058 }
22059 break;
22060 case NM_ANDI16:
22061 {
22062 uint32_t u = extract32(ctx->opcode, 0, 4);
22063 u = (u == 12) ? 0xff :
22064 (u == 13) ? 0xffff : u;
22065 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
22066 }
22067 break;
22068 case NM_P16_LB:
22069 offset = extract32(ctx->opcode, 0, 2);
22070 switch (extract32(ctx->opcode, 2, 2)) {
22071 case NM_LB16:
22072 gen_ld(ctx, OPC_LB, rt, rs, offset);
22073 break;
22074 case NM_SB16:
22075 rt = decode_gpr_gpr3_src_store(
22076 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22077 gen_st(ctx, OPC_SB, rt, rs, offset);
22078 break;
22079 case NM_LBU16:
22080 gen_ld(ctx, OPC_LBU, rt, rs, offset);
22081 break;
22082 default:
22083 generate_exception_end(ctx, EXCP_RI);
22084 break;
22085 }
22086 break;
22087 case NM_P16_LH:
22088 offset = extract32(ctx->opcode, 1, 2) << 1;
22089 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
22090 case NM_LH16:
22091 gen_ld(ctx, OPC_LH, rt, rs, offset);
22092 break;
22093 case NM_SH16:
22094 rt = decode_gpr_gpr3_src_store(
22095 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22096 gen_st(ctx, OPC_SH, rt, rs, offset);
22097 break;
22098 case NM_LHU16:
22099 gen_ld(ctx, OPC_LHU, rt, rs, offset);
22100 break;
22101 default:
22102 generate_exception_end(ctx, EXCP_RI);
22103 break;
22104 }
22105 break;
22106 case NM_LW16:
22107 offset = extract32(ctx->opcode, 0, 4) << 2;
22108 gen_ld(ctx, OPC_LW, rt, rs, offset);
22109 break;
22110 case NM_LWSP16:
22111 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22112 offset = extract32(ctx->opcode, 0, 5) << 2;
22113 gen_ld(ctx, OPC_LW, rt, 29, offset);
22114 break;
22115 case NM_LW4X4:
22116 check_nms(ctx);
22117 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22118 extract32(ctx->opcode, 5, 3);
22119 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22120 extract32(ctx->opcode, 0, 3);
22121 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22122 (extract32(ctx->opcode, 8, 1) << 2);
22123 rt = decode_gpr_gpr4(rt);
22124 rs = decode_gpr_gpr4(rs);
22125 gen_ld(ctx, OPC_LW, rt, rs, offset);
22126 break;
22127 case NM_SW4X4:
22128 check_nms(ctx);
22129 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22130 extract32(ctx->opcode, 5, 3);
22131 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22132 extract32(ctx->opcode, 0, 3);
22133 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22134 (extract32(ctx->opcode, 8, 1) << 2);
22135 rt = decode_gpr_gpr4_zero(rt);
22136 rs = decode_gpr_gpr4(rs);
22137 gen_st(ctx, OPC_SW, rt, rs, offset);
22138 break;
22139 case NM_LWGP16:
22140 offset = extract32(ctx->opcode, 0, 7) << 2;
22141 gen_ld(ctx, OPC_LW, rt, 28, offset);
22142 break;
22143 case NM_SWSP16:
22144 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22145 offset = extract32(ctx->opcode, 0, 5) << 2;
22146 gen_st(ctx, OPC_SW, rt, 29, offset);
22147 break;
22148 case NM_SW16:
22149 rt = decode_gpr_gpr3_src_store(
22150 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22151 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22152 offset = extract32(ctx->opcode, 0, 4) << 2;
22153 gen_st(ctx, OPC_SW, rt, rs, offset);
22154 break;
22155 case NM_SWGP16:
22156 rt = decode_gpr_gpr3_src_store(
22157 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22158 offset = extract32(ctx->opcode, 0, 7) << 2;
22159 gen_st(ctx, OPC_SW, rt, 28, offset);
22160 break;
22161 case NM_BC16:
22162 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
22163 (sextract32(ctx->opcode, 0, 1) << 10) |
22164 (extract32(ctx->opcode, 1, 9) << 1));
22165 break;
22166 case NM_BALC16:
22167 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
22168 (sextract32(ctx->opcode, 0, 1) << 10) |
22169 (extract32(ctx->opcode, 1, 9) << 1));
22170 break;
22171 case NM_BEQZC16:
22172 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
22173 (sextract32(ctx->opcode, 0, 1) << 7) |
22174 (extract32(ctx->opcode, 1, 6) << 1));
22175 break;
22176 case NM_BNEZC16:
22177 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
22178 (sextract32(ctx->opcode, 0, 1) << 7) |
22179 (extract32(ctx->opcode, 1, 6) << 1));
22180 break;
22181 case NM_P16_BR:
22182 switch (ctx->opcode & 0xf) {
22183 case 0:
22184 /* P16.JRC */
22185 switch (extract32(ctx->opcode, 4, 1)) {
22186 case NM_JRC:
22187 gen_compute_branch_nm(ctx, OPC_JR, 2,
22188 extract32(ctx->opcode, 5, 5), 0, 0);
22189 break;
22190 case NM_JALRC16:
22191 gen_compute_branch_nm(ctx, OPC_JALR, 2,
22192 extract32(ctx->opcode, 5, 5), 31, 0);
22193 break;
22194 }
22195 break;
22196 default:
22197 {
22198 /* P16.BRI */
22199 uint32_t opc = extract32(ctx->opcode, 4, 3) <
22200 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
22201 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
22202 extract32(ctx->opcode, 0, 4) << 1);
22203 }
22204 break;
22205 }
22206 break;
22207 case NM_P16_SR:
22208 {
22209 int count = extract32(ctx->opcode, 0, 4);
22210 int u = extract32(ctx->opcode, 4, 4) << 4;
22211
22212 rt = 30 + extract32(ctx->opcode, 9, 1);
22213 switch (extract32(ctx->opcode, 8, 1)) {
22214 case NM_SAVE16:
22215 gen_save(ctx, rt, count, 0, u);
22216 break;
22217 case NM_RESTORE_JRC16:
22218 gen_restore(ctx, rt, count, 0, u);
22219 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
22220 break;
22221 }
22222 }
22223 break;
22224 case NM_MOVEP:
22225 case NM_MOVEPREV:
22226 check_nms(ctx);
22227 {
22228 static const int gpr2reg1[] = {4, 5, 6, 7};
22229 static const int gpr2reg2[] = {5, 6, 7, 8};
22230 int re;
22231 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
22232 extract32(ctx->opcode, 8, 1);
22233 int r1 = gpr2reg1[rd2];
22234 int r2 = gpr2reg2[rd2];
22235 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
22236 extract32(ctx->opcode, 0, 3);
22237 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
22238 extract32(ctx->opcode, 5, 3);
22239 TCGv t0 = tcg_temp_new();
22240 TCGv t1 = tcg_temp_new();
22241 if (op == NM_MOVEP) {
22242 rd = r1;
22243 re = r2;
22244 rs = decode_gpr_gpr4_zero(r3);
22245 rt = decode_gpr_gpr4_zero(r4);
22246 } else {
22247 rd = decode_gpr_gpr4(r3);
22248 re = decode_gpr_gpr4(r4);
22249 rs = r1;
22250 rt = r2;
22251 }
22252 gen_load_gpr(t0, rs);
22253 gen_load_gpr(t1, rt);
22254 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22255 tcg_gen_mov_tl(cpu_gpr[re], t1);
22256 tcg_temp_free(t0);
22257 tcg_temp_free(t1);
22258 }
22259 break;
22260 default:
22261 return decode_nanomips_32_48_opc(env, ctx);
22262 }
22263
22264 return 2;
22265 }
22266
22267
22268 /* SmartMIPS extension to MIPS32 */
22269
22270 #if defined(TARGET_MIPS64)
22271
22272 /* MDMX extension to MIPS64 */
22273
22274 #endif
22275
22276 /* MIPSDSP functions. */
22277 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
22278 int rd, int base, int offset)
22279 {
22280 TCGv t0;
22281
22282 check_dsp(ctx);
22283 t0 = tcg_temp_new();
22284
22285 if (base == 0) {
22286 gen_load_gpr(t0, offset);
22287 } else if (offset == 0) {
22288 gen_load_gpr(t0, base);
22289 } else {
22290 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
22291 }
22292
22293 switch (opc) {
22294 case OPC_LBUX:
22295 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
22296 gen_store_gpr(t0, rd);
22297 break;
22298 case OPC_LHX:
22299 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
22300 gen_store_gpr(t0, rd);
22301 break;
22302 case OPC_LWX:
22303 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
22304 gen_store_gpr(t0, rd);
22305 break;
22306 #if defined(TARGET_MIPS64)
22307 case OPC_LDX:
22308 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
22309 gen_store_gpr(t0, rd);
22310 break;
22311 #endif
22312 }
22313 tcg_temp_free(t0);
22314 }
22315
22316 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
22317 int ret, int v1, int v2)
22318 {
22319 TCGv v1_t;
22320 TCGv v2_t;
22321
22322 if (ret == 0) {
22323 /* Treat as NOP. */
22324 return;
22325 }
22326
22327 v1_t = tcg_temp_new();
22328 v2_t = tcg_temp_new();
22329
22330 gen_load_gpr(v1_t, v1);
22331 gen_load_gpr(v2_t, v2);
22332
22333 switch (op1) {
22334 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
22335 case OPC_MULT_G_2E:
22336 check_dsp_r2(ctx);
22337 switch (op2) {
22338 case OPC_ADDUH_QB:
22339 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
22340 break;
22341 case OPC_ADDUH_R_QB:
22342 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22343 break;
22344 case OPC_ADDQH_PH:
22345 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
22346 break;
22347 case OPC_ADDQH_R_PH:
22348 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22349 break;
22350 case OPC_ADDQH_W:
22351 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
22352 break;
22353 case OPC_ADDQH_R_W:
22354 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22355 break;
22356 case OPC_SUBUH_QB:
22357 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
22358 break;
22359 case OPC_SUBUH_R_QB:
22360 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22361 break;
22362 case OPC_SUBQH_PH:
22363 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
22364 break;
22365 case OPC_SUBQH_R_PH:
22366 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22367 break;
22368 case OPC_SUBQH_W:
22369 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
22370 break;
22371 case OPC_SUBQH_R_W:
22372 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22373 break;
22374 }
22375 break;
22376 case OPC_ABSQ_S_PH_DSP:
22377 switch (op2) {
22378 case OPC_ABSQ_S_QB:
22379 check_dsp_r2(ctx);
22380 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
22381 break;
22382 case OPC_ABSQ_S_PH:
22383 check_dsp(ctx);
22384 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
22385 break;
22386 case OPC_ABSQ_S_W:
22387 check_dsp(ctx);
22388 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
22389 break;
22390 case OPC_PRECEQ_W_PHL:
22391 check_dsp(ctx);
22392 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
22393 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22394 break;
22395 case OPC_PRECEQ_W_PHR:
22396 check_dsp(ctx);
22397 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
22398 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
22399 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22400 break;
22401 case OPC_PRECEQU_PH_QBL:
22402 check_dsp(ctx);
22403 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
22404 break;
22405 case OPC_PRECEQU_PH_QBR:
22406 check_dsp(ctx);
22407 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
22408 break;
22409 case OPC_PRECEQU_PH_QBLA:
22410 check_dsp(ctx);
22411 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
22412 break;
22413 case OPC_PRECEQU_PH_QBRA:
22414 check_dsp(ctx);
22415 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
22416 break;
22417 case OPC_PRECEU_PH_QBL:
22418 check_dsp(ctx);
22419 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
22420 break;
22421 case OPC_PRECEU_PH_QBR:
22422 check_dsp(ctx);
22423 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
22424 break;
22425 case OPC_PRECEU_PH_QBLA:
22426 check_dsp(ctx);
22427 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
22428 break;
22429 case OPC_PRECEU_PH_QBRA:
22430 check_dsp(ctx);
22431 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
22432 break;
22433 }
22434 break;
22435 case OPC_ADDU_QB_DSP:
22436 switch (op2) {
22437 case OPC_ADDQ_PH:
22438 check_dsp(ctx);
22439 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22440 break;
22441 case OPC_ADDQ_S_PH:
22442 check_dsp(ctx);
22443 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22444 break;
22445 case OPC_ADDQ_S_W:
22446 check_dsp(ctx);
22447 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22448 break;
22449 case OPC_ADDU_QB:
22450 check_dsp(ctx);
22451 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22452 break;
22453 case OPC_ADDU_S_QB:
22454 check_dsp(ctx);
22455 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22456 break;
22457 case OPC_ADDU_PH:
22458 check_dsp_r2(ctx);
22459 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22460 break;
22461 case OPC_ADDU_S_PH:
22462 check_dsp_r2(ctx);
22463 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22464 break;
22465 case OPC_SUBQ_PH:
22466 check_dsp(ctx);
22467 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22468 break;
22469 case OPC_SUBQ_S_PH:
22470 check_dsp(ctx);
22471 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22472 break;
22473 case OPC_SUBQ_S_W:
22474 check_dsp(ctx);
22475 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22476 break;
22477 case OPC_SUBU_QB:
22478 check_dsp(ctx);
22479 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22480 break;
22481 case OPC_SUBU_S_QB:
22482 check_dsp(ctx);
22483 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22484 break;
22485 case OPC_SUBU_PH:
22486 check_dsp_r2(ctx);
22487 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22488 break;
22489 case OPC_SUBU_S_PH:
22490 check_dsp_r2(ctx);
22491 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22492 break;
22493 case OPC_ADDSC:
22494 check_dsp(ctx);
22495 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22496 break;
22497 case OPC_ADDWC:
22498 check_dsp(ctx);
22499 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22500 break;
22501 case OPC_MODSUB:
22502 check_dsp(ctx);
22503 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
22504 break;
22505 case OPC_RADDU_W_QB:
22506 check_dsp(ctx);
22507 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
22508 break;
22509 }
22510 break;
22511 case OPC_CMPU_EQ_QB_DSP:
22512 switch (op2) {
22513 case OPC_PRECR_QB_PH:
22514 check_dsp_r2(ctx);
22515 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22516 break;
22517 case OPC_PRECRQ_QB_PH:
22518 check_dsp(ctx);
22519 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22520 break;
22521 case OPC_PRECR_SRA_PH_W:
22522 check_dsp_r2(ctx);
22523 {
22524 TCGv_i32 sa_t = tcg_const_i32(v2);
22525 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
22526 cpu_gpr[ret]);
22527 tcg_temp_free_i32(sa_t);
22528 break;
22529 }
22530 case OPC_PRECR_SRA_R_PH_W:
22531 check_dsp_r2(ctx);
22532 {
22533 TCGv_i32 sa_t = tcg_const_i32(v2);
22534 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
22535 cpu_gpr[ret]);
22536 tcg_temp_free_i32(sa_t);
22537 break;
22538 }
22539 case OPC_PRECRQ_PH_W:
22540 check_dsp(ctx);
22541 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
22542 break;
22543 case OPC_PRECRQ_RS_PH_W:
22544 check_dsp(ctx);
22545 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22546 break;
22547 case OPC_PRECRQU_S_QB_PH:
22548 check_dsp(ctx);
22549 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22550 break;
22551 }
22552 break;
22553 #ifdef TARGET_MIPS64
22554 case OPC_ABSQ_S_QH_DSP:
22555 switch (op2) {
22556 case OPC_PRECEQ_L_PWL:
22557 check_dsp(ctx);
22558 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
22559 break;
22560 case OPC_PRECEQ_L_PWR:
22561 check_dsp(ctx);
22562 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
22563 break;
22564 case OPC_PRECEQ_PW_QHL:
22565 check_dsp(ctx);
22566 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
22567 break;
22568 case OPC_PRECEQ_PW_QHR:
22569 check_dsp(ctx);
22570 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
22571 break;
22572 case OPC_PRECEQ_PW_QHLA:
22573 check_dsp(ctx);
22574 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
22575 break;
22576 case OPC_PRECEQ_PW_QHRA:
22577 check_dsp(ctx);
22578 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
22579 break;
22580 case OPC_PRECEQU_QH_OBL:
22581 check_dsp(ctx);
22582 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
22583 break;
22584 case OPC_PRECEQU_QH_OBR:
22585 check_dsp(ctx);
22586 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
22587 break;
22588 case OPC_PRECEQU_QH_OBLA:
22589 check_dsp(ctx);
22590 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
22591 break;
22592 case OPC_PRECEQU_QH_OBRA:
22593 check_dsp(ctx);
22594 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
22595 break;
22596 case OPC_PRECEU_QH_OBL:
22597 check_dsp(ctx);
22598 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
22599 break;
22600 case OPC_PRECEU_QH_OBR:
22601 check_dsp(ctx);
22602 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
22603 break;
22604 case OPC_PRECEU_QH_OBLA:
22605 check_dsp(ctx);
22606 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
22607 break;
22608 case OPC_PRECEU_QH_OBRA:
22609 check_dsp(ctx);
22610 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
22611 break;
22612 case OPC_ABSQ_S_OB:
22613 check_dsp_r2(ctx);
22614 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
22615 break;
22616 case OPC_ABSQ_S_PW:
22617 check_dsp(ctx);
22618 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
22619 break;
22620 case OPC_ABSQ_S_QH:
22621 check_dsp(ctx);
22622 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
22623 break;
22624 }
22625 break;
22626 case OPC_ADDU_OB_DSP:
22627 switch (op2) {
22628 case OPC_RADDU_L_OB:
22629 check_dsp(ctx);
22630 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
22631 break;
22632 case OPC_SUBQ_PW:
22633 check_dsp(ctx);
22634 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22635 break;
22636 case OPC_SUBQ_S_PW:
22637 check_dsp(ctx);
22638 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22639 break;
22640 case OPC_SUBQ_QH:
22641 check_dsp(ctx);
22642 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22643 break;
22644 case OPC_SUBQ_S_QH:
22645 check_dsp(ctx);
22646 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22647 break;
22648 case OPC_SUBU_OB:
22649 check_dsp(ctx);
22650 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22651 break;
22652 case OPC_SUBU_S_OB:
22653 check_dsp(ctx);
22654 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22655 break;
22656 case OPC_SUBU_QH:
22657 check_dsp_r2(ctx);
22658 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22659 break;
22660 case OPC_SUBU_S_QH:
22661 check_dsp_r2(ctx);
22662 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22663 break;
22664 case OPC_SUBUH_OB:
22665 check_dsp_r2(ctx);
22666 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
22667 break;
22668 case OPC_SUBUH_R_OB:
22669 check_dsp_r2(ctx);
22670 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22671 break;
22672 case OPC_ADDQ_PW:
22673 check_dsp(ctx);
22674 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22675 break;
22676 case OPC_ADDQ_S_PW:
22677 check_dsp(ctx);
22678 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22679 break;
22680 case OPC_ADDQ_QH:
22681 check_dsp(ctx);
22682 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22683 break;
22684 case OPC_ADDQ_S_QH:
22685 check_dsp(ctx);
22686 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22687 break;
22688 case OPC_ADDU_OB:
22689 check_dsp(ctx);
22690 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22691 break;
22692 case OPC_ADDU_S_OB:
22693 check_dsp(ctx);
22694 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22695 break;
22696 case OPC_ADDU_QH:
22697 check_dsp_r2(ctx);
22698 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22699 break;
22700 case OPC_ADDU_S_QH:
22701 check_dsp_r2(ctx);
22702 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22703 break;
22704 case OPC_ADDUH_OB:
22705 check_dsp_r2(ctx);
22706 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
22707 break;
22708 case OPC_ADDUH_R_OB:
22709 check_dsp_r2(ctx);
22710 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22711 break;
22712 }
22713 break;
22714 case OPC_CMPU_EQ_OB_DSP:
22715 switch (op2) {
22716 case OPC_PRECR_OB_QH:
22717 check_dsp_r2(ctx);
22718 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22719 break;
22720 case OPC_PRECR_SRA_QH_PW:
22721 check_dsp_r2(ctx);
22722 {
22723 TCGv_i32 ret_t = tcg_const_i32(ret);
22724 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
22725 tcg_temp_free_i32(ret_t);
22726 break;
22727 }
22728 case OPC_PRECR_SRA_R_QH_PW:
22729 check_dsp_r2(ctx);
22730 {
22731 TCGv_i32 sa_v = tcg_const_i32(ret);
22732 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
22733 tcg_temp_free_i32(sa_v);
22734 break;
22735 }
22736 case OPC_PRECRQ_OB_QH:
22737 check_dsp(ctx);
22738 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22739 break;
22740 case OPC_PRECRQ_PW_L:
22741 check_dsp(ctx);
22742 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
22743 break;
22744 case OPC_PRECRQ_QH_PW:
22745 check_dsp(ctx);
22746 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
22747 break;
22748 case OPC_PRECRQ_RS_QH_PW:
22749 check_dsp(ctx);
22750 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22751 break;
22752 case OPC_PRECRQU_S_OB_QH:
22753 check_dsp(ctx);
22754 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22755 break;
22756 }
22757 break;
22758 #endif
22759 }
22760
22761 tcg_temp_free(v1_t);
22762 tcg_temp_free(v2_t);
22763 }
22764
22765 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
22766 int ret, int v1, int v2)
22767 {
22768 uint32_t op2;
22769 TCGv t0;
22770 TCGv v1_t;
22771 TCGv v2_t;
22772
22773 if (ret == 0) {
22774 /* Treat as NOP. */
22775 return;
22776 }
22777
22778 t0 = tcg_temp_new();
22779 v1_t = tcg_temp_new();
22780 v2_t = tcg_temp_new();
22781
22782 tcg_gen_movi_tl(t0, v1);
22783 gen_load_gpr(v1_t, v1);
22784 gen_load_gpr(v2_t, v2);
22785
22786 switch (opc) {
22787 case OPC_SHLL_QB_DSP:
22788 {
22789 op2 = MASK_SHLL_QB(ctx->opcode);
22790 switch (op2) {
22791 case OPC_SHLL_QB:
22792 check_dsp(ctx);
22793 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
22794 break;
22795 case OPC_SHLLV_QB:
22796 check_dsp(ctx);
22797 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22798 break;
22799 case OPC_SHLL_PH:
22800 check_dsp(ctx);
22801 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22802 break;
22803 case OPC_SHLLV_PH:
22804 check_dsp(ctx);
22805 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22806 break;
22807 case OPC_SHLL_S_PH:
22808 check_dsp(ctx);
22809 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22810 break;
22811 case OPC_SHLLV_S_PH:
22812 check_dsp(ctx);
22813 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22814 break;
22815 case OPC_SHLL_S_W:
22816 check_dsp(ctx);
22817 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
22818 break;
22819 case OPC_SHLLV_S_W:
22820 check_dsp(ctx);
22821 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22822 break;
22823 case OPC_SHRL_QB:
22824 check_dsp(ctx);
22825 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
22826 break;
22827 case OPC_SHRLV_QB:
22828 check_dsp(ctx);
22829 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
22830 break;
22831 case OPC_SHRL_PH:
22832 check_dsp_r2(ctx);
22833 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
22834 break;
22835 case OPC_SHRLV_PH:
22836 check_dsp_r2(ctx);
22837 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
22838 break;
22839 case OPC_SHRA_QB:
22840 check_dsp_r2(ctx);
22841 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
22842 break;
22843 case OPC_SHRA_R_QB:
22844 check_dsp_r2(ctx);
22845 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
22846 break;
22847 case OPC_SHRAV_QB:
22848 check_dsp_r2(ctx);
22849 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
22850 break;
22851 case OPC_SHRAV_R_QB:
22852 check_dsp_r2(ctx);
22853 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
22854 break;
22855 case OPC_SHRA_PH:
22856 check_dsp(ctx);
22857 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
22858 break;
22859 case OPC_SHRA_R_PH:
22860 check_dsp(ctx);
22861 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
22862 break;
22863 case OPC_SHRAV_PH:
22864 check_dsp(ctx);
22865 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
22866 break;
22867 case OPC_SHRAV_R_PH:
22868 check_dsp(ctx);
22869 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
22870 break;
22871 case OPC_SHRA_R_W:
22872 check_dsp(ctx);
22873 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
22874 break;
22875 case OPC_SHRAV_R_W:
22876 check_dsp(ctx);
22877 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
22878 break;
22879 default: /* Invalid */
22880 MIPS_INVAL("MASK SHLL.QB");
22881 generate_exception_end(ctx, EXCP_RI);
22882 break;
22883 }
22884 break;
22885 }
22886 #ifdef TARGET_MIPS64
22887 case OPC_SHLL_OB_DSP:
22888 op2 = MASK_SHLL_OB(ctx->opcode);
22889 switch (op2) {
22890 case OPC_SHLL_PW:
22891 check_dsp(ctx);
22892 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22893 break;
22894 case OPC_SHLLV_PW:
22895 check_dsp(ctx);
22896 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22897 break;
22898 case OPC_SHLL_S_PW:
22899 check_dsp(ctx);
22900 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22901 break;
22902 case OPC_SHLLV_S_PW:
22903 check_dsp(ctx);
22904 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22905 break;
22906 case OPC_SHLL_OB:
22907 check_dsp(ctx);
22908 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
22909 break;
22910 case OPC_SHLLV_OB:
22911 check_dsp(ctx);
22912 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22913 break;
22914 case OPC_SHLL_QH:
22915 check_dsp(ctx);
22916 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22917 break;
22918 case OPC_SHLLV_QH:
22919 check_dsp(ctx);
22920 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22921 break;
22922 case OPC_SHLL_S_QH:
22923 check_dsp(ctx);
22924 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22925 break;
22926 case OPC_SHLLV_S_QH:
22927 check_dsp(ctx);
22928 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22929 break;
22930 case OPC_SHRA_OB:
22931 check_dsp_r2(ctx);
22932 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
22933 break;
22934 case OPC_SHRAV_OB:
22935 check_dsp_r2(ctx);
22936 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
22937 break;
22938 case OPC_SHRA_R_OB:
22939 check_dsp_r2(ctx);
22940 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
22941 break;
22942 case OPC_SHRAV_R_OB:
22943 check_dsp_r2(ctx);
22944 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
22945 break;
22946 case OPC_SHRA_PW:
22947 check_dsp(ctx);
22948 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
22949 break;
22950 case OPC_SHRAV_PW:
22951 check_dsp(ctx);
22952 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
22953 break;
22954 case OPC_SHRA_R_PW:
22955 check_dsp(ctx);
22956 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
22957 break;
22958 case OPC_SHRAV_R_PW:
22959 check_dsp(ctx);
22960 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
22961 break;
22962 case OPC_SHRA_QH:
22963 check_dsp(ctx);
22964 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
22965 break;
22966 case OPC_SHRAV_QH:
22967 check_dsp(ctx);
22968 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
22969 break;
22970 case OPC_SHRA_R_QH:
22971 check_dsp(ctx);
22972 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
22973 break;
22974 case OPC_SHRAV_R_QH:
22975 check_dsp(ctx);
22976 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
22977 break;
22978 case OPC_SHRL_OB:
22979 check_dsp(ctx);
22980 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
22981 break;
22982 case OPC_SHRLV_OB:
22983 check_dsp(ctx);
22984 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
22985 break;
22986 case OPC_SHRL_QH:
22987 check_dsp_r2(ctx);
22988 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
22989 break;
22990 case OPC_SHRLV_QH:
22991 check_dsp_r2(ctx);
22992 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
22993 break;
22994 default: /* Invalid */
22995 MIPS_INVAL("MASK SHLL.OB");
22996 generate_exception_end(ctx, EXCP_RI);
22997 break;
22998 }
22999 break;
23000 #endif
23001 }
23002
23003 tcg_temp_free(t0);
23004 tcg_temp_free(v1_t);
23005 tcg_temp_free(v2_t);
23006 }
23007
23008 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
23009 int ret, int v1, int v2, int check_ret)
23010 {
23011 TCGv_i32 t0;
23012 TCGv v1_t;
23013 TCGv v2_t;
23014
23015 if ((ret == 0) && (check_ret == 1)) {
23016 /* Treat as NOP. */
23017 return;
23018 }
23019
23020 t0 = tcg_temp_new_i32();
23021 v1_t = tcg_temp_new();
23022 v2_t = tcg_temp_new();
23023
23024 tcg_gen_movi_i32(t0, ret);
23025 gen_load_gpr(v1_t, v1);
23026 gen_load_gpr(v2_t, v2);
23027
23028 switch (op1) {
23029 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
23030 * the same mask and op1. */
23031 case OPC_MULT_G_2E:
23032 check_dsp_r2(ctx);
23033 switch (op2) {
23034 case OPC_MUL_PH:
23035 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23036 break;
23037 case OPC_MUL_S_PH:
23038 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23039 break;
23040 case OPC_MULQ_S_W:
23041 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23042 break;
23043 case OPC_MULQ_RS_W:
23044 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23045 break;
23046 }
23047 break;
23048 case OPC_DPA_W_PH_DSP:
23049 switch (op2) {
23050 case OPC_DPAU_H_QBL:
23051 check_dsp(ctx);
23052 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
23053 break;
23054 case OPC_DPAU_H_QBR:
23055 check_dsp(ctx);
23056 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
23057 break;
23058 case OPC_DPSU_H_QBL:
23059 check_dsp(ctx);
23060 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
23061 break;
23062 case OPC_DPSU_H_QBR:
23063 check_dsp(ctx);
23064 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
23065 break;
23066 case OPC_DPA_W_PH:
23067 check_dsp_r2(ctx);
23068 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
23069 break;
23070 case OPC_DPAX_W_PH:
23071 check_dsp_r2(ctx);
23072 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
23073 break;
23074 case OPC_DPAQ_S_W_PH:
23075 check_dsp(ctx);
23076 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23077 break;
23078 case OPC_DPAQX_S_W_PH:
23079 check_dsp_r2(ctx);
23080 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23081 break;
23082 case OPC_DPAQX_SA_W_PH:
23083 check_dsp_r2(ctx);
23084 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23085 break;
23086 case OPC_DPS_W_PH:
23087 check_dsp_r2(ctx);
23088 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
23089 break;
23090 case OPC_DPSX_W_PH:
23091 check_dsp_r2(ctx);
23092 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
23093 break;
23094 case OPC_DPSQ_S_W_PH:
23095 check_dsp(ctx);
23096 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23097 break;
23098 case OPC_DPSQX_S_W_PH:
23099 check_dsp_r2(ctx);
23100 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23101 break;
23102 case OPC_DPSQX_SA_W_PH:
23103 check_dsp_r2(ctx);
23104 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23105 break;
23106 case OPC_MULSAQ_S_W_PH:
23107 check_dsp(ctx);
23108 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23109 break;
23110 case OPC_DPAQ_SA_L_W:
23111 check_dsp(ctx);
23112 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23113 break;
23114 case OPC_DPSQ_SA_L_W:
23115 check_dsp(ctx);
23116 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23117 break;
23118 case OPC_MAQ_S_W_PHL:
23119 check_dsp(ctx);
23120 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
23121 break;
23122 case OPC_MAQ_S_W_PHR:
23123 check_dsp(ctx);
23124 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
23125 break;
23126 case OPC_MAQ_SA_W_PHL:
23127 check_dsp(ctx);
23128 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
23129 break;
23130 case OPC_MAQ_SA_W_PHR:
23131 check_dsp(ctx);
23132 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
23133 break;
23134 case OPC_MULSA_W_PH:
23135 check_dsp_r2(ctx);
23136 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
23137 break;
23138 }
23139 break;
23140 #ifdef TARGET_MIPS64
23141 case OPC_DPAQ_W_QH_DSP:
23142 {
23143 int ac = ret & 0x03;
23144 tcg_gen_movi_i32(t0, ac);
23145
23146 switch (op2) {
23147 case OPC_DMADD:
23148 check_dsp(ctx);
23149 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
23150 break;
23151 case OPC_DMADDU:
23152 check_dsp(ctx);
23153 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
23154 break;
23155 case OPC_DMSUB:
23156 check_dsp(ctx);
23157 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
23158 break;
23159 case OPC_DMSUBU:
23160 check_dsp(ctx);
23161 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
23162 break;
23163 case OPC_DPA_W_QH:
23164 check_dsp_r2(ctx);
23165 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
23166 break;
23167 case OPC_DPAQ_S_W_QH:
23168 check_dsp(ctx);
23169 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23170 break;
23171 case OPC_DPAQ_SA_L_PW:
23172 check_dsp(ctx);
23173 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23174 break;
23175 case OPC_DPAU_H_OBL:
23176 check_dsp(ctx);
23177 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
23178 break;
23179 case OPC_DPAU_H_OBR:
23180 check_dsp(ctx);
23181 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
23182 break;
23183 case OPC_DPS_W_QH:
23184 check_dsp_r2(ctx);
23185 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
23186 break;
23187 case OPC_DPSQ_S_W_QH:
23188 check_dsp(ctx);
23189 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23190 break;
23191 case OPC_DPSQ_SA_L_PW:
23192 check_dsp(ctx);
23193 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23194 break;
23195 case OPC_DPSU_H_OBL:
23196 check_dsp(ctx);
23197 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
23198 break;
23199 case OPC_DPSU_H_OBR:
23200 check_dsp(ctx);
23201 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
23202 break;
23203 case OPC_MAQ_S_L_PWL:
23204 check_dsp(ctx);
23205 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
23206 break;
23207 case OPC_MAQ_S_L_PWR:
23208 check_dsp(ctx);
23209 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
23210 break;
23211 case OPC_MAQ_S_W_QHLL:
23212 check_dsp(ctx);
23213 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
23214 break;
23215 case OPC_MAQ_SA_W_QHLL:
23216 check_dsp(ctx);
23217 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
23218 break;
23219 case OPC_MAQ_S_W_QHLR:
23220 check_dsp(ctx);
23221 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
23222 break;
23223 case OPC_MAQ_SA_W_QHLR:
23224 check_dsp(ctx);
23225 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
23226 break;
23227 case OPC_MAQ_S_W_QHRL:
23228 check_dsp(ctx);
23229 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
23230 break;
23231 case OPC_MAQ_SA_W_QHRL:
23232 check_dsp(ctx);
23233 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
23234 break;
23235 case OPC_MAQ_S_W_QHRR:
23236 check_dsp(ctx);
23237 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
23238 break;
23239 case OPC_MAQ_SA_W_QHRR:
23240 check_dsp(ctx);
23241 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
23242 break;
23243 case OPC_MULSAQ_S_L_PW:
23244 check_dsp(ctx);
23245 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
23246 break;
23247 case OPC_MULSAQ_S_W_QH:
23248 check_dsp(ctx);
23249 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23250 break;
23251 }
23252 }
23253 break;
23254 #endif
23255 case OPC_ADDU_QB_DSP:
23256 switch (op2) {
23257 case OPC_MULEU_S_PH_QBL:
23258 check_dsp(ctx);
23259 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23260 break;
23261 case OPC_MULEU_S_PH_QBR:
23262 check_dsp(ctx);
23263 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23264 break;
23265 case OPC_MULQ_RS_PH:
23266 check_dsp(ctx);
23267 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23268 break;
23269 case OPC_MULEQ_S_W_PHL:
23270 check_dsp(ctx);
23271 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23272 break;
23273 case OPC_MULEQ_S_W_PHR:
23274 check_dsp(ctx);
23275 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23276 break;
23277 case OPC_MULQ_S_PH:
23278 check_dsp_r2(ctx);
23279 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23280 break;
23281 }
23282 break;
23283 #ifdef TARGET_MIPS64
23284 case OPC_ADDU_OB_DSP:
23285 switch (op2) {
23286 case OPC_MULEQ_S_PW_QHL:
23287 check_dsp(ctx);
23288 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23289 break;
23290 case OPC_MULEQ_S_PW_QHR:
23291 check_dsp(ctx);
23292 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23293 break;
23294 case OPC_MULEU_S_QH_OBL:
23295 check_dsp(ctx);
23296 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23297 break;
23298 case OPC_MULEU_S_QH_OBR:
23299 check_dsp(ctx);
23300 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23301 break;
23302 case OPC_MULQ_RS_QH:
23303 check_dsp(ctx);
23304 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23305 break;
23306 }
23307 break;
23308 #endif
23309 }
23310
23311 tcg_temp_free_i32(t0);
23312 tcg_temp_free(v1_t);
23313 tcg_temp_free(v2_t);
23314 }
23315
23316 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23317 int ret, int val)
23318 {
23319 int16_t imm;
23320 TCGv t0;
23321 TCGv val_t;
23322
23323 if (ret == 0) {
23324 /* Treat as NOP. */
23325 return;
23326 }
23327
23328 t0 = tcg_temp_new();
23329 val_t = tcg_temp_new();
23330 gen_load_gpr(val_t, val);
23331
23332 switch (op1) {
23333 case OPC_ABSQ_S_PH_DSP:
23334 switch (op2) {
23335 case OPC_BITREV:
23336 check_dsp(ctx);
23337 gen_helper_bitrev(cpu_gpr[ret], val_t);
23338 break;
23339 case OPC_REPL_QB:
23340 check_dsp(ctx);
23341 {
23342 target_long result;
23343 imm = (ctx->opcode >> 16) & 0xFF;
23344 result = (uint32_t)imm << 24 |
23345 (uint32_t)imm << 16 |
23346 (uint32_t)imm << 8 |
23347 (uint32_t)imm;
23348 result = (int32_t)result;
23349 tcg_gen_movi_tl(cpu_gpr[ret], result);
23350 }
23351 break;
23352 case OPC_REPLV_QB:
23353 check_dsp(ctx);
23354 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23355 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23356 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23357 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23358 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23359 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23360 break;
23361 case OPC_REPL_PH:
23362 check_dsp(ctx);
23363 {
23364 imm = (ctx->opcode >> 16) & 0x03FF;
23365 imm = (int16_t)(imm << 6) >> 6;
23366 tcg_gen_movi_tl(cpu_gpr[ret], \
23367 (target_long)((int32_t)imm << 16 | \
23368 (uint16_t)imm));
23369 }
23370 break;
23371 case OPC_REPLV_PH:
23372 check_dsp(ctx);
23373 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23374 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23375 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23376 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23377 break;
23378 }
23379 break;
23380 #ifdef TARGET_MIPS64
23381 case OPC_ABSQ_S_QH_DSP:
23382 switch (op2) {
23383 case OPC_REPL_OB:
23384 check_dsp(ctx);
23385 {
23386 target_long temp;
23387
23388 imm = (ctx->opcode >> 16) & 0xFF;
23389 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
23390 temp = (temp << 16) | temp;
23391 temp = (temp << 32) | temp;
23392 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23393 break;
23394 }
23395 case OPC_REPL_PW:
23396 check_dsp(ctx);
23397 {
23398 target_long temp;
23399
23400 imm = (ctx->opcode >> 16) & 0x03FF;
23401 imm = (int16_t)(imm << 6) >> 6;
23402 temp = ((target_long)imm << 32) \
23403 | ((target_long)imm & 0xFFFFFFFF);
23404 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23405 break;
23406 }
23407 case OPC_REPL_QH:
23408 check_dsp(ctx);
23409 {
23410 target_long temp;
23411
23412 imm = (ctx->opcode >> 16) & 0x03FF;
23413 imm = (int16_t)(imm << 6) >> 6;
23414
23415 temp = ((uint64_t)(uint16_t)imm << 48) |
23416 ((uint64_t)(uint16_t)imm << 32) |
23417 ((uint64_t)(uint16_t)imm << 16) |
23418 (uint64_t)(uint16_t)imm;
23419 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23420 break;
23421 }
23422 case OPC_REPLV_OB:
23423 check_dsp(ctx);
23424 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23425 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23426 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23427 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23428 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23429 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23430 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23431 break;
23432 case OPC_REPLV_PW:
23433 check_dsp(ctx);
23434 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
23435 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23436 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23437 break;
23438 case OPC_REPLV_QH:
23439 check_dsp(ctx);
23440 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23441 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23442 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23443 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23444 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23445 break;
23446 }
23447 break;
23448 #endif
23449 }
23450 tcg_temp_free(t0);
23451 tcg_temp_free(val_t);
23452 }
23453
23454 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
23455 uint32_t op1, uint32_t op2,
23456 int ret, int v1, int v2, int check_ret)
23457 {
23458 TCGv t1;
23459 TCGv v1_t;
23460 TCGv v2_t;
23461
23462 if ((ret == 0) && (check_ret == 1)) {
23463 /* Treat as NOP. */
23464 return;
23465 }
23466
23467 t1 = tcg_temp_new();
23468 v1_t = tcg_temp_new();
23469 v2_t = tcg_temp_new();
23470
23471 gen_load_gpr(v1_t, v1);
23472 gen_load_gpr(v2_t, v2);
23473
23474 switch (op1) {
23475 case OPC_CMPU_EQ_QB_DSP:
23476 switch (op2) {
23477 case OPC_CMPU_EQ_QB:
23478 check_dsp(ctx);
23479 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
23480 break;
23481 case OPC_CMPU_LT_QB:
23482 check_dsp(ctx);
23483 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
23484 break;
23485 case OPC_CMPU_LE_QB:
23486 check_dsp(ctx);
23487 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
23488 break;
23489 case OPC_CMPGU_EQ_QB:
23490 check_dsp(ctx);
23491 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
23492 break;
23493 case OPC_CMPGU_LT_QB:
23494 check_dsp(ctx);
23495 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
23496 break;
23497 case OPC_CMPGU_LE_QB:
23498 check_dsp(ctx);
23499 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
23500 break;
23501 case OPC_CMPGDU_EQ_QB:
23502 check_dsp_r2(ctx);
23503 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
23504 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23505 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23506 tcg_gen_shli_tl(t1, t1, 24);
23507 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23508 break;
23509 case OPC_CMPGDU_LT_QB:
23510 check_dsp_r2(ctx);
23511 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
23512 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23513 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23514 tcg_gen_shli_tl(t1, t1, 24);
23515 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23516 break;
23517 case OPC_CMPGDU_LE_QB:
23518 check_dsp_r2(ctx);
23519 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
23520 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23521 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23522 tcg_gen_shli_tl(t1, t1, 24);
23523 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23524 break;
23525 case OPC_CMP_EQ_PH:
23526 check_dsp(ctx);
23527 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
23528 break;
23529 case OPC_CMP_LT_PH:
23530 check_dsp(ctx);
23531 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
23532 break;
23533 case OPC_CMP_LE_PH:
23534 check_dsp(ctx);
23535 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
23536 break;
23537 case OPC_PICK_QB:
23538 check_dsp(ctx);
23539 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23540 break;
23541 case OPC_PICK_PH:
23542 check_dsp(ctx);
23543 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23544 break;
23545 case OPC_PACKRL_PH:
23546 check_dsp(ctx);
23547 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
23548 break;
23549 }
23550 break;
23551 #ifdef TARGET_MIPS64
23552 case OPC_CMPU_EQ_OB_DSP:
23553 switch (op2) {
23554 case OPC_CMP_EQ_PW:
23555 check_dsp(ctx);
23556 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
23557 break;
23558 case OPC_CMP_LT_PW:
23559 check_dsp(ctx);
23560 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
23561 break;
23562 case OPC_CMP_LE_PW:
23563 check_dsp(ctx);
23564 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
23565 break;
23566 case OPC_CMP_EQ_QH:
23567 check_dsp(ctx);
23568 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
23569 break;
23570 case OPC_CMP_LT_QH:
23571 check_dsp(ctx);
23572 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
23573 break;
23574 case OPC_CMP_LE_QH:
23575 check_dsp(ctx);
23576 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
23577 break;
23578 case OPC_CMPGDU_EQ_OB:
23579 check_dsp_r2(ctx);
23580 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23581 break;
23582 case OPC_CMPGDU_LT_OB:
23583 check_dsp_r2(ctx);
23584 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23585 break;
23586 case OPC_CMPGDU_LE_OB:
23587 check_dsp_r2(ctx);
23588 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23589 break;
23590 case OPC_CMPGU_EQ_OB:
23591 check_dsp(ctx);
23592 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
23593 break;
23594 case OPC_CMPGU_LT_OB:
23595 check_dsp(ctx);
23596 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
23597 break;
23598 case OPC_CMPGU_LE_OB:
23599 check_dsp(ctx);
23600 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
23601 break;
23602 case OPC_CMPU_EQ_OB:
23603 check_dsp(ctx);
23604 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
23605 break;
23606 case OPC_CMPU_LT_OB:
23607 check_dsp(ctx);
23608 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
23609 break;
23610 case OPC_CMPU_LE_OB:
23611 check_dsp(ctx);
23612 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
23613 break;
23614 case OPC_PACKRL_PW:
23615 check_dsp(ctx);
23616 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
23617 break;
23618 case OPC_PICK_OB:
23619 check_dsp(ctx);
23620 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23621 break;
23622 case OPC_PICK_PW:
23623 check_dsp(ctx);
23624 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23625 break;
23626 case OPC_PICK_QH:
23627 check_dsp(ctx);
23628 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23629 break;
23630 }
23631 break;
23632 #endif
23633 }
23634
23635 tcg_temp_free(t1);
23636 tcg_temp_free(v1_t);
23637 tcg_temp_free(v2_t);
23638 }
23639
23640 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
23641 uint32_t op1, int rt, int rs, int sa)
23642 {
23643 TCGv t0;
23644
23645 check_dsp_r2(ctx);
23646
23647 if (rt == 0) {
23648 /* Treat as NOP. */
23649 return;
23650 }
23651
23652 t0 = tcg_temp_new();
23653 gen_load_gpr(t0, rs);
23654
23655 switch (op1) {
23656 case OPC_APPEND_DSP:
23657 switch (MASK_APPEND(ctx->opcode)) {
23658 case OPC_APPEND:
23659 if (sa != 0) {
23660 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
23661 }
23662 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23663 break;
23664 case OPC_PREPEND:
23665 if (sa != 0) {
23666 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
23667 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23668 tcg_gen_shli_tl(t0, t0, 32 - sa);
23669 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23670 }
23671 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23672 break;
23673 case OPC_BALIGN:
23674 sa &= 3;
23675 if (sa != 0 && sa != 2) {
23676 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23677 tcg_gen_ext32u_tl(t0, t0);
23678 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
23679 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23680 }
23681 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23682 break;
23683 default: /* Invalid */
23684 MIPS_INVAL("MASK APPEND");
23685 generate_exception_end(ctx, EXCP_RI);
23686 break;
23687 }
23688 break;
23689 #ifdef TARGET_MIPS64
23690 case OPC_DAPPEND_DSP:
23691 switch (MASK_DAPPEND(ctx->opcode)) {
23692 case OPC_DAPPEND:
23693 if (sa != 0) {
23694 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
23695 }
23696 break;
23697 case OPC_PREPENDD:
23698 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
23699 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
23700 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
23701 break;
23702 case OPC_PREPENDW:
23703 if (sa != 0) {
23704 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23705 tcg_gen_shli_tl(t0, t0, 64 - sa);
23706 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23707 }
23708 break;
23709 case OPC_DBALIGN:
23710 sa &= 7;
23711 if (sa != 0 && sa != 2 && sa != 4) {
23712 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23713 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
23714 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23715 }
23716 break;
23717 default: /* Invalid */
23718 MIPS_INVAL("MASK DAPPEND");
23719 generate_exception_end(ctx, EXCP_RI);
23720 break;
23721 }
23722 break;
23723 #endif
23724 }
23725 tcg_temp_free(t0);
23726 }
23727
23728 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23729 int ret, int v1, int v2, int check_ret)
23730
23731 {
23732 TCGv t0;
23733 TCGv t1;
23734 TCGv v1_t;
23735 TCGv v2_t;
23736 int16_t imm;
23737
23738 if ((ret == 0) && (check_ret == 1)) {
23739 /* Treat as NOP. */
23740 return;
23741 }
23742
23743 t0 = tcg_temp_new();
23744 t1 = tcg_temp_new();
23745 v1_t = tcg_temp_new();
23746 v2_t = tcg_temp_new();
23747
23748 gen_load_gpr(v1_t, v1);
23749 gen_load_gpr(v2_t, v2);
23750
23751 switch (op1) {
23752 case OPC_EXTR_W_DSP:
23753 check_dsp(ctx);
23754 switch (op2) {
23755 case OPC_EXTR_W:
23756 tcg_gen_movi_tl(t0, v2);
23757 tcg_gen_movi_tl(t1, v1);
23758 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
23759 break;
23760 case OPC_EXTR_R_W:
23761 tcg_gen_movi_tl(t0, v2);
23762 tcg_gen_movi_tl(t1, v1);
23763 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23764 break;
23765 case OPC_EXTR_RS_W:
23766 tcg_gen_movi_tl(t0, v2);
23767 tcg_gen_movi_tl(t1, v1);
23768 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23769 break;
23770 case OPC_EXTR_S_H:
23771 tcg_gen_movi_tl(t0, v2);
23772 tcg_gen_movi_tl(t1, v1);
23773 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23774 break;
23775 case OPC_EXTRV_S_H:
23776 tcg_gen_movi_tl(t0, v2);
23777 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
23778 break;
23779 case OPC_EXTRV_W:
23780 tcg_gen_movi_tl(t0, v2);
23781 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23782 break;
23783 case OPC_EXTRV_R_W:
23784 tcg_gen_movi_tl(t0, v2);
23785 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23786 break;
23787 case OPC_EXTRV_RS_W:
23788 tcg_gen_movi_tl(t0, v2);
23789 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23790 break;
23791 case OPC_EXTP:
23792 tcg_gen_movi_tl(t0, v2);
23793 tcg_gen_movi_tl(t1, v1);
23794 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
23795 break;
23796 case OPC_EXTPV:
23797 tcg_gen_movi_tl(t0, v2);
23798 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
23799 break;
23800 case OPC_EXTPDP:
23801 tcg_gen_movi_tl(t0, v2);
23802 tcg_gen_movi_tl(t1, v1);
23803 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
23804 break;
23805 case OPC_EXTPDPV:
23806 tcg_gen_movi_tl(t0, v2);
23807 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23808 break;
23809 case OPC_SHILO:
23810 imm = (ctx->opcode >> 20) & 0x3F;
23811 tcg_gen_movi_tl(t0, ret);
23812 tcg_gen_movi_tl(t1, imm);
23813 gen_helper_shilo(t0, t1, cpu_env);
23814 break;
23815 case OPC_SHILOV:
23816 tcg_gen_movi_tl(t0, ret);
23817 gen_helper_shilo(t0, v1_t, cpu_env);
23818 break;
23819 case OPC_MTHLIP:
23820 tcg_gen_movi_tl(t0, ret);
23821 gen_helper_mthlip(t0, v1_t, cpu_env);
23822 break;
23823 case OPC_WRDSP:
23824 imm = (ctx->opcode >> 11) & 0x3FF;
23825 tcg_gen_movi_tl(t0, imm);
23826 gen_helper_wrdsp(v1_t, t0, cpu_env);
23827 break;
23828 case OPC_RDDSP:
23829 imm = (ctx->opcode >> 16) & 0x03FF;
23830 tcg_gen_movi_tl(t0, imm);
23831 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
23832 break;
23833 }
23834 break;
23835 #ifdef TARGET_MIPS64
23836 case OPC_DEXTR_W_DSP:
23837 check_dsp(ctx);
23838 switch (op2) {
23839 case OPC_DMTHLIP:
23840 tcg_gen_movi_tl(t0, ret);
23841 gen_helper_dmthlip(v1_t, t0, cpu_env);
23842 break;
23843 case OPC_DSHILO:
23844 {
23845 int shift = (ctx->opcode >> 19) & 0x7F;
23846 int ac = (ctx->opcode >> 11) & 0x03;
23847 tcg_gen_movi_tl(t0, shift);
23848 tcg_gen_movi_tl(t1, ac);
23849 gen_helper_dshilo(t0, t1, cpu_env);
23850 break;
23851 }
23852 case OPC_DSHILOV:
23853 {
23854 int ac = (ctx->opcode >> 11) & 0x03;
23855 tcg_gen_movi_tl(t0, ac);
23856 gen_helper_dshilo(v1_t, t0, cpu_env);
23857 break;
23858 }
23859 case OPC_DEXTP:
23860 tcg_gen_movi_tl(t0, v2);
23861 tcg_gen_movi_tl(t1, v1);
23862
23863 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
23864 break;
23865 case OPC_DEXTPV:
23866 tcg_gen_movi_tl(t0, v2);
23867 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
23868 break;
23869 case OPC_DEXTPDP:
23870 tcg_gen_movi_tl(t0, v2);
23871 tcg_gen_movi_tl(t1, v1);
23872 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
23873 break;
23874 case OPC_DEXTPDPV:
23875 tcg_gen_movi_tl(t0, v2);
23876 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23877 break;
23878 case OPC_DEXTR_L:
23879 tcg_gen_movi_tl(t0, v2);
23880 tcg_gen_movi_tl(t1, v1);
23881 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
23882 break;
23883 case OPC_DEXTR_R_L:
23884 tcg_gen_movi_tl(t0, v2);
23885 tcg_gen_movi_tl(t1, v1);
23886 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
23887 break;
23888 case OPC_DEXTR_RS_L:
23889 tcg_gen_movi_tl(t0, v2);
23890 tcg_gen_movi_tl(t1, v1);
23891 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
23892 break;
23893 case OPC_DEXTR_W:
23894 tcg_gen_movi_tl(t0, v2);
23895 tcg_gen_movi_tl(t1, v1);
23896 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
23897 break;
23898 case OPC_DEXTR_R_W:
23899 tcg_gen_movi_tl(t0, v2);
23900 tcg_gen_movi_tl(t1, v1);
23901 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23902 break;
23903 case OPC_DEXTR_RS_W:
23904 tcg_gen_movi_tl(t0, v2);
23905 tcg_gen_movi_tl(t1, v1);
23906 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23907 break;
23908 case OPC_DEXTR_S_H:
23909 tcg_gen_movi_tl(t0, v2);
23910 tcg_gen_movi_tl(t1, v1);
23911 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23912 break;
23913 case OPC_DEXTRV_S_H:
23914 tcg_gen_movi_tl(t0, v2);
23915 tcg_gen_movi_tl(t1, v1);
23916 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23917 break;
23918 case OPC_DEXTRV_L:
23919 tcg_gen_movi_tl(t0, v2);
23920 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23921 break;
23922 case OPC_DEXTRV_R_L:
23923 tcg_gen_movi_tl(t0, v2);
23924 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23925 break;
23926 case OPC_DEXTRV_RS_L:
23927 tcg_gen_movi_tl(t0, v2);
23928 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23929 break;
23930 case OPC_DEXTRV_W:
23931 tcg_gen_movi_tl(t0, v2);
23932 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23933 break;
23934 case OPC_DEXTRV_R_W:
23935 tcg_gen_movi_tl(t0, v2);
23936 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23937 break;
23938 case OPC_DEXTRV_RS_W:
23939 tcg_gen_movi_tl(t0, v2);
23940 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23941 break;
23942 }
23943 break;
23944 #endif
23945 }
23946
23947 tcg_temp_free(t0);
23948 tcg_temp_free(t1);
23949 tcg_temp_free(v1_t);
23950 tcg_temp_free(v2_t);
23951 }
23952
23953 /* End MIPSDSP functions. */
23954
23955 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
23956 {
23957 int rs, rt, rd, sa;
23958 uint32_t op1, op2;
23959
23960 rs = (ctx->opcode >> 21) & 0x1f;
23961 rt = (ctx->opcode >> 16) & 0x1f;
23962 rd = (ctx->opcode >> 11) & 0x1f;
23963 sa = (ctx->opcode >> 6) & 0x1f;
23964
23965 op1 = MASK_SPECIAL(ctx->opcode);
23966 switch (op1) {
23967 case OPC_LSA:
23968 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
23969 break;
23970 case OPC_MULT:
23971 case OPC_MULTU:
23972 case OPC_DIV:
23973 case OPC_DIVU:
23974 op2 = MASK_R6_MULDIV(ctx->opcode);
23975 switch (op2) {
23976 case R6_OPC_MUL:
23977 case R6_OPC_MUH:
23978 case R6_OPC_MULU:
23979 case R6_OPC_MUHU:
23980 case R6_OPC_DIV:
23981 case R6_OPC_MOD:
23982 case R6_OPC_DIVU:
23983 case R6_OPC_MODU:
23984 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23985 break;
23986 default:
23987 MIPS_INVAL("special_r6 muldiv");
23988 generate_exception_end(ctx, EXCP_RI);
23989 break;
23990 }
23991 break;
23992 case OPC_SELEQZ:
23993 case OPC_SELNEZ:
23994 gen_cond_move(ctx, op1, rd, rs, rt);
23995 break;
23996 case R6_OPC_CLO:
23997 case R6_OPC_CLZ:
23998 if (rt == 0 && sa == 1) {
23999 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
24000 We need additionally to check other fields */
24001 gen_cl(ctx, op1, rd, rs);
24002 } else {
24003 generate_exception_end(ctx, EXCP_RI);
24004 }
24005 break;
24006 case R6_OPC_SDBBP:
24007 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
24008 gen_helper_do_semihosting(cpu_env);
24009 } else {
24010 if (ctx->hflags & MIPS_HFLAG_SBRI) {
24011 generate_exception_end(ctx, EXCP_RI);
24012 } else {
24013 generate_exception_end(ctx, EXCP_DBp);
24014 }
24015 }
24016 break;
24017 #if defined(TARGET_MIPS64)
24018 case OPC_DLSA:
24019 check_mips_64(ctx);
24020 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
24021 break;
24022 case R6_OPC_DCLO:
24023 case R6_OPC_DCLZ:
24024 if (rt == 0 && sa == 1) {
24025 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
24026 We need additionally to check other fields */
24027 check_mips_64(ctx);
24028 gen_cl(ctx, op1, rd, rs);
24029 } else {
24030 generate_exception_end(ctx, EXCP_RI);
24031 }
24032 break;
24033 case OPC_DMULT:
24034 case OPC_DMULTU:
24035 case OPC_DDIV:
24036 case OPC_DDIVU:
24037
24038 op2 = MASK_R6_MULDIV(ctx->opcode);
24039 switch (op2) {
24040 case R6_OPC_DMUL:
24041 case R6_OPC_DMUH:
24042 case R6_OPC_DMULU:
24043 case R6_OPC_DMUHU:
24044 case R6_OPC_DDIV:
24045 case R6_OPC_DMOD:
24046 case R6_OPC_DDIVU:
24047 case R6_OPC_DMODU:
24048 check_mips_64(ctx);
24049 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24050 break;
24051 default:
24052 MIPS_INVAL("special_r6 muldiv");
24053 generate_exception_end(ctx, EXCP_RI);
24054 break;
24055 }
24056 break;
24057 #endif
24058 default: /* Invalid */
24059 MIPS_INVAL("special_r6");
24060 generate_exception_end(ctx, EXCP_RI);
24061 break;
24062 }
24063 }
24064
24065 static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
24066 {
24067 int rs = extract32(ctx->opcode, 21, 5);
24068 int rt = extract32(ctx->opcode, 16, 5);
24069 int rd = extract32(ctx->opcode, 11, 5);
24070 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
24071
24072 switch (op1) {
24073 case OPC_MOVN: /* Conditional move */
24074 case OPC_MOVZ:
24075 gen_cond_move(ctx, op1, rd, rs, rt);
24076 break;
24077 case OPC_MFHI: /* Move from HI/LO */
24078 case OPC_MFLO:
24079 gen_HILO(ctx, op1, 0, rd);
24080 break;
24081 case OPC_MTHI:
24082 case OPC_MTLO: /* Move to HI/LO */
24083 gen_HILO(ctx, op1, 0, rs);
24084 break;
24085 case OPC_MULT:
24086 case OPC_MULTU:
24087 gen_mul_txx9(ctx, op1, rd, rs, rt);
24088 break;
24089 case OPC_DIV:
24090 case OPC_DIVU:
24091 gen_muldiv(ctx, op1, 0, rs, rt);
24092 break;
24093 #if defined(TARGET_MIPS64)
24094 case OPC_DMULT:
24095 case OPC_DMULTU:
24096 case OPC_DDIV:
24097 case OPC_DDIVU:
24098 check_insn_opc_user_only(ctx, INSN_R5900);
24099 gen_muldiv(ctx, op1, 0, rs, rt);
24100 break;
24101 #endif
24102 case OPC_JR:
24103 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
24104 break;
24105 default: /* Invalid */
24106 MIPS_INVAL("special_tx79");
24107 generate_exception_end(ctx, EXCP_RI);
24108 break;
24109 }
24110 }
24111
24112 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
24113 {
24114 int rs, rt, rd, sa;
24115 uint32_t op1;
24116
24117 rs = (ctx->opcode >> 21) & 0x1f;
24118 rt = (ctx->opcode >> 16) & 0x1f;
24119 rd = (ctx->opcode >> 11) & 0x1f;
24120 sa = (ctx->opcode >> 6) & 0x1f;
24121
24122 op1 = MASK_SPECIAL(ctx->opcode);
24123 switch (op1) {
24124 case OPC_MOVN: /* Conditional move */
24125 case OPC_MOVZ:
24126 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
24127 INSN_LOONGSON2E | INSN_LOONGSON2F);
24128 gen_cond_move(ctx, op1, rd, rs, rt);
24129 break;
24130 case OPC_MFHI: /* Move from HI/LO */
24131 case OPC_MFLO:
24132 gen_HILO(ctx, op1, rs & 3, rd);
24133 break;
24134 case OPC_MTHI:
24135 case OPC_MTLO: /* Move to HI/LO */
24136 gen_HILO(ctx, op1, rd & 3, rs);
24137 break;
24138 case OPC_MOVCI:
24139 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
24140 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
24141 check_cp1_enabled(ctx);
24142 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
24143 (ctx->opcode >> 16) & 1);
24144 } else {
24145 generate_exception_err(ctx, EXCP_CpU, 1);
24146 }
24147 break;
24148 case OPC_MULT:
24149 case OPC_MULTU:
24150 if (sa) {
24151 check_insn(ctx, INSN_VR54XX);
24152 op1 = MASK_MUL_VR54XX(ctx->opcode);
24153 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
24154 } else {
24155 gen_muldiv(ctx, op1, rd & 3, rs, rt);
24156 }
24157 break;
24158 case OPC_DIV:
24159 case OPC_DIVU:
24160 gen_muldiv(ctx, op1, 0, rs, rt);
24161 break;
24162 #if defined(TARGET_MIPS64)
24163 case OPC_DMULT:
24164 case OPC_DMULTU:
24165 case OPC_DDIV:
24166 case OPC_DDIVU:
24167 check_insn(ctx, ISA_MIPS3);
24168 check_mips_64(ctx);
24169 gen_muldiv(ctx, op1, 0, rs, rt);
24170 break;
24171 #endif
24172 case OPC_JR:
24173 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24174 break;
24175 case OPC_SPIM:
24176 #ifdef MIPS_STRICT_STANDARD
24177 MIPS_INVAL("SPIM");
24178 generate_exception_end(ctx, EXCP_RI);
24179 #else
24180 /* Implemented as RI exception for now. */
24181 MIPS_INVAL("spim (unofficial)");
24182 generate_exception_end(ctx, EXCP_RI);
24183 #endif
24184 break;
24185 default: /* Invalid */
24186 MIPS_INVAL("special_legacy");
24187 generate_exception_end(ctx, EXCP_RI);
24188 break;
24189 }
24190 }
24191
24192 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
24193 {
24194 int rs, rt, rd, sa;
24195 uint32_t op1;
24196
24197 rs = (ctx->opcode >> 21) & 0x1f;
24198 rt = (ctx->opcode >> 16) & 0x1f;
24199 rd = (ctx->opcode >> 11) & 0x1f;
24200 sa = (ctx->opcode >> 6) & 0x1f;
24201
24202 op1 = MASK_SPECIAL(ctx->opcode);
24203 switch (op1) {
24204 case OPC_SLL: /* Shift with immediate */
24205 if (sa == 5 && rd == 0 &&
24206 rs == 0 && rt == 0) { /* PAUSE */
24207 if ((ctx->insn_flags & ISA_MIPS32R6) &&
24208 (ctx->hflags & MIPS_HFLAG_BMASK)) {
24209 generate_exception_end(ctx, EXCP_RI);
24210 break;
24211 }
24212 }
24213 /* Fallthrough */
24214 case OPC_SRA:
24215 gen_shift_imm(ctx, op1, rd, rt, sa);
24216 break;
24217 case OPC_SRL:
24218 switch ((ctx->opcode >> 21) & 0x1f) {
24219 case 1:
24220 /* rotr is decoded as srl on non-R2 CPUs */
24221 if (ctx->insn_flags & ISA_MIPS32R2) {
24222 op1 = OPC_ROTR;
24223 }
24224 /* Fallthrough */
24225 case 0:
24226 gen_shift_imm(ctx, op1, rd, rt, sa);
24227 break;
24228 default:
24229 generate_exception_end(ctx, EXCP_RI);
24230 break;
24231 }
24232 break;
24233 case OPC_ADD:
24234 case OPC_ADDU:
24235 case OPC_SUB:
24236 case OPC_SUBU:
24237 gen_arith(ctx, op1, rd, rs, rt);
24238 break;
24239 case OPC_SLLV: /* Shifts */
24240 case OPC_SRAV:
24241 gen_shift(ctx, op1, rd, rs, rt);
24242 break;
24243 case OPC_SRLV:
24244 switch ((ctx->opcode >> 6) & 0x1f) {
24245 case 1:
24246 /* rotrv is decoded as srlv on non-R2 CPUs */
24247 if (ctx->insn_flags & ISA_MIPS32R2) {
24248 op1 = OPC_ROTRV;
24249 }
24250 /* Fallthrough */
24251 case 0:
24252 gen_shift(ctx, op1, rd, rs, rt);
24253 break;
24254 default:
24255 generate_exception_end(ctx, EXCP_RI);
24256 break;
24257 }
24258 break;
24259 case OPC_SLT: /* Set on less than */
24260 case OPC_SLTU:
24261 gen_slt(ctx, op1, rd, rs, rt);
24262 break;
24263 case OPC_AND: /* Logic*/
24264 case OPC_OR:
24265 case OPC_NOR:
24266 case OPC_XOR:
24267 gen_logic(ctx, op1, rd, rs, rt);
24268 break;
24269 case OPC_JALR:
24270 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24271 break;
24272 case OPC_TGE: /* Traps */
24273 case OPC_TGEU:
24274 case OPC_TLT:
24275 case OPC_TLTU:
24276 case OPC_TEQ:
24277 case OPC_TNE:
24278 check_insn(ctx, ISA_MIPS2);
24279 gen_trap(ctx, op1, rs, rt, -1);
24280 break;
24281 case OPC_LSA: /* OPC_PMON */
24282 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24283 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
24284 decode_opc_special_r6(env, ctx);
24285 } else {
24286 /* Pmon entry point, also R4010 selsl */
24287 #ifdef MIPS_STRICT_STANDARD
24288 MIPS_INVAL("PMON / selsl");
24289 generate_exception_end(ctx, EXCP_RI);
24290 #else
24291 gen_helper_0e0i(pmon, sa);
24292 #endif
24293 }
24294 break;
24295 case OPC_SYSCALL:
24296 generate_exception_end(ctx, EXCP_SYSCALL);
24297 break;
24298 case OPC_BREAK:
24299 generate_exception_end(ctx, EXCP_BREAK);
24300 break;
24301 case OPC_SYNC:
24302 check_insn(ctx, ISA_MIPS2);
24303 gen_sync(extract32(ctx->opcode, 6, 5));
24304 break;
24305
24306 #if defined(TARGET_MIPS64)
24307 /* MIPS64 specific opcodes */
24308 case OPC_DSLL:
24309 case OPC_DSRA:
24310 case OPC_DSLL32:
24311 case OPC_DSRA32:
24312 check_insn(ctx, ISA_MIPS3);
24313 check_mips_64(ctx);
24314 gen_shift_imm(ctx, op1, rd, rt, sa);
24315 break;
24316 case OPC_DSRL:
24317 switch ((ctx->opcode >> 21) & 0x1f) {
24318 case 1:
24319 /* drotr is decoded as dsrl on non-R2 CPUs */
24320 if (ctx->insn_flags & ISA_MIPS32R2) {
24321 op1 = OPC_DROTR;
24322 }
24323 /* Fallthrough */
24324 case 0:
24325 check_insn(ctx, ISA_MIPS3);
24326 check_mips_64(ctx);
24327 gen_shift_imm(ctx, op1, rd, rt, sa);
24328 break;
24329 default:
24330 generate_exception_end(ctx, EXCP_RI);
24331 break;
24332 }
24333 break;
24334 case OPC_DSRL32:
24335 switch ((ctx->opcode >> 21) & 0x1f) {
24336 case 1:
24337 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
24338 if (ctx->insn_flags & ISA_MIPS32R2) {
24339 op1 = OPC_DROTR32;
24340 }
24341 /* Fallthrough */
24342 case 0:
24343 check_insn(ctx, ISA_MIPS3);
24344 check_mips_64(ctx);
24345 gen_shift_imm(ctx, op1, rd, rt, sa);
24346 break;
24347 default:
24348 generate_exception_end(ctx, EXCP_RI);
24349 break;
24350 }
24351 break;
24352 case OPC_DADD:
24353 case OPC_DADDU:
24354 case OPC_DSUB:
24355 case OPC_DSUBU:
24356 check_insn(ctx, ISA_MIPS3);
24357 check_mips_64(ctx);
24358 gen_arith(ctx, op1, rd, rs, rt);
24359 break;
24360 case OPC_DSLLV:
24361 case OPC_DSRAV:
24362 check_insn(ctx, ISA_MIPS3);
24363 check_mips_64(ctx);
24364 gen_shift(ctx, op1, rd, rs, rt);
24365 break;
24366 case OPC_DSRLV:
24367 switch ((ctx->opcode >> 6) & 0x1f) {
24368 case 1:
24369 /* drotrv is decoded as dsrlv on non-R2 CPUs */
24370 if (ctx->insn_flags & ISA_MIPS32R2) {
24371 op1 = OPC_DROTRV;
24372 }
24373 /* Fallthrough */
24374 case 0:
24375 check_insn(ctx, ISA_MIPS3);
24376 check_mips_64(ctx);
24377 gen_shift(ctx, op1, rd, rs, rt);
24378 break;
24379 default:
24380 generate_exception_end(ctx, EXCP_RI);
24381 break;
24382 }
24383 break;
24384 case OPC_DLSA:
24385 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24386 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
24387 decode_opc_special_r6(env, ctx);
24388 }
24389 break;
24390 #endif
24391 default:
24392 if (ctx->insn_flags & ISA_MIPS32R6) {
24393 decode_opc_special_r6(env, ctx);
24394 } else if (ctx->insn_flags & INSN_R5900) {
24395 decode_opc_special_tx79(env, ctx);
24396 } else {
24397 decode_opc_special_legacy(env, ctx);
24398 }
24399 }
24400 }
24401
24402
24403 #if defined(TARGET_MIPS64)
24404
24405 /*
24406 *
24407 * MMI (MultiMedia Interface) ASE instructions
24408 * ===========================================
24409 */
24410
24411 /*
24412 * MMI instructions category: data communication
24413 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24414 *
24415 * PCPYH PEXCH PEXTLB PINTH PPACB PEXT5 PREVH
24416 * PCPYLD PEXCW PEXTLH PINTEH PPACH PPAC5 PROT3W
24417 * PCPYUD PEXEH PEXTLW PPACW
24418 * PEXEW PEXTUB
24419 * PEXTUH
24420 * PEXTUW
24421 */
24422
24423 /*
24424 * PCPYH rd, rt
24425 *
24426 * Parallel Copy Halfword
24427 *
24428 * 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
24429 * +-----------+---------+---------+---------+---------+-----------+
24430 * | MMI |0 0 0 0 0| rt | rd | PCPYH | MMI3 |
24431 * +-----------+---------+---------+---------+---------+-----------+
24432 */
24433 static void gen_mmi_pcpyh(DisasContext *ctx)
24434 {
24435 uint32_t pd, rt, rd;
24436 uint32_t opcode;
24437
24438 opcode = ctx->opcode;
24439
24440 pd = extract32(opcode, 21, 5);
24441 rt = extract32(opcode, 16, 5);
24442 rd = extract32(opcode, 11, 5);
24443
24444 if (unlikely(pd != 0)) {
24445 generate_exception_end(ctx, EXCP_RI);
24446 } else if (rd == 0) {
24447 /* nop */
24448 } else if (rt == 0) {
24449 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24450 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24451 } else {
24452 TCGv_i64 t0 = tcg_temp_new();
24453 TCGv_i64 t1 = tcg_temp_new();
24454 uint64_t mask = (1ULL << 16) - 1;
24455
24456 tcg_gen_andi_i64(t0, cpu_gpr[rt], mask);
24457 tcg_gen_movi_i64(t1, 0);
24458 tcg_gen_or_i64(t1, t0, t1);
24459 tcg_gen_shli_i64(t0, t0, 16);
24460 tcg_gen_or_i64(t1, t0, t1);
24461 tcg_gen_shli_i64(t0, t0, 16);
24462 tcg_gen_or_i64(t1, t0, t1);
24463 tcg_gen_shli_i64(t0, t0, 16);
24464 tcg_gen_or_i64(t1, t0, t1);
24465
24466 tcg_gen_mov_i64(cpu_gpr[rd], t1);
24467
24468 tcg_gen_andi_i64(t0, cpu_mmr[rt], mask);
24469 tcg_gen_movi_i64(t1, 0);
24470 tcg_gen_or_i64(t1, t0, t1);
24471 tcg_gen_shli_i64(t0, t0, 16);
24472 tcg_gen_or_i64(t1, t0, t1);
24473 tcg_gen_shli_i64(t0, t0, 16);
24474 tcg_gen_or_i64(t1, t0, t1);
24475 tcg_gen_shli_i64(t0, t0, 16);
24476 tcg_gen_or_i64(t1, t0, t1);
24477
24478 tcg_gen_mov_i64(cpu_mmr[rd], t1);
24479
24480 tcg_temp_free(t0);
24481 tcg_temp_free(t1);
24482 }
24483 }
24484
24485 /*
24486 * PCPYLD rd, rs, rt
24487 *
24488 * Parallel Copy Lower Doubleword
24489 *
24490 * 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
24491 * +-----------+---------+---------+---------+---------+-----------+
24492 * | MMI | rs | rt | rd | PCPYLD | MMI2 |
24493 * +-----------+---------+---------+---------+---------+-----------+
24494 */
24495 static void gen_mmi_pcpyld(DisasContext *ctx)
24496 {
24497 uint32_t rs, rt, rd;
24498 uint32_t opcode;
24499
24500 opcode = ctx->opcode;
24501
24502 rs = extract32(opcode, 21, 5);
24503 rt = extract32(opcode, 16, 5);
24504 rd = extract32(opcode, 11, 5);
24505
24506 if (rd == 0) {
24507 /* nop */
24508 } else {
24509 if (rs == 0) {
24510 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24511 } else {
24512 tcg_gen_mov_i64(cpu_mmr[rd], cpu_gpr[rs]);
24513 }
24514 if (rt == 0) {
24515 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24516 } else {
24517 if (rd != rt) {
24518 tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr[rt]);
24519 }
24520 }
24521 }
24522 }
24523
24524 /*
24525 * PCPYUD rd, rs, rt
24526 *
24527 * Parallel Copy Upper Doubleword
24528 *
24529 * 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
24530 * +-----------+---------+---------+---------+---------+-----------+
24531 * | MMI | rs | rt | rd | PCPYUD | MMI3 |
24532 * +-----------+---------+---------+---------+---------+-----------+
24533 */
24534 static void gen_mmi_pcpyud(DisasContext *ctx)
24535 {
24536 uint32_t rs, rt, rd;
24537 uint32_t opcode;
24538
24539 opcode = ctx->opcode;
24540
24541 rs = extract32(opcode, 21, 5);
24542 rt = extract32(opcode, 16, 5);
24543 rd = extract32(opcode, 11, 5);
24544
24545 if (rd == 0) {
24546 /* nop */
24547 } else {
24548 if (rs == 0) {
24549 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24550 } else {
24551 tcg_gen_mov_i64(cpu_gpr[rd], cpu_mmr[rs]);
24552 }
24553 if (rt == 0) {
24554 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24555 } else {
24556 if (rd != rt) {
24557 tcg_gen_mov_i64(cpu_mmr[rd], cpu_mmr[rt]);
24558 }
24559 }
24560 }
24561 }
24562
24563 #endif
24564
24565
24566 #if !defined(TARGET_MIPS64)
24567
24568 /* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
24569 #define MXU_APTN1_A 0
24570 #define MXU_APTN1_S 1
24571
24572 /* MXU accumulate add/subtract 2-bit pattern 'aptn2' */
24573 #define MXU_APTN2_AA 0
24574 #define MXU_APTN2_AS 1
24575 #define MXU_APTN2_SA 2
24576 #define MXU_APTN2_SS 3
24577
24578 /* MXU execute add/subtract 2-bit pattern 'eptn2' */
24579 #define MXU_EPTN2_AA 0
24580 #define MXU_EPTN2_AS 1
24581 #define MXU_EPTN2_SA 2
24582 #define MXU_EPTN2_SS 3
24583
24584 /* MXU operand getting pattern 'optn2' */
24585 #define MXU_OPTN2_PTN0 0
24586 #define MXU_OPTN2_PTN1 1
24587 #define MXU_OPTN2_PTN2 2
24588 #define MXU_OPTN2_PTN3 3
24589 /* alternative naming scheme for 'optn2' */
24590 #define MXU_OPTN2_WW 0
24591 #define MXU_OPTN2_LW 1
24592 #define MXU_OPTN2_HW 2
24593 #define MXU_OPTN2_XW 3
24594
24595 /* MXU operand getting pattern 'optn3' */
24596 #define MXU_OPTN3_PTN0 0
24597 #define MXU_OPTN3_PTN1 1
24598 #define MXU_OPTN3_PTN2 2
24599 #define MXU_OPTN3_PTN3 3
24600 #define MXU_OPTN3_PTN4 4
24601 #define MXU_OPTN3_PTN5 5
24602 #define MXU_OPTN3_PTN6 6
24603 #define MXU_OPTN3_PTN7 7
24604
24605
24606 /*
24607 * S32I2M XRa, rb - Register move from GRF to XRF
24608 */
24609 static void gen_mxu_s32i2m(DisasContext *ctx)
24610 {
24611 TCGv t0;
24612 uint32_t XRa, Rb;
24613
24614 t0 = tcg_temp_new();
24615
24616 XRa = extract32(ctx->opcode, 6, 5);
24617 Rb = extract32(ctx->opcode, 16, 5);
24618
24619 gen_load_gpr(t0, Rb);
24620 if (XRa <= 15) {
24621 gen_store_mxu_gpr(t0, XRa);
24622 } else if (XRa == 16) {
24623 gen_store_mxu_cr(t0);
24624 }
24625
24626 tcg_temp_free(t0);
24627 }
24628
24629 /*
24630 * S32M2I XRa, rb - Register move from XRF to GRF
24631 */
24632 static void gen_mxu_s32m2i(DisasContext *ctx)
24633 {
24634 TCGv t0;
24635 uint32_t XRa, Rb;
24636
24637 t0 = tcg_temp_new();
24638
24639 XRa = extract32(ctx->opcode, 6, 5);
24640 Rb = extract32(ctx->opcode, 16, 5);
24641
24642 if (XRa <= 15) {
24643 gen_load_mxu_gpr(t0, XRa);
24644 } else if (XRa == 16) {
24645 gen_load_mxu_cr(t0);
24646 }
24647
24648 gen_store_gpr(t0, Rb);
24649
24650 tcg_temp_free(t0);
24651 }
24652
24653 /*
24654 * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF
24655 */
24656 static void gen_mxu_s8ldd(DisasContext *ctx)
24657 {
24658 TCGv t0, t1;
24659 uint32_t XRa, Rb, s8, optn3;
24660
24661 t0 = tcg_temp_new();
24662 t1 = tcg_temp_new();
24663
24664 XRa = extract32(ctx->opcode, 6, 4);
24665 s8 = extract32(ctx->opcode, 10, 8);
24666 optn3 = extract32(ctx->opcode, 18, 3);
24667 Rb = extract32(ctx->opcode, 21, 5);
24668
24669 gen_load_gpr(t0, Rb);
24670 tcg_gen_addi_tl(t0, t0, (int8_t)s8);
24671
24672 switch (optn3) {
24673 /* XRa[7:0] = tmp8 */
24674 case MXU_OPTN3_PTN0:
24675 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24676 gen_load_mxu_gpr(t0, XRa);
24677 tcg_gen_deposit_tl(t0, t0, t1, 0, 8);
24678 break;
24679 /* XRa[15:8] = tmp8 */
24680 case MXU_OPTN3_PTN1:
24681 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24682 gen_load_mxu_gpr(t0, XRa);
24683 tcg_gen_deposit_tl(t0, t0, t1, 8, 8);
24684 break;
24685 /* XRa[23:16] = tmp8 */
24686 case MXU_OPTN3_PTN2:
24687 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24688 gen_load_mxu_gpr(t0, XRa);
24689 tcg_gen_deposit_tl(t0, t0, t1, 16, 8);
24690 break;
24691 /* XRa[31:24] = tmp8 */
24692 case MXU_OPTN3_PTN3:
24693 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24694 gen_load_mxu_gpr(t0, XRa);
24695 tcg_gen_deposit_tl(t0, t0, t1, 24, 8);
24696 break;
24697 /* XRa = {8'b0, tmp8, 8'b0, tmp8} */
24698 case MXU_OPTN3_PTN4:
24699 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24700 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24701 break;
24702 /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */
24703 case MXU_OPTN3_PTN5:
24704 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24705 tcg_gen_shli_tl(t1, t1, 8);
24706 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24707 break;
24708 /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */
24709 case MXU_OPTN3_PTN6:
24710 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB);
24711 tcg_gen_mov_tl(t0, t1);
24712 tcg_gen_andi_tl(t0, t0, 0xFF00FFFF);
24713 tcg_gen_shli_tl(t1, t1, 16);
24714 tcg_gen_or_tl(t0, t0, t1);
24715 break;
24716 /* XRa = {tmp8, tmp8, tmp8, tmp8} */
24717 case MXU_OPTN3_PTN7:
24718 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24719 tcg_gen_deposit_tl(t1, t1, t1, 8, 8);
24720 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24721 break;
24722 }
24723
24724 gen_store_mxu_gpr(t0, XRa);
24725
24726 tcg_temp_free(t0);
24727 tcg_temp_free(t1);
24728 }
24729
24730 /*
24731 * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication
24732 */
24733 static void gen_mxu_d16mul(DisasContext *ctx)
24734 {
24735 TCGv t0, t1, t2, t3;
24736 uint32_t XRa, XRb, XRc, XRd, optn2;
24737
24738 t0 = tcg_temp_new();
24739 t1 = tcg_temp_new();
24740 t2 = tcg_temp_new();
24741 t3 = tcg_temp_new();
24742
24743 XRa = extract32(ctx->opcode, 6, 4);
24744 XRb = extract32(ctx->opcode, 10, 4);
24745 XRc = extract32(ctx->opcode, 14, 4);
24746 XRd = extract32(ctx->opcode, 18, 4);
24747 optn2 = extract32(ctx->opcode, 22, 2);
24748
24749 gen_load_mxu_gpr(t1, XRb);
24750 tcg_gen_sextract_tl(t0, t1, 0, 16);
24751 tcg_gen_sextract_tl(t1, t1, 16, 16);
24752 gen_load_mxu_gpr(t3, XRc);
24753 tcg_gen_sextract_tl(t2, t3, 0, 16);
24754 tcg_gen_sextract_tl(t3, t3, 16, 16);
24755
24756 switch (optn2) {
24757 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
24758 tcg_gen_mul_tl(t3, t1, t3);
24759 tcg_gen_mul_tl(t2, t0, t2);
24760 break;
24761 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
24762 tcg_gen_mul_tl(t3, t0, t3);
24763 tcg_gen_mul_tl(t2, t0, t2);
24764 break;
24765 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
24766 tcg_gen_mul_tl(t3, t1, t3);
24767 tcg_gen_mul_tl(t2, t1, t2);
24768 break;
24769 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
24770 tcg_gen_mul_tl(t3, t0, t3);
24771 tcg_gen_mul_tl(t2, t1, t2);
24772 break;
24773 }
24774 gen_store_mxu_gpr(t3, XRa);
24775 gen_store_mxu_gpr(t2, XRd);
24776
24777 tcg_temp_free(t0);
24778 tcg_temp_free(t1);
24779 tcg_temp_free(t2);
24780 tcg_temp_free(t3);
24781 }
24782
24783 /*
24784 * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply
24785 * and accumulate
24786 */
24787 static void gen_mxu_d16mac(DisasContext *ctx)
24788 {
24789 TCGv t0, t1, t2, t3;
24790 uint32_t XRa, XRb, XRc, XRd, optn2, aptn2;
24791
24792 t0 = tcg_temp_new();
24793 t1 = tcg_temp_new();
24794 t2 = tcg_temp_new();
24795 t3 = tcg_temp_new();
24796
24797 XRa = extract32(ctx->opcode, 6, 4);
24798 XRb = extract32(ctx->opcode, 10, 4);
24799 XRc = extract32(ctx->opcode, 14, 4);
24800 XRd = extract32(ctx->opcode, 18, 4);
24801 optn2 = extract32(ctx->opcode, 22, 2);
24802 aptn2 = extract32(ctx->opcode, 24, 2);
24803
24804 gen_load_mxu_gpr(t1, XRb);
24805 tcg_gen_sextract_tl(t0, t1, 0, 16);
24806 tcg_gen_sextract_tl(t1, t1, 16, 16);
24807
24808 gen_load_mxu_gpr(t3, XRc);
24809 tcg_gen_sextract_tl(t2, t3, 0, 16);
24810 tcg_gen_sextract_tl(t3, t3, 16, 16);
24811
24812 switch (optn2) {
24813 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
24814 tcg_gen_mul_tl(t3, t1, t3);
24815 tcg_gen_mul_tl(t2, t0, t2);
24816 break;
24817 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
24818 tcg_gen_mul_tl(t3, t0, t3);
24819 tcg_gen_mul_tl(t2, t0, t2);
24820 break;
24821 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
24822 tcg_gen_mul_tl(t3, t1, t3);
24823 tcg_gen_mul_tl(t2, t1, t2);
24824 break;
24825 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
24826 tcg_gen_mul_tl(t3, t0, t3);
24827 tcg_gen_mul_tl(t2, t1, t2);
24828 break;
24829 }
24830 gen_load_mxu_gpr(t0, XRa);
24831 gen_load_mxu_gpr(t1, XRd);
24832
24833 switch (aptn2) {
24834 case MXU_APTN2_AA:
24835 tcg_gen_add_tl(t3, t0, t3);
24836 tcg_gen_add_tl(t2, t1, t2);
24837 break;
24838 case MXU_APTN2_AS:
24839 tcg_gen_add_tl(t3, t0, t3);
24840 tcg_gen_sub_tl(t2, t1, t2);
24841 break;
24842 case MXU_APTN2_SA:
24843 tcg_gen_sub_tl(t3, t0, t3);
24844 tcg_gen_add_tl(t2, t1, t2);
24845 break;
24846 case MXU_APTN2_SS:
24847 tcg_gen_sub_tl(t3, t0, t3);
24848 tcg_gen_sub_tl(t2, t1, t2);
24849 break;
24850 }
24851 gen_store_mxu_gpr(t3, XRa);
24852 gen_store_mxu_gpr(t2, XRd);
24853
24854 tcg_temp_free(t0);
24855 tcg_temp_free(t1);
24856 tcg_temp_free(t2);
24857 tcg_temp_free(t3);
24858 }
24859
24860 /*
24861 * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply
24862 * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply
24863 */
24864 static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx)
24865 {
24866 TCGv t0, t1, t2, t3, t4, t5, t6, t7;
24867 uint32_t XRa, XRb, XRc, XRd, sel;
24868
24869 t0 = tcg_temp_new();
24870 t1 = tcg_temp_new();
24871 t2 = tcg_temp_new();
24872 t3 = tcg_temp_new();
24873 t4 = tcg_temp_new();
24874 t5 = tcg_temp_new();
24875 t6 = tcg_temp_new();
24876 t7 = tcg_temp_new();
24877
24878 XRa = extract32(ctx->opcode, 6, 4);
24879 XRb = extract32(ctx->opcode, 10, 4);
24880 XRc = extract32(ctx->opcode, 14, 4);
24881 XRd = extract32(ctx->opcode, 18, 4);
24882 sel = extract32(ctx->opcode, 22, 2);
24883
24884 gen_load_mxu_gpr(t3, XRb);
24885 gen_load_mxu_gpr(t7, XRc);
24886
24887 if (sel == 0x2) {
24888 /* Q8MULSU */
24889 tcg_gen_ext8s_tl(t0, t3);
24890 tcg_gen_shri_tl(t3, t3, 8);
24891 tcg_gen_ext8s_tl(t1, t3);
24892 tcg_gen_shri_tl(t3, t3, 8);
24893 tcg_gen_ext8s_tl(t2, t3);
24894 tcg_gen_shri_tl(t3, t3, 8);
24895 tcg_gen_ext8s_tl(t3, t3);
24896 } else {
24897 /* Q8MUL */
24898 tcg_gen_ext8u_tl(t0, t3);
24899 tcg_gen_shri_tl(t3, t3, 8);
24900 tcg_gen_ext8u_tl(t1, t3);
24901 tcg_gen_shri_tl(t3, t3, 8);
24902 tcg_gen_ext8u_tl(t2, t3);
24903 tcg_gen_shri_tl(t3, t3, 8);
24904 tcg_gen_ext8u_tl(t3, t3);
24905 }
24906
24907 tcg_gen_ext8u_tl(t4, t7);
24908 tcg_gen_shri_tl(t7, t7, 8);
24909 tcg_gen_ext8u_tl(t5, t7);
24910 tcg_gen_shri_tl(t7, t7, 8);
24911 tcg_gen_ext8u_tl(t6, t7);
24912 tcg_gen_shri_tl(t7, t7, 8);
24913 tcg_gen_ext8u_tl(t7, t7);
24914
24915 tcg_gen_mul_tl(t0, t0, t4);
24916 tcg_gen_mul_tl(t1, t1, t5);
24917 tcg_gen_mul_tl(t2, t2, t6);
24918 tcg_gen_mul_tl(t3, t3, t7);
24919
24920 tcg_gen_andi_tl(t0, t0, 0xFFFF);
24921 tcg_gen_andi_tl(t1, t1, 0xFFFF);
24922 tcg_gen_andi_tl(t2, t2, 0xFFFF);
24923 tcg_gen_andi_tl(t3, t3, 0xFFFF);
24924
24925 tcg_gen_shli_tl(t1, t1, 16);
24926 tcg_gen_shli_tl(t3, t3, 16);
24927
24928 tcg_gen_or_tl(t0, t0, t1);
24929 tcg_gen_or_tl(t1, t2, t3);
24930
24931 gen_store_mxu_gpr(t0, XRd);
24932 gen_store_mxu_gpr(t1, XRa);
24933
24934 tcg_temp_free(t0);
24935 tcg_temp_free(t1);
24936 tcg_temp_free(t2);
24937 tcg_temp_free(t3);
24938 tcg_temp_free(t4);
24939 tcg_temp_free(t5);
24940 tcg_temp_free(t6);
24941 tcg_temp_free(t7);
24942 }
24943
24944 /*
24945 * S32LDD XRa, Rb, S12 - Load a word from memory to XRF
24946 * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte seq.
24947 */
24948 static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx)
24949 {
24950 TCGv t0, t1;
24951 uint32_t XRa, Rb, s12, sel;
24952
24953 t0 = tcg_temp_new();
24954 t1 = tcg_temp_new();
24955
24956 XRa = extract32(ctx->opcode, 6, 4);
24957 s12 = extract32(ctx->opcode, 10, 10);
24958 sel = extract32(ctx->opcode, 20, 1);
24959 Rb = extract32(ctx->opcode, 21, 5);
24960
24961 gen_load_gpr(t0, Rb);
24962
24963 tcg_gen_movi_tl(t1, s12);
24964 tcg_gen_shli_tl(t1, t1, 2);
24965 if (s12 & 0x200) {
24966 tcg_gen_ori_tl(t1, t1, 0xFFFFF000);
24967 }
24968 tcg_gen_add_tl(t1, t0, t1);
24969 tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL);
24970
24971 if (sel == 1) {
24972 /* S32LDDR */
24973 tcg_gen_bswap32_tl(t1, t1);
24974 }
24975 gen_store_mxu_gpr(t1, XRa);
24976
24977 tcg_temp_free(t0);
24978 tcg_temp_free(t1);
24979 }
24980
24981
24982 /*
24983 * MXU instruction category: logic
24984 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24985 *
24986 * S32NOR S32AND S32OR S32XOR
24987 */
24988
24989 /*
24990 * S32NOR XRa, XRb, XRc
24991 * Update XRa with the result of logical bitwise 'nor' operation
24992 * applied to the content of XRb and XRc.
24993 *
24994 * 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
24995 * +-----------+---------+-----+-------+-------+-------+-----------+
24996 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
24997 * +-----------+---------+-----+-------+-------+-------+-----------+
24998 */
24999 static void gen_mxu_S32NOR(DisasContext *ctx)
25000 {
25001 uint32_t pad, XRc, XRb, XRa;
25002
25003 pad = extract32(ctx->opcode, 21, 5);
25004 XRc = extract32(ctx->opcode, 14, 4);
25005 XRb = extract32(ctx->opcode, 10, 4);
25006 XRa = extract32(ctx->opcode, 6, 4);
25007
25008 if (unlikely(pad != 0)) {
25009 /* opcode padding incorrect -> do nothing */
25010 } else if (unlikely(XRa == 0)) {
25011 /* destination is zero register -> do nothing */
25012 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25013 /* both operands zero registers -> just set destination to all 1s */
25014 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF);
25015 } else if (unlikely(XRb == 0)) {
25016 /* XRb zero register -> just set destination to the negation of XRc */
25017 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25018 } else if (unlikely(XRc == 0)) {
25019 /* XRa zero register -> just set destination to the negation of XRb */
25020 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25021 } else if (unlikely(XRb == XRc)) {
25022 /* both operands same -> just set destination to the negation of XRb */
25023 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25024 } else {
25025 /* the most general case */
25026 tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25027 }
25028 }
25029
25030 /*
25031 * S32AND XRa, XRb, XRc
25032 * Update XRa with the result of logical bitwise 'and' operation
25033 * applied to the content of XRb and XRc.
25034 *
25035 * 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
25036 * +-----------+---------+-----+-------+-------+-------+-----------+
25037 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25038 * +-----------+---------+-----+-------+-------+-------+-----------+
25039 */
25040 static void gen_mxu_S32AND(DisasContext *ctx)
25041 {
25042 uint32_t pad, XRc, XRb, XRa;
25043
25044 pad = extract32(ctx->opcode, 21, 5);
25045 XRc = extract32(ctx->opcode, 14, 4);
25046 XRb = extract32(ctx->opcode, 10, 4);
25047 XRa = extract32(ctx->opcode, 6, 4);
25048
25049 if (unlikely(pad != 0)) {
25050 /* opcode padding incorrect -> do nothing */
25051 } else if (unlikely(XRa == 0)) {
25052 /* destination is zero register -> do nothing */
25053 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25054 /* one of operands zero register -> just set destination to all 0s */
25055 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25056 } else if (unlikely(XRb == XRc)) {
25057 /* both operands same -> just set destination to one of them */
25058 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25059 } else {
25060 /* the most general case */
25061 tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25062 }
25063 }
25064
25065 /*
25066 * S32OR XRa, XRb, XRc
25067 * Update XRa with the result of logical bitwise 'or' operation
25068 * applied to the content of XRb and XRc.
25069 *
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 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25073 * +-----------+---------+-----+-------+-------+-------+-----------+
25074 */
25075 static void gen_mxu_S32OR(DisasContext *ctx)
25076 {
25077 uint32_t pad, XRc, XRb, XRa;
25078
25079 pad = extract32(ctx->opcode, 21, 5);
25080 XRc = extract32(ctx->opcode, 14, 4);
25081 XRb = extract32(ctx->opcode, 10, 4);
25082 XRa = extract32(ctx->opcode, 6, 4);
25083
25084 if (unlikely(pad != 0)) {
25085 /* opcode padding incorrect -> do nothing */
25086 } else if (unlikely(XRa == 0)) {
25087 /* destination is zero register -> do nothing */
25088 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25089 /* both operands zero registers -> just set destination to all 0s */
25090 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25091 } else if (unlikely(XRb == 0)) {
25092 /* XRb zero register -> just set destination to the content of XRc */
25093 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25094 } else if (unlikely(XRc == 0)) {
25095 /* XRc zero register -> just set destination to the content of XRb */
25096 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25097 } else if (unlikely(XRb == XRc)) {
25098 /* both operands same -> just set destination to one of them */
25099 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25100 } else {
25101 /* the most general case */
25102 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25103 }
25104 }
25105
25106 /*
25107 * S32XOR XRa, XRb, XRc
25108 * Update XRa with the result of logical bitwise 'xor' operation
25109 * applied to the content of XRb and XRc.
25110 *
25111 * 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
25112 * +-----------+---------+-----+-------+-------+-------+-----------+
25113 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25114 * +-----------+---------+-----+-------+-------+-------+-----------+
25115 */
25116 static void gen_mxu_S32XOR(DisasContext *ctx)
25117 {
25118 uint32_t pad, XRc, XRb, XRa;
25119
25120 pad = extract32(ctx->opcode, 21, 5);
25121 XRc = extract32(ctx->opcode, 14, 4);
25122 XRb = extract32(ctx->opcode, 10, 4);
25123 XRa = extract32(ctx->opcode, 6, 4);
25124
25125 if (unlikely(pad != 0)) {
25126 /* opcode padding incorrect -> do nothing */
25127 } else if (unlikely(XRa == 0)) {
25128 /* destination is zero register -> do nothing */
25129 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25130 /* both operands zero registers -> just set destination to all 0s */
25131 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25132 } else if (unlikely(XRb == 0)) {
25133 /* XRb zero register -> just set destination to the content of XRc */
25134 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25135 } else if (unlikely(XRc == 0)) {
25136 /* XRc zero register -> just set destination to the content of XRb */
25137 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25138 } else if (unlikely(XRb == XRc)) {
25139 /* both operands same -> just set destination to all 0s */
25140 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25141 } else {
25142 /* the most general case */
25143 tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25144 }
25145 }
25146
25147
25148 /*
25149 * MXU instruction category max/min
25150 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25151 *
25152 * S32MAX D16MAX Q8MAX
25153 * S32MIN D16MIN Q8MIN
25154 */
25155
25156 /*
25157 * S32MAX XRa, XRb, XRc
25158 * Update XRa with the maximum of signed 32-bit integers contained
25159 * in XRb and XRc.
25160 *
25161 * S32MIN XRa, XRb, XRc
25162 * Update XRa with the minimum of signed 32-bit integers contained
25163 * in XRb and XRc.
25164 *
25165 * 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
25166 * +-----------+---------+-----+-------+-------+-------+-----------+
25167 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25168 * +-----------+---------+-----+-------+-------+-------+-----------+
25169 */
25170 static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx)
25171 {
25172 uint32_t pad, opc, XRc, XRb, XRa;
25173
25174 pad = extract32(ctx->opcode, 21, 5);
25175 opc = extract32(ctx->opcode, 18, 3);
25176 XRc = extract32(ctx->opcode, 14, 4);
25177 XRb = extract32(ctx->opcode, 10, 4);
25178 XRa = extract32(ctx->opcode, 6, 4);
25179
25180 if (unlikely(pad != 0)) {
25181 /* opcode padding incorrect -> do nothing */
25182 } else if (unlikely(XRa == 0)) {
25183 /* destination is zero register -> do nothing */
25184 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25185 /* both operands zero registers -> just set destination to zero */
25186 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25187 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25188 /* exactly one operand is zero register - find which one is not...*/
25189 uint32_t XRx = XRb ? XRb : XRc;
25190 /* ...and do max/min operation with one operand 0 */
25191 if (opc == OPC_MXU_S32MAX) {
25192 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25193 } else {
25194 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25195 }
25196 } else if (unlikely(XRb == XRc)) {
25197 /* both operands same -> just set destination to one of them */
25198 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25199 } else {
25200 /* the most general case */
25201 if (opc == OPC_MXU_S32MAX) {
25202 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25203 mxu_gpr[XRc - 1]);
25204 } else {
25205 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25206 mxu_gpr[XRc - 1]);
25207 }
25208 }
25209 }
25210
25211 /*
25212 * D16MAX
25213 * Update XRa with the 16-bit-wise maximums of signed integers
25214 * contained in XRb and XRc.
25215 *
25216 * D16MIN
25217 * Update XRa with the 16-bit-wise minimums of signed integers
25218 * contained in XRb and XRc.
25219 *
25220 * 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
25221 * +-----------+---------+-----+-------+-------+-------+-----------+
25222 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25223 * +-----------+---------+-----+-------+-------+-------+-----------+
25224 */
25225 static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx)
25226 {
25227 uint32_t pad, opc, XRc, XRb, XRa;
25228
25229 pad = extract32(ctx->opcode, 21, 5);
25230 opc = extract32(ctx->opcode, 18, 3);
25231 XRc = extract32(ctx->opcode, 14, 4);
25232 XRb = extract32(ctx->opcode, 10, 4);
25233 XRa = extract32(ctx->opcode, 6, 4);
25234
25235 if (unlikely(pad != 0)) {
25236 /* opcode padding incorrect -> do nothing */
25237 } else if (unlikely(XRc == 0)) {
25238 /* destination is zero register -> do nothing */
25239 } else if (unlikely((XRb == 0) && (XRa == 0))) {
25240 /* both operands zero registers -> just set destination to zero */
25241 tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0);
25242 } else if (unlikely((XRb == 0) || (XRa == 0))) {
25243 /* exactly one operand is zero register - find which one is not...*/
25244 uint32_t XRx = XRb ? XRb : XRc;
25245 /* ...and do half-word-wise max/min with one operand 0 */
25246 TCGv_i32 t0 = tcg_temp_new();
25247 TCGv_i32 t1 = tcg_const_i32(0);
25248
25249 /* the left half-word first */
25250 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000);
25251 if (opc == OPC_MXU_D16MAX) {
25252 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25253 } else {
25254 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25255 }
25256
25257 /* the right half-word */
25258 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF);
25259 /* move half-words to the leftmost position */
25260 tcg_gen_shli_i32(t0, t0, 16);
25261 /* t0 will be max/min of t0 and t1 */
25262 if (opc == OPC_MXU_D16MAX) {
25263 tcg_gen_smax_i32(t0, t0, t1);
25264 } else {
25265 tcg_gen_smin_i32(t0, t0, t1);
25266 }
25267 /* return resulting half-words to its original position */
25268 tcg_gen_shri_i32(t0, t0, 16);
25269 /* finaly update the destination */
25270 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25271
25272 tcg_temp_free(t1);
25273 tcg_temp_free(t0);
25274 } else if (unlikely(XRb == XRc)) {
25275 /* both operands same -> just set destination to one of them */
25276 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25277 } else {
25278 /* the most general case */
25279 TCGv_i32 t0 = tcg_temp_new();
25280 TCGv_i32 t1 = tcg_temp_new();
25281
25282 /* the left half-word first */
25283 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000);
25284 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25285 if (opc == OPC_MXU_D16MAX) {
25286 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25287 } else {
25288 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25289 }
25290
25291 /* the right half-word */
25292 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25293 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF);
25294 /* move half-words to the leftmost position */
25295 tcg_gen_shli_i32(t0, t0, 16);
25296 tcg_gen_shli_i32(t1, t1, 16);
25297 /* t0 will be max/min of t0 and t1 */
25298 if (opc == OPC_MXU_D16MAX) {
25299 tcg_gen_smax_i32(t0, t0, t1);
25300 } else {
25301 tcg_gen_smin_i32(t0, t0, t1);
25302 }
25303 /* return resulting half-words to its original position */
25304 tcg_gen_shri_i32(t0, t0, 16);
25305 /* finaly update the destination */
25306 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25307
25308 tcg_temp_free(t1);
25309 tcg_temp_free(t0);
25310 }
25311 }
25312
25313 /*
25314 * Q8MAX
25315 * Update XRa with the 8-bit-wise maximums of signed integers
25316 * contained in XRb and XRc.
25317 *
25318 * Q8MIN
25319 * Update XRa with the 8-bit-wise minimums of signed integers
25320 * contained in XRb and XRc.
25321 *
25322 * 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
25323 * +-----------+---------+-----+-------+-------+-------+-----------+
25324 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25325 * +-----------+---------+-----+-------+-------+-------+-----------+
25326 */
25327 static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx)
25328 {
25329 uint32_t pad, opc, XRc, XRb, XRa;
25330
25331 pad = extract32(ctx->opcode, 21, 5);
25332 opc = extract32(ctx->opcode, 18, 3);
25333 XRc = extract32(ctx->opcode, 14, 4);
25334 XRb = extract32(ctx->opcode, 10, 4);
25335 XRa = extract32(ctx->opcode, 6, 4);
25336
25337 if (unlikely(pad != 0)) {
25338 /* opcode padding incorrect -> do nothing */
25339 } else if (unlikely(XRa == 0)) {
25340 /* destination is zero register -> do nothing */
25341 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25342 /* both operands zero registers -> just set destination to zero */
25343 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25344 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25345 /* exactly one operand is zero register - make it be the first...*/
25346 uint32_t XRx = XRb ? XRb : XRc;
25347 /* ...and do byte-wise max/min with one operand 0 */
25348 TCGv_i32 t0 = tcg_temp_new();
25349 TCGv_i32 t1 = tcg_const_i32(0);
25350 int32_t i;
25351
25352 /* the leftmost byte (byte 3) first */
25353 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000);
25354 if (opc == OPC_MXU_Q8MAX) {
25355 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25356 } else {
25357 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25358 }
25359
25360 /* bytes 2, 1, 0 */
25361 for (i = 2; i >= 0; i--) {
25362 /* extract the byte */
25363 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i));
25364 /* move the byte to the leftmost position */
25365 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25366 /* t0 will be max/min of t0 and t1 */
25367 if (opc == OPC_MXU_Q8MAX) {
25368 tcg_gen_smax_i32(t0, t0, t1);
25369 } else {
25370 tcg_gen_smin_i32(t0, t0, t1);
25371 }
25372 /* return resulting byte to its original position */
25373 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25374 /* finaly update the destination */
25375 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25376 }
25377
25378 tcg_temp_free(t1);
25379 tcg_temp_free(t0);
25380 } else if (unlikely(XRb == XRc)) {
25381 /* both operands same -> just set destination to one of them */
25382 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25383 } else {
25384 /* the most general case */
25385 TCGv_i32 t0 = tcg_temp_new();
25386 TCGv_i32 t1 = tcg_temp_new();
25387 int32_t i;
25388
25389 /* the leftmost bytes (bytes 3) first */
25390 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000);
25391 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25392 if (opc == OPC_MXU_Q8MAX) {
25393 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25394 } else {
25395 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25396 }
25397
25398 /* bytes 2, 1, 0 */
25399 for (i = 2; i >= 0; i--) {
25400 /* extract corresponding bytes */
25401 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i));
25402 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i));
25403 /* move the bytes to the leftmost position */
25404 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25405 tcg_gen_shli_i32(t1, t1, 8 * (3 - i));
25406 /* t0 will be max/min of t0 and t1 */
25407 if (opc == OPC_MXU_Q8MAX) {
25408 tcg_gen_smax_i32(t0, t0, t1);
25409 } else {
25410 tcg_gen_smin_i32(t0, t0, t1);
25411 }
25412 /* return resulting byte to its original position */
25413 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25414 /* finaly update the destination */
25415 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25416 }
25417
25418 tcg_temp_free(t1);
25419 tcg_temp_free(t0);
25420 }
25421 }
25422
25423
25424 /*
25425 * MXU instruction category: align
25426 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25427 *
25428 * S32ALN S32ALNI
25429 */
25430
25431 /*
25432 * S32ALNI XRc, XRb, XRa, optn3
25433 * Arrange bytes from XRb and XRc according to one of five sets of
25434 * rules determined by optn3, and place the result in XRa.
25435 *
25436 * 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
25437 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25438 * | SPECIAL2 |optn3|0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
25439 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25440 *
25441 */
25442 static void gen_mxu_S32ALNI(DisasContext *ctx)
25443 {
25444 uint32_t optn3, pad, XRc, XRb, XRa;
25445
25446 optn3 = extract32(ctx->opcode, 23, 3);
25447 pad = extract32(ctx->opcode, 21, 2);
25448 XRc = extract32(ctx->opcode, 14, 4);
25449 XRb = extract32(ctx->opcode, 10, 4);
25450 XRa = extract32(ctx->opcode, 6, 4);
25451
25452 if (unlikely(pad != 0)) {
25453 /* opcode padding incorrect -> do nothing */
25454 } else if (unlikely(XRa == 0)) {
25455 /* destination is zero register -> do nothing */
25456 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25457 /* both operands zero registers -> just set destination to all 0s */
25458 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25459 } else if (unlikely(XRb == 0)) {
25460 /* XRb zero register -> just appropriatelly shift XRc into XRa */
25461 switch (optn3) {
25462 case MXU_OPTN3_PTN0:
25463 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25464 break;
25465 case MXU_OPTN3_PTN1:
25466 case MXU_OPTN3_PTN2:
25467 case MXU_OPTN3_PTN3:
25468 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1],
25469 8 * (4 - optn3));
25470 break;
25471 case MXU_OPTN3_PTN4:
25472 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25473 break;
25474 }
25475 } else if (unlikely(XRc == 0)) {
25476 /* XRc zero register -> just appropriatelly shift XRb into XRa */
25477 switch (optn3) {
25478 case MXU_OPTN3_PTN0:
25479 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25480 break;
25481 case MXU_OPTN3_PTN1:
25482 case MXU_OPTN3_PTN2:
25483 case MXU_OPTN3_PTN3:
25484 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25485 break;
25486 case MXU_OPTN3_PTN4:
25487 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25488 break;
25489 }
25490 } else if (unlikely(XRb == XRc)) {
25491 /* both operands same -> just rotation or moving from any of them */
25492 switch (optn3) {
25493 case MXU_OPTN3_PTN0:
25494 case MXU_OPTN3_PTN4:
25495 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25496 break;
25497 case MXU_OPTN3_PTN1:
25498 case MXU_OPTN3_PTN2:
25499 case MXU_OPTN3_PTN3:
25500 tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25501 break;
25502 }
25503 } else {
25504 /* the most general case */
25505 switch (optn3) {
25506 case MXU_OPTN3_PTN0:
25507 {
25508 /* */
25509 /* XRb XRc */
25510 /* +---------------+ */
25511 /* | A B C D | E F G H */
25512 /* +-------+-------+ */
25513 /* | */
25514 /* XRa */
25515 /* */
25516
25517 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25518 }
25519 break;
25520 case MXU_OPTN3_PTN1:
25521 {
25522 /* */
25523 /* XRb XRc */
25524 /* +-------------------+ */
25525 /* A | B C D E | F G H */
25526 /* +---------+---------+ */
25527 /* | */
25528 /* XRa */
25529 /* */
25530
25531 TCGv_i32 t0 = tcg_temp_new();
25532 TCGv_i32 t1 = tcg_temp_new();
25533
25534 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF);
25535 tcg_gen_shli_i32(t0, t0, 8);
25536
25537 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25538 tcg_gen_shri_i32(t1, t1, 24);
25539
25540 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25541
25542 tcg_temp_free(t1);
25543 tcg_temp_free(t0);
25544 }
25545 break;
25546 case MXU_OPTN3_PTN2:
25547 {
25548 /* */
25549 /* XRb XRc */
25550 /* +-------------------+ */
25551 /* A B | C D E F | G H */
25552 /* +---------+---------+ */
25553 /* | */
25554 /* XRa */
25555 /* */
25556
25557 TCGv_i32 t0 = tcg_temp_new();
25558 TCGv_i32 t1 = tcg_temp_new();
25559
25560 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25561 tcg_gen_shli_i32(t0, t0, 16);
25562
25563 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25564 tcg_gen_shri_i32(t1, t1, 16);
25565
25566 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25567
25568 tcg_temp_free(t1);
25569 tcg_temp_free(t0);
25570 }
25571 break;
25572 case MXU_OPTN3_PTN3:
25573 {
25574 /* */
25575 /* XRb XRc */
25576 /* +-------------------+ */
25577 /* A B C | D E F G | H */
25578 /* +---------+---------+ */
25579 /* | */
25580 /* XRa */
25581 /* */
25582
25583 TCGv_i32 t0 = tcg_temp_new();
25584 TCGv_i32 t1 = tcg_temp_new();
25585
25586 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF);
25587 tcg_gen_shli_i32(t0, t0, 24);
25588
25589 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00);
25590 tcg_gen_shri_i32(t1, t1, 8);
25591
25592 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25593
25594 tcg_temp_free(t1);
25595 tcg_temp_free(t0);
25596 }
25597 break;
25598 case MXU_OPTN3_PTN4:
25599 {
25600 /* */
25601 /* XRb XRc */
25602 /* +---------------+ */
25603 /* A B C D | E F G H | */
25604 /* +-------+-------+ */
25605 /* | */
25606 /* XRa */
25607 /* */
25608
25609 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25610 }
25611 break;
25612 }
25613 }
25614 }
25615
25616
25617 /*
25618 * Decoding engine for MXU
25619 * =======================
25620 */
25621
25622 /*
25623 *
25624 * Decode MXU pool00
25625 *
25626 * 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
25627 * +-----------+---------+-----+-------+-------+-------+-----------+
25628 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL00|
25629 * +-----------+---------+-----+-------+-------+-------+-----------+
25630 *
25631 */
25632 static void decode_opc_mxu__pool00(CPUMIPSState *env, DisasContext *ctx)
25633 {
25634 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25635
25636 switch (opcode) {
25637 case OPC_MXU_S32MAX:
25638 case OPC_MXU_S32MIN:
25639 gen_mxu_S32MAX_S32MIN(ctx);
25640 break;
25641 case OPC_MXU_D16MAX:
25642 case OPC_MXU_D16MIN:
25643 gen_mxu_D16MAX_D16MIN(ctx);
25644 break;
25645 case OPC_MXU_Q8MAX:
25646 case OPC_MXU_Q8MIN:
25647 gen_mxu_Q8MAX_Q8MIN(ctx);
25648 break;
25649 case OPC_MXU_Q8SLT:
25650 /* TODO: Implement emulation of Q8SLT instruction. */
25651 MIPS_INVAL("OPC_MXU_Q8SLT");
25652 generate_exception_end(ctx, EXCP_RI);
25653 break;
25654 case OPC_MXU_Q8SLTU:
25655 /* TODO: Implement emulation of Q8SLTU instruction. */
25656 MIPS_INVAL("OPC_MXU_Q8SLTU");
25657 generate_exception_end(ctx, EXCP_RI);
25658 break;
25659 default:
25660 MIPS_INVAL("decode_opc_mxu");
25661 generate_exception_end(ctx, EXCP_RI);
25662 break;
25663 }
25664 }
25665
25666 /*
25667 *
25668 * Decode MXU pool01
25669 *
25670 * S32SLT, D16SLT, D16AVG, D16AVGR, Q8AVG, Q8AVGR:
25671 * 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
25672 * +-----------+---------+-----+-------+-------+-------+-----------+
25673 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
25674 * +-----------+---------+-----+-------+-------+-------+-----------+
25675 *
25676 * Q8ADD:
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 |en2|0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
25680 * +-----------+---+-----+-----+-------+-------+-------+-----------+
25681 *
25682 */
25683 static void decode_opc_mxu__pool01(CPUMIPSState *env, DisasContext *ctx)
25684 {
25685 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25686
25687 switch (opcode) {
25688 case OPC_MXU_S32SLT:
25689 /* TODO: Implement emulation of S32SLT instruction. */
25690 MIPS_INVAL("OPC_MXU_S32SLT");
25691 generate_exception_end(ctx, EXCP_RI);
25692 break;
25693 case OPC_MXU_D16SLT:
25694 /* TODO: Implement emulation of D16SLT instruction. */
25695 MIPS_INVAL("OPC_MXU_D16SLT");
25696 generate_exception_end(ctx, EXCP_RI);
25697 break;
25698 case OPC_MXU_D16AVG:
25699 /* TODO: Implement emulation of D16AVG instruction. */
25700 MIPS_INVAL("OPC_MXU_D16AVG");
25701 generate_exception_end(ctx, EXCP_RI);
25702 break;
25703 case OPC_MXU_D16AVGR:
25704 /* TODO: Implement emulation of D16AVGR instruction. */
25705 MIPS_INVAL("OPC_MXU_D16AVGR");
25706 generate_exception_end(ctx, EXCP_RI);
25707 break;
25708 case OPC_MXU_Q8AVG:
25709 /* TODO: Implement emulation of Q8AVG instruction. */
25710 MIPS_INVAL("OPC_MXU_Q8AVG");
25711 generate_exception_end(ctx, EXCP_RI);
25712 break;
25713 case OPC_MXU_Q8AVGR:
25714 /* TODO: Implement emulation of Q8AVGR instruction. */
25715 MIPS_INVAL("OPC_MXU_Q8AVGR");
25716 generate_exception_end(ctx, EXCP_RI);
25717 break;
25718 case OPC_MXU_Q8ADD:
25719 /* TODO: Implement emulation of Q8ADD instruction. */
25720 MIPS_INVAL("OPC_MXU_Q8ADD");
25721 generate_exception_end(ctx, EXCP_RI);
25722 break;
25723 default:
25724 MIPS_INVAL("decode_opc_mxu");
25725 generate_exception_end(ctx, EXCP_RI);
25726 break;
25727 }
25728 }
25729
25730 /*
25731 *
25732 * Decode MXU pool02
25733 *
25734 * 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
25735 * +-----------+---------+-----+-------+-------+-------+-----------+
25736 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL02|
25737 * +-----------+---------+-----+-------+-------+-------+-----------+
25738 *
25739 */
25740 static void decode_opc_mxu__pool02(CPUMIPSState *env, DisasContext *ctx)
25741 {
25742 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25743
25744 switch (opcode) {
25745 case OPC_MXU_S32CPS:
25746 /* TODO: Implement emulation of S32CPS instruction. */
25747 MIPS_INVAL("OPC_MXU_S32CPS");
25748 generate_exception_end(ctx, EXCP_RI);
25749 break;
25750 case OPC_MXU_D16CPS:
25751 /* TODO: Implement emulation of D16CPS instruction. */
25752 MIPS_INVAL("OPC_MXU_D16CPS");
25753 generate_exception_end(ctx, EXCP_RI);
25754 break;
25755 case OPC_MXU_Q8ABD:
25756 /* TODO: Implement emulation of Q8ABD instruction. */
25757 MIPS_INVAL("OPC_MXU_Q8ABD");
25758 generate_exception_end(ctx, EXCP_RI);
25759 break;
25760 case OPC_MXU_Q16SAT:
25761 /* TODO: Implement emulation of Q16SAT instruction. */
25762 MIPS_INVAL("OPC_MXU_Q16SAT");
25763 generate_exception_end(ctx, EXCP_RI);
25764 break;
25765 default:
25766 MIPS_INVAL("decode_opc_mxu");
25767 generate_exception_end(ctx, EXCP_RI);
25768 break;
25769 }
25770 }
25771
25772 /*
25773 *
25774 * Decode MXU pool03
25775 *
25776 * D16MULF:
25777 * 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
25778 * +-----------+---+---+-------+-------+-------+-------+-----------+
25779 * | SPECIAL2 |x x|on2|0 0 0 0| XRc | XRb | XRa |MXU__POOL03|
25780 * +-----------+---+---+-------+-------+-------+-------+-----------+
25781 *
25782 * D16MULE:
25783 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25784 * +-----------+---+---+-------+-------+-------+-------+-----------+
25785 * | SPECIAL2 |x x|on2| Xd | XRc | XRb | XRa |MXU__POOL03|
25786 * +-----------+---+---+-------+-------+-------+-------+-----------+
25787 *
25788 */
25789 static void decode_opc_mxu__pool03(CPUMIPSState *env, DisasContext *ctx)
25790 {
25791 uint32_t opcode = extract32(ctx->opcode, 24, 2);
25792
25793 switch (opcode) {
25794 case OPC_MXU_D16MULF:
25795 /* TODO: Implement emulation of D16MULF instruction. */
25796 MIPS_INVAL("OPC_MXU_D16MULF");
25797 generate_exception_end(ctx, EXCP_RI);
25798 break;
25799 case OPC_MXU_D16MULE:
25800 /* TODO: Implement emulation of D16MULE instruction. */
25801 MIPS_INVAL("OPC_MXU_D16MULE");
25802 generate_exception_end(ctx, EXCP_RI);
25803 break;
25804 default:
25805 MIPS_INVAL("decode_opc_mxu");
25806 generate_exception_end(ctx, EXCP_RI);
25807 break;
25808 }
25809 }
25810
25811 /*
25812 *
25813 * Decode MXU pool04
25814 *
25815 * 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
25816 * +-----------+---------+-+-------------------+-------+-----------+
25817 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL04|
25818 * +-----------+---------+-+-------------------+-------+-----------+
25819 *
25820 */
25821 static void decode_opc_mxu__pool04(CPUMIPSState *env, DisasContext *ctx)
25822 {
25823 uint32_t opcode = extract32(ctx->opcode, 20, 1);
25824
25825 switch (opcode) {
25826 case OPC_MXU_S32LDD:
25827 case OPC_MXU_S32LDDR:
25828 gen_mxu_s32ldd_s32lddr(ctx);
25829 break;
25830 default:
25831 MIPS_INVAL("decode_opc_mxu");
25832 generate_exception_end(ctx, EXCP_RI);
25833 break;
25834 }
25835 }
25836
25837 /*
25838 *
25839 * Decode MXU pool05
25840 *
25841 * 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
25842 * +-----------+---------+-+-------------------+-------+-----------+
25843 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL05|
25844 * +-----------+---------+-+-------------------+-------+-----------+
25845 *
25846 */
25847 static void decode_opc_mxu__pool05(CPUMIPSState *env, DisasContext *ctx)
25848 {
25849 uint32_t opcode = extract32(ctx->opcode, 20, 1);
25850
25851 switch (opcode) {
25852 case OPC_MXU_S32STD:
25853 /* TODO: Implement emulation of S32STD instruction. */
25854 MIPS_INVAL("OPC_MXU_S32STD");
25855 generate_exception_end(ctx, EXCP_RI);
25856 break;
25857 case OPC_MXU_S32STDR:
25858 /* TODO: Implement emulation of S32STDR instruction. */
25859 MIPS_INVAL("OPC_MXU_S32STDR");
25860 generate_exception_end(ctx, EXCP_RI);
25861 break;
25862 default:
25863 MIPS_INVAL("decode_opc_mxu");
25864 generate_exception_end(ctx, EXCP_RI);
25865 break;
25866 }
25867 }
25868
25869 /*
25870 *
25871 * Decode MXU pool06
25872 *
25873 * 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
25874 * +-----------+---------+---------+---+-------+-------+-----------+
25875 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL06|
25876 * +-----------+---------+---------+---+-------+-------+-----------+
25877 *
25878 */
25879 static void decode_opc_mxu__pool06(CPUMIPSState *env, DisasContext *ctx)
25880 {
25881 uint32_t opcode = extract32(ctx->opcode, 10, 4);
25882
25883 switch (opcode) {
25884 case OPC_MXU_S32LDDV:
25885 /* TODO: Implement emulation of S32LDDV instruction. */
25886 MIPS_INVAL("OPC_MXU_S32LDDV");
25887 generate_exception_end(ctx, EXCP_RI);
25888 break;
25889 case OPC_MXU_S32LDDVR:
25890 /* TODO: Implement emulation of S32LDDVR instruction. */
25891 MIPS_INVAL("OPC_MXU_S32LDDVR");
25892 generate_exception_end(ctx, EXCP_RI);
25893 break;
25894 default:
25895 MIPS_INVAL("decode_opc_mxu");
25896 generate_exception_end(ctx, EXCP_RI);
25897 break;
25898 }
25899 }
25900
25901 /*
25902 *
25903 * Decode MXU pool07
25904 *
25905 * 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
25906 * +-----------+---------+---------+---+-------+-------+-----------+
25907 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL07|
25908 * +-----------+---------+---------+---+-------+-------+-----------+
25909 *
25910 */
25911 static void decode_opc_mxu__pool07(CPUMIPSState *env, DisasContext *ctx)
25912 {
25913 uint32_t opcode = extract32(ctx->opcode, 10, 4);
25914
25915 switch (opcode) {
25916 case OPC_MXU_S32STDV:
25917 /* TODO: Implement emulation of S32TDV instruction. */
25918 MIPS_INVAL("OPC_MXU_S32TDV");
25919 generate_exception_end(ctx, EXCP_RI);
25920 break;
25921 case OPC_MXU_S32STDVR:
25922 /* TODO: Implement emulation of S32TDVR instruction. */
25923 MIPS_INVAL("OPC_MXU_S32TDVR");
25924 generate_exception_end(ctx, EXCP_RI);
25925 break;
25926 default:
25927 MIPS_INVAL("decode_opc_mxu");
25928 generate_exception_end(ctx, EXCP_RI);
25929 break;
25930 }
25931 }
25932
25933 /*
25934 *
25935 * Decode MXU pool08
25936 *
25937 * 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
25938 * +-----------+---------+-+-------------------+-------+-----------+
25939 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL08|
25940 * +-----------+---------+-+-------------------+-------+-----------+
25941 *
25942 */
25943 static void decode_opc_mxu__pool08(CPUMIPSState *env, DisasContext *ctx)
25944 {
25945 uint32_t opcode = extract32(ctx->opcode, 20, 1);
25946
25947 switch (opcode) {
25948 case OPC_MXU_S32LDI:
25949 /* TODO: Implement emulation of S32LDI instruction. */
25950 MIPS_INVAL("OPC_MXU_S32LDI");
25951 generate_exception_end(ctx, EXCP_RI);
25952 break;
25953 case OPC_MXU_S32LDIR:
25954 /* TODO: Implement emulation of S32LDIR instruction. */
25955 MIPS_INVAL("OPC_MXU_S32LDIR");
25956 generate_exception_end(ctx, EXCP_RI);
25957 break;
25958 default:
25959 MIPS_INVAL("decode_opc_mxu");
25960 generate_exception_end(ctx, EXCP_RI);
25961 break;
25962 }
25963 }
25964
25965 /*
25966 *
25967 * Decode MXU pool09
25968 *
25969 * 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
25970 * +-----------+---------+-+-------------------+-------+-----------+
25971 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL09|
25972 * +-----------+---------+-+-------------------+-------+-----------+
25973 *
25974 */
25975 static void decode_opc_mxu__pool09(CPUMIPSState *env, DisasContext *ctx)
25976 {
25977 uint32_t opcode = extract32(ctx->opcode, 5, 0);
25978
25979 switch (opcode) {
25980 case OPC_MXU_S32SDI:
25981 /* TODO: Implement emulation of S32SDI instruction. */
25982 MIPS_INVAL("OPC_MXU_S32SDI");
25983 generate_exception_end(ctx, EXCP_RI);
25984 break;
25985 case OPC_MXU_S32SDIR:
25986 /* TODO: Implement emulation of S32SDIR instruction. */
25987 MIPS_INVAL("OPC_MXU_S32SDIR");
25988 generate_exception_end(ctx, EXCP_RI);
25989 break;
25990 default:
25991 MIPS_INVAL("decode_opc_mxu");
25992 generate_exception_end(ctx, EXCP_RI);
25993 break;
25994 }
25995 }
25996
25997 /*
25998 *
25999 * Decode MXU pool10
26000 *
26001 * 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
26002 * +-----------+---------+---------+---+-------+-------+-----------+
26003 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL10|
26004 * +-----------+---------+---------+---+-------+-------+-----------+
26005 *
26006 */
26007 static void decode_opc_mxu__pool10(CPUMIPSState *env, DisasContext *ctx)
26008 {
26009 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26010
26011 switch (opcode) {
26012 case OPC_MXU_S32LDIV:
26013 /* TODO: Implement emulation of S32LDIV instruction. */
26014 MIPS_INVAL("OPC_MXU_S32LDIV");
26015 generate_exception_end(ctx, EXCP_RI);
26016 break;
26017 case OPC_MXU_S32LDIVR:
26018 /* TODO: Implement emulation of S32LDIVR instruction. */
26019 MIPS_INVAL("OPC_MXU_S32LDIVR");
26020 generate_exception_end(ctx, EXCP_RI);
26021 break;
26022 default:
26023 MIPS_INVAL("decode_opc_mxu");
26024 generate_exception_end(ctx, EXCP_RI);
26025 break;
26026 }
26027 }
26028
26029 /*
26030 *
26031 * Decode MXU pool11
26032 *
26033 * 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
26034 * +-----------+---------+---------+---+-------+-------+-----------+
26035 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL11|
26036 * +-----------+---------+---------+---+-------+-------+-----------+
26037 *
26038 */
26039 static void decode_opc_mxu__pool11(CPUMIPSState *env, DisasContext *ctx)
26040 {
26041 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26042
26043 switch (opcode) {
26044 case OPC_MXU_S32SDIV:
26045 /* TODO: Implement emulation of S32SDIV instruction. */
26046 MIPS_INVAL("OPC_MXU_S32SDIV");
26047 generate_exception_end(ctx, EXCP_RI);
26048 break;
26049 case OPC_MXU_S32SDIVR:
26050 /* TODO: Implement emulation of S32SDIVR instruction. */
26051 MIPS_INVAL("OPC_MXU_S32SDIVR");
26052 generate_exception_end(ctx, EXCP_RI);
26053 break;
26054 default:
26055 MIPS_INVAL("decode_opc_mxu");
26056 generate_exception_end(ctx, EXCP_RI);
26057 break;
26058 }
26059 }
26060
26061 /*
26062 *
26063 * Decode MXU pool12
26064 *
26065 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26066 * +-----------+---+---+-------+-------+-------+-------+-----------+
26067 * | SPECIAL2 |an2|x x| Xd | XRc | XRb | XRa |MXU__POOL12|
26068 * +-----------+---+---+-------+-------+-------+-------+-----------+
26069 *
26070 */
26071 static void decode_opc_mxu__pool12(CPUMIPSState *env, DisasContext *ctx)
26072 {
26073 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26074
26075 switch (opcode) {
26076 case OPC_MXU_D32ACC:
26077 /* TODO: Implement emulation of D32ACC instruction. */
26078 MIPS_INVAL("OPC_MXU_D32ACC");
26079 generate_exception_end(ctx, EXCP_RI);
26080 break;
26081 case OPC_MXU_D32ACCM:
26082 /* TODO: Implement emulation of D32ACCM instruction. */
26083 MIPS_INVAL("OPC_MXU_D32ACCM");
26084 generate_exception_end(ctx, EXCP_RI);
26085 break;
26086 case OPC_MXU_D32ASUM:
26087 /* TODO: Implement emulation of D32ASUM instruction. */
26088 MIPS_INVAL("OPC_MXU_D32ASUM");
26089 generate_exception_end(ctx, EXCP_RI);
26090 break;
26091 default:
26092 MIPS_INVAL("decode_opc_mxu");
26093 generate_exception_end(ctx, EXCP_RI);
26094 break;
26095 }
26096 }
26097
26098 /*
26099 *
26100 * Decode MXU pool13
26101 *
26102 * 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
26103 * +-----------+---+---+-------+-------+-------+-------+-----------+
26104 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL13|
26105 * +-----------+---+---+-------+-------+-------+-------+-----------+
26106 *
26107 */
26108 static void decode_opc_mxu__pool13(CPUMIPSState *env, DisasContext *ctx)
26109 {
26110 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26111
26112 switch (opcode) {
26113 case OPC_MXU_Q16ACC:
26114 /* TODO: Implement emulation of Q16ACC instruction. */
26115 MIPS_INVAL("OPC_MXU_Q16ACC");
26116 generate_exception_end(ctx, EXCP_RI);
26117 break;
26118 case OPC_MXU_Q16ACCM:
26119 /* TODO: Implement emulation of Q16ACCM instruction. */
26120 MIPS_INVAL("OPC_MXU_Q16ACCM");
26121 generate_exception_end(ctx, EXCP_RI);
26122 break;
26123 case OPC_MXU_Q16ASUM:
26124 /* TODO: Implement emulation of Q16ASUM instruction. */
26125 MIPS_INVAL("OPC_MXU_Q16ASUM");
26126 generate_exception_end(ctx, EXCP_RI);
26127 break;
26128 default:
26129 MIPS_INVAL("decode_opc_mxu");
26130 generate_exception_end(ctx, EXCP_RI);
26131 break;
26132 }
26133 }
26134
26135 /*
26136 *
26137 * Decode MXU pool14
26138 *
26139 * Q8ADDE, Q8ACCE:
26140 * 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
26141 * +-----------+---+---+-------+-------+-------+-------+-----------+
26142 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL14|
26143 * +-----------+---+---+-------+-------+-------+-------+-----------+
26144 *
26145 * D8SUM, D8SUMC:
26146 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26147 * +-----------+---+---+-------+-------+-------+-------+-----------+
26148 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL14|
26149 * +-----------+---+---+-------+-------+-------+-------+-----------+
26150 *
26151 */
26152 static void decode_opc_mxu__pool14(CPUMIPSState *env, DisasContext *ctx)
26153 {
26154 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26155
26156 switch (opcode) {
26157 case OPC_MXU_Q8ADDE:
26158 /* TODO: Implement emulation of Q8ADDE instruction. */
26159 MIPS_INVAL("OPC_MXU_Q8ADDE");
26160 generate_exception_end(ctx, EXCP_RI);
26161 break;
26162 case OPC_MXU_D8SUM:
26163 /* TODO: Implement emulation of D8SUM instruction. */
26164 MIPS_INVAL("OPC_MXU_D8SUM");
26165 generate_exception_end(ctx, EXCP_RI);
26166 break;
26167 case OPC_MXU_D8SUMC:
26168 /* TODO: Implement emulation of D8SUMC instruction. */
26169 MIPS_INVAL("OPC_MXU_D8SUMC");
26170 generate_exception_end(ctx, EXCP_RI);
26171 break;
26172 default:
26173 MIPS_INVAL("decode_opc_mxu");
26174 generate_exception_end(ctx, EXCP_RI);
26175 break;
26176 }
26177 }
26178
26179 /*
26180 *
26181 * Decode MXU pool15
26182 *
26183 * S32MUL, S32MULU, S32EXTRV:
26184 * 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
26185 * +-----------+---------+---------+---+-------+-------+-----------+
26186 * | SPECIAL2 | rs | rt |x x| XRd | XRa |MXU__POOL15|
26187 * +-----------+---------+---------+---+-------+-------+-----------+
26188 *
26189 * S32EXTR:
26190 * 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
26191 * +-----------+---------+---------+---+-------+-------+-----------+
26192 * | SPECIAL2 | rb | sft5 |x x| XRd | XRa |MXU__POOL15|
26193 * +-----------+---------+---------+---+-------+-------+-----------+
26194 *
26195 */
26196 static void decode_opc_mxu__pool15(CPUMIPSState *env, DisasContext *ctx)
26197 {
26198 uint32_t opcode = extract32(ctx->opcode, 14, 2);
26199
26200 switch (opcode) {
26201 case OPC_MXU_S32MUL:
26202 /* TODO: Implement emulation of S32MUL instruction. */
26203 MIPS_INVAL("OPC_MXU_S32MUL");
26204 generate_exception_end(ctx, EXCP_RI);
26205 break;
26206 case OPC_MXU_S32MULU:
26207 /* TODO: Implement emulation of S32MULU instruction. */
26208 MIPS_INVAL("OPC_MXU_S32MULU");
26209 generate_exception_end(ctx, EXCP_RI);
26210 break;
26211 case OPC_MXU_S32EXTR:
26212 /* TODO: Implement emulation of S32EXTR instruction. */
26213 MIPS_INVAL("OPC_MXU_S32EXTR");
26214 generate_exception_end(ctx, EXCP_RI);
26215 break;
26216 case OPC_MXU_S32EXTRV:
26217 /* TODO: Implement emulation of S32EXTRV instruction. */
26218 MIPS_INVAL("OPC_MXU_S32EXTRV");
26219 generate_exception_end(ctx, EXCP_RI);
26220 break;
26221 default:
26222 MIPS_INVAL("decode_opc_mxu");
26223 generate_exception_end(ctx, EXCP_RI);
26224 break;
26225 }
26226 }
26227
26228 /*
26229 *
26230 * Decode MXU pool16
26231 *
26232 * D32SARW:
26233 * 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
26234 * +-----------+---------+-----+-------+-------+-------+-----------+
26235 * | SPECIAL2 | rb |x x x| XRc | XRb | XRa |MXU__POOL16|
26236 * +-----------+---------+-----+-------+-------+-------+-----------+
26237 *
26238 * S32ALN:
26239 * 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
26240 * +-----------+---------+-----+-------+-------+-------+-----------+
26241 * | SPECIAL2 | rs |x x x| XRc | XRb | XRa |MXU__POOL16|
26242 * +-----------+---------+-----+-------+-------+-------+-----------+
26243 *
26244 * S32ALNI:
26245 * 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
26246 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26247 * | SPECIAL2 | s3 |0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26248 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26249 *
26250 * S32LUI:
26251 * 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
26252 * +-----------+-----+---+-----+-------+---------------+-----------+
26253 * | SPECIAL2 |optn3|0 0|x x x| XRc | s8 |MXU__POOL16|
26254 * +-----------+-----+---+-----+-------+---------------+-----------+
26255 *
26256 * S32NOR, S32AND, S32OR, S32XOR:
26257 * 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
26258 * +-----------+---------+-----+-------+-------+-------+-----------+
26259 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26260 * +-----------+---------+-----+-------+-------+-------+-----------+
26261 *
26262 */
26263 static void decode_opc_mxu__pool16(CPUMIPSState *env, DisasContext *ctx)
26264 {
26265 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26266
26267 switch (opcode) {
26268 case OPC_MXU_D32SARW:
26269 /* TODO: Implement emulation of D32SARW instruction. */
26270 MIPS_INVAL("OPC_MXU_D32SARW");
26271 generate_exception_end(ctx, EXCP_RI);
26272 break;
26273 case OPC_MXU_S32ALN:
26274 /* TODO: Implement emulation of S32ALN instruction. */
26275 MIPS_INVAL("OPC_MXU_S32ALN");
26276 generate_exception_end(ctx, EXCP_RI);
26277 break;
26278 case OPC_MXU_S32ALNI:
26279 gen_mxu_S32ALNI(ctx);
26280 break;
26281 case OPC_MXU_S32LUI:
26282 /* TODO: Implement emulation of S32LUI instruction. */
26283 MIPS_INVAL("OPC_MXU_S32LUI");
26284 generate_exception_end(ctx, EXCP_RI);
26285 break;
26286 case OPC_MXU_S32NOR:
26287 gen_mxu_S32NOR(ctx);
26288 break;
26289 case OPC_MXU_S32AND:
26290 gen_mxu_S32AND(ctx);
26291 break;
26292 case OPC_MXU_S32OR:
26293 gen_mxu_S32OR(ctx);
26294 break;
26295 case OPC_MXU_S32XOR:
26296 gen_mxu_S32XOR(ctx);
26297 break;
26298 default:
26299 MIPS_INVAL("decode_opc_mxu");
26300 generate_exception_end(ctx, EXCP_RI);
26301 break;
26302 }
26303 }
26304
26305 /*
26306 *
26307 * Decode MXU pool17
26308 *
26309 * 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
26310 * +-----------+---------+---------+---+---------+-----+-----------+
26311 * | SPECIAL2 | rs | rt |0 0| rd |x x x|MXU__POOL15|
26312 * +-----------+---------+---------+---+---------+-----+-----------+
26313 *
26314 */
26315 static void decode_opc_mxu__pool17(CPUMIPSState *env, DisasContext *ctx)
26316 {
26317 uint32_t opcode = extract32(ctx->opcode, 6, 2);
26318
26319 switch (opcode) {
26320 case OPC_MXU_LXW:
26321 /* TODO: Implement emulation of LXW instruction. */
26322 MIPS_INVAL("OPC_MXU_LXW");
26323 generate_exception_end(ctx, EXCP_RI);
26324 break;
26325 case OPC_MXU_LXH:
26326 /* TODO: Implement emulation of LXH instruction. */
26327 MIPS_INVAL("OPC_MXU_LXH");
26328 generate_exception_end(ctx, EXCP_RI);
26329 break;
26330 case OPC_MXU_LXHU:
26331 /* TODO: Implement emulation of LXHU instruction. */
26332 MIPS_INVAL("OPC_MXU_LXHU");
26333 generate_exception_end(ctx, EXCP_RI);
26334 break;
26335 case OPC_MXU_LXB:
26336 /* TODO: Implement emulation of LXB instruction. */
26337 MIPS_INVAL("OPC_MXU_LXB");
26338 generate_exception_end(ctx, EXCP_RI);
26339 break;
26340 case OPC_MXU_LXBU:
26341 /* TODO: Implement emulation of LXBU instruction. */
26342 MIPS_INVAL("OPC_MXU_LXBU");
26343 generate_exception_end(ctx, EXCP_RI);
26344 break;
26345 default:
26346 MIPS_INVAL("decode_opc_mxu");
26347 generate_exception_end(ctx, EXCP_RI);
26348 break;
26349 }
26350 }
26351 /*
26352 *
26353 * Decode MXU pool18
26354 *
26355 * 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
26356 * +-----------+---------+-----+-------+-------+-------+-----------+
26357 * | SPECIAL2 | rb |x x x| XRd | XRa |0 0 0 0|MXU__POOL18|
26358 * +-----------+---------+-----+-------+-------+-------+-----------+
26359 *
26360 */
26361 static void decode_opc_mxu__pool18(CPUMIPSState *env, DisasContext *ctx)
26362 {
26363 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26364
26365 switch (opcode) {
26366 case OPC_MXU_D32SLLV:
26367 /* TODO: Implement emulation of D32SLLV instruction. */
26368 MIPS_INVAL("OPC_MXU_D32SLLV");
26369 generate_exception_end(ctx, EXCP_RI);
26370 break;
26371 case OPC_MXU_D32SLRV:
26372 /* TODO: Implement emulation of D32SLRV instruction. */
26373 MIPS_INVAL("OPC_MXU_D32SLRV");
26374 generate_exception_end(ctx, EXCP_RI);
26375 break;
26376 case OPC_MXU_D32SARV:
26377 /* TODO: Implement emulation of D32SARV instruction. */
26378 MIPS_INVAL("OPC_MXU_D32SARV");
26379 generate_exception_end(ctx, EXCP_RI);
26380 break;
26381 case OPC_MXU_Q16SLLV:
26382 /* TODO: Implement emulation of Q16SLLV instruction. */
26383 MIPS_INVAL("OPC_MXU_Q16SLLV");
26384 generate_exception_end(ctx, EXCP_RI);
26385 break;
26386 case OPC_MXU_Q16SLRV:
26387 /* TODO: Implement emulation of Q16SLRV instruction. */
26388 MIPS_INVAL("OPC_MXU_Q16SLRV");
26389 generate_exception_end(ctx, EXCP_RI);
26390 break;
26391 case OPC_MXU_Q16SARV:
26392 /* TODO: Implement emulation of Q16SARV instruction. */
26393 MIPS_INVAL("OPC_MXU_Q16SARV");
26394 generate_exception_end(ctx, EXCP_RI);
26395 break;
26396 default:
26397 MIPS_INVAL("decode_opc_mxu");
26398 generate_exception_end(ctx, EXCP_RI);
26399 break;
26400 }
26401 }
26402
26403 /*
26404 *
26405 * Decode MXU pool19
26406 *
26407 * 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
26408 * +-----------+---+---+-------+-------+-------+-------+-----------+
26409 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL19|
26410 * +-----------+---+---+-------+-------+-------+-------+-----------+
26411 *
26412 */
26413 static void decode_opc_mxu__pool19(CPUMIPSState *env, DisasContext *ctx)
26414 {
26415 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26416
26417 switch (opcode) {
26418 case OPC_MXU_Q8MUL:
26419 case OPC_MXU_Q8MULSU:
26420 gen_mxu_q8mul_q8mulsu(ctx);
26421 break;
26422 default:
26423 MIPS_INVAL("decode_opc_mxu");
26424 generate_exception_end(ctx, EXCP_RI);
26425 break;
26426 }
26427 }
26428
26429 /*
26430 *
26431 * Decode MXU pool20
26432 *
26433 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26434 * +-----------+---------+-----+-------+-------+-------+-----------+
26435 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL20|
26436 * +-----------+---------+-----+-------+-------+-------+-----------+
26437 *
26438 */
26439 static void decode_opc_mxu__pool20(CPUMIPSState *env, DisasContext *ctx)
26440 {
26441 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26442
26443 switch (opcode) {
26444 case OPC_MXU_Q8MOVZ:
26445 /* TODO: Implement emulation of Q8MOVZ instruction. */
26446 MIPS_INVAL("OPC_MXU_Q8MOVZ");
26447 generate_exception_end(ctx, EXCP_RI);
26448 break;
26449 case OPC_MXU_Q8MOVN:
26450 /* TODO: Implement emulation of Q8MOVN instruction. */
26451 MIPS_INVAL("OPC_MXU_Q8MOVN");
26452 generate_exception_end(ctx, EXCP_RI);
26453 break;
26454 case OPC_MXU_D16MOVZ:
26455 /* TODO: Implement emulation of D16MOVZ instruction. */
26456 MIPS_INVAL("OPC_MXU_D16MOVZ");
26457 generate_exception_end(ctx, EXCP_RI);
26458 break;
26459 case OPC_MXU_D16MOVN:
26460 /* TODO: Implement emulation of D16MOVN instruction. */
26461 MIPS_INVAL("OPC_MXU_D16MOVN");
26462 generate_exception_end(ctx, EXCP_RI);
26463 break;
26464 case OPC_MXU_S32MOVZ:
26465 /* TODO: Implement emulation of S32MOVZ instruction. */
26466 MIPS_INVAL("OPC_MXU_S32MOVZ");
26467 generate_exception_end(ctx, EXCP_RI);
26468 break;
26469 case OPC_MXU_S32MOVN:
26470 /* TODO: Implement emulation of S32MOVN instruction. */
26471 MIPS_INVAL("OPC_MXU_S32MOVN");
26472 generate_exception_end(ctx, EXCP_RI);
26473 break;
26474 default:
26475 MIPS_INVAL("decode_opc_mxu");
26476 generate_exception_end(ctx, EXCP_RI);
26477 break;
26478 }
26479 }
26480
26481 /*
26482 *
26483 * Decode MXU pool21
26484 *
26485 * 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
26486 * +-----------+---+---+-------+-------+-------+-------+-----------+
26487 * | SPECIAL2 |an2|x x| XRd | XRc | XRb | XRa |MXU__POOL21|
26488 * +-----------+---+---+-------+-------+-------+-------+-----------+
26489 *
26490 */
26491 static void decode_opc_mxu__pool21(CPUMIPSState *env, DisasContext *ctx)
26492 {
26493 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26494
26495 switch (opcode) {
26496 case OPC_MXU_Q8MAC:
26497 /* TODO: Implement emulation of Q8MAC instruction. */
26498 MIPS_INVAL("OPC_MXU_Q8MAC");
26499 generate_exception_end(ctx, EXCP_RI);
26500 break;
26501 case OPC_MXU_Q8MACSU:
26502 /* TODO: Implement emulation of Q8MACSU instruction. */
26503 MIPS_INVAL("OPC_MXU_Q8MACSU");
26504 generate_exception_end(ctx, EXCP_RI);
26505 break;
26506 default:
26507 MIPS_INVAL("decode_opc_mxu");
26508 generate_exception_end(ctx, EXCP_RI);
26509 break;
26510 }
26511 }
26512
26513
26514 /*
26515 * Main MXU decoding function
26516 *
26517 * 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
26518 * +-----------+---------------------------------------+-----------+
26519 * | SPECIAL2 | |x x x x x x|
26520 * +-----------+---------------------------------------+-----------+
26521 *
26522 */
26523 static void decode_opc_mxu(CPUMIPSState *env, DisasContext *ctx)
26524 {
26525 /*
26526 * TODO: Investigate necessity of including handling of
26527 * CLZ, CLO, SDBB in this function, as they belong to
26528 * SPECIAL2 opcode space for regular pre-R6 MIPS ISAs.
26529 */
26530 uint32_t opcode = extract32(ctx->opcode, 0, 6);
26531
26532 if (opcode == OPC__MXU_MUL) {
26533 uint32_t rs, rt, rd, op1;
26534
26535 rs = extract32(ctx->opcode, 21, 5);
26536 rt = extract32(ctx->opcode, 16, 5);
26537 rd = extract32(ctx->opcode, 11, 5);
26538 op1 = MASK_SPECIAL2(ctx->opcode);
26539
26540 gen_arith(ctx, op1, rd, rs, rt);
26541
26542 return;
26543 }
26544
26545 if (opcode == OPC_MXU_S32M2I) {
26546 gen_mxu_s32m2i(ctx);
26547 return;
26548 }
26549
26550 if (opcode == OPC_MXU_S32I2M) {
26551 gen_mxu_s32i2m(ctx);
26552 return;
26553 }
26554
26555 {
26556 TCGv t_mxu_cr = tcg_temp_new();
26557 TCGLabel *l_exit = gen_new_label();
26558
26559 gen_load_mxu_cr(t_mxu_cr);
26560 tcg_gen_andi_tl(t_mxu_cr, t_mxu_cr, MXU_CR_MXU_EN);
26561 tcg_gen_brcondi_tl(TCG_COND_NE, t_mxu_cr, MXU_CR_MXU_EN, l_exit);
26562
26563 switch (opcode) {
26564 case OPC_MXU_S32MADD:
26565 /* TODO: Implement emulation of S32MADD instruction. */
26566 MIPS_INVAL("OPC_MXU_S32MADD");
26567 generate_exception_end(ctx, EXCP_RI);
26568 break;
26569 case OPC_MXU_S32MADDU:
26570 /* TODO: Implement emulation of S32MADDU instruction. */
26571 MIPS_INVAL("OPC_MXU_S32MADDU");
26572 generate_exception_end(ctx, EXCP_RI);
26573 break;
26574 case OPC_MXU__POOL00:
26575 decode_opc_mxu__pool00(env, ctx);
26576 break;
26577 case OPC_MXU_S32MSUB:
26578 /* TODO: Implement emulation of S32MSUB instruction. */
26579 MIPS_INVAL("OPC_MXU_S32MSUB");
26580 generate_exception_end(ctx, EXCP_RI);
26581 break;
26582 case OPC_MXU_S32MSUBU:
26583 /* TODO: Implement emulation of S32MSUBU instruction. */
26584 MIPS_INVAL("OPC_MXU_S32MSUBU");
26585 generate_exception_end(ctx, EXCP_RI);
26586 break;
26587 case OPC_MXU__POOL01:
26588 decode_opc_mxu__pool01(env, ctx);
26589 break;
26590 case OPC_MXU__POOL02:
26591 decode_opc_mxu__pool02(env, ctx);
26592 break;
26593 case OPC_MXU_D16MUL:
26594 gen_mxu_d16mul(ctx);
26595 break;
26596 case OPC_MXU__POOL03:
26597 decode_opc_mxu__pool03(env, ctx);
26598 break;
26599 case OPC_MXU_D16MAC:
26600 gen_mxu_d16mac(ctx);
26601 break;
26602 case OPC_MXU_D16MACF:
26603 /* TODO: Implement emulation of D16MACF instruction. */
26604 MIPS_INVAL("OPC_MXU_D16MACF");
26605 generate_exception_end(ctx, EXCP_RI);
26606 break;
26607 case OPC_MXU_D16MADL:
26608 /* TODO: Implement emulation of D16MADL instruction. */
26609 MIPS_INVAL("OPC_MXU_D16MADL");
26610 generate_exception_end(ctx, EXCP_RI);
26611 break;
26612 case OPC_MXU_S16MAD:
26613 /* TODO: Implement emulation of S16MAD instruction. */
26614 MIPS_INVAL("OPC_MXU_S16MAD");
26615 generate_exception_end(ctx, EXCP_RI);
26616 break;
26617 case OPC_MXU_Q16ADD:
26618 /* TODO: Implement emulation of Q16ADD instruction. */
26619 MIPS_INVAL("OPC_MXU_Q16ADD");
26620 generate_exception_end(ctx, EXCP_RI);
26621 break;
26622 case OPC_MXU_D16MACE:
26623 /* TODO: Implement emulation of D16MACE instruction. */
26624 MIPS_INVAL("OPC_MXU_D16MACE");
26625 generate_exception_end(ctx, EXCP_RI);
26626 break;
26627 case OPC_MXU__POOL04:
26628 decode_opc_mxu__pool04(env, ctx);
26629 break;
26630 case OPC_MXU__POOL05:
26631 decode_opc_mxu__pool05(env, ctx);
26632 break;
26633 case OPC_MXU__POOL06:
26634 decode_opc_mxu__pool06(env, ctx);
26635 break;
26636 case OPC_MXU__POOL07:
26637 decode_opc_mxu__pool07(env, ctx);
26638 break;
26639 case OPC_MXU__POOL08:
26640 decode_opc_mxu__pool08(env, ctx);
26641 break;
26642 case OPC_MXU__POOL09:
26643 decode_opc_mxu__pool09(env, ctx);
26644 break;
26645 case OPC_MXU__POOL10:
26646 decode_opc_mxu__pool10(env, ctx);
26647 break;
26648 case OPC_MXU__POOL11:
26649 decode_opc_mxu__pool11(env, ctx);
26650 break;
26651 case OPC_MXU_D32ADD:
26652 /* TODO: Implement emulation of D32ADD instruction. */
26653 MIPS_INVAL("OPC_MXU_D32ADD");
26654 generate_exception_end(ctx, EXCP_RI);
26655 break;
26656 case OPC_MXU__POOL12:
26657 decode_opc_mxu__pool12(env, ctx);
26658 break;
26659 case OPC_MXU__POOL13:
26660 decode_opc_mxu__pool13(env, ctx);
26661 break;
26662 case OPC_MXU__POOL14:
26663 decode_opc_mxu__pool14(env, ctx);
26664 break;
26665 case OPC_MXU_Q8ACCE:
26666 /* TODO: Implement emulation of Q8ACCE instruction. */
26667 MIPS_INVAL("OPC_MXU_Q8ACCE");
26668 generate_exception_end(ctx, EXCP_RI);
26669 break;
26670 case OPC_MXU_S8LDD:
26671 gen_mxu_s8ldd(ctx);
26672 break;
26673 case OPC_MXU_S8STD:
26674 /* TODO: Implement emulation of S8STD instruction. */
26675 MIPS_INVAL("OPC_MXU_S8STD");
26676 generate_exception_end(ctx, EXCP_RI);
26677 break;
26678 case OPC_MXU_S8LDI:
26679 /* TODO: Implement emulation of S8LDI instruction. */
26680 MIPS_INVAL("OPC_MXU_S8LDI");
26681 generate_exception_end(ctx, EXCP_RI);
26682 break;
26683 case OPC_MXU_S8SDI:
26684 /* TODO: Implement emulation of S8SDI instruction. */
26685 MIPS_INVAL("OPC_MXU_S8SDI");
26686 generate_exception_end(ctx, EXCP_RI);
26687 break;
26688 case OPC_MXU__POOL15:
26689 decode_opc_mxu__pool15(env, ctx);
26690 break;
26691 case OPC_MXU__POOL16:
26692 decode_opc_mxu__pool16(env, ctx);
26693 break;
26694 case OPC_MXU__POOL17:
26695 decode_opc_mxu__pool17(env, ctx);
26696 break;
26697 case OPC_MXU_S16LDD:
26698 /* TODO: Implement emulation of S16LDD instruction. */
26699 MIPS_INVAL("OPC_MXU_S16LDD");
26700 generate_exception_end(ctx, EXCP_RI);
26701 break;
26702 case OPC_MXU_S16STD:
26703 /* TODO: Implement emulation of S16STD instruction. */
26704 MIPS_INVAL("OPC_MXU_S16STD");
26705 generate_exception_end(ctx, EXCP_RI);
26706 break;
26707 case OPC_MXU_S16LDI:
26708 /* TODO: Implement emulation of S16LDI instruction. */
26709 MIPS_INVAL("OPC_MXU_S16LDI");
26710 generate_exception_end(ctx, EXCP_RI);
26711 break;
26712 case OPC_MXU_S16SDI:
26713 /* TODO: Implement emulation of S16SDI instruction. */
26714 MIPS_INVAL("OPC_MXU_S16SDI");
26715 generate_exception_end(ctx, EXCP_RI);
26716 break;
26717 case OPC_MXU_D32SLL:
26718 /* TODO: Implement emulation of D32SLL instruction. */
26719 MIPS_INVAL("OPC_MXU_D32SLL");
26720 generate_exception_end(ctx, EXCP_RI);
26721 break;
26722 case OPC_MXU_D32SLR:
26723 /* TODO: Implement emulation of D32SLR instruction. */
26724 MIPS_INVAL("OPC_MXU_D32SLR");
26725 generate_exception_end(ctx, EXCP_RI);
26726 break;
26727 case OPC_MXU_D32SARL:
26728 /* TODO: Implement emulation of D32SARL instruction. */
26729 MIPS_INVAL("OPC_MXU_D32SARL");
26730 generate_exception_end(ctx, EXCP_RI);
26731 break;
26732 case OPC_MXU_D32SAR:
26733 /* TODO: Implement emulation of D32SAR instruction. */
26734 MIPS_INVAL("OPC_MXU_D32SAR");
26735 generate_exception_end(ctx, EXCP_RI);
26736 break;
26737 case OPC_MXU_Q16SLL:
26738 /* TODO: Implement emulation of Q16SLL instruction. */
26739 MIPS_INVAL("OPC_MXU_Q16SLL");
26740 generate_exception_end(ctx, EXCP_RI);
26741 break;
26742 case OPC_MXU_Q16SLR:
26743 /* TODO: Implement emulation of Q16SLR instruction. */
26744 MIPS_INVAL("OPC_MXU_Q16SLR");
26745 generate_exception_end(ctx, EXCP_RI);
26746 break;
26747 case OPC_MXU__POOL18:
26748 decode_opc_mxu__pool18(env, ctx);
26749 break;
26750 case OPC_MXU_Q16SAR:
26751 /* TODO: Implement emulation of Q16SAR instruction. */
26752 MIPS_INVAL("OPC_MXU_Q16SAR");
26753 generate_exception_end(ctx, EXCP_RI);
26754 break;
26755 case OPC_MXU__POOL19:
26756 decode_opc_mxu__pool19(env, ctx);
26757 break;
26758 case OPC_MXU__POOL20:
26759 decode_opc_mxu__pool20(env, ctx);
26760 break;
26761 case OPC_MXU__POOL21:
26762 decode_opc_mxu__pool21(env, ctx);
26763 break;
26764 case OPC_MXU_Q16SCOP:
26765 /* TODO: Implement emulation of Q16SCOP instruction. */
26766 MIPS_INVAL("OPC_MXU_Q16SCOP");
26767 generate_exception_end(ctx, EXCP_RI);
26768 break;
26769 case OPC_MXU_Q8MADL:
26770 /* TODO: Implement emulation of Q8MADL instruction. */
26771 MIPS_INVAL("OPC_MXU_Q8MADL");
26772 generate_exception_end(ctx, EXCP_RI);
26773 break;
26774 case OPC_MXU_S32SFL:
26775 /* TODO: Implement emulation of S32SFL instruction. */
26776 MIPS_INVAL("OPC_MXU_S32SFL");
26777 generate_exception_end(ctx, EXCP_RI);
26778 break;
26779 case OPC_MXU_Q8SAD:
26780 /* TODO: Implement emulation of Q8SAD instruction. */
26781 MIPS_INVAL("OPC_MXU_Q8SAD");
26782 generate_exception_end(ctx, EXCP_RI);
26783 break;
26784 default:
26785 MIPS_INVAL("decode_opc_mxu");
26786 generate_exception_end(ctx, EXCP_RI);
26787 }
26788
26789 gen_set_label(l_exit);
26790 tcg_temp_free(t_mxu_cr);
26791 }
26792 }
26793
26794 #endif /* !defined(TARGET_MIPS64) */
26795
26796
26797 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
26798 {
26799 int rs, rt, rd;
26800 uint32_t op1;
26801
26802 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26803
26804 rs = (ctx->opcode >> 21) & 0x1f;
26805 rt = (ctx->opcode >> 16) & 0x1f;
26806 rd = (ctx->opcode >> 11) & 0x1f;
26807
26808 op1 = MASK_SPECIAL2(ctx->opcode);
26809 switch (op1) {
26810 case OPC_MADD: /* Multiply and add/sub */
26811 case OPC_MADDU:
26812 case OPC_MSUB:
26813 case OPC_MSUBU:
26814 check_insn(ctx, ISA_MIPS32);
26815 gen_muldiv(ctx, op1, rd & 3, rs, rt);
26816 break;
26817 case OPC_MUL:
26818 gen_arith(ctx, op1, rd, rs, rt);
26819 break;
26820 case OPC_DIV_G_2F:
26821 case OPC_DIVU_G_2F:
26822 case OPC_MULT_G_2F:
26823 case OPC_MULTU_G_2F:
26824 case OPC_MOD_G_2F:
26825 case OPC_MODU_G_2F:
26826 check_insn(ctx, INSN_LOONGSON2F);
26827 gen_loongson_integer(ctx, op1, rd, rs, rt);
26828 break;
26829 case OPC_CLO:
26830 case OPC_CLZ:
26831 check_insn(ctx, ISA_MIPS32);
26832 gen_cl(ctx, op1, rd, rs);
26833 break;
26834 case OPC_SDBBP:
26835 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
26836 gen_helper_do_semihosting(cpu_env);
26837 } else {
26838 /* XXX: not clear which exception should be raised
26839 * when in debug mode...
26840 */
26841 check_insn(ctx, ISA_MIPS32);
26842 generate_exception_end(ctx, EXCP_DBp);
26843 }
26844 break;
26845 #if defined(TARGET_MIPS64)
26846 case OPC_DCLO:
26847 case OPC_DCLZ:
26848 check_insn(ctx, ISA_MIPS64);
26849 check_mips_64(ctx);
26850 gen_cl(ctx, op1, rd, rs);
26851 break;
26852 case OPC_DMULT_G_2F:
26853 case OPC_DMULTU_G_2F:
26854 case OPC_DDIV_G_2F:
26855 case OPC_DDIVU_G_2F:
26856 case OPC_DMOD_G_2F:
26857 case OPC_DMODU_G_2F:
26858 check_insn(ctx, INSN_LOONGSON2F);
26859 gen_loongson_integer(ctx, op1, rd, rs, rt);
26860 break;
26861 #endif
26862 default: /* Invalid */
26863 MIPS_INVAL("special2_legacy");
26864 generate_exception_end(ctx, EXCP_RI);
26865 break;
26866 }
26867 }
26868
26869 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
26870 {
26871 int rs, rt, rd, sa;
26872 uint32_t op1, op2;
26873 int16_t imm;
26874
26875 rs = (ctx->opcode >> 21) & 0x1f;
26876 rt = (ctx->opcode >> 16) & 0x1f;
26877 rd = (ctx->opcode >> 11) & 0x1f;
26878 sa = (ctx->opcode >> 6) & 0x1f;
26879 imm = (int16_t)ctx->opcode >> 7;
26880
26881 op1 = MASK_SPECIAL3(ctx->opcode);
26882 switch (op1) {
26883 case R6_OPC_PREF:
26884 if (rt >= 24) {
26885 /* hint codes 24-31 are reserved and signal RI */
26886 generate_exception_end(ctx, EXCP_RI);
26887 }
26888 /* Treat as NOP. */
26889 break;
26890 case R6_OPC_CACHE:
26891 check_cp0_enabled(ctx);
26892 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
26893 gen_cache_operation(ctx, rt, rs, imm);
26894 }
26895 break;
26896 case R6_OPC_SC:
26897 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
26898 break;
26899 case R6_OPC_LL:
26900 gen_ld(ctx, op1, rt, rs, imm);
26901 break;
26902 case OPC_BSHFL:
26903 {
26904 if (rd == 0) {
26905 /* Treat as NOP. */
26906 break;
26907 }
26908 op2 = MASK_BSHFL(ctx->opcode);
26909 switch (op2) {
26910 case OPC_ALIGN:
26911 case OPC_ALIGN_1:
26912 case OPC_ALIGN_2:
26913 case OPC_ALIGN_3:
26914 gen_align(ctx, 32, rd, rs, rt, sa & 3);
26915 break;
26916 case OPC_BITSWAP:
26917 gen_bitswap(ctx, op2, rd, rt);
26918 break;
26919 }
26920 }
26921 break;
26922 #if defined(TARGET_MIPS64)
26923 case R6_OPC_SCD:
26924 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
26925 break;
26926 case R6_OPC_LLD:
26927 gen_ld(ctx, op1, rt, rs, imm);
26928 break;
26929 case OPC_DBSHFL:
26930 check_mips_64(ctx);
26931 {
26932 if (rd == 0) {
26933 /* Treat as NOP. */
26934 break;
26935 }
26936 op2 = MASK_DBSHFL(ctx->opcode);
26937 switch (op2) {
26938 case OPC_DALIGN:
26939 case OPC_DALIGN_1:
26940 case OPC_DALIGN_2:
26941 case OPC_DALIGN_3:
26942 case OPC_DALIGN_4:
26943 case OPC_DALIGN_5:
26944 case OPC_DALIGN_6:
26945 case OPC_DALIGN_7:
26946 gen_align(ctx, 64, rd, rs, rt, sa & 7);
26947 break;
26948 case OPC_DBITSWAP:
26949 gen_bitswap(ctx, op2, rd, rt);
26950 break;
26951 }
26952
26953 }
26954 break;
26955 #endif
26956 default: /* Invalid */
26957 MIPS_INVAL("special3_r6");
26958 generate_exception_end(ctx, EXCP_RI);
26959 break;
26960 }
26961 }
26962
26963 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
26964 {
26965 int rs, rt, rd;
26966 uint32_t op1, op2;
26967
26968 rs = (ctx->opcode >> 21) & 0x1f;
26969 rt = (ctx->opcode >> 16) & 0x1f;
26970 rd = (ctx->opcode >> 11) & 0x1f;
26971
26972 op1 = MASK_SPECIAL3(ctx->opcode);
26973 switch (op1) {
26974 case OPC_DIV_G_2E:
26975 case OPC_DIVU_G_2E:
26976 case OPC_MOD_G_2E:
26977 case OPC_MODU_G_2E:
26978 case OPC_MULT_G_2E:
26979 case OPC_MULTU_G_2E:
26980 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
26981 * the same mask and op1. */
26982 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
26983 op2 = MASK_ADDUH_QB(ctx->opcode);
26984 switch (op2) {
26985 case OPC_ADDUH_QB:
26986 case OPC_ADDUH_R_QB:
26987 case OPC_ADDQH_PH:
26988 case OPC_ADDQH_R_PH:
26989 case OPC_ADDQH_W:
26990 case OPC_ADDQH_R_W:
26991 case OPC_SUBUH_QB:
26992 case OPC_SUBUH_R_QB:
26993 case OPC_SUBQH_PH:
26994 case OPC_SUBQH_R_PH:
26995 case OPC_SUBQH_W:
26996 case OPC_SUBQH_R_W:
26997 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26998 break;
26999 case OPC_MUL_PH:
27000 case OPC_MUL_S_PH:
27001 case OPC_MULQ_S_W:
27002 case OPC_MULQ_RS_W:
27003 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27004 break;
27005 default:
27006 MIPS_INVAL("MASK ADDUH.QB");
27007 generate_exception_end(ctx, EXCP_RI);
27008 break;
27009 }
27010 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
27011 gen_loongson_integer(ctx, op1, rd, rs, rt);
27012 } else {
27013 generate_exception_end(ctx, EXCP_RI);
27014 }
27015 break;
27016 case OPC_LX_DSP:
27017 op2 = MASK_LX(ctx->opcode);
27018 switch (op2) {
27019 #if defined(TARGET_MIPS64)
27020 case OPC_LDX:
27021 #endif
27022 case OPC_LBUX:
27023 case OPC_LHX:
27024 case OPC_LWX:
27025 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
27026 break;
27027 default: /* Invalid */
27028 MIPS_INVAL("MASK LX");
27029 generate_exception_end(ctx, EXCP_RI);
27030 break;
27031 }
27032 break;
27033 case OPC_ABSQ_S_PH_DSP:
27034 op2 = MASK_ABSQ_S_PH(ctx->opcode);
27035 switch (op2) {
27036 case OPC_ABSQ_S_QB:
27037 case OPC_ABSQ_S_PH:
27038 case OPC_ABSQ_S_W:
27039 case OPC_PRECEQ_W_PHL:
27040 case OPC_PRECEQ_W_PHR:
27041 case OPC_PRECEQU_PH_QBL:
27042 case OPC_PRECEQU_PH_QBR:
27043 case OPC_PRECEQU_PH_QBLA:
27044 case OPC_PRECEQU_PH_QBRA:
27045 case OPC_PRECEU_PH_QBL:
27046 case OPC_PRECEU_PH_QBR:
27047 case OPC_PRECEU_PH_QBLA:
27048 case OPC_PRECEU_PH_QBRA:
27049 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27050 break;
27051 case OPC_BITREV:
27052 case OPC_REPL_QB:
27053 case OPC_REPLV_QB:
27054 case OPC_REPL_PH:
27055 case OPC_REPLV_PH:
27056 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27057 break;
27058 default:
27059 MIPS_INVAL("MASK ABSQ_S.PH");
27060 generate_exception_end(ctx, EXCP_RI);
27061 break;
27062 }
27063 break;
27064 case OPC_ADDU_QB_DSP:
27065 op2 = MASK_ADDU_QB(ctx->opcode);
27066 switch (op2) {
27067 case OPC_ADDQ_PH:
27068 case OPC_ADDQ_S_PH:
27069 case OPC_ADDQ_S_W:
27070 case OPC_ADDU_QB:
27071 case OPC_ADDU_S_QB:
27072 case OPC_ADDU_PH:
27073 case OPC_ADDU_S_PH:
27074 case OPC_SUBQ_PH:
27075 case OPC_SUBQ_S_PH:
27076 case OPC_SUBQ_S_W:
27077 case OPC_SUBU_QB:
27078 case OPC_SUBU_S_QB:
27079 case OPC_SUBU_PH:
27080 case OPC_SUBU_S_PH:
27081 case OPC_ADDSC:
27082 case OPC_ADDWC:
27083 case OPC_MODSUB:
27084 case OPC_RADDU_W_QB:
27085 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27086 break;
27087 case OPC_MULEU_S_PH_QBL:
27088 case OPC_MULEU_S_PH_QBR:
27089 case OPC_MULQ_RS_PH:
27090 case OPC_MULEQ_S_W_PHL:
27091 case OPC_MULEQ_S_W_PHR:
27092 case OPC_MULQ_S_PH:
27093 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27094 break;
27095 default: /* Invalid */
27096 MIPS_INVAL("MASK ADDU.QB");
27097 generate_exception_end(ctx, EXCP_RI);
27098 break;
27099
27100 }
27101 break;
27102 case OPC_CMPU_EQ_QB_DSP:
27103 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
27104 switch (op2) {
27105 case OPC_PRECR_SRA_PH_W:
27106 case OPC_PRECR_SRA_R_PH_W:
27107 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
27108 break;
27109 case OPC_PRECR_QB_PH:
27110 case OPC_PRECRQ_QB_PH:
27111 case OPC_PRECRQ_PH_W:
27112 case OPC_PRECRQ_RS_PH_W:
27113 case OPC_PRECRQU_S_QB_PH:
27114 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27115 break;
27116 case OPC_CMPU_EQ_QB:
27117 case OPC_CMPU_LT_QB:
27118 case OPC_CMPU_LE_QB:
27119 case OPC_CMP_EQ_PH:
27120 case OPC_CMP_LT_PH:
27121 case OPC_CMP_LE_PH:
27122 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
27123 break;
27124 case OPC_CMPGU_EQ_QB:
27125 case OPC_CMPGU_LT_QB:
27126 case OPC_CMPGU_LE_QB:
27127 case OPC_CMPGDU_EQ_QB:
27128 case OPC_CMPGDU_LT_QB:
27129 case OPC_CMPGDU_LE_QB:
27130 case OPC_PICK_QB:
27131 case OPC_PICK_PH:
27132 case OPC_PACKRL_PH:
27133 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27134 break;
27135 default: /* Invalid */
27136 MIPS_INVAL("MASK CMPU.EQ.QB");
27137 generate_exception_end(ctx, EXCP_RI);
27138 break;
27139 }
27140 break;
27141 case OPC_SHLL_QB_DSP:
27142 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27143 break;
27144 case OPC_DPA_W_PH_DSP:
27145 op2 = MASK_DPA_W_PH(ctx->opcode);
27146 switch (op2) {
27147 case OPC_DPAU_H_QBL:
27148 case OPC_DPAU_H_QBR:
27149 case OPC_DPSU_H_QBL:
27150 case OPC_DPSU_H_QBR:
27151 case OPC_DPA_W_PH:
27152 case OPC_DPAX_W_PH:
27153 case OPC_DPAQ_S_W_PH:
27154 case OPC_DPAQX_S_W_PH:
27155 case OPC_DPAQX_SA_W_PH:
27156 case OPC_DPS_W_PH:
27157 case OPC_DPSX_W_PH:
27158 case OPC_DPSQ_S_W_PH:
27159 case OPC_DPSQX_S_W_PH:
27160 case OPC_DPSQX_SA_W_PH:
27161 case OPC_MULSAQ_S_W_PH:
27162 case OPC_DPAQ_SA_L_W:
27163 case OPC_DPSQ_SA_L_W:
27164 case OPC_MAQ_S_W_PHL:
27165 case OPC_MAQ_S_W_PHR:
27166 case OPC_MAQ_SA_W_PHL:
27167 case OPC_MAQ_SA_W_PHR:
27168 case OPC_MULSA_W_PH:
27169 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27170 break;
27171 default: /* Invalid */
27172 MIPS_INVAL("MASK DPAW.PH");
27173 generate_exception_end(ctx, EXCP_RI);
27174 break;
27175 }
27176 break;
27177 case OPC_INSV_DSP:
27178 op2 = MASK_INSV(ctx->opcode);
27179 switch (op2) {
27180 case OPC_INSV:
27181 check_dsp(ctx);
27182 {
27183 TCGv t0, t1;
27184
27185 if (rt == 0) {
27186 break;
27187 }
27188
27189 t0 = tcg_temp_new();
27190 t1 = tcg_temp_new();
27191
27192 gen_load_gpr(t0, rt);
27193 gen_load_gpr(t1, rs);
27194
27195 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
27196
27197 tcg_temp_free(t0);
27198 tcg_temp_free(t1);
27199 break;
27200 }
27201 default: /* Invalid */
27202 MIPS_INVAL("MASK INSV");
27203 generate_exception_end(ctx, EXCP_RI);
27204 break;
27205 }
27206 break;
27207 case OPC_APPEND_DSP:
27208 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27209 break;
27210 case OPC_EXTR_W_DSP:
27211 op2 = MASK_EXTR_W(ctx->opcode);
27212 switch (op2) {
27213 case OPC_EXTR_W:
27214 case OPC_EXTR_R_W:
27215 case OPC_EXTR_RS_W:
27216 case OPC_EXTR_S_H:
27217 case OPC_EXTRV_S_H:
27218 case OPC_EXTRV_W:
27219 case OPC_EXTRV_R_W:
27220 case OPC_EXTRV_RS_W:
27221 case OPC_EXTP:
27222 case OPC_EXTPV:
27223 case OPC_EXTPDP:
27224 case OPC_EXTPDPV:
27225 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27226 break;
27227 case OPC_RDDSP:
27228 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
27229 break;
27230 case OPC_SHILO:
27231 case OPC_SHILOV:
27232 case OPC_MTHLIP:
27233 case OPC_WRDSP:
27234 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27235 break;
27236 default: /* Invalid */
27237 MIPS_INVAL("MASK EXTR.W");
27238 generate_exception_end(ctx, EXCP_RI);
27239 break;
27240 }
27241 break;
27242 #if defined(TARGET_MIPS64)
27243 case OPC_DDIV_G_2E:
27244 case OPC_DDIVU_G_2E:
27245 case OPC_DMULT_G_2E:
27246 case OPC_DMULTU_G_2E:
27247 case OPC_DMOD_G_2E:
27248 case OPC_DMODU_G_2E:
27249 check_insn(ctx, INSN_LOONGSON2E);
27250 gen_loongson_integer(ctx, op1, rd, rs, rt);
27251 break;
27252 case OPC_ABSQ_S_QH_DSP:
27253 op2 = MASK_ABSQ_S_QH(ctx->opcode);
27254 switch (op2) {
27255 case OPC_PRECEQ_L_PWL:
27256 case OPC_PRECEQ_L_PWR:
27257 case OPC_PRECEQ_PW_QHL:
27258 case OPC_PRECEQ_PW_QHR:
27259 case OPC_PRECEQ_PW_QHLA:
27260 case OPC_PRECEQ_PW_QHRA:
27261 case OPC_PRECEQU_QH_OBL:
27262 case OPC_PRECEQU_QH_OBR:
27263 case OPC_PRECEQU_QH_OBLA:
27264 case OPC_PRECEQU_QH_OBRA:
27265 case OPC_PRECEU_QH_OBL:
27266 case OPC_PRECEU_QH_OBR:
27267 case OPC_PRECEU_QH_OBLA:
27268 case OPC_PRECEU_QH_OBRA:
27269 case OPC_ABSQ_S_OB:
27270 case OPC_ABSQ_S_PW:
27271 case OPC_ABSQ_S_QH:
27272 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27273 break;
27274 case OPC_REPL_OB:
27275 case OPC_REPL_PW:
27276 case OPC_REPL_QH:
27277 case OPC_REPLV_OB:
27278 case OPC_REPLV_PW:
27279 case OPC_REPLV_QH:
27280 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27281 break;
27282 default: /* Invalid */
27283 MIPS_INVAL("MASK ABSQ_S.QH");
27284 generate_exception_end(ctx, EXCP_RI);
27285 break;
27286 }
27287 break;
27288 case OPC_ADDU_OB_DSP:
27289 op2 = MASK_ADDU_OB(ctx->opcode);
27290 switch (op2) {
27291 case OPC_RADDU_L_OB:
27292 case OPC_SUBQ_PW:
27293 case OPC_SUBQ_S_PW:
27294 case OPC_SUBQ_QH:
27295 case OPC_SUBQ_S_QH:
27296 case OPC_SUBU_OB:
27297 case OPC_SUBU_S_OB:
27298 case OPC_SUBU_QH:
27299 case OPC_SUBU_S_QH:
27300 case OPC_SUBUH_OB:
27301 case OPC_SUBUH_R_OB:
27302 case OPC_ADDQ_PW:
27303 case OPC_ADDQ_S_PW:
27304 case OPC_ADDQ_QH:
27305 case OPC_ADDQ_S_QH:
27306 case OPC_ADDU_OB:
27307 case OPC_ADDU_S_OB:
27308 case OPC_ADDU_QH:
27309 case OPC_ADDU_S_QH:
27310 case OPC_ADDUH_OB:
27311 case OPC_ADDUH_R_OB:
27312 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27313 break;
27314 case OPC_MULEQ_S_PW_QHL:
27315 case OPC_MULEQ_S_PW_QHR:
27316 case OPC_MULEU_S_QH_OBL:
27317 case OPC_MULEU_S_QH_OBR:
27318 case OPC_MULQ_RS_QH:
27319 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27320 break;
27321 default: /* Invalid */
27322 MIPS_INVAL("MASK ADDU.OB");
27323 generate_exception_end(ctx, EXCP_RI);
27324 break;
27325 }
27326 break;
27327 case OPC_CMPU_EQ_OB_DSP:
27328 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
27329 switch (op2) {
27330 case OPC_PRECR_SRA_QH_PW:
27331 case OPC_PRECR_SRA_R_QH_PW:
27332 /* Return value is rt. */
27333 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
27334 break;
27335 case OPC_PRECR_OB_QH:
27336 case OPC_PRECRQ_OB_QH:
27337 case OPC_PRECRQ_PW_L:
27338 case OPC_PRECRQ_QH_PW:
27339 case OPC_PRECRQ_RS_QH_PW:
27340 case OPC_PRECRQU_S_OB_QH:
27341 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27342 break;
27343 case OPC_CMPU_EQ_OB:
27344 case OPC_CMPU_LT_OB:
27345 case OPC_CMPU_LE_OB:
27346 case OPC_CMP_EQ_QH:
27347 case OPC_CMP_LT_QH:
27348 case OPC_CMP_LE_QH:
27349 case OPC_CMP_EQ_PW:
27350 case OPC_CMP_LT_PW:
27351 case OPC_CMP_LE_PW:
27352 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
27353 break;
27354 case OPC_CMPGDU_EQ_OB:
27355 case OPC_CMPGDU_LT_OB:
27356 case OPC_CMPGDU_LE_OB:
27357 case OPC_CMPGU_EQ_OB:
27358 case OPC_CMPGU_LT_OB:
27359 case OPC_CMPGU_LE_OB:
27360 case OPC_PACKRL_PW:
27361 case OPC_PICK_OB:
27362 case OPC_PICK_PW:
27363 case OPC_PICK_QH:
27364 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27365 break;
27366 default: /* Invalid */
27367 MIPS_INVAL("MASK CMPU_EQ.OB");
27368 generate_exception_end(ctx, EXCP_RI);
27369 break;
27370 }
27371 break;
27372 case OPC_DAPPEND_DSP:
27373 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27374 break;
27375 case OPC_DEXTR_W_DSP:
27376 op2 = MASK_DEXTR_W(ctx->opcode);
27377 switch (op2) {
27378 case OPC_DEXTP:
27379 case OPC_DEXTPDP:
27380 case OPC_DEXTPDPV:
27381 case OPC_DEXTPV:
27382 case OPC_DEXTR_L:
27383 case OPC_DEXTR_R_L:
27384 case OPC_DEXTR_RS_L:
27385 case OPC_DEXTR_W:
27386 case OPC_DEXTR_R_W:
27387 case OPC_DEXTR_RS_W:
27388 case OPC_DEXTR_S_H:
27389 case OPC_DEXTRV_L:
27390 case OPC_DEXTRV_R_L:
27391 case OPC_DEXTRV_RS_L:
27392 case OPC_DEXTRV_S_H:
27393 case OPC_DEXTRV_W:
27394 case OPC_DEXTRV_R_W:
27395 case OPC_DEXTRV_RS_W:
27396 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27397 break;
27398 case OPC_DMTHLIP:
27399 case OPC_DSHILO:
27400 case OPC_DSHILOV:
27401 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27402 break;
27403 default: /* Invalid */
27404 MIPS_INVAL("MASK EXTR.W");
27405 generate_exception_end(ctx, EXCP_RI);
27406 break;
27407 }
27408 break;
27409 case OPC_DPAQ_W_QH_DSP:
27410 op2 = MASK_DPAQ_W_QH(ctx->opcode);
27411 switch (op2) {
27412 case OPC_DPAU_H_OBL:
27413 case OPC_DPAU_H_OBR:
27414 case OPC_DPSU_H_OBL:
27415 case OPC_DPSU_H_OBR:
27416 case OPC_DPA_W_QH:
27417 case OPC_DPAQ_S_W_QH:
27418 case OPC_DPS_W_QH:
27419 case OPC_DPSQ_S_W_QH:
27420 case OPC_MULSAQ_S_W_QH:
27421 case OPC_DPAQ_SA_L_PW:
27422 case OPC_DPSQ_SA_L_PW:
27423 case OPC_MULSAQ_S_L_PW:
27424 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27425 break;
27426 case OPC_MAQ_S_W_QHLL:
27427 case OPC_MAQ_S_W_QHLR:
27428 case OPC_MAQ_S_W_QHRL:
27429 case OPC_MAQ_S_W_QHRR:
27430 case OPC_MAQ_SA_W_QHLL:
27431 case OPC_MAQ_SA_W_QHLR:
27432 case OPC_MAQ_SA_W_QHRL:
27433 case OPC_MAQ_SA_W_QHRR:
27434 case OPC_MAQ_S_L_PWL:
27435 case OPC_MAQ_S_L_PWR:
27436 case OPC_DMADD:
27437 case OPC_DMADDU:
27438 case OPC_DMSUB:
27439 case OPC_DMSUBU:
27440 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27441 break;
27442 default: /* Invalid */
27443 MIPS_INVAL("MASK DPAQ.W.QH");
27444 generate_exception_end(ctx, EXCP_RI);
27445 break;
27446 }
27447 break;
27448 case OPC_DINSV_DSP:
27449 op2 = MASK_INSV(ctx->opcode);
27450 switch (op2) {
27451 case OPC_DINSV:
27452 {
27453 TCGv t0, t1;
27454
27455 if (rt == 0) {
27456 break;
27457 }
27458 check_dsp(ctx);
27459
27460 t0 = tcg_temp_new();
27461 t1 = tcg_temp_new();
27462
27463 gen_load_gpr(t0, rt);
27464 gen_load_gpr(t1, rs);
27465
27466 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
27467
27468 tcg_temp_free(t0);
27469 tcg_temp_free(t1);
27470 break;
27471 }
27472 default: /* Invalid */
27473 MIPS_INVAL("MASK DINSV");
27474 generate_exception_end(ctx, EXCP_RI);
27475 break;
27476 }
27477 break;
27478 case OPC_SHLL_OB_DSP:
27479 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27480 break;
27481 #endif
27482 default: /* Invalid */
27483 MIPS_INVAL("special3_legacy");
27484 generate_exception_end(ctx, EXCP_RI);
27485 break;
27486 }
27487 }
27488
27489
27490 #if defined(TARGET_MIPS64)
27491
27492 static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx)
27493 {
27494 uint32_t opc = MASK_MMI0(ctx->opcode);
27495
27496 switch (opc) {
27497 case MMI_OPC_0_PADDW: /* TODO: MMI_OPC_0_PADDW */
27498 case MMI_OPC_0_PSUBW: /* TODO: MMI_OPC_0_PSUBW */
27499 case MMI_OPC_0_PCGTW: /* TODO: MMI_OPC_0_PCGTW */
27500 case MMI_OPC_0_PMAXW: /* TODO: MMI_OPC_0_PMAXW */
27501 case MMI_OPC_0_PADDH: /* TODO: MMI_OPC_0_PADDH */
27502 case MMI_OPC_0_PSUBH: /* TODO: MMI_OPC_0_PSUBH */
27503 case MMI_OPC_0_PCGTH: /* TODO: MMI_OPC_0_PCGTH */
27504 case MMI_OPC_0_PMAXH: /* TODO: MMI_OPC_0_PMAXH */
27505 case MMI_OPC_0_PADDB: /* TODO: MMI_OPC_0_PADDB */
27506 case MMI_OPC_0_PSUBB: /* TODO: MMI_OPC_0_PSUBB */
27507 case MMI_OPC_0_PCGTB: /* TODO: MMI_OPC_0_PCGTB */
27508 case MMI_OPC_0_PADDSW: /* TODO: MMI_OPC_0_PADDSW */
27509 case MMI_OPC_0_PSUBSW: /* TODO: MMI_OPC_0_PSUBSW */
27510 case MMI_OPC_0_PEXTLW: /* TODO: MMI_OPC_0_PEXTLW */
27511 case MMI_OPC_0_PPACW: /* TODO: MMI_OPC_0_PPACW */
27512 case MMI_OPC_0_PADDSH: /* TODO: MMI_OPC_0_PADDSH */
27513 case MMI_OPC_0_PSUBSH: /* TODO: MMI_OPC_0_PSUBSH */
27514 case MMI_OPC_0_PEXTLH: /* TODO: MMI_OPC_0_PEXTLH */
27515 case MMI_OPC_0_PPACH: /* TODO: MMI_OPC_0_PPACH */
27516 case MMI_OPC_0_PADDSB: /* TODO: MMI_OPC_0_PADDSB */
27517 case MMI_OPC_0_PSUBSB: /* TODO: MMI_OPC_0_PSUBSB */
27518 case MMI_OPC_0_PEXTLB: /* TODO: MMI_OPC_0_PEXTLB */
27519 case MMI_OPC_0_PPACB: /* TODO: MMI_OPC_0_PPACB */
27520 case MMI_OPC_0_PEXT5: /* TODO: MMI_OPC_0_PEXT5 */
27521 case MMI_OPC_0_PPAC5: /* TODO: MMI_OPC_0_PPAC5 */
27522 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI0 */
27523 break;
27524 default:
27525 MIPS_INVAL("TX79 MMI class MMI0");
27526 generate_exception_end(ctx, EXCP_RI);
27527 break;
27528 }
27529 }
27530
27531 static void decode_mmi1(CPUMIPSState *env, DisasContext *ctx)
27532 {
27533 uint32_t opc = MASK_MMI1(ctx->opcode);
27534
27535 switch (opc) {
27536 case MMI_OPC_1_PABSW: /* TODO: MMI_OPC_1_PABSW */
27537 case MMI_OPC_1_PCEQW: /* TODO: MMI_OPC_1_PCEQW */
27538 case MMI_OPC_1_PMINW: /* TODO: MMI_OPC_1_PMINW */
27539 case MMI_OPC_1_PADSBH: /* TODO: MMI_OPC_1_PADSBH */
27540 case MMI_OPC_1_PABSH: /* TODO: MMI_OPC_1_PABSH */
27541 case MMI_OPC_1_PCEQH: /* TODO: MMI_OPC_1_PCEQH */
27542 case MMI_OPC_1_PMINH: /* TODO: MMI_OPC_1_PMINH */
27543 case MMI_OPC_1_PCEQB: /* TODO: MMI_OPC_1_PCEQB */
27544 case MMI_OPC_1_PADDUW: /* TODO: MMI_OPC_1_PADDUW */
27545 case MMI_OPC_1_PSUBUW: /* TODO: MMI_OPC_1_PSUBUW */
27546 case MMI_OPC_1_PEXTUW: /* TODO: MMI_OPC_1_PEXTUW */
27547 case MMI_OPC_1_PADDUH: /* TODO: MMI_OPC_1_PADDUH */
27548 case MMI_OPC_1_PSUBUH: /* TODO: MMI_OPC_1_PSUBUH */
27549 case MMI_OPC_1_PEXTUH: /* TODO: MMI_OPC_1_PEXTUH */
27550 case MMI_OPC_1_PADDUB: /* TODO: MMI_OPC_1_PADDUB */
27551 case MMI_OPC_1_PSUBUB: /* TODO: MMI_OPC_1_PSUBUB */
27552 case MMI_OPC_1_PEXTUB: /* TODO: MMI_OPC_1_PEXTUB */
27553 case MMI_OPC_1_QFSRV: /* TODO: MMI_OPC_1_QFSRV */
27554 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI1 */
27555 break;
27556 default:
27557 MIPS_INVAL("TX79 MMI class MMI1");
27558 generate_exception_end(ctx, EXCP_RI);
27559 break;
27560 }
27561 }
27562
27563 static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx)
27564 {
27565 uint32_t opc = MASK_MMI2(ctx->opcode);
27566
27567 switch (opc) {
27568 case MMI_OPC_2_PMADDW: /* TODO: MMI_OPC_2_PMADDW */
27569 case MMI_OPC_2_PSLLVW: /* TODO: MMI_OPC_2_PSLLVW */
27570 case MMI_OPC_2_PSRLVW: /* TODO: MMI_OPC_2_PSRLVW */
27571 case MMI_OPC_2_PMSUBW: /* TODO: MMI_OPC_2_PMSUBW */
27572 case MMI_OPC_2_PMFHI: /* TODO: MMI_OPC_2_PMFHI */
27573 case MMI_OPC_2_PMFLO: /* TODO: MMI_OPC_2_PMFLO */
27574 case MMI_OPC_2_PINTH: /* TODO: MMI_OPC_2_PINTH */
27575 case MMI_OPC_2_PMULTW: /* TODO: MMI_OPC_2_PMULTW */
27576 case MMI_OPC_2_PDIVW: /* TODO: MMI_OPC_2_PDIVW */
27577 case MMI_OPC_2_PMADDH: /* TODO: MMI_OPC_2_PMADDH */
27578 case MMI_OPC_2_PHMADH: /* TODO: MMI_OPC_2_PHMADH */
27579 case MMI_OPC_2_PAND: /* TODO: MMI_OPC_2_PAND */
27580 case MMI_OPC_2_PXOR: /* TODO: MMI_OPC_2_PXOR */
27581 case MMI_OPC_2_PMSUBH: /* TODO: MMI_OPC_2_PMSUBH */
27582 case MMI_OPC_2_PHMSBH: /* TODO: MMI_OPC_2_PHMSBH */
27583 case MMI_OPC_2_PEXEH: /* TODO: MMI_OPC_2_PEXEH */
27584 case MMI_OPC_2_PREVH: /* TODO: MMI_OPC_2_PREVH */
27585 case MMI_OPC_2_PMULTH: /* TODO: MMI_OPC_2_PMULTH */
27586 case MMI_OPC_2_PDIVBW: /* TODO: MMI_OPC_2_PDIVBW */
27587 case MMI_OPC_2_PEXEW: /* TODO: MMI_OPC_2_PEXEW */
27588 case MMI_OPC_2_PROT3W: /* TODO: MMI_OPC_2_PROT3W */
27589 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI2 */
27590 break;
27591 case MMI_OPC_2_PCPYLD:
27592 gen_mmi_pcpyld(ctx);
27593 break;
27594 default:
27595 MIPS_INVAL("TX79 MMI class MMI2");
27596 generate_exception_end(ctx, EXCP_RI);
27597 break;
27598 }
27599 }
27600
27601 static void decode_mmi3(CPUMIPSState *env, DisasContext *ctx)
27602 {
27603 uint32_t opc = MASK_MMI3(ctx->opcode);
27604
27605 switch (opc) {
27606 case MMI_OPC_3_PMADDUW: /* TODO: MMI_OPC_3_PMADDUW */
27607 case MMI_OPC_3_PSRAVW: /* TODO: MMI_OPC_3_PSRAVW */
27608 case MMI_OPC_3_PMTHI: /* TODO: MMI_OPC_3_PMTHI */
27609 case MMI_OPC_3_PMTLO: /* TODO: MMI_OPC_3_PMTLO */
27610 case MMI_OPC_3_PINTEH: /* TODO: MMI_OPC_3_PINTEH */
27611 case MMI_OPC_3_PMULTUW: /* TODO: MMI_OPC_3_PMULTUW */
27612 case MMI_OPC_3_PDIVUW: /* TODO: MMI_OPC_3_PDIVUW */
27613 case MMI_OPC_3_POR: /* TODO: MMI_OPC_3_POR */
27614 case MMI_OPC_3_PNOR: /* TODO: MMI_OPC_3_PNOR */
27615 case MMI_OPC_3_PEXCH: /* TODO: MMI_OPC_3_PEXCH */
27616 case MMI_OPC_3_PEXCW: /* TODO: MMI_OPC_3_PEXCW */
27617 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI3 */
27618 break;
27619 case MMI_OPC_3_PCPYH:
27620 gen_mmi_pcpyh(ctx);
27621 break;
27622 case MMI_OPC_3_PCPYUD:
27623 gen_mmi_pcpyud(ctx);
27624 break;
27625 default:
27626 MIPS_INVAL("TX79 MMI class MMI3");
27627 generate_exception_end(ctx, EXCP_RI);
27628 break;
27629 }
27630 }
27631
27632 static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
27633 {
27634 uint32_t opc = MASK_MMI(ctx->opcode);
27635 int rs = extract32(ctx->opcode, 21, 5);
27636 int rt = extract32(ctx->opcode, 16, 5);
27637 int rd = extract32(ctx->opcode, 11, 5);
27638
27639 switch (opc) {
27640 case MMI_OPC_CLASS_MMI0:
27641 decode_mmi0(env, ctx);
27642 break;
27643 case MMI_OPC_CLASS_MMI1:
27644 decode_mmi1(env, ctx);
27645 break;
27646 case MMI_OPC_CLASS_MMI2:
27647 decode_mmi2(env, ctx);
27648 break;
27649 case MMI_OPC_CLASS_MMI3:
27650 decode_mmi3(env, ctx);
27651 break;
27652 case MMI_OPC_MULT1:
27653 case MMI_OPC_MULTU1:
27654 case MMI_OPC_MADD:
27655 case MMI_OPC_MADDU:
27656 case MMI_OPC_MADD1:
27657 case MMI_OPC_MADDU1:
27658 gen_mul_txx9(ctx, opc, rd, rs, rt);
27659 break;
27660 case MMI_OPC_DIV1:
27661 case MMI_OPC_DIVU1:
27662 gen_div1_tx79(ctx, opc, rs, rt);
27663 break;
27664 case MMI_OPC_MTLO1:
27665 case MMI_OPC_MTHI1:
27666 gen_HILO1_tx79(ctx, opc, rs);
27667 break;
27668 case MMI_OPC_MFLO1:
27669 case MMI_OPC_MFHI1:
27670 gen_HILO1_tx79(ctx, opc, rd);
27671 break;
27672 case MMI_OPC_PLZCW: /* TODO: MMI_OPC_PLZCW */
27673 case MMI_OPC_PMFHL: /* TODO: MMI_OPC_PMFHL */
27674 case MMI_OPC_PMTHL: /* TODO: MMI_OPC_PMTHL */
27675 case MMI_OPC_PSLLH: /* TODO: MMI_OPC_PSLLH */
27676 case MMI_OPC_PSRLH: /* TODO: MMI_OPC_PSRLH */
27677 case MMI_OPC_PSRAH: /* TODO: MMI_OPC_PSRAH */
27678 case MMI_OPC_PSLLW: /* TODO: MMI_OPC_PSLLW */
27679 case MMI_OPC_PSRLW: /* TODO: MMI_OPC_PSRLW */
27680 case MMI_OPC_PSRAW: /* TODO: MMI_OPC_PSRAW */
27681 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI */
27682 break;
27683 default:
27684 MIPS_INVAL("TX79 MMI class");
27685 generate_exception_end(ctx, EXCP_RI);
27686 break;
27687 }
27688 }
27689
27690 static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
27691 {
27692 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_LQ */
27693 }
27694
27695 static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
27696 {
27697 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_SQ */
27698 }
27699
27700 /*
27701 * The TX79-specific instruction Store Quadword
27702 *
27703 * +--------+-------+-------+------------------------+
27704 * | 011111 | base | rt | offset | SQ
27705 * +--------+-------+-------+------------------------+
27706 * 6 5 5 16
27707 *
27708 * has the same opcode as the Read Hardware Register instruction
27709 *
27710 * +--------+-------+-------+-------+-------+--------+
27711 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
27712 * +--------+-------+-------+-------+-------+--------+
27713 * 6 5 5 5 5 6
27714 *
27715 * that is required, trapped and emulated by the Linux kernel. However, all
27716 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
27717 * offset is odd. Therefore all valid SQ instructions can execute normally.
27718 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
27719 * between SQ and RDHWR, as the Linux kernel does.
27720 */
27721 static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
27722 {
27723 int base = extract32(ctx->opcode, 21, 5);
27724 int rt = extract32(ctx->opcode, 16, 5);
27725 int offset = extract32(ctx->opcode, 0, 16);
27726
27727 #ifdef CONFIG_USER_ONLY
27728 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
27729 uint32_t op2 = extract32(ctx->opcode, 6, 5);
27730
27731 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
27732 int rd = extract32(ctx->opcode, 11, 5);
27733
27734 gen_rdhwr(ctx, rt, rd, 0);
27735 return;
27736 }
27737 #endif
27738
27739 gen_mmi_sq(ctx, base, rt, offset);
27740 }
27741
27742 #endif
27743
27744 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
27745 {
27746 int rs, rt, rd, sa;
27747 uint32_t op1, op2;
27748 int16_t imm;
27749
27750 rs = (ctx->opcode >> 21) & 0x1f;
27751 rt = (ctx->opcode >> 16) & 0x1f;
27752 rd = (ctx->opcode >> 11) & 0x1f;
27753 sa = (ctx->opcode >> 6) & 0x1f;
27754 imm = sextract32(ctx->opcode, 7, 9);
27755
27756 op1 = MASK_SPECIAL3(ctx->opcode);
27757
27758 /*
27759 * EVA loads and stores overlap Loongson 2E instructions decoded by
27760 * decode_opc_special3_legacy(), so be careful to allow their decoding when
27761 * EVA is absent.
27762 */
27763 if (ctx->eva) {
27764 switch (op1) {
27765 case OPC_LWLE:
27766 case OPC_LWRE:
27767 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27768 /* fall through */
27769 case OPC_LBUE:
27770 case OPC_LHUE:
27771 case OPC_LBE:
27772 case OPC_LHE:
27773 case OPC_LLE:
27774 case OPC_LWE:
27775 check_cp0_enabled(ctx);
27776 gen_ld(ctx, op1, rt, rs, imm);
27777 return;
27778 case OPC_SWLE:
27779 case OPC_SWRE:
27780 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27781 /* fall through */
27782 case OPC_SBE:
27783 case OPC_SHE:
27784 case OPC_SWE:
27785 check_cp0_enabled(ctx);
27786 gen_st(ctx, op1, rt, rs, imm);
27787 return;
27788 case OPC_SCE:
27789 check_cp0_enabled(ctx);
27790 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
27791 return;
27792 case OPC_CACHEE:
27793 check_cp0_enabled(ctx);
27794 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
27795 gen_cache_operation(ctx, rt, rs, imm);
27796 }
27797 /* Treat as NOP. */
27798 return;
27799 case OPC_PREFE:
27800 check_cp0_enabled(ctx);
27801 /* Treat as NOP. */
27802 return;
27803 }
27804 }
27805
27806 switch (op1) {
27807 case OPC_EXT:
27808 case OPC_INS:
27809 check_insn(ctx, ISA_MIPS32R2);
27810 gen_bitops(ctx, op1, rt, rs, sa, rd);
27811 break;
27812 case OPC_BSHFL:
27813 op2 = MASK_BSHFL(ctx->opcode);
27814 switch (op2) {
27815 case OPC_ALIGN:
27816 case OPC_ALIGN_1:
27817 case OPC_ALIGN_2:
27818 case OPC_ALIGN_3:
27819 case OPC_BITSWAP:
27820 check_insn(ctx, ISA_MIPS32R6);
27821 decode_opc_special3_r6(env, ctx);
27822 break;
27823 default:
27824 check_insn(ctx, ISA_MIPS32R2);
27825 gen_bshfl(ctx, op2, rt, rd);
27826 break;
27827 }
27828 break;
27829 #if defined(TARGET_MIPS64)
27830 case OPC_DEXTM:
27831 case OPC_DEXTU:
27832 case OPC_DEXT:
27833 case OPC_DINSM:
27834 case OPC_DINSU:
27835 case OPC_DINS:
27836 check_insn(ctx, ISA_MIPS64R2);
27837 check_mips_64(ctx);
27838 gen_bitops(ctx, op1, rt, rs, sa, rd);
27839 break;
27840 case OPC_DBSHFL:
27841 op2 = MASK_DBSHFL(ctx->opcode);
27842 switch (op2) {
27843 case OPC_DALIGN:
27844 case OPC_DALIGN_1:
27845 case OPC_DALIGN_2:
27846 case OPC_DALIGN_3:
27847 case OPC_DALIGN_4:
27848 case OPC_DALIGN_5:
27849 case OPC_DALIGN_6:
27850 case OPC_DALIGN_7:
27851 case OPC_DBITSWAP:
27852 check_insn(ctx, ISA_MIPS32R6);
27853 decode_opc_special3_r6(env, ctx);
27854 break;
27855 default:
27856 check_insn(ctx, ISA_MIPS64R2);
27857 check_mips_64(ctx);
27858 op2 = MASK_DBSHFL(ctx->opcode);
27859 gen_bshfl(ctx, op2, rt, rd);
27860 break;
27861 }
27862 break;
27863 #endif
27864 case OPC_RDHWR:
27865 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
27866 break;
27867 case OPC_FORK:
27868 check_mt(ctx);
27869 {
27870 TCGv t0 = tcg_temp_new();
27871 TCGv t1 = tcg_temp_new();
27872
27873 gen_load_gpr(t0, rt);
27874 gen_load_gpr(t1, rs);
27875 gen_helper_fork(t0, t1);
27876 tcg_temp_free(t0);
27877 tcg_temp_free(t1);
27878 }
27879 break;
27880 case OPC_YIELD:
27881 check_mt(ctx);
27882 {
27883 TCGv t0 = tcg_temp_new();
27884
27885 gen_load_gpr(t0, rs);
27886 gen_helper_yield(t0, cpu_env, t0);
27887 gen_store_gpr(t0, rd);
27888 tcg_temp_free(t0);
27889 }
27890 break;
27891 default:
27892 if (ctx->insn_flags & ISA_MIPS32R6) {
27893 decode_opc_special3_r6(env, ctx);
27894 } else {
27895 decode_opc_special3_legacy(env, ctx);
27896 }
27897 }
27898 }
27899
27900 /* MIPS SIMD Architecture (MSA) */
27901 static inline int check_msa_access(DisasContext *ctx)
27902 {
27903 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
27904 !(ctx->hflags & MIPS_HFLAG_F64))) {
27905 generate_exception_end(ctx, EXCP_RI);
27906 return 0;
27907 }
27908
27909 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
27910 if (ctx->insn_flags & ASE_MSA) {
27911 generate_exception_end(ctx, EXCP_MSADIS);
27912 return 0;
27913 } else {
27914 generate_exception_end(ctx, EXCP_RI);
27915 return 0;
27916 }
27917 }
27918 return 1;
27919 }
27920
27921 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
27922 {
27923 /* generates tcg ops to check if any element is 0 */
27924 /* Note this function only works with MSA_WRLEN = 128 */
27925 uint64_t eval_zero_or_big = 0;
27926 uint64_t eval_big = 0;
27927 TCGv_i64 t0 = tcg_temp_new_i64();
27928 TCGv_i64 t1 = tcg_temp_new_i64();
27929 switch (df) {
27930 case DF_BYTE:
27931 eval_zero_or_big = 0x0101010101010101ULL;
27932 eval_big = 0x8080808080808080ULL;
27933 break;
27934 case DF_HALF:
27935 eval_zero_or_big = 0x0001000100010001ULL;
27936 eval_big = 0x8000800080008000ULL;
27937 break;
27938 case DF_WORD:
27939 eval_zero_or_big = 0x0000000100000001ULL;
27940 eval_big = 0x8000000080000000ULL;
27941 break;
27942 case DF_DOUBLE:
27943 eval_zero_or_big = 0x0000000000000001ULL;
27944 eval_big = 0x8000000000000000ULL;
27945 break;
27946 }
27947 tcg_gen_subi_i64(t0, msa_wr_d[wt << 1], eval_zero_or_big);
27948 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt << 1]);
27949 tcg_gen_andi_i64(t0, t0, eval_big);
27950 tcg_gen_subi_i64(t1, msa_wr_d[(wt << 1) + 1], eval_zero_or_big);
27951 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt << 1) + 1]);
27952 tcg_gen_andi_i64(t1, t1, eval_big);
27953 tcg_gen_or_i64(t0, t0, t1);
27954 /* if all bits are zero then all elements are not zero */
27955 /* if some bit is non-zero then some element is zero */
27956 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
27957 tcg_gen_trunc_i64_tl(tresult, t0);
27958 tcg_temp_free_i64(t0);
27959 tcg_temp_free_i64(t1);
27960 }
27961
27962 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
27963 {
27964 uint8_t df = (ctx->opcode >> 21) & 0x3;
27965 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
27966 int64_t s16 = (int16_t)ctx->opcode;
27967
27968 check_msa_access(ctx);
27969
27970 if (ctx->hflags & MIPS_HFLAG_BMASK) {
27971 generate_exception_end(ctx, EXCP_RI);
27972 return;
27973 }
27974 switch (op1) {
27975 case OPC_BZ_V:
27976 case OPC_BNZ_V:
27977 {
27978 TCGv_i64 t0 = tcg_temp_new_i64();
27979 tcg_gen_or_i64(t0, msa_wr_d[wt << 1], msa_wr_d[(wt << 1) + 1]);
27980 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
27981 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
27982 tcg_gen_trunc_i64_tl(bcond, t0);
27983 tcg_temp_free_i64(t0);
27984 }
27985 break;
27986 case OPC_BZ_B:
27987 case OPC_BZ_H:
27988 case OPC_BZ_W:
27989 case OPC_BZ_D:
27990 gen_check_zero_element(bcond, df, wt);
27991 break;
27992 case OPC_BNZ_B:
27993 case OPC_BNZ_H:
27994 case OPC_BNZ_W:
27995 case OPC_BNZ_D:
27996 gen_check_zero_element(bcond, df, wt);
27997 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
27998 break;
27999 }
28000
28001 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
28002
28003 ctx->hflags |= MIPS_HFLAG_BC;
28004 ctx->hflags |= MIPS_HFLAG_BDS32;
28005 }
28006
28007 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
28008 {
28009 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
28010 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
28011 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28012 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28013
28014 TCGv_i32 twd = tcg_const_i32(wd);
28015 TCGv_i32 tws = tcg_const_i32(ws);
28016 TCGv_i32 ti8 = tcg_const_i32(i8);
28017
28018 switch (MASK_MSA_I8(ctx->opcode)) {
28019 case OPC_ANDI_B:
28020 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
28021 break;
28022 case OPC_ORI_B:
28023 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
28024 break;
28025 case OPC_NORI_B:
28026 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
28027 break;
28028 case OPC_XORI_B:
28029 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
28030 break;
28031 case OPC_BMNZI_B:
28032 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
28033 break;
28034 case OPC_BMZI_B:
28035 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
28036 break;
28037 case OPC_BSELI_B:
28038 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
28039 break;
28040 case OPC_SHF_B:
28041 case OPC_SHF_H:
28042 case OPC_SHF_W:
28043 {
28044 uint8_t df = (ctx->opcode >> 24) & 0x3;
28045 if (df == DF_DOUBLE) {
28046 generate_exception_end(ctx, EXCP_RI);
28047 } else {
28048 TCGv_i32 tdf = tcg_const_i32(df);
28049 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
28050 tcg_temp_free_i32(tdf);
28051 }
28052 }
28053 break;
28054 default:
28055 MIPS_INVAL("MSA instruction");
28056 generate_exception_end(ctx, EXCP_RI);
28057 break;
28058 }
28059
28060 tcg_temp_free_i32(twd);
28061 tcg_temp_free_i32(tws);
28062 tcg_temp_free_i32(ti8);
28063 }
28064
28065 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
28066 {
28067 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28068 uint8_t df = (ctx->opcode >> 21) & 0x3;
28069 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
28070 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
28071 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28072 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28073
28074 TCGv_i32 tdf = tcg_const_i32(df);
28075 TCGv_i32 twd = tcg_const_i32(wd);
28076 TCGv_i32 tws = tcg_const_i32(ws);
28077 TCGv_i32 timm = tcg_temp_new_i32();
28078 tcg_gen_movi_i32(timm, u5);
28079
28080 switch (MASK_MSA_I5(ctx->opcode)) {
28081 case OPC_ADDVI_df:
28082 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
28083 break;
28084 case OPC_SUBVI_df:
28085 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
28086 break;
28087 case OPC_MAXI_S_df:
28088 tcg_gen_movi_i32(timm, s5);
28089 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
28090 break;
28091 case OPC_MAXI_U_df:
28092 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
28093 break;
28094 case OPC_MINI_S_df:
28095 tcg_gen_movi_i32(timm, s5);
28096 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
28097 break;
28098 case OPC_MINI_U_df:
28099 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
28100 break;
28101 case OPC_CEQI_df:
28102 tcg_gen_movi_i32(timm, s5);
28103 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
28104 break;
28105 case OPC_CLTI_S_df:
28106 tcg_gen_movi_i32(timm, s5);
28107 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
28108 break;
28109 case OPC_CLTI_U_df:
28110 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
28111 break;
28112 case OPC_CLEI_S_df:
28113 tcg_gen_movi_i32(timm, s5);
28114 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
28115 break;
28116 case OPC_CLEI_U_df:
28117 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
28118 break;
28119 case OPC_LDI_df:
28120 {
28121 int32_t s10 = sextract32(ctx->opcode, 11, 10);
28122 tcg_gen_movi_i32(timm, s10);
28123 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
28124 }
28125 break;
28126 default:
28127 MIPS_INVAL("MSA instruction");
28128 generate_exception_end(ctx, EXCP_RI);
28129 break;
28130 }
28131
28132 tcg_temp_free_i32(tdf);
28133 tcg_temp_free_i32(twd);
28134 tcg_temp_free_i32(tws);
28135 tcg_temp_free_i32(timm);
28136 }
28137
28138 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
28139 {
28140 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28141 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
28142 uint32_t df = 0, m = 0;
28143 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28144 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28145
28146 TCGv_i32 tdf;
28147 TCGv_i32 tm;
28148 TCGv_i32 twd;
28149 TCGv_i32 tws;
28150
28151 if ((dfm & 0x40) == 0x00) {
28152 m = dfm & 0x3f;
28153 df = DF_DOUBLE;
28154 } else if ((dfm & 0x60) == 0x40) {
28155 m = dfm & 0x1f;
28156 df = DF_WORD;
28157 } else if ((dfm & 0x70) == 0x60) {
28158 m = dfm & 0x0f;
28159 df = DF_HALF;
28160 } else if ((dfm & 0x78) == 0x70) {
28161 m = dfm & 0x7;
28162 df = DF_BYTE;
28163 } else {
28164 generate_exception_end(ctx, EXCP_RI);
28165 return;
28166 }
28167
28168 tdf = tcg_const_i32(df);
28169 tm = tcg_const_i32(m);
28170 twd = tcg_const_i32(wd);
28171 tws = tcg_const_i32(ws);
28172
28173 switch (MASK_MSA_BIT(ctx->opcode)) {
28174 case OPC_SLLI_df:
28175 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
28176 break;
28177 case OPC_SRAI_df:
28178 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
28179 break;
28180 case OPC_SRLI_df:
28181 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
28182 break;
28183 case OPC_BCLRI_df:
28184 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
28185 break;
28186 case OPC_BSETI_df:
28187 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
28188 break;
28189 case OPC_BNEGI_df:
28190 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
28191 break;
28192 case OPC_BINSLI_df:
28193 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
28194 break;
28195 case OPC_BINSRI_df:
28196 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
28197 break;
28198 case OPC_SAT_S_df:
28199 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
28200 break;
28201 case OPC_SAT_U_df:
28202 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
28203 break;
28204 case OPC_SRARI_df:
28205 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
28206 break;
28207 case OPC_SRLRI_df:
28208 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
28209 break;
28210 default:
28211 MIPS_INVAL("MSA instruction");
28212 generate_exception_end(ctx, EXCP_RI);
28213 break;
28214 }
28215
28216 tcg_temp_free_i32(tdf);
28217 tcg_temp_free_i32(tm);
28218 tcg_temp_free_i32(twd);
28219 tcg_temp_free_i32(tws);
28220 }
28221
28222 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
28223 {
28224 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28225 uint8_t df = (ctx->opcode >> 21) & 0x3;
28226 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28227 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28228 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28229
28230 TCGv_i32 tdf = tcg_const_i32(df);
28231 TCGv_i32 twd = tcg_const_i32(wd);
28232 TCGv_i32 tws = tcg_const_i32(ws);
28233 TCGv_i32 twt = tcg_const_i32(wt);
28234
28235 switch (MASK_MSA_3R(ctx->opcode)) {
28236 case OPC_SLL_df:
28237 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
28238 break;
28239 case OPC_ADDV_df:
28240 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
28241 break;
28242 case OPC_CEQ_df:
28243 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
28244 break;
28245 case OPC_ADD_A_df:
28246 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
28247 break;
28248 case OPC_SUBS_S_df:
28249 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
28250 break;
28251 case OPC_MULV_df:
28252 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
28253 break;
28254 case OPC_SLD_df:
28255 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
28256 break;
28257 case OPC_VSHF_df:
28258 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
28259 break;
28260 case OPC_SRA_df:
28261 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
28262 break;
28263 case OPC_SUBV_df:
28264 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
28265 break;
28266 case OPC_ADDS_A_df:
28267 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
28268 break;
28269 case OPC_SUBS_U_df:
28270 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
28271 break;
28272 case OPC_MADDV_df:
28273 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
28274 break;
28275 case OPC_SPLAT_df:
28276 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
28277 break;
28278 case OPC_SRAR_df:
28279 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
28280 break;
28281 case OPC_SRL_df:
28282 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
28283 break;
28284 case OPC_MAX_S_df:
28285 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
28286 break;
28287 case OPC_CLT_S_df:
28288 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
28289 break;
28290 case OPC_ADDS_S_df:
28291 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
28292 break;
28293 case OPC_SUBSUS_U_df:
28294 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
28295 break;
28296 case OPC_MSUBV_df:
28297 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
28298 break;
28299 case OPC_PCKEV_df:
28300 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
28301 break;
28302 case OPC_SRLR_df:
28303 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
28304 break;
28305 case OPC_BCLR_df:
28306 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
28307 break;
28308 case OPC_MAX_U_df:
28309 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
28310 break;
28311 case OPC_CLT_U_df:
28312 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
28313 break;
28314 case OPC_ADDS_U_df:
28315 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
28316 break;
28317 case OPC_SUBSUU_S_df:
28318 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
28319 break;
28320 case OPC_PCKOD_df:
28321 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
28322 break;
28323 case OPC_BSET_df:
28324 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
28325 break;
28326 case OPC_MIN_S_df:
28327 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
28328 break;
28329 case OPC_CLE_S_df:
28330 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
28331 break;
28332 case OPC_AVE_S_df:
28333 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
28334 break;
28335 case OPC_ASUB_S_df:
28336 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
28337 break;
28338 case OPC_DIV_S_df:
28339 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
28340 break;
28341 case OPC_ILVL_df:
28342 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
28343 break;
28344 case OPC_BNEG_df:
28345 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
28346 break;
28347 case OPC_MIN_U_df:
28348 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
28349 break;
28350 case OPC_CLE_U_df:
28351 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
28352 break;
28353 case OPC_AVE_U_df:
28354 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
28355 break;
28356 case OPC_ASUB_U_df:
28357 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
28358 break;
28359 case OPC_DIV_U_df:
28360 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
28361 break;
28362 case OPC_ILVR_df:
28363 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
28364 break;
28365 case OPC_BINSL_df:
28366 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
28367 break;
28368 case OPC_MAX_A_df:
28369 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
28370 break;
28371 case OPC_AVER_S_df:
28372 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
28373 break;
28374 case OPC_MOD_S_df:
28375 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
28376 break;
28377 case OPC_ILVEV_df:
28378 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
28379 break;
28380 case OPC_BINSR_df:
28381 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
28382 break;
28383 case OPC_MIN_A_df:
28384 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
28385 break;
28386 case OPC_AVER_U_df:
28387 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
28388 break;
28389 case OPC_MOD_U_df:
28390 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
28391 break;
28392 case OPC_ILVOD_df:
28393 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
28394 break;
28395
28396 case OPC_DOTP_S_df:
28397 case OPC_DOTP_U_df:
28398 case OPC_DPADD_S_df:
28399 case OPC_DPADD_U_df:
28400 case OPC_DPSUB_S_df:
28401 case OPC_HADD_S_df:
28402 case OPC_DPSUB_U_df:
28403 case OPC_HADD_U_df:
28404 case OPC_HSUB_S_df:
28405 case OPC_HSUB_U_df:
28406 if (df == DF_BYTE) {
28407 generate_exception_end(ctx, EXCP_RI);
28408 break;
28409 }
28410 switch (MASK_MSA_3R(ctx->opcode)) {
28411 case OPC_DOTP_S_df:
28412 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
28413 break;
28414 case OPC_DOTP_U_df:
28415 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
28416 break;
28417 case OPC_DPADD_S_df:
28418 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
28419 break;
28420 case OPC_DPADD_U_df:
28421 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
28422 break;
28423 case OPC_DPSUB_S_df:
28424 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
28425 break;
28426 case OPC_HADD_S_df:
28427 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
28428 break;
28429 case OPC_DPSUB_U_df:
28430 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
28431 break;
28432 case OPC_HADD_U_df:
28433 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
28434 break;
28435 case OPC_HSUB_S_df:
28436 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
28437 break;
28438 case OPC_HSUB_U_df:
28439 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
28440 break;
28441 }
28442 break;
28443 default:
28444 MIPS_INVAL("MSA instruction");
28445 generate_exception_end(ctx, EXCP_RI);
28446 break;
28447 }
28448 tcg_temp_free_i32(twd);
28449 tcg_temp_free_i32(tws);
28450 tcg_temp_free_i32(twt);
28451 tcg_temp_free_i32(tdf);
28452 }
28453
28454 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
28455 {
28456 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
28457 uint8_t source = (ctx->opcode >> 11) & 0x1f;
28458 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
28459 TCGv telm = tcg_temp_new();
28460 TCGv_i32 tsr = tcg_const_i32(source);
28461 TCGv_i32 tdt = tcg_const_i32(dest);
28462
28463 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
28464 case OPC_CTCMSA:
28465 gen_load_gpr(telm, source);
28466 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
28467 break;
28468 case OPC_CFCMSA:
28469 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
28470 gen_store_gpr(telm, dest);
28471 break;
28472 case OPC_MOVE_V:
28473 gen_helper_msa_move_v(cpu_env, tdt, tsr);
28474 break;
28475 default:
28476 MIPS_INVAL("MSA instruction");
28477 generate_exception_end(ctx, EXCP_RI);
28478 break;
28479 }
28480
28481 tcg_temp_free(telm);
28482 tcg_temp_free_i32(tdt);
28483 tcg_temp_free_i32(tsr);
28484 }
28485
28486 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
28487 uint32_t n)
28488 {
28489 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
28490 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28491 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28492
28493 TCGv_i32 tws = tcg_const_i32(ws);
28494 TCGv_i32 twd = tcg_const_i32(wd);
28495 TCGv_i32 tn = tcg_const_i32(n);
28496 TCGv_i32 tdf = tcg_const_i32(df);
28497
28498 switch (MASK_MSA_ELM(ctx->opcode)) {
28499 case OPC_SLDI_df:
28500 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
28501 break;
28502 case OPC_SPLATI_df:
28503 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
28504 break;
28505 case OPC_INSVE_df:
28506 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
28507 break;
28508 case OPC_COPY_S_df:
28509 case OPC_COPY_U_df:
28510 case OPC_INSERT_df:
28511 #if !defined(TARGET_MIPS64)
28512 /* Double format valid only for MIPS64 */
28513 if (df == DF_DOUBLE) {
28514 generate_exception_end(ctx, EXCP_RI);
28515 break;
28516 }
28517 if ((MASK_MSA_ELM(ctx->opcode) == OPC_COPY_U_df) &&
28518 (df == DF_WORD)) {
28519 generate_exception_end(ctx, EXCP_RI);
28520 break;
28521 }
28522 #endif
28523 switch (MASK_MSA_ELM(ctx->opcode)) {
28524 case OPC_COPY_S_df:
28525 if (likely(wd != 0)) {
28526 switch (df) {
28527 case DF_BYTE:
28528 gen_helper_msa_copy_s_b(cpu_env, twd, tws, tn);
28529 break;
28530 case DF_HALF:
28531 gen_helper_msa_copy_s_h(cpu_env, twd, tws, tn);
28532 break;
28533 case DF_WORD:
28534 gen_helper_msa_copy_s_w(cpu_env, twd, tws, tn);
28535 break;
28536 #if defined(TARGET_MIPS64)
28537 case DF_DOUBLE:
28538 gen_helper_msa_copy_s_d(cpu_env, twd, tws, tn);
28539 break;
28540 #endif
28541 default:
28542 assert(0);
28543 }
28544 }
28545 break;
28546 case OPC_COPY_U_df:
28547 if (likely(wd != 0)) {
28548 switch (df) {
28549 case DF_BYTE:
28550 gen_helper_msa_copy_u_b(cpu_env, twd, tws, tn);
28551 break;
28552 case DF_HALF:
28553 gen_helper_msa_copy_u_h(cpu_env, twd, tws, tn);
28554 break;
28555 #if defined(TARGET_MIPS64)
28556 case DF_WORD:
28557 gen_helper_msa_copy_u_w(cpu_env, twd, tws, tn);
28558 break;
28559 #endif
28560 default:
28561 assert(0);
28562 }
28563 }
28564 break;
28565 case OPC_INSERT_df:
28566 switch (df) {
28567 case DF_BYTE:
28568 gen_helper_msa_insert_b(cpu_env, twd, tws, tn);
28569 break;
28570 case DF_HALF:
28571 gen_helper_msa_insert_h(cpu_env, twd, tws, tn);
28572 break;
28573 case DF_WORD:
28574 gen_helper_msa_insert_w(cpu_env, twd, tws, tn);
28575 break;
28576 #if defined(TARGET_MIPS64)
28577 case DF_DOUBLE:
28578 gen_helper_msa_insert_d(cpu_env, twd, tws, tn);
28579 break;
28580 #endif
28581 default:
28582 assert(0);
28583 }
28584 break;
28585 }
28586 break;
28587 default:
28588 MIPS_INVAL("MSA instruction");
28589 generate_exception_end(ctx, EXCP_RI);
28590 }
28591 tcg_temp_free_i32(twd);
28592 tcg_temp_free_i32(tws);
28593 tcg_temp_free_i32(tn);
28594 tcg_temp_free_i32(tdf);
28595 }
28596
28597 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
28598 {
28599 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
28600 uint32_t df = 0, n = 0;
28601
28602 if ((dfn & 0x30) == 0x00) {
28603 n = dfn & 0x0f;
28604 df = DF_BYTE;
28605 } else if ((dfn & 0x38) == 0x20) {
28606 n = dfn & 0x07;
28607 df = DF_HALF;
28608 } else if ((dfn & 0x3c) == 0x30) {
28609 n = dfn & 0x03;
28610 df = DF_WORD;
28611 } else if ((dfn & 0x3e) == 0x38) {
28612 n = dfn & 0x01;
28613 df = DF_DOUBLE;
28614 } else if (dfn == 0x3E) {
28615 /* CTCMSA, CFCMSA, MOVE.V */
28616 gen_msa_elm_3e(env, ctx);
28617 return;
28618 } else {
28619 generate_exception_end(ctx, EXCP_RI);
28620 return;
28621 }
28622
28623 gen_msa_elm_df(env, ctx, df, n);
28624 }
28625
28626 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
28627 {
28628 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
28629 uint8_t df = (ctx->opcode >> 21) & 0x1;
28630 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28631 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28632 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28633
28634 TCGv_i32 twd = tcg_const_i32(wd);
28635 TCGv_i32 tws = tcg_const_i32(ws);
28636 TCGv_i32 twt = tcg_const_i32(wt);
28637 TCGv_i32 tdf = tcg_temp_new_i32();
28638
28639 /* adjust df value for floating-point instruction */
28640 tcg_gen_movi_i32(tdf, df + 2);
28641
28642 switch (MASK_MSA_3RF(ctx->opcode)) {
28643 case OPC_FCAF_df:
28644 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
28645 break;
28646 case OPC_FADD_df:
28647 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
28648 break;
28649 case OPC_FCUN_df:
28650 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
28651 break;
28652 case OPC_FSUB_df:
28653 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
28654 break;
28655 case OPC_FCOR_df:
28656 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
28657 break;
28658 case OPC_FCEQ_df:
28659 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
28660 break;
28661 case OPC_FMUL_df:
28662 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
28663 break;
28664 case OPC_FCUNE_df:
28665 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
28666 break;
28667 case OPC_FCUEQ_df:
28668 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
28669 break;
28670 case OPC_FDIV_df:
28671 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
28672 break;
28673 case OPC_FCNE_df:
28674 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
28675 break;
28676 case OPC_FCLT_df:
28677 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
28678 break;
28679 case OPC_FMADD_df:
28680 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
28681 break;
28682 case OPC_MUL_Q_df:
28683 tcg_gen_movi_i32(tdf, df + 1);
28684 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
28685 break;
28686 case OPC_FCULT_df:
28687 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
28688 break;
28689 case OPC_FMSUB_df:
28690 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
28691 break;
28692 case OPC_MADD_Q_df:
28693 tcg_gen_movi_i32(tdf, df + 1);
28694 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
28695 break;
28696 case OPC_FCLE_df:
28697 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
28698 break;
28699 case OPC_MSUB_Q_df:
28700 tcg_gen_movi_i32(tdf, df + 1);
28701 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
28702 break;
28703 case OPC_FCULE_df:
28704 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
28705 break;
28706 case OPC_FEXP2_df:
28707 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
28708 break;
28709 case OPC_FSAF_df:
28710 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
28711 break;
28712 case OPC_FEXDO_df:
28713 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
28714 break;
28715 case OPC_FSUN_df:
28716 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
28717 break;
28718 case OPC_FSOR_df:
28719 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
28720 break;
28721 case OPC_FSEQ_df:
28722 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
28723 break;
28724 case OPC_FTQ_df:
28725 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
28726 break;
28727 case OPC_FSUNE_df:
28728 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
28729 break;
28730 case OPC_FSUEQ_df:
28731 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
28732 break;
28733 case OPC_FSNE_df:
28734 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
28735 break;
28736 case OPC_FSLT_df:
28737 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
28738 break;
28739 case OPC_FMIN_df:
28740 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
28741 break;
28742 case OPC_MULR_Q_df:
28743 tcg_gen_movi_i32(tdf, df + 1);
28744 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
28745 break;
28746 case OPC_FSULT_df:
28747 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
28748 break;
28749 case OPC_FMIN_A_df:
28750 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
28751 break;
28752 case OPC_MADDR_Q_df:
28753 tcg_gen_movi_i32(tdf, df + 1);
28754 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
28755 break;
28756 case OPC_FSLE_df:
28757 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
28758 break;
28759 case OPC_FMAX_df:
28760 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
28761 break;
28762 case OPC_MSUBR_Q_df:
28763 tcg_gen_movi_i32(tdf, df + 1);
28764 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
28765 break;
28766 case OPC_FSULE_df:
28767 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
28768 break;
28769 case OPC_FMAX_A_df:
28770 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
28771 break;
28772 default:
28773 MIPS_INVAL("MSA instruction");
28774 generate_exception_end(ctx, EXCP_RI);
28775 break;
28776 }
28777
28778 tcg_temp_free_i32(twd);
28779 tcg_temp_free_i32(tws);
28780 tcg_temp_free_i32(twt);
28781 tcg_temp_free_i32(tdf);
28782 }
28783
28784 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
28785 {
28786 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
28787 (op & (0x7 << 18)))
28788 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28789 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28790 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28791 uint8_t df = (ctx->opcode >> 16) & 0x3;
28792 TCGv_i32 twd = tcg_const_i32(wd);
28793 TCGv_i32 tws = tcg_const_i32(ws);
28794 TCGv_i32 twt = tcg_const_i32(wt);
28795 TCGv_i32 tdf = tcg_const_i32(df);
28796
28797 switch (MASK_MSA_2R(ctx->opcode)) {
28798 case OPC_FILL_df:
28799 #if !defined(TARGET_MIPS64)
28800 /* Double format valid only for MIPS64 */
28801 if (df == DF_DOUBLE) {
28802 generate_exception_end(ctx, EXCP_RI);
28803 break;
28804 }
28805 #endif
28806 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
28807 break;
28808 case OPC_PCNT_df:
28809 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
28810 break;
28811 case OPC_NLOC_df:
28812 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
28813 break;
28814 case OPC_NLZC_df:
28815 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
28816 break;
28817 default:
28818 MIPS_INVAL("MSA instruction");
28819 generate_exception_end(ctx, EXCP_RI);
28820 break;
28821 }
28822
28823 tcg_temp_free_i32(twd);
28824 tcg_temp_free_i32(tws);
28825 tcg_temp_free_i32(twt);
28826 tcg_temp_free_i32(tdf);
28827 }
28828
28829 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
28830 {
28831 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
28832 (op & (0xf << 17)))
28833 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28834 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28835 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28836 uint8_t df = (ctx->opcode >> 16) & 0x1;
28837 TCGv_i32 twd = tcg_const_i32(wd);
28838 TCGv_i32 tws = tcg_const_i32(ws);
28839 TCGv_i32 twt = tcg_const_i32(wt);
28840 /* adjust df value for floating-point instruction */
28841 TCGv_i32 tdf = tcg_const_i32(df + 2);
28842
28843 switch (MASK_MSA_2RF(ctx->opcode)) {
28844 case OPC_FCLASS_df:
28845 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
28846 break;
28847 case OPC_FTRUNC_S_df:
28848 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
28849 break;
28850 case OPC_FTRUNC_U_df:
28851 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
28852 break;
28853 case OPC_FSQRT_df:
28854 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
28855 break;
28856 case OPC_FRSQRT_df:
28857 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
28858 break;
28859 case OPC_FRCP_df:
28860 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
28861 break;
28862 case OPC_FRINT_df:
28863 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
28864 break;
28865 case OPC_FLOG2_df:
28866 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
28867 break;
28868 case OPC_FEXUPL_df:
28869 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
28870 break;
28871 case OPC_FEXUPR_df:
28872 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
28873 break;
28874 case OPC_FFQL_df:
28875 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
28876 break;
28877 case OPC_FFQR_df:
28878 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
28879 break;
28880 case OPC_FTINT_S_df:
28881 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
28882 break;
28883 case OPC_FTINT_U_df:
28884 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
28885 break;
28886 case OPC_FFINT_S_df:
28887 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
28888 break;
28889 case OPC_FFINT_U_df:
28890 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
28891 break;
28892 }
28893
28894 tcg_temp_free_i32(twd);
28895 tcg_temp_free_i32(tws);
28896 tcg_temp_free_i32(twt);
28897 tcg_temp_free_i32(tdf);
28898 }
28899
28900 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
28901 {
28902 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
28903 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28904 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28905 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28906 TCGv_i32 twd = tcg_const_i32(wd);
28907 TCGv_i32 tws = tcg_const_i32(ws);
28908 TCGv_i32 twt = tcg_const_i32(wt);
28909
28910 switch (MASK_MSA_VEC(ctx->opcode)) {
28911 case OPC_AND_V:
28912 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
28913 break;
28914 case OPC_OR_V:
28915 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
28916 break;
28917 case OPC_NOR_V:
28918 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
28919 break;
28920 case OPC_XOR_V:
28921 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
28922 break;
28923 case OPC_BMNZ_V:
28924 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
28925 break;
28926 case OPC_BMZ_V:
28927 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
28928 break;
28929 case OPC_BSEL_V:
28930 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
28931 break;
28932 default:
28933 MIPS_INVAL("MSA instruction");
28934 generate_exception_end(ctx, EXCP_RI);
28935 break;
28936 }
28937
28938 tcg_temp_free_i32(twd);
28939 tcg_temp_free_i32(tws);
28940 tcg_temp_free_i32(twt);
28941 }
28942
28943 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
28944 {
28945 switch (MASK_MSA_VEC(ctx->opcode)) {
28946 case OPC_AND_V:
28947 case OPC_OR_V:
28948 case OPC_NOR_V:
28949 case OPC_XOR_V:
28950 case OPC_BMNZ_V:
28951 case OPC_BMZ_V:
28952 case OPC_BSEL_V:
28953 gen_msa_vec_v(env, ctx);
28954 break;
28955 case OPC_MSA_2R:
28956 gen_msa_2r(env, ctx);
28957 break;
28958 case OPC_MSA_2RF:
28959 gen_msa_2rf(env, ctx);
28960 break;
28961 default:
28962 MIPS_INVAL("MSA instruction");
28963 generate_exception_end(ctx, EXCP_RI);
28964 break;
28965 }
28966 }
28967
28968 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
28969 {
28970 uint32_t opcode = ctx->opcode;
28971 check_insn(ctx, ASE_MSA);
28972 check_msa_access(ctx);
28973
28974 switch (MASK_MSA_MINOR(opcode)) {
28975 case OPC_MSA_I8_00:
28976 case OPC_MSA_I8_01:
28977 case OPC_MSA_I8_02:
28978 gen_msa_i8(env, ctx);
28979 break;
28980 case OPC_MSA_I5_06:
28981 case OPC_MSA_I5_07:
28982 gen_msa_i5(env, ctx);
28983 break;
28984 case OPC_MSA_BIT_09:
28985 case OPC_MSA_BIT_0A:
28986 gen_msa_bit(env, ctx);
28987 break;
28988 case OPC_MSA_3R_0D:
28989 case OPC_MSA_3R_0E:
28990 case OPC_MSA_3R_0F:
28991 case OPC_MSA_3R_10:
28992 case OPC_MSA_3R_11:
28993 case OPC_MSA_3R_12:
28994 case OPC_MSA_3R_13:
28995 case OPC_MSA_3R_14:
28996 case OPC_MSA_3R_15:
28997 gen_msa_3r(env, ctx);
28998 break;
28999 case OPC_MSA_ELM:
29000 gen_msa_elm(env, ctx);
29001 break;
29002 case OPC_MSA_3RF_1A:
29003 case OPC_MSA_3RF_1B:
29004 case OPC_MSA_3RF_1C:
29005 gen_msa_3rf(env, ctx);
29006 break;
29007 case OPC_MSA_VEC:
29008 gen_msa_vec(env, ctx);
29009 break;
29010 case OPC_LD_B:
29011 case OPC_LD_H:
29012 case OPC_LD_W:
29013 case OPC_LD_D:
29014 case OPC_ST_B:
29015 case OPC_ST_H:
29016 case OPC_ST_W:
29017 case OPC_ST_D:
29018 {
29019 int32_t s10 = sextract32(ctx->opcode, 16, 10);
29020 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
29021 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29022 uint8_t df = (ctx->opcode >> 0) & 0x3;
29023
29024 TCGv_i32 twd = tcg_const_i32(wd);
29025 TCGv taddr = tcg_temp_new();
29026 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
29027
29028 switch (MASK_MSA_MINOR(opcode)) {
29029 case OPC_LD_B:
29030 gen_helper_msa_ld_b(cpu_env, twd, taddr);
29031 break;
29032 case OPC_LD_H:
29033 gen_helper_msa_ld_h(cpu_env, twd, taddr);
29034 break;
29035 case OPC_LD_W:
29036 gen_helper_msa_ld_w(cpu_env, twd, taddr);
29037 break;
29038 case OPC_LD_D:
29039 gen_helper_msa_ld_d(cpu_env, twd, taddr);
29040 break;
29041 case OPC_ST_B:
29042 gen_helper_msa_st_b(cpu_env, twd, taddr);
29043 break;
29044 case OPC_ST_H:
29045 gen_helper_msa_st_h(cpu_env, twd, taddr);
29046 break;
29047 case OPC_ST_W:
29048 gen_helper_msa_st_w(cpu_env, twd, taddr);
29049 break;
29050 case OPC_ST_D:
29051 gen_helper_msa_st_d(cpu_env, twd, taddr);
29052 break;
29053 }
29054
29055 tcg_temp_free_i32(twd);
29056 tcg_temp_free(taddr);
29057 }
29058 break;
29059 default:
29060 MIPS_INVAL("MSA instruction");
29061 generate_exception_end(ctx, EXCP_RI);
29062 break;
29063 }
29064
29065 }
29066
29067 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
29068 {
29069 int32_t offset;
29070 int rs, rt, rd, sa;
29071 uint32_t op, op1;
29072 int16_t imm;
29073
29074 /* make sure instructions are on a word boundary */
29075 if (ctx->base.pc_next & 0x3) {
29076 env->CP0_BadVAddr = ctx->base.pc_next;
29077 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
29078 return;
29079 }
29080
29081 /* Handle blikely not taken case */
29082 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
29083 TCGLabel *l1 = gen_new_label();
29084
29085 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
29086 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
29087 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
29088 gen_set_label(l1);
29089 }
29090
29091 op = MASK_OP_MAJOR(ctx->opcode);
29092 rs = (ctx->opcode >> 21) & 0x1f;
29093 rt = (ctx->opcode >> 16) & 0x1f;
29094 rd = (ctx->opcode >> 11) & 0x1f;
29095 sa = (ctx->opcode >> 6) & 0x1f;
29096 imm = (int16_t)ctx->opcode;
29097 switch (op) {
29098 case OPC_SPECIAL:
29099 decode_opc_special(env, ctx);
29100 break;
29101 case OPC_SPECIAL2:
29102 #if defined(TARGET_MIPS64)
29103 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
29104 decode_mmi(env, ctx);
29105 #else
29106 if (ctx->insn_flags & ASE_MXU) {
29107 decode_opc_mxu(env, ctx);
29108 #endif
29109 } else {
29110 decode_opc_special2_legacy(env, ctx);
29111 }
29112 break;
29113 case OPC_SPECIAL3:
29114 #if defined(TARGET_MIPS64)
29115 if (ctx->insn_flags & INSN_R5900) {
29116 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
29117 } else {
29118 decode_opc_special3(env, ctx);
29119 }
29120 #else
29121 decode_opc_special3(env, ctx);
29122 #endif
29123 break;
29124 case OPC_REGIMM:
29125 op1 = MASK_REGIMM(ctx->opcode);
29126 switch (op1) {
29127 case OPC_BLTZL: /* REGIMM branches */
29128 case OPC_BGEZL:
29129 case OPC_BLTZALL:
29130 case OPC_BGEZALL:
29131 check_insn(ctx, ISA_MIPS2);
29132 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29133 /* Fallthrough */
29134 case OPC_BLTZ:
29135 case OPC_BGEZ:
29136 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
29137 break;
29138 case OPC_BLTZAL:
29139 case OPC_BGEZAL:
29140 if (ctx->insn_flags & ISA_MIPS32R6) {
29141 if (rs == 0) {
29142 /* OPC_NAL, OPC_BAL */
29143 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
29144 } else {
29145 generate_exception_end(ctx, EXCP_RI);
29146 }
29147 } else {
29148 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
29149 }
29150 break;
29151 case OPC_TGEI: /* REGIMM traps */
29152 case OPC_TGEIU:
29153 case OPC_TLTI:
29154 case OPC_TLTIU:
29155 case OPC_TEQI:
29156
29157 case OPC_TNEI:
29158 check_insn(ctx, ISA_MIPS2);
29159 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29160 gen_trap(ctx, op1, rs, -1, imm);
29161 break;
29162 case OPC_SIGRIE:
29163 check_insn(ctx, ISA_MIPS32R6);
29164 generate_exception_end(ctx, EXCP_RI);
29165 break;
29166 case OPC_SYNCI:
29167 check_insn(ctx, ISA_MIPS32R2);
29168 /* Break the TB to be able to sync copied instructions
29169 immediately */
29170 ctx->base.is_jmp = DISAS_STOP;
29171 break;
29172 case OPC_BPOSGE32: /* MIPS DSP branch */
29173 #if defined(TARGET_MIPS64)
29174 case OPC_BPOSGE64:
29175 #endif
29176 check_dsp(ctx);
29177 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
29178 break;
29179 #if defined(TARGET_MIPS64)
29180 case OPC_DAHI:
29181 check_insn(ctx, ISA_MIPS32R6);
29182 check_mips_64(ctx);
29183 if (rs != 0) {
29184 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
29185 }
29186 break;
29187 case OPC_DATI:
29188 check_insn(ctx, ISA_MIPS32R6);
29189 check_mips_64(ctx);
29190 if (rs != 0) {
29191 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
29192 }
29193 break;
29194 #endif
29195 default: /* Invalid */
29196 MIPS_INVAL("regimm");
29197 generate_exception_end(ctx, EXCP_RI);
29198 break;
29199 }
29200 break;
29201 case OPC_CP0:
29202 check_cp0_enabled(ctx);
29203 op1 = MASK_CP0(ctx->opcode);
29204 switch (op1) {
29205 case OPC_MFC0:
29206 case OPC_MTC0:
29207 case OPC_MFTR:
29208 case OPC_MTTR:
29209 case OPC_MFHC0:
29210 case OPC_MTHC0:
29211 #if defined(TARGET_MIPS64)
29212 case OPC_DMFC0:
29213 case OPC_DMTC0:
29214 #endif
29215 #ifndef CONFIG_USER_ONLY
29216 gen_cp0(env, ctx, op1, rt, rd);
29217 #endif /* !CONFIG_USER_ONLY */
29218 break;
29219 case OPC_C0:
29220 case OPC_C0_1:
29221 case OPC_C0_2:
29222 case OPC_C0_3:
29223 case OPC_C0_4:
29224 case OPC_C0_5:
29225 case OPC_C0_6:
29226 case OPC_C0_7:
29227 case OPC_C0_8:
29228 case OPC_C0_9:
29229 case OPC_C0_A:
29230 case OPC_C0_B:
29231 case OPC_C0_C:
29232 case OPC_C0_D:
29233 case OPC_C0_E:
29234 case OPC_C0_F:
29235 #ifndef CONFIG_USER_ONLY
29236 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
29237 #endif /* !CONFIG_USER_ONLY */
29238 break;
29239 case OPC_MFMC0:
29240 #ifndef CONFIG_USER_ONLY
29241 {
29242 uint32_t op2;
29243 TCGv t0 = tcg_temp_new();
29244
29245 op2 = MASK_MFMC0(ctx->opcode);
29246 switch (op2) {
29247 case OPC_DMT:
29248 check_cp0_mt(ctx);
29249 gen_helper_dmt(t0);
29250 gen_store_gpr(t0, rt);
29251 break;
29252 case OPC_EMT:
29253 check_cp0_mt(ctx);
29254 gen_helper_emt(t0);
29255 gen_store_gpr(t0, rt);
29256 break;
29257 case OPC_DVPE:
29258 check_cp0_mt(ctx);
29259 gen_helper_dvpe(t0, cpu_env);
29260 gen_store_gpr(t0, rt);
29261 break;
29262 case OPC_EVPE:
29263 check_cp0_mt(ctx);
29264 gen_helper_evpe(t0, cpu_env);
29265 gen_store_gpr(t0, rt);
29266 break;
29267 case OPC_DVP:
29268 check_insn(ctx, ISA_MIPS32R6);
29269 if (ctx->vp) {
29270 gen_helper_dvp(t0, cpu_env);
29271 gen_store_gpr(t0, rt);
29272 }
29273 break;
29274 case OPC_EVP:
29275 check_insn(ctx, ISA_MIPS32R6);
29276 if (ctx->vp) {
29277 gen_helper_evp(t0, cpu_env);
29278 gen_store_gpr(t0, rt);
29279 }
29280 break;
29281 case OPC_DI:
29282 check_insn(ctx, ISA_MIPS32R2);
29283 save_cpu_state(ctx, 1);
29284 gen_helper_di(t0, cpu_env);
29285 gen_store_gpr(t0, rt);
29286 /* Stop translation as we may have switched
29287 the execution mode. */
29288 ctx->base.is_jmp = DISAS_STOP;
29289 break;
29290 case OPC_EI:
29291 check_insn(ctx, ISA_MIPS32R2);
29292 save_cpu_state(ctx, 1);
29293 gen_helper_ei(t0, cpu_env);
29294 gen_store_gpr(t0, rt);
29295 /* DISAS_STOP isn't sufficient, we need to ensure we break
29296 out of translated code to check for pending interrupts */
29297 gen_save_pc(ctx->base.pc_next + 4);
29298 ctx->base.is_jmp = DISAS_EXIT;
29299 break;
29300 default: /* Invalid */
29301 MIPS_INVAL("mfmc0");
29302 generate_exception_end(ctx, EXCP_RI);
29303 break;
29304 }
29305 tcg_temp_free(t0);
29306 }
29307 #endif /* !CONFIG_USER_ONLY */
29308 break;
29309 case OPC_RDPGPR:
29310 check_insn(ctx, ISA_MIPS32R2);
29311 gen_load_srsgpr(rt, rd);
29312 break;
29313 case OPC_WRPGPR:
29314 check_insn(ctx, ISA_MIPS32R2);
29315 gen_store_srsgpr(rt, rd);
29316 break;
29317 default:
29318 MIPS_INVAL("cp0");
29319 generate_exception_end(ctx, EXCP_RI);
29320 break;
29321 }
29322 break;
29323 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
29324 if (ctx->insn_flags & ISA_MIPS32R6) {
29325 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
29326 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29327 } else {
29328 /* OPC_ADDI */
29329 /* Arithmetic with immediate opcode */
29330 gen_arith_imm(ctx, op, rt, rs, imm);
29331 }
29332 break;
29333 case OPC_ADDIU:
29334 gen_arith_imm(ctx, op, rt, rs, imm);
29335 break;
29336 case OPC_SLTI: /* Set on less than with immediate opcode */
29337 case OPC_SLTIU:
29338 gen_slt_imm(ctx, op, rt, rs, imm);
29339 break;
29340 case OPC_ANDI: /* Arithmetic with immediate opcode */
29341 case OPC_LUI: /* OPC_AUI */
29342 case OPC_ORI:
29343 case OPC_XORI:
29344 gen_logic_imm(ctx, op, rt, rs, imm);
29345 break;
29346 case OPC_J: /* Jump */
29347 case OPC_JAL:
29348 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
29349 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
29350 break;
29351 /* Branch */
29352 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
29353 if (ctx->insn_flags & ISA_MIPS32R6) {
29354 if (rt == 0) {
29355 generate_exception_end(ctx, EXCP_RI);
29356 break;
29357 }
29358 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
29359 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29360 } else {
29361 /* OPC_BLEZL */
29362 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29363 }
29364 break;
29365 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
29366 if (ctx->insn_flags & ISA_MIPS32R6) {
29367 if (rt == 0) {
29368 generate_exception_end(ctx, EXCP_RI);
29369 break;
29370 }
29371 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
29372 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29373 } else {
29374 /* OPC_BGTZL */
29375 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29376 }
29377 break;
29378 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
29379 if (rt == 0) {
29380 /* OPC_BLEZ */
29381 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29382 } else {
29383 check_insn(ctx, ISA_MIPS32R6);
29384 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
29385 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29386 }
29387 break;
29388 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
29389 if (rt == 0) {
29390 /* OPC_BGTZ */
29391 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29392 } else {
29393 check_insn(ctx, ISA_MIPS32R6);
29394 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
29395 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29396 }
29397 break;
29398 case OPC_BEQL:
29399 case OPC_BNEL:
29400 check_insn(ctx, ISA_MIPS2);
29401 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29402 /* Fallthrough */
29403 case OPC_BEQ:
29404 case OPC_BNE:
29405 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29406 break;
29407 case OPC_LL: /* Load and stores */
29408 check_insn(ctx, ISA_MIPS2);
29409 if (ctx->insn_flags & INSN_R5900) {
29410 check_insn_opc_user_only(ctx, INSN_R5900);
29411 }
29412 /* Fallthrough */
29413 case OPC_LWL:
29414 case OPC_LWR:
29415 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29416 /* Fallthrough */
29417 case OPC_LB:
29418 case OPC_LH:
29419 case OPC_LW:
29420 case OPC_LWPC:
29421 case OPC_LBU:
29422 case OPC_LHU:
29423 gen_ld(ctx, op, rt, rs, imm);
29424 break;
29425 case OPC_SWL:
29426 case OPC_SWR:
29427 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29428 /* fall through */
29429 case OPC_SB:
29430 case OPC_SH:
29431 case OPC_SW:
29432 gen_st(ctx, op, rt, rs, imm);
29433 break;
29434 case OPC_SC:
29435 check_insn(ctx, ISA_MIPS2);
29436 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29437 if (ctx->insn_flags & INSN_R5900) {
29438 check_insn_opc_user_only(ctx, INSN_R5900);
29439 }
29440 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
29441 break;
29442 case OPC_CACHE:
29443 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29444 check_cp0_enabled(ctx);
29445 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
29446 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
29447 gen_cache_operation(ctx, rt, rs, imm);
29448 }
29449 /* Treat as NOP. */
29450 break;
29451 case OPC_PREF:
29452 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29453 if (ctx->insn_flags & INSN_R5900) {
29454 /* Treat as NOP. */
29455 } else {
29456 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
29457 /* Treat as NOP. */
29458 }
29459 break;
29460
29461 /* Floating point (COP1). */
29462 case OPC_LWC1:
29463 case OPC_LDC1:
29464 case OPC_SWC1:
29465 case OPC_SDC1:
29466 gen_cop1_ldst(ctx, op, rt, rs, imm);
29467 break;
29468
29469 case OPC_CP1:
29470 op1 = MASK_CP1(ctx->opcode);
29471
29472 switch (op1) {
29473 case OPC_MFHC1:
29474 case OPC_MTHC1:
29475 check_cp1_enabled(ctx);
29476 check_insn(ctx, ISA_MIPS32R2);
29477 /* fall through */
29478 case OPC_MFC1:
29479 case OPC_CFC1:
29480 case OPC_MTC1:
29481 case OPC_CTC1:
29482 check_cp1_enabled(ctx);
29483 gen_cp1(ctx, op1, rt, rd);
29484 break;
29485 #if defined(TARGET_MIPS64)
29486 case OPC_DMFC1:
29487 case OPC_DMTC1:
29488 check_cp1_enabled(ctx);
29489 check_insn(ctx, ISA_MIPS3);
29490 check_mips_64(ctx);
29491 gen_cp1(ctx, op1, rt, rd);
29492 break;
29493 #endif
29494 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
29495 check_cp1_enabled(ctx);
29496 if (ctx->insn_flags & ISA_MIPS32R6) {
29497 /* OPC_BC1EQZ */
29498 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
29499 rt, imm << 2, 4);
29500 } else {
29501 /* OPC_BC1ANY2 */
29502 check_cop1x(ctx);
29503 check_insn(ctx, ASE_MIPS3D);
29504 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
29505 (rt >> 2) & 0x7, imm << 2);
29506 }
29507 break;
29508 case OPC_BC1NEZ:
29509 check_cp1_enabled(ctx);
29510 check_insn(ctx, ISA_MIPS32R6);
29511 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
29512 rt, imm << 2, 4);
29513 break;
29514 case OPC_BC1ANY4:
29515 check_cp1_enabled(ctx);
29516 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29517 check_cop1x(ctx);
29518 check_insn(ctx, ASE_MIPS3D);
29519 /* fall through */
29520 case OPC_BC1:
29521 check_cp1_enabled(ctx);
29522 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29523 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
29524 (rt >> 2) & 0x7, imm << 2);
29525 break;
29526 case OPC_PS_FMT:
29527 check_ps(ctx);
29528 /* fall through */
29529 case OPC_S_FMT:
29530 case OPC_D_FMT:
29531 check_cp1_enabled(ctx);
29532 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
29533 (imm >> 8) & 0x7);
29534 break;
29535 case OPC_W_FMT:
29536 case OPC_L_FMT:
29537 {
29538 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
29539 check_cp1_enabled(ctx);
29540 if (ctx->insn_flags & ISA_MIPS32R6) {
29541 switch (r6_op) {
29542 case R6_OPC_CMP_AF_S:
29543 case R6_OPC_CMP_UN_S:
29544 case R6_OPC_CMP_EQ_S:
29545 case R6_OPC_CMP_UEQ_S:
29546 case R6_OPC_CMP_LT_S:
29547 case R6_OPC_CMP_ULT_S:
29548 case R6_OPC_CMP_LE_S:
29549 case R6_OPC_CMP_ULE_S:
29550 case R6_OPC_CMP_SAF_S:
29551 case R6_OPC_CMP_SUN_S:
29552 case R6_OPC_CMP_SEQ_S:
29553 case R6_OPC_CMP_SEUQ_S:
29554 case R6_OPC_CMP_SLT_S:
29555 case R6_OPC_CMP_SULT_S:
29556 case R6_OPC_CMP_SLE_S:
29557 case R6_OPC_CMP_SULE_S:
29558 case R6_OPC_CMP_OR_S:
29559 case R6_OPC_CMP_UNE_S:
29560 case R6_OPC_CMP_NE_S:
29561 case R6_OPC_CMP_SOR_S:
29562 case R6_OPC_CMP_SUNE_S:
29563 case R6_OPC_CMP_SNE_S:
29564 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
29565 break;
29566 case R6_OPC_CMP_AF_D:
29567 case R6_OPC_CMP_UN_D:
29568 case R6_OPC_CMP_EQ_D:
29569 case R6_OPC_CMP_UEQ_D:
29570 case R6_OPC_CMP_LT_D:
29571 case R6_OPC_CMP_ULT_D:
29572 case R6_OPC_CMP_LE_D:
29573 case R6_OPC_CMP_ULE_D:
29574 case R6_OPC_CMP_SAF_D:
29575 case R6_OPC_CMP_SUN_D:
29576 case R6_OPC_CMP_SEQ_D:
29577 case R6_OPC_CMP_SEUQ_D:
29578 case R6_OPC_CMP_SLT_D:
29579 case R6_OPC_CMP_SULT_D:
29580 case R6_OPC_CMP_SLE_D:
29581 case R6_OPC_CMP_SULE_D:
29582 case R6_OPC_CMP_OR_D:
29583 case R6_OPC_CMP_UNE_D:
29584 case R6_OPC_CMP_NE_D:
29585 case R6_OPC_CMP_SOR_D:
29586 case R6_OPC_CMP_SUNE_D:
29587 case R6_OPC_CMP_SNE_D:
29588 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
29589 break;
29590 default:
29591 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
29592 rt, rd, sa, (imm >> 8) & 0x7);
29593
29594 break;
29595 }
29596 } else {
29597 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
29598 (imm >> 8) & 0x7);
29599 }
29600 break;
29601 }
29602 case OPC_BZ_V:
29603 case OPC_BNZ_V:
29604 case OPC_BZ_B:
29605 case OPC_BZ_H:
29606 case OPC_BZ_W:
29607 case OPC_BZ_D:
29608 case OPC_BNZ_B:
29609 case OPC_BNZ_H:
29610 case OPC_BNZ_W:
29611 case OPC_BNZ_D:
29612 check_insn(ctx, ASE_MSA);
29613 gen_msa_branch(env, ctx, op1);
29614 break;
29615 default:
29616 MIPS_INVAL("cp1");
29617 generate_exception_end(ctx, EXCP_RI);
29618 break;
29619 }
29620 break;
29621
29622 /* Compact branches [R6] and COP2 [non-R6] */
29623 case OPC_BC: /* OPC_LWC2 */
29624 case OPC_BALC: /* OPC_SWC2 */
29625 if (ctx->insn_flags & ISA_MIPS32R6) {
29626 /* OPC_BC, OPC_BALC */
29627 gen_compute_compact_branch(ctx, op, 0, 0,
29628 sextract32(ctx->opcode << 2, 0, 28));
29629 } else {
29630 /* OPC_LWC2, OPC_SWC2 */
29631 /* COP2: Not implemented. */
29632 generate_exception_err(ctx, EXCP_CpU, 2);
29633 }
29634 break;
29635 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
29636 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
29637 if (ctx->insn_flags & ISA_MIPS32R6) {
29638 if (rs != 0) {
29639 /* OPC_BEQZC, OPC_BNEZC */
29640 gen_compute_compact_branch(ctx, op, rs, 0,
29641 sextract32(ctx->opcode << 2, 0, 23));
29642 } else {
29643 /* OPC_JIC, OPC_JIALC */
29644 gen_compute_compact_branch(ctx, op, 0, rt, imm);
29645 }
29646 } else {
29647 /* OPC_LWC2, OPC_SWC2 */
29648 /* COP2: Not implemented. */
29649 generate_exception_err(ctx, EXCP_CpU, 2);
29650 }
29651 break;
29652 case OPC_CP2:
29653 check_insn(ctx, INSN_LOONGSON2F);
29654 /* Note that these instructions use different fields. */
29655 gen_loongson_multimedia(ctx, sa, rd, rt);
29656 break;
29657
29658 case OPC_CP3:
29659 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29660 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
29661 check_cp1_enabled(ctx);
29662 op1 = MASK_CP3(ctx->opcode);
29663 switch (op1) {
29664 case OPC_LUXC1:
29665 case OPC_SUXC1:
29666 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
29667 /* Fallthrough */
29668 case OPC_LWXC1:
29669 case OPC_LDXC1:
29670 case OPC_SWXC1:
29671 case OPC_SDXC1:
29672 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
29673 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
29674 break;
29675 case OPC_PREFX:
29676 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
29677 /* Treat as NOP. */
29678 break;
29679 case OPC_ALNV_PS:
29680 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
29681 /* Fallthrough */
29682 case OPC_MADD_S:
29683 case OPC_MADD_D:
29684 case OPC_MADD_PS:
29685 case OPC_MSUB_S:
29686 case OPC_MSUB_D:
29687 case OPC_MSUB_PS:
29688 case OPC_NMADD_S:
29689 case OPC_NMADD_D:
29690 case OPC_NMADD_PS:
29691 case OPC_NMSUB_S:
29692 case OPC_NMSUB_D:
29693 case OPC_NMSUB_PS:
29694 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
29695 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
29696 break;
29697 default:
29698 MIPS_INVAL("cp3");
29699 generate_exception_end(ctx, EXCP_RI);
29700 break;
29701 }
29702 } else {
29703 generate_exception_err(ctx, EXCP_CpU, 1);
29704 }
29705 break;
29706
29707 #if defined(TARGET_MIPS64)
29708 /* MIPS64 opcodes */
29709 case OPC_LLD:
29710 if (ctx->insn_flags & INSN_R5900) {
29711 check_insn_opc_user_only(ctx, INSN_R5900);
29712 }
29713 /* fall through */
29714 case OPC_LDL:
29715 case OPC_LDR:
29716 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29717 /* fall through */
29718 case OPC_LWU:
29719 case OPC_LD:
29720 check_insn(ctx, ISA_MIPS3);
29721 check_mips_64(ctx);
29722 gen_ld(ctx, op, rt, rs, imm);
29723 break;
29724 case OPC_SDL:
29725 case OPC_SDR:
29726 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29727 /* fall through */
29728 case OPC_SD:
29729 check_insn(ctx, ISA_MIPS3);
29730 check_mips_64(ctx);
29731 gen_st(ctx, op, rt, rs, imm);
29732 break;
29733 case OPC_SCD:
29734 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29735 check_insn(ctx, ISA_MIPS3);
29736 if (ctx->insn_flags & INSN_R5900) {
29737 check_insn_opc_user_only(ctx, INSN_R5900);
29738 }
29739 check_mips_64(ctx);
29740 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
29741 break;
29742 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
29743 if (ctx->insn_flags & ISA_MIPS32R6) {
29744 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
29745 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29746 } else {
29747 /* OPC_DADDI */
29748 check_insn(ctx, ISA_MIPS3);
29749 check_mips_64(ctx);
29750 gen_arith_imm(ctx, op, rt, rs, imm);
29751 }
29752 break;
29753 case OPC_DADDIU:
29754 check_insn(ctx, ISA_MIPS3);
29755 check_mips_64(ctx);
29756 gen_arith_imm(ctx, op, rt, rs, imm);
29757 break;
29758 #else
29759 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
29760 if (ctx->insn_flags & ISA_MIPS32R6) {
29761 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29762 } else {
29763 MIPS_INVAL("major opcode");
29764 generate_exception_end(ctx, EXCP_RI);
29765 }
29766 break;
29767 #endif
29768 case OPC_DAUI: /* OPC_JALX */
29769 if (ctx->insn_flags & ISA_MIPS32R6) {
29770 #if defined(TARGET_MIPS64)
29771 /* OPC_DAUI */
29772 check_mips_64(ctx);
29773 if (rs == 0) {
29774 generate_exception(ctx, EXCP_RI);
29775 } else if (rt != 0) {
29776 TCGv t0 = tcg_temp_new();
29777 gen_load_gpr(t0, rs);
29778 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
29779 tcg_temp_free(t0);
29780 }
29781 #else
29782 generate_exception_end(ctx, EXCP_RI);
29783 MIPS_INVAL("major opcode");
29784 #endif
29785 } else {
29786 /* OPC_JALX */
29787 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
29788 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
29789 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
29790 }
29791 break;
29792 case OPC_MSA: /* OPC_MDMX */
29793 if (ctx->insn_flags & INSN_R5900) {
29794 #if defined(TARGET_MIPS64)
29795 gen_mmi_lq(env, ctx); /* MMI_OPC_LQ */
29796 #endif
29797 } else {
29798 /* MDMX: Not implemented. */
29799 gen_msa(env, ctx);
29800 }
29801 break;
29802 case OPC_PCREL:
29803 check_insn(ctx, ISA_MIPS32R6);
29804 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
29805 break;
29806 default: /* Invalid */
29807 MIPS_INVAL("major opcode");
29808 generate_exception_end(ctx, EXCP_RI);
29809 break;
29810 }
29811 }
29812
29813 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
29814 {
29815 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29816 CPUMIPSState *env = cs->env_ptr;
29817
29818 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
29819 ctx->saved_pc = -1;
29820 ctx->insn_flags = env->insn_flags;
29821 ctx->CP0_Config1 = env->CP0_Config1;
29822 ctx->CP0_Config2 = env->CP0_Config2;
29823 ctx->CP0_Config3 = env->CP0_Config3;
29824 ctx->CP0_Config5 = env->CP0_Config5;
29825 ctx->btarget = 0;
29826 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
29827 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
29828 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
29829 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
29830 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
29831 ctx->PAMask = env->PAMask;
29832 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
29833 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
29834 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
29835 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
29836 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
29837 /* Restore delay slot state from the tb context. */
29838 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
29839 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
29840 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
29841 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
29842 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
29843 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
29844 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
29845 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
29846 restore_cpu_state(env, ctx);
29847 #ifdef CONFIG_USER_ONLY
29848 ctx->mem_idx = MIPS_HFLAG_UM;
29849 #else
29850 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
29851 #endif
29852 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
29853 MO_UNALN : MO_ALIGN;
29854
29855 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
29856 ctx->hflags);
29857 }
29858
29859 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
29860 {
29861 }
29862
29863 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
29864 {
29865 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29866
29867 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
29868 ctx->btarget);
29869 }
29870
29871 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
29872 const CPUBreakpoint *bp)
29873 {
29874 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29875
29876 save_cpu_state(ctx, 1);
29877 ctx->base.is_jmp = DISAS_NORETURN;
29878 gen_helper_raise_exception_debug(cpu_env);
29879 /* The address covered by the breakpoint must be included in
29880 [tb->pc, tb->pc + tb->size) in order to for it to be
29881 properly cleared -- thus we increment the PC here so that
29882 the logic setting tb->size below does the right thing. */
29883 ctx->base.pc_next += 4;
29884 return true;
29885 }
29886
29887 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
29888 {
29889 CPUMIPSState *env = cs->env_ptr;
29890 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29891 int insn_bytes;
29892 int is_slot;
29893
29894 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
29895 if (ctx->insn_flags & ISA_NANOMIPS32) {
29896 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
29897 insn_bytes = decode_nanomips_opc(env, ctx);
29898 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
29899 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
29900 insn_bytes = 4;
29901 decode_opc(env, ctx);
29902 } else if (ctx->insn_flags & ASE_MICROMIPS) {
29903 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
29904 insn_bytes = decode_micromips_opc(env, ctx);
29905 } else if (ctx->insn_flags & ASE_MIPS16) {
29906 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
29907 insn_bytes = decode_mips16_opc(env, ctx);
29908 } else {
29909 generate_exception_end(ctx, EXCP_RI);
29910 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
29911 return;
29912 }
29913
29914 if (ctx->hflags & MIPS_HFLAG_BMASK) {
29915 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
29916 MIPS_HFLAG_FBNSLOT))) {
29917 /* force to generate branch as there is neither delay nor
29918 forbidden slot */
29919 is_slot = 1;
29920 }
29921 if ((ctx->hflags & MIPS_HFLAG_M16) &&
29922 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
29923 /* Force to generate branch as microMIPS R6 doesn't restrict
29924 branches in the forbidden slot. */
29925 is_slot = 1;
29926 }
29927 }
29928 if (is_slot) {
29929 gen_branch(ctx, insn_bytes);
29930 }
29931 ctx->base.pc_next += insn_bytes;
29932
29933 if (ctx->base.is_jmp != DISAS_NEXT) {
29934 return;
29935 }
29936 /* Execute a branch and its delay slot as a single instruction.
29937 This is what GDB expects and is consistent with what the
29938 hardware does (e.g. if a delay slot instruction faults, the
29939 reported PC is the PC of the branch). */
29940 if (ctx->base.singlestep_enabled &&
29941 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
29942 ctx->base.is_jmp = DISAS_TOO_MANY;
29943 }
29944 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
29945 ctx->base.is_jmp = DISAS_TOO_MANY;
29946 }
29947 }
29948
29949 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
29950 {
29951 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29952
29953 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
29954 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
29955 gen_helper_raise_exception_debug(cpu_env);
29956 } else {
29957 switch (ctx->base.is_jmp) {
29958 case DISAS_STOP:
29959 gen_save_pc(ctx->base.pc_next);
29960 tcg_gen_lookup_and_goto_ptr();
29961 break;
29962 case DISAS_NEXT:
29963 case DISAS_TOO_MANY:
29964 save_cpu_state(ctx, 0);
29965 gen_goto_tb(ctx, 0, ctx->base.pc_next);
29966 break;
29967 case DISAS_EXIT:
29968 tcg_gen_exit_tb(NULL, 0);
29969 break;
29970 case DISAS_NORETURN:
29971 break;
29972 default:
29973 g_assert_not_reached();
29974 }
29975 }
29976 }
29977
29978 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
29979 {
29980 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
29981 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
29982 }
29983
29984 static const TranslatorOps mips_tr_ops = {
29985 .init_disas_context = mips_tr_init_disas_context,
29986 .tb_start = mips_tr_tb_start,
29987 .insn_start = mips_tr_insn_start,
29988 .breakpoint_check = mips_tr_breakpoint_check,
29989 .translate_insn = mips_tr_translate_insn,
29990 .tb_stop = mips_tr_tb_stop,
29991 .disas_log = mips_tr_disas_log,
29992 };
29993
29994 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
29995 {
29996 DisasContext ctx;
29997
29998 translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
29999 }
30000
30001 static void fpu_dump_state(CPUMIPSState *env, FILE *f, int flags)
30002 {
30003 int i;
30004 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
30005
30006 #define printfpr(fp) \
30007 do { \
30008 if (is_fpu64) \
30009 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
30010 " fd:%13g fs:%13g psu: %13g\n", \
30011 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
30012 (double)(fp)->fd, \
30013 (double)(fp)->fs[FP_ENDIAN_IDX], \
30014 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
30015 else { \
30016 fpr_t tmp; \
30017 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
30018 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
30019 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
30020 " fd:%13g fs:%13g psu:%13g\n", \
30021 tmp.w[FP_ENDIAN_IDX], tmp.d, \
30022 (double)tmp.fd, \
30023 (double)tmp.fs[FP_ENDIAN_IDX], \
30024 (double)tmp.fs[!FP_ENDIAN_IDX]); \
30025 } \
30026 } while(0)
30027
30028
30029 qemu_fprintf(f,
30030 "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
30031 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
30032 get_float_exception_flags(&env->active_fpu.fp_status));
30033 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
30034 qemu_fprintf(f, "%3s: ", fregnames[i]);
30035 printfpr(&env->active_fpu.fpr[i]);
30036 }
30037
30038 #undef printfpr
30039 }
30040
30041 void mips_cpu_dump_state(CPUState *cs, FILE *f, int flags)
30042 {
30043 MIPSCPU *cpu = MIPS_CPU(cs);
30044 CPUMIPSState *env = &cpu->env;
30045 int i;
30046
30047 qemu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
30048 " LO=0x" TARGET_FMT_lx " ds %04x "
30049 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
30050 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
30051 env->hflags, env->btarget, env->bcond);
30052 for (i = 0; i < 32; i++) {
30053 if ((i & 3) == 0) {
30054 qemu_fprintf(f, "GPR%02d:", i);
30055 }
30056 qemu_fprintf(f, " %s " TARGET_FMT_lx,
30057 regnames[i], env->active_tc.gpr[i]);
30058 if ((i & 3) == 3) {
30059 qemu_fprintf(f, "\n");
30060 }
30061 }
30062
30063 qemu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
30064 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
30065 qemu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
30066 PRIx64 "\n",
30067 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
30068 qemu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
30069 env->CP0_Config2, env->CP0_Config3);
30070 qemu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
30071 env->CP0_Config4, env->CP0_Config5);
30072 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
30073 fpu_dump_state(env, f, flags);
30074 }
30075 }
30076
30077 void mips_tcg_init(void)
30078 {
30079 int i;
30080
30081 cpu_gpr[0] = NULL;
30082 for (i = 1; i < 32; i++)
30083 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
30084 offsetof(CPUMIPSState, active_tc.gpr[i]),
30085 regnames[i]);
30086
30087 for (i = 0; i < 32; i++) {
30088 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
30089 msa_wr_d[i * 2] =
30090 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
30091 /* The scalar floating-point unit (FPU) registers are mapped on
30092 * the MSA vector registers. */
30093 fpu_f64[i] = msa_wr_d[i * 2];
30094 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
30095 msa_wr_d[i * 2 + 1] =
30096 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
30097 }
30098
30099 cpu_PC = tcg_global_mem_new(cpu_env,
30100 offsetof(CPUMIPSState, active_tc.PC), "PC");
30101 for (i = 0; i < MIPS_DSP_ACC; i++) {
30102 cpu_HI[i] = tcg_global_mem_new(cpu_env,
30103 offsetof(CPUMIPSState, active_tc.HI[i]),
30104 regnames_HI[i]);
30105 cpu_LO[i] = tcg_global_mem_new(cpu_env,
30106 offsetof(CPUMIPSState, active_tc.LO[i]),
30107 regnames_LO[i]);
30108 }
30109 cpu_dspctrl = tcg_global_mem_new(cpu_env,
30110 offsetof(CPUMIPSState, active_tc.DSPControl),
30111 "DSPControl");
30112 bcond = tcg_global_mem_new(cpu_env,
30113 offsetof(CPUMIPSState, bcond), "bcond");
30114 btarget = tcg_global_mem_new(cpu_env,
30115 offsetof(CPUMIPSState, btarget), "btarget");
30116 hflags = tcg_global_mem_new_i32(cpu_env,
30117 offsetof(CPUMIPSState, hflags), "hflags");
30118
30119 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
30120 offsetof(CPUMIPSState, active_fpu.fcr0),
30121 "fcr0");
30122 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
30123 offsetof(CPUMIPSState, active_fpu.fcr31),
30124 "fcr31");
30125 cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
30126 "lladdr");
30127 cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
30128 "llval");
30129
30130 #if defined(TARGET_MIPS64)
30131 cpu_mmr[0] = NULL;
30132 for (i = 1; i < 32; i++) {
30133 cpu_mmr[i] = tcg_global_mem_new_i64(cpu_env,
30134 offsetof(CPUMIPSState,
30135 active_tc.mmr[i]),
30136 regnames[i]);
30137 }
30138 #endif
30139
30140 #if !defined(TARGET_MIPS64)
30141 for (i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
30142 mxu_gpr[i] = tcg_global_mem_new(cpu_env,
30143 offsetof(CPUMIPSState,
30144 active_tc.mxu_gpr[i]),
30145 mxuregnames[i]);
30146 }
30147
30148 mxu_CR = tcg_global_mem_new(cpu_env,
30149 offsetof(CPUMIPSState, active_tc.mxu_cr),
30150 mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
30151 #endif
30152 }
30153
30154 #include "translate_init.inc.c"
30155
30156 void cpu_mips_realize_env(CPUMIPSState *env)
30157 {
30158 env->exception_base = (int32_t)0xBFC00000;
30159
30160 #ifndef CONFIG_USER_ONLY
30161 mmu_init(env, env->cpu_model);
30162 #endif
30163 fpu_init(env, env->cpu_model);
30164 mvp_init(env, env->cpu_model);
30165 }
30166
30167 bool cpu_supports_cps_smp(const char *cpu_type)
30168 {
30169 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
30170 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
30171 }
30172
30173 bool cpu_supports_isa(const char *cpu_type, uint64_t isa)
30174 {
30175 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
30176 return (mcc->cpu_def->insn_flags & isa) != 0;
30177 }
30178
30179 void cpu_set_exception_base(int vp_index, target_ulong address)
30180 {
30181 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
30182 vp->env.exception_base = address;
30183 }
30184
30185 void cpu_state_reset(CPUMIPSState *env)
30186 {
30187 CPUState *cs = env_cpu(env);
30188
30189 /* Reset registers to their default values */
30190 env->CP0_PRid = env->cpu_model->CP0_PRid;
30191 env->CP0_Config0 = env->cpu_model->CP0_Config0;
30192 #ifdef TARGET_WORDS_BIGENDIAN
30193 env->CP0_Config0 |= (1 << CP0C0_BE);
30194 #endif
30195 env->CP0_Config1 = env->cpu_model->CP0_Config1;
30196 env->CP0_Config2 = env->cpu_model->CP0_Config2;
30197 env->CP0_Config3 = env->cpu_model->CP0_Config3;
30198 env->CP0_Config4 = env->cpu_model->CP0_Config4;
30199 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
30200 env->CP0_Config5 = env->cpu_model->CP0_Config5;
30201 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
30202 env->CP0_Config6 = env->cpu_model->CP0_Config6;
30203 env->CP0_Config7 = env->cpu_model->CP0_Config7;
30204 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
30205 << env->cpu_model->CP0_LLAddr_shift;
30206 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
30207 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
30208 env->CCRes = env->cpu_model->CCRes;
30209 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
30210 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
30211 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
30212 env->current_tc = 0;
30213 env->SEGBITS = env->cpu_model->SEGBITS;
30214 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
30215 #if defined(TARGET_MIPS64)
30216 if (env->cpu_model->insn_flags & ISA_MIPS3) {
30217 env->SEGMask |= 3ULL << 62;
30218 }
30219 #endif
30220 env->PABITS = env->cpu_model->PABITS;
30221 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
30222 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
30223 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
30224 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
30225 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
30226 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
30227 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
30228 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
30229 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
30230 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
30231 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
30232 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
30233 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
30234 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
30235 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
30236 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
30237 env->msair = env->cpu_model->MSAIR;
30238 env->insn_flags = env->cpu_model->insn_flags;
30239
30240 #if defined(CONFIG_USER_ONLY)
30241 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
30242 # ifdef TARGET_MIPS64
30243 /* Enable 64-bit register mode. */
30244 env->CP0_Status |= (1 << CP0St_PX);
30245 # endif
30246 # ifdef TARGET_ABI_MIPSN64
30247 /* Enable 64-bit address mode. */
30248 env->CP0_Status |= (1 << CP0St_UX);
30249 # endif
30250 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
30251 hardware registers. */
30252 env->CP0_HWREna |= 0x0000000F;
30253 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
30254 env->CP0_Status |= (1 << CP0St_CU1);
30255 }
30256 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
30257 env->CP0_Status |= (1 << CP0St_MX);
30258 }
30259 # if defined(TARGET_MIPS64)
30260 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
30261 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
30262 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
30263 env->CP0_Status |= (1 << CP0St_FR);
30264 }
30265 # endif
30266 #else
30267 if (env->hflags & MIPS_HFLAG_BMASK) {
30268 /* If the exception was raised from a delay slot,
30269 come back to the jump. */
30270 env->CP0_ErrorEPC = (env->active_tc.PC
30271 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
30272 } else {
30273 env->CP0_ErrorEPC = env->active_tc.PC;
30274 }
30275 env->active_tc.PC = env->exception_base;
30276 env->CP0_Random = env->tlb->nb_tlb - 1;
30277 env->tlb->tlb_in_use = env->tlb->nb_tlb;
30278 env->CP0_Wired = 0;
30279 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
30280 env->CP0_EBase = (cs->cpu_index & 0x3FF);
30281 if (mips_um_ksegs_enabled()) {
30282 env->CP0_EBase |= 0x40000000;
30283 } else {
30284 env->CP0_EBase |= (int32_t)0x80000000;
30285 }
30286 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
30287 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
30288 }
30289 env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
30290 0x3ff : 0xff;
30291 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
30292 /* vectored interrupts not implemented, timer on int 7,
30293 no performance counters. */
30294 env->CP0_IntCtl = 0xe0000000;
30295 {
30296 int i;
30297
30298 for (i = 0; i < 7; i++) {
30299 env->CP0_WatchLo[i] = 0;
30300 env->CP0_WatchHi[i] = 0x80000000;
30301 }
30302 env->CP0_WatchLo[7] = 0;
30303 env->CP0_WatchHi[7] = 0;
30304 }
30305 /* Count register increments in debug mode, EJTAG version 1 */
30306 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
30307
30308 cpu_mips_store_count(env, 1);
30309
30310 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
30311 int i;
30312
30313 /* Only TC0 on VPE 0 starts as active. */
30314 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
30315 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
30316 env->tcs[i].CP0_TCHalt = 1;
30317 }
30318 env->active_tc.CP0_TCHalt = 1;
30319 cs->halted = 1;
30320
30321 if (cs->cpu_index == 0) {
30322 /* VPE0 starts up enabled. */
30323 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
30324 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
30325
30326 /* TC0 starts up unhalted. */
30327 cs->halted = 0;
30328 env->active_tc.CP0_TCHalt = 0;
30329 env->tcs[0].CP0_TCHalt = 0;
30330 /* With thread 0 active. */
30331 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
30332 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
30333 }
30334 }
30335
30336 /*
30337 * Configure default legacy segmentation control. We use this regardless of
30338 * whether segmentation control is presented to the guest.
30339 */
30340 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
30341 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
30342 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
30343 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
30344 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
30345 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
30346 (2 << CP0SC_C);
30347 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
30348 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
30349 (3 << CP0SC_C)) << 16;
30350 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
30351 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
30352 (1 << CP0SC_EU) | (2 << CP0SC_C);
30353 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
30354 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
30355 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
30356 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
30357 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
30358 #endif
30359 if ((env->insn_flags & ISA_MIPS32R6) &&
30360 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
30361 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
30362 env->CP0_Status |= (1 << CP0St_FR);
30363 }
30364
30365 if (env->insn_flags & ISA_MIPS32R6) {
30366 /* PTW = 1 */
30367 env->CP0_PWSize = 0x40;
30368 /* GDI = 12 */
30369 /* UDI = 12 */
30370 /* MDI = 12 */
30371 /* PRI = 12 */
30372 /* PTEI = 2 */
30373 env->CP0_PWField = 0x0C30C302;
30374 } else {
30375 /* GDI = 0 */
30376 /* UDI = 0 */
30377 /* MDI = 0 */
30378 /* PRI = 0 */
30379 /* PTEI = 2 */
30380 env->CP0_PWField = 0x02;
30381 }
30382
30383 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
30384 /* microMIPS on reset when Config3.ISA is 3 */
30385 env->hflags |= MIPS_HFLAG_M16;
30386 }
30387
30388 /* MSA */
30389 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
30390 msa_reset(env);
30391 }
30392
30393 compute_hflags(env);
30394 restore_fp_status(env);
30395 restore_pamask(env);
30396 cs->exception_index = EXCP_NONE;
30397
30398 if (semihosting_get_argc()) {
30399 /* UHI interface can be used to obtain argc and argv */
30400 env->active_tc.gpr[4] = -1;
30401 }
30402 }
30403
30404 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
30405 target_ulong *data)
30406 {
30407 env->active_tc.PC = data[0];
30408 env->hflags &= ~MIPS_HFLAG_BMASK;
30409 env->hflags |= data[1];
30410 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
30411 case MIPS_HFLAG_BR:
30412 break;
30413 case MIPS_HFLAG_BC:
30414 case MIPS_HFLAG_BL:
30415 case MIPS_HFLAG_B:
30416 env->btarget = data[2];
30417 break;
30418 }
30419 }