target/mips: Promote 128-bit multimedia registers as global ones
[qemu/ar7.git] / target / mips / translate.c
blob2df76592470d30bb8d5e4027e1a2ad9a8e98e50f
1 /*
2 * MIPS emulation for QEMU - main translation routines
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
8 * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
9 * Copyright (c) 2020 Philippe Mathieu-Daudé
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
25 #include "qemu/osdep.h"
26 #include "cpu.h"
27 #include "internal.h"
28 #include "tcg/tcg-op.h"
29 #include "exec/translator.h"
30 #include "exec/helper-proto.h"
31 #include "exec/helper-gen.h"
32 #include "hw/semihosting/semihost.h"
34 #include "target/mips/trace.h"
35 #include "trace-tcg.h"
36 #include "exec/translator.h"
37 #include "exec/log.h"
38 #include "qemu/qemu-print.h"
39 #include "fpu_helper.h"
40 #include "translate.h"
42 enum {
43 /* indirect opcode tables */
44 OPC_SPECIAL = (0x00 << 26),
45 OPC_REGIMM = (0x01 << 26),
46 OPC_CP0 = (0x10 << 26),
47 OPC_CP2 = (0x12 << 26),
48 OPC_CP3 = (0x13 << 26),
49 OPC_SPECIAL2 = (0x1C << 26),
50 OPC_SPECIAL3 = (0x1F << 26),
51 /* arithmetic with immediate */
52 OPC_ADDI = (0x08 << 26),
53 OPC_ADDIU = (0x09 << 26),
54 OPC_SLTI = (0x0A << 26),
55 OPC_SLTIU = (0x0B << 26),
56 /* logic with immediate */
57 OPC_ANDI = (0x0C << 26),
58 OPC_ORI = (0x0D << 26),
59 OPC_XORI = (0x0E << 26),
60 OPC_LUI = (0x0F << 26),
61 /* arithmetic with immediate */
62 OPC_DADDI = (0x18 << 26),
63 OPC_DADDIU = (0x19 << 26),
64 /* Jump and branches */
65 OPC_J = (0x02 << 26),
66 OPC_JAL = (0x03 << 26),
67 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
68 OPC_BEQL = (0x14 << 26),
69 OPC_BNE = (0x05 << 26),
70 OPC_BNEL = (0x15 << 26),
71 OPC_BLEZ = (0x06 << 26),
72 OPC_BLEZL = (0x16 << 26),
73 OPC_BGTZ = (0x07 << 26),
74 OPC_BGTZL = (0x17 << 26),
75 OPC_JALX = (0x1D << 26),
76 OPC_DAUI = (0x1D << 26),
77 /* Load and stores */
78 OPC_LDL = (0x1A << 26),
79 OPC_LDR = (0x1B << 26),
80 OPC_LB = (0x20 << 26),
81 OPC_LH = (0x21 << 26),
82 OPC_LWL = (0x22 << 26),
83 OPC_LW = (0x23 << 26),
84 OPC_LWPC = OPC_LW | 0x5,
85 OPC_LBU = (0x24 << 26),
86 OPC_LHU = (0x25 << 26),
87 OPC_LWR = (0x26 << 26),
88 OPC_LWU = (0x27 << 26),
89 OPC_SB = (0x28 << 26),
90 OPC_SH = (0x29 << 26),
91 OPC_SWL = (0x2A << 26),
92 OPC_SW = (0x2B << 26),
93 OPC_SDL = (0x2C << 26),
94 OPC_SDR = (0x2D << 26),
95 OPC_SWR = (0x2E << 26),
96 OPC_LL = (0x30 << 26),
97 OPC_LLD = (0x34 << 26),
98 OPC_LD = (0x37 << 26),
99 OPC_LDPC = OPC_LD | 0x5,
100 OPC_SC = (0x38 << 26),
101 OPC_SCD = (0x3C << 26),
102 OPC_SD = (0x3F << 26),
103 /* Floating point load/store */
104 OPC_LWC1 = (0x31 << 26),
105 OPC_LWC2 = (0x32 << 26),
106 OPC_LDC1 = (0x35 << 26),
107 OPC_LDC2 = (0x36 << 26),
108 OPC_SWC1 = (0x39 << 26),
109 OPC_SWC2 = (0x3A << 26),
110 OPC_SDC1 = (0x3D << 26),
111 OPC_SDC2 = (0x3E << 26),
112 /* Compact Branches */
113 OPC_BLEZALC = (0x06 << 26),
114 OPC_BGEZALC = (0x06 << 26),
115 OPC_BGEUC = (0x06 << 26),
116 OPC_BGTZALC = (0x07 << 26),
117 OPC_BLTZALC = (0x07 << 26),
118 OPC_BLTUC = (0x07 << 26),
119 OPC_BOVC = (0x08 << 26),
120 OPC_BEQZALC = (0x08 << 26),
121 OPC_BEQC = (0x08 << 26),
122 OPC_BLEZC = (0x16 << 26),
123 OPC_BGEZC = (0x16 << 26),
124 OPC_BGEC = (0x16 << 26),
125 OPC_BGTZC = (0x17 << 26),
126 OPC_BLTZC = (0x17 << 26),
127 OPC_BLTC = (0x17 << 26),
128 OPC_BNVC = (0x18 << 26),
129 OPC_BNEZALC = (0x18 << 26),
130 OPC_BNEC = (0x18 << 26),
131 OPC_BC = (0x32 << 26),
132 OPC_BEQZC = (0x36 << 26),
133 OPC_JIC = (0x36 << 26),
134 OPC_BALC = (0x3A << 26),
135 OPC_BNEZC = (0x3E << 26),
136 OPC_JIALC = (0x3E << 26),
137 /* MDMX ASE specific */
138 OPC_MDMX = (0x1E << 26),
139 /* Cache and prefetch */
140 OPC_CACHE = (0x2F << 26),
141 OPC_PREF = (0x33 << 26),
142 /* PC-relative address computation / loads */
143 OPC_PCREL = (0x3B << 26),
146 /* PC-relative address computation / loads */
147 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
148 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
149 enum {
150 /* Instructions determined by bits 19 and 20 */
151 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
152 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
153 OPC_LWUPC = OPC_PCREL | (2 << 19),
155 /* Instructions determined by bits 16 ... 20 */
156 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
157 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
159 /* Other */
160 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
163 /* MIPS special opcodes */
164 #define MASK_SPECIAL(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
166 enum {
167 /* Shifts */
168 OPC_SLL = 0x00 | OPC_SPECIAL,
169 /* NOP is SLL r0, r0, 0 */
170 /* SSNOP is SLL r0, r0, 1 */
171 /* EHB is SLL r0, r0, 3 */
172 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
173 OPC_ROTR = OPC_SRL | (1 << 21),
174 OPC_SRA = 0x03 | OPC_SPECIAL,
175 OPC_SLLV = 0x04 | OPC_SPECIAL,
176 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
177 OPC_ROTRV = OPC_SRLV | (1 << 6),
178 OPC_SRAV = 0x07 | OPC_SPECIAL,
179 OPC_DSLLV = 0x14 | OPC_SPECIAL,
180 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
181 OPC_DROTRV = OPC_DSRLV | (1 << 6),
182 OPC_DSRAV = 0x17 | OPC_SPECIAL,
183 OPC_DSLL = 0x38 | OPC_SPECIAL,
184 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
185 OPC_DROTR = OPC_DSRL | (1 << 21),
186 OPC_DSRA = 0x3B | OPC_SPECIAL,
187 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
188 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
189 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
190 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
191 /* Multiplication / division */
192 OPC_MULT = 0x18 | OPC_SPECIAL,
193 OPC_MULTU = 0x19 | OPC_SPECIAL,
194 OPC_DIV = 0x1A | OPC_SPECIAL,
195 OPC_DIVU = 0x1B | OPC_SPECIAL,
196 OPC_DMULT = 0x1C | OPC_SPECIAL,
197 OPC_DMULTU = 0x1D | OPC_SPECIAL,
198 OPC_DDIV = 0x1E | OPC_SPECIAL,
199 OPC_DDIVU = 0x1F | OPC_SPECIAL,
201 /* 2 registers arithmetic / logic */
202 OPC_ADD = 0x20 | OPC_SPECIAL,
203 OPC_ADDU = 0x21 | OPC_SPECIAL,
204 OPC_SUB = 0x22 | OPC_SPECIAL,
205 OPC_SUBU = 0x23 | OPC_SPECIAL,
206 OPC_AND = 0x24 | OPC_SPECIAL,
207 OPC_OR = 0x25 | OPC_SPECIAL,
208 OPC_XOR = 0x26 | OPC_SPECIAL,
209 OPC_NOR = 0x27 | OPC_SPECIAL,
210 OPC_SLT = 0x2A | OPC_SPECIAL,
211 OPC_SLTU = 0x2B | OPC_SPECIAL,
212 OPC_DADD = 0x2C | OPC_SPECIAL,
213 OPC_DADDU = 0x2D | OPC_SPECIAL,
214 OPC_DSUB = 0x2E | OPC_SPECIAL,
215 OPC_DSUBU = 0x2F | OPC_SPECIAL,
216 /* Jumps */
217 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
218 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
219 /* Traps */
220 OPC_TGE = 0x30 | OPC_SPECIAL,
221 OPC_TGEU = 0x31 | OPC_SPECIAL,
222 OPC_TLT = 0x32 | OPC_SPECIAL,
223 OPC_TLTU = 0x33 | OPC_SPECIAL,
224 OPC_TEQ = 0x34 | OPC_SPECIAL,
225 OPC_TNE = 0x36 | OPC_SPECIAL,
226 /* HI / LO registers load & stores */
227 OPC_MFHI = 0x10 | OPC_SPECIAL,
228 OPC_MTHI = 0x11 | OPC_SPECIAL,
229 OPC_MFLO = 0x12 | OPC_SPECIAL,
230 OPC_MTLO = 0x13 | OPC_SPECIAL,
231 /* Conditional moves */
232 OPC_MOVZ = 0x0A | OPC_SPECIAL,
233 OPC_MOVN = 0x0B | OPC_SPECIAL,
235 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
236 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
238 OPC_MOVCI = 0x01 | OPC_SPECIAL,
240 /* Special */
241 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
242 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
243 OPC_BREAK = 0x0D | OPC_SPECIAL,
244 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
245 OPC_SYNC = 0x0F | OPC_SPECIAL,
247 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
248 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
249 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
250 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
254 * R6 Multiply and Divide instructions have the same opcode
255 * and function field as legacy OPC_MULT[U]/OPC_DIV[U]
257 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
259 enum {
260 R6_OPC_MUL = OPC_MULT | (2 << 6),
261 R6_OPC_MUH = OPC_MULT | (3 << 6),
262 R6_OPC_MULU = OPC_MULTU | (2 << 6),
263 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
264 R6_OPC_DIV = OPC_DIV | (2 << 6),
265 R6_OPC_MOD = OPC_DIV | (3 << 6),
266 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
267 R6_OPC_MODU = OPC_DIVU | (3 << 6),
269 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
270 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
271 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
272 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
273 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
274 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
275 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
276 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
278 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
279 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
280 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
281 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
282 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
285 /* Multiplication variants of the vr54xx. */
286 #define MASK_MUL_VR54XX(op) (MASK_SPECIAL(op) | (op & (0x1F << 6)))
288 enum {
289 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
290 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
291 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
292 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
293 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
294 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
295 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
296 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
297 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
298 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
299 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
300 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
301 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
302 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
305 /* REGIMM (rt field) opcodes */
306 #define MASK_REGIMM(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 16)))
308 enum {
309 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
310 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
311 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
312 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
313 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
314 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
315 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
316 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
317 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
318 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
319 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
320 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
321 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
322 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
323 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
324 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
326 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
327 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
330 /* Special2 opcodes */
331 #define MASK_SPECIAL2(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
333 enum {
334 /* Multiply & xxx operations */
335 OPC_MADD = 0x00 | OPC_SPECIAL2,
336 OPC_MADDU = 0x01 | OPC_SPECIAL2,
337 OPC_MUL = 0x02 | OPC_SPECIAL2,
338 OPC_MSUB = 0x04 | OPC_SPECIAL2,
339 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
340 /* Loongson 2F */
341 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
342 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
343 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
344 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
345 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
346 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
347 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
348 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
349 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
350 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
351 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
352 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
353 /* Misc */
354 OPC_CLZ = 0x20 | OPC_SPECIAL2,
355 OPC_CLO = 0x21 | OPC_SPECIAL2,
356 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
357 OPC_DCLO = 0x25 | OPC_SPECIAL2,
358 /* Special */
359 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
362 /* Special3 opcodes */
363 #define MASK_SPECIAL3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
365 enum {
366 OPC_EXT = 0x00 | OPC_SPECIAL3,
367 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
368 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
369 OPC_DEXT = 0x03 | OPC_SPECIAL3,
370 OPC_INS = 0x04 | OPC_SPECIAL3,
371 OPC_DINSM = 0x05 | OPC_SPECIAL3,
372 OPC_DINSU = 0x06 | OPC_SPECIAL3,
373 OPC_DINS = 0x07 | OPC_SPECIAL3,
374 OPC_FORK = 0x08 | OPC_SPECIAL3,
375 OPC_YIELD = 0x09 | OPC_SPECIAL3,
376 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
377 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
378 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
379 OPC_GINV = 0x3D | OPC_SPECIAL3,
381 /* Loongson 2E */
382 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
383 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
384 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
385 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
386 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
387 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
388 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
389 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
390 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
391 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
392 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
393 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
395 /* MIPS DSP Load */
396 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
397 /* MIPS DSP Arithmetic */
398 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
399 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
400 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
401 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
402 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
403 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
404 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
405 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
406 /* MIPS DSP GPR-Based Shift Sub-class */
407 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
408 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
409 /* MIPS DSP Multiply Sub-class insns */
410 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
411 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
412 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
413 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
414 /* DSP Bit/Manipulation Sub-class */
415 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
416 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
417 /* MIPS DSP Append Sub-class */
418 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
419 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
420 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
421 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
422 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
424 /* EVA */
425 OPC_LWLE = 0x19 | OPC_SPECIAL3,
426 OPC_LWRE = 0x1A | OPC_SPECIAL3,
427 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
428 OPC_SBE = 0x1C | OPC_SPECIAL3,
429 OPC_SHE = 0x1D | OPC_SPECIAL3,
430 OPC_SCE = 0x1E | OPC_SPECIAL3,
431 OPC_SWE = 0x1F | OPC_SPECIAL3,
432 OPC_SWLE = 0x21 | OPC_SPECIAL3,
433 OPC_SWRE = 0x22 | OPC_SPECIAL3,
434 OPC_PREFE = 0x23 | OPC_SPECIAL3,
435 OPC_LBUE = 0x28 | OPC_SPECIAL3,
436 OPC_LHUE = 0x29 | OPC_SPECIAL3,
437 OPC_LBE = 0x2C | OPC_SPECIAL3,
438 OPC_LHE = 0x2D | OPC_SPECIAL3,
439 OPC_LLE = 0x2E | OPC_SPECIAL3,
440 OPC_LWE = 0x2F | OPC_SPECIAL3,
442 /* R6 */
443 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
444 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
445 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
446 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
447 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
448 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
451 /* Loongson EXT load/store quad word opcodes */
452 #define MASK_LOONGSON_GSLSQ(op) (MASK_OP_MAJOR(op) | (op & 0x8020))
453 enum {
454 OPC_GSLQ = 0x0020 | OPC_LWC2,
455 OPC_GSLQC1 = 0x8020 | OPC_LWC2,
456 OPC_GSSHFL = OPC_LWC2,
457 OPC_GSSQ = 0x0020 | OPC_SWC2,
458 OPC_GSSQC1 = 0x8020 | OPC_SWC2,
459 OPC_GSSHFS = OPC_SWC2,
462 /* Loongson EXT shifted load/store opcodes */
463 #define MASK_LOONGSON_GSSHFLS(op) (MASK_OP_MAJOR(op) | (op & 0xc03f))
464 enum {
465 OPC_GSLWLC1 = 0x4 | OPC_GSSHFL,
466 OPC_GSLWRC1 = 0x5 | OPC_GSSHFL,
467 OPC_GSLDLC1 = 0x6 | OPC_GSSHFL,
468 OPC_GSLDRC1 = 0x7 | OPC_GSSHFL,
469 OPC_GSSWLC1 = 0x4 | OPC_GSSHFS,
470 OPC_GSSWRC1 = 0x5 | OPC_GSSHFS,
471 OPC_GSSDLC1 = 0x6 | OPC_GSSHFS,
472 OPC_GSSDRC1 = 0x7 | OPC_GSSHFS,
475 /* Loongson EXT LDC2/SDC2 opcodes */
476 #define MASK_LOONGSON_LSDC2(op) (MASK_OP_MAJOR(op) | (op & 0x7))
478 enum {
479 OPC_GSLBX = 0x0 | OPC_LDC2,
480 OPC_GSLHX = 0x1 | OPC_LDC2,
481 OPC_GSLWX = 0x2 | OPC_LDC2,
482 OPC_GSLDX = 0x3 | OPC_LDC2,
483 OPC_GSLWXC1 = 0x6 | OPC_LDC2,
484 OPC_GSLDXC1 = 0x7 | OPC_LDC2,
485 OPC_GSSBX = 0x0 | OPC_SDC2,
486 OPC_GSSHX = 0x1 | OPC_SDC2,
487 OPC_GSSWX = 0x2 | OPC_SDC2,
488 OPC_GSSDX = 0x3 | OPC_SDC2,
489 OPC_GSSWXC1 = 0x6 | OPC_SDC2,
490 OPC_GSSDXC1 = 0x7 | OPC_SDC2,
493 /* BSHFL opcodes */
494 #define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
496 enum {
497 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
498 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
499 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
500 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
501 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
502 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
503 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
504 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
507 /* DBSHFL opcodes */
508 #define MASK_DBSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
510 enum {
511 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
512 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
513 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
514 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
515 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
516 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
517 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
518 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
519 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
520 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
521 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
524 /* MIPS DSP REGIMM opcodes */
525 enum {
526 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
527 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
530 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
531 /* MIPS DSP Load */
532 enum {
533 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
534 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
535 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
536 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
539 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
540 enum {
541 /* MIPS DSP Arithmetic Sub-class */
542 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
543 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
544 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
545 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
546 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
547 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
548 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
549 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
550 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
551 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
552 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
553 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
554 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
555 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
556 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
557 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
558 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
559 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
560 /* MIPS DSP Multiply Sub-class insns */
561 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
562 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
563 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
564 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
565 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
566 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
569 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
570 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
571 enum {
572 /* MIPS DSP Arithmetic Sub-class */
573 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
574 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
575 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
576 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
577 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
578 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
579 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
580 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
581 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
582 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
583 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
584 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
585 /* MIPS DSP Multiply Sub-class insns */
586 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
587 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
588 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
589 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
592 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
593 enum {
594 /* MIPS DSP Arithmetic Sub-class */
595 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
596 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
597 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
598 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
599 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
600 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
601 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
602 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
603 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
604 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
605 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
606 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
607 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
608 /* DSP Bit/Manipulation Sub-class */
609 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
610 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
611 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
612 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
613 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
616 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
617 enum {
618 /* MIPS DSP Arithmetic Sub-class */
619 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
620 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
621 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
622 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
623 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
624 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
625 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
626 /* DSP Compare-Pick Sub-class */
627 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
628 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
629 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
630 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
631 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
632 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
633 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
634 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
635 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
636 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
637 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
638 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
639 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
640 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
641 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
644 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
645 enum {
646 /* MIPS DSP GPR-Based Shift Sub-class */
647 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
648 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
649 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
650 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
651 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
652 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
653 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
654 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
655 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
656 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
657 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
658 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
659 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
660 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
661 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
662 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
663 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
664 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
665 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
666 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
667 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
668 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
671 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
672 enum {
673 /* MIPS DSP Multiply Sub-class insns */
674 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
675 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
676 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
677 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
678 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
679 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
680 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
681 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
682 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
683 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
684 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
685 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
686 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
687 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
688 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
689 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
690 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
691 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
692 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
693 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
694 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
695 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
698 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
699 enum {
700 /* DSP Bit/Manipulation Sub-class */
701 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
704 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
705 enum {
706 /* MIPS DSP Append Sub-class */
707 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
708 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
709 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
712 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
713 enum {
714 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
715 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
716 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
717 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
718 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
719 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
720 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
721 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
722 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
723 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
724 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
725 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
726 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
727 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
728 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
729 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
730 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
731 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
734 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
735 enum {
736 /* MIPS DSP Arithmetic Sub-class */
737 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
738 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
739 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
740 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
741 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
742 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
743 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
744 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
745 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
746 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
747 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
748 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
749 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
750 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
751 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
752 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
753 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
754 /* DSP Bit/Manipulation Sub-class */
755 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
756 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
757 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
758 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
759 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
760 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
763 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
764 enum {
765 /* MIPS DSP Multiply Sub-class insns */
766 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
767 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
768 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
769 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
770 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
771 /* MIPS DSP Arithmetic Sub-class */
772 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
773 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
774 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
775 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
776 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
777 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
778 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
779 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
780 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
781 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
782 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
783 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
784 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
785 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
786 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
787 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
788 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
789 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
790 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
791 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
792 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
795 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
796 enum {
797 /* DSP Compare-Pick Sub-class */
798 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
799 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
800 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
801 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
802 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
803 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
804 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
805 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
806 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
807 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
808 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
809 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
810 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
811 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
812 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
813 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
814 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
815 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
816 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
817 /* MIPS DSP Arithmetic Sub-class */
818 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
819 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
820 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
821 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
822 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
823 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
824 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
825 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
828 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
829 enum {
830 /* DSP Append Sub-class */
831 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
832 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
833 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
834 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
837 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
838 enum {
839 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
840 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
841 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
842 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
843 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
844 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
845 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
846 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
847 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
848 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
849 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
850 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
851 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
852 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
853 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
854 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
855 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
856 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
857 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
858 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
859 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
860 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
863 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
864 enum {
865 /* DSP Bit/Manipulation Sub-class */
866 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
869 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
870 enum {
871 /* MIPS DSP Multiply Sub-class insns */
872 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
873 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
874 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
875 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
876 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
877 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
878 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
879 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
880 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
881 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
882 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
883 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
884 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
885 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
886 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
887 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
888 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
889 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
890 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
891 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
892 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
893 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
894 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
895 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
896 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
897 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
900 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
901 enum {
902 /* MIPS DSP GPR-Based Shift Sub-class */
903 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
904 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
905 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
906 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
907 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
908 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
909 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
910 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
911 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
912 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
913 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
914 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
915 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
916 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
917 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
918 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
919 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
920 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
921 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
922 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
923 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
924 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
925 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
926 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
927 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
928 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
931 /* Coprocessor 0 (rs field) */
932 #define MASK_CP0(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
934 enum {
935 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
936 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
937 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
938 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
939 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
940 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
941 OPC_MFTR = (0x08 << 21) | OPC_CP0,
942 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
943 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
944 OPC_MTTR = (0x0C << 21) | OPC_CP0,
945 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
946 OPC_C0 = (0x10 << 21) | OPC_CP0,
947 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
948 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
949 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
950 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
951 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
952 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
953 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
954 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
955 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
956 OPC_C0_A = (0x1A << 21) | OPC_CP0,
957 OPC_C0_B = (0x1B << 21) | OPC_CP0,
958 OPC_C0_C = (0x1C << 21) | OPC_CP0,
959 OPC_C0_D = (0x1D << 21) | OPC_CP0,
960 OPC_C0_E = (0x1E << 21) | OPC_CP0,
961 OPC_C0_F = (0x1F << 21) | OPC_CP0,
964 /* MFMC0 opcodes */
965 #define MASK_MFMC0(op) (MASK_CP0(op) | (op & 0xFFFF))
967 enum {
968 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
969 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
970 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
971 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
972 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
973 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
974 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
975 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
978 /* Coprocessor 0 (with rs == C0) */
979 #define MASK_C0(op) (MASK_CP0(op) | (op & 0x3F))
981 enum {
982 OPC_TLBR = 0x01 | OPC_C0,
983 OPC_TLBWI = 0x02 | OPC_C0,
984 OPC_TLBINV = 0x03 | OPC_C0,
985 OPC_TLBINVF = 0x04 | OPC_C0,
986 OPC_TLBWR = 0x06 | OPC_C0,
987 OPC_TLBP = 0x08 | OPC_C0,
988 OPC_RFE = 0x10 | OPC_C0,
989 OPC_ERET = 0x18 | OPC_C0,
990 OPC_DERET = 0x1F | OPC_C0,
991 OPC_WAIT = 0x20 | OPC_C0,
994 #define MASK_CP2(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
996 enum {
997 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
998 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
999 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1000 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1001 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1002 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1003 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1004 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1005 OPC_BC2 = (0x08 << 21) | OPC_CP2,
1006 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1007 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1010 #define MASK_LMMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1012 enum {
1013 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1014 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1015 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1016 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1017 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1018 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1019 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1020 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1022 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1023 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1024 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1025 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1026 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1027 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1028 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1029 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1031 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1032 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1033 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1034 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1035 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1036 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1037 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1038 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1040 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1041 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1042 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1043 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1044 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1045 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1046 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1047 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1049 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1050 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1051 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1052 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1053 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1054 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1056 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1057 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1058 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1059 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1060 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1061 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1063 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1064 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1065 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1066 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1067 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1068 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1070 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1071 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1072 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1073 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1074 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1075 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1077 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1078 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1079 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1080 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1081 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1082 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1084 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1085 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1086 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1087 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1088 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1089 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1091 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1092 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1093 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1094 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1095 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1096 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1098 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1099 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1100 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1101 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1102 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1103 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1107 #define MASK_CP3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1109 enum {
1110 OPC_LWXC1 = 0x00 | OPC_CP3,
1111 OPC_LDXC1 = 0x01 | OPC_CP3,
1112 OPC_LUXC1 = 0x05 | OPC_CP3,
1113 OPC_SWXC1 = 0x08 | OPC_CP3,
1114 OPC_SDXC1 = 0x09 | OPC_CP3,
1115 OPC_SUXC1 = 0x0D | OPC_CP3,
1116 OPC_PREFX = 0x0F | OPC_CP3,
1117 OPC_ALNV_PS = 0x1E | OPC_CP3,
1118 OPC_MADD_S = 0x20 | OPC_CP3,
1119 OPC_MADD_D = 0x21 | OPC_CP3,
1120 OPC_MADD_PS = 0x26 | OPC_CP3,
1121 OPC_MSUB_S = 0x28 | OPC_CP3,
1122 OPC_MSUB_D = 0x29 | OPC_CP3,
1123 OPC_MSUB_PS = 0x2E | OPC_CP3,
1124 OPC_NMADD_S = 0x30 | OPC_CP3,
1125 OPC_NMADD_D = 0x31 | OPC_CP3,
1126 OPC_NMADD_PS = 0x36 | OPC_CP3,
1127 OPC_NMSUB_S = 0x38 | OPC_CP3,
1128 OPC_NMSUB_D = 0x39 | OPC_CP3,
1129 OPC_NMSUB_PS = 0x3E | OPC_CP3,
1134 * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
1135 * ============================================
1138 * MXU (full name: MIPS eXtension/enhanced Unit) is a SIMD extension of MIPS32
1139 * instructions set. It is designed to fit the needs of signal, graphical and
1140 * video processing applications. MXU instruction set is used in Xburst family
1141 * of microprocessors by Ingenic.
1143 * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
1144 * the control register.
1147 * The notation used in MXU assembler mnemonics
1148 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1150 * Register operands:
1152 * XRa, XRb, XRc, XRd - MXU registers
1153 * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
1155 * Non-register operands:
1157 * aptn1 - 1-bit accumulate add/subtract pattern
1158 * aptn2 - 2-bit accumulate add/subtract pattern
1159 * eptn2 - 2-bit execute add/subtract pattern
1160 * optn2 - 2-bit operand pattern
1161 * optn3 - 3-bit operand pattern
1162 * sft4 - 4-bit shift amount
1163 * strd2 - 2-bit stride amount
1165 * Prefixes:
1167 * Level of parallelism: Operand size:
1168 * S - single operation at a time 32 - word
1169 * D - two operations in parallel 16 - half word
1170 * Q - four operations in parallel 8 - byte
1172 * Operations:
1174 * ADD - Add or subtract
1175 * ADDC - Add with carry-in
1176 * ACC - Accumulate
1177 * ASUM - Sum together then accumulate (add or subtract)
1178 * ASUMC - Sum together then accumulate (add or subtract) with carry-in
1179 * AVG - Average between 2 operands
1180 * ABD - Absolute difference
1181 * ALN - Align data
1182 * AND - Logical bitwise 'and' operation
1183 * CPS - Copy sign
1184 * EXTR - Extract bits
1185 * I2M - Move from GPR register to MXU register
1186 * LDD - Load data from memory to XRF
1187 * LDI - Load data from memory to XRF (and increase the address base)
1188 * LUI - Load unsigned immediate
1189 * MUL - Multiply
1190 * MULU - Unsigned multiply
1191 * MADD - 64-bit operand add 32x32 product
1192 * MSUB - 64-bit operand subtract 32x32 product
1193 * MAC - Multiply and accumulate (add or subtract)
1194 * MAD - Multiply and add or subtract
1195 * MAX - Maximum between 2 operands
1196 * MIN - Minimum between 2 operands
1197 * M2I - Move from MXU register to GPR register
1198 * MOVZ - Move if zero
1199 * MOVN - Move if non-zero
1200 * NOR - Logical bitwise 'nor' operation
1201 * OR - Logical bitwise 'or' operation
1202 * STD - Store data from XRF to memory
1203 * SDI - Store data from XRF to memory (and increase the address base)
1204 * SLT - Set of less than comparison
1205 * SAD - Sum of absolute differences
1206 * SLL - Logical shift left
1207 * SLR - Logical shift right
1208 * SAR - Arithmetic shift right
1209 * SAT - Saturation
1210 * SFL - Shuffle
1211 * SCOP - Calculate x’s scope (-1, means x<0; 0, means x==0; 1, means x>0)
1212 * XOR - Logical bitwise 'exclusive or' operation
1214 * Suffixes:
1216 * E - Expand results
1217 * F - Fixed point multiplication
1218 * L - Low part result
1219 * R - Doing rounding
1220 * V - Variable instead of immediate
1221 * W - Combine above L and V
1224 * The list of MXU instructions grouped by functionality
1225 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1227 * Load/Store instructions Multiplication instructions
1228 * ----------------------- ---------------------------
1230 * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
1231 * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
1232 * S32LDDV XRa, Rb, rc, strd2 S32MSUB XRa, XRd, Rs, Rt
1233 * S32STDV XRa, Rb, rc, strd2 S32MSUBU XRa, XRd, Rs, Rt
1234 * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
1235 * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
1236 * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
1237 * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
1238 * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
1239 * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
1240 * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
1241 * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
1242 * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
1243 * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
1244 * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
1245 * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
1246 * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
1247 * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
1248 * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
1249 * S16SDI XRa, Rb, s10, eptn2
1250 * S8LDD XRa, Rb, s8, eptn3
1251 * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
1252 * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
1253 * S8SDI XRa, Rb, s8, eptn3
1254 * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
1255 * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
1256 * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
1257 * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
1258 * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
1259 * S32CPS XRa, XRb, XRc
1260 * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
1261 * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
1262 * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
1263 * D16ASUM XRa, XRb, XRc, XRd, eptn2
1264 * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
1265 * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
1266 * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
1267 * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
1268 * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
1269 * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
1270 * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
1271 * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
1272 * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
1273 * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
1274 * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
1275 * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
1276 * Q8SLT XRa, XRb, XRc
1277 * Q8SLTU XRa, XRb, XRc
1278 * Q8MOVZ XRa, XRb, XRc Shift instructions
1279 * Q8MOVN XRa, XRb, XRc ------------------
1281 * D32SLL XRa, XRb, XRc, XRd, sft4
1282 * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
1283 * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
1284 * D32SARL XRa, XRb, XRc, sft4
1285 * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
1286 * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
1287 * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
1288 * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
1289 * Q16SLL XRa, XRb, XRc, XRd, sft4
1290 * Q16SLR XRa, XRb, XRc, XRd, sft4
1291 * Miscellaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
1292 * ------------------------- Q16SLLV XRa, XRb, Rb
1293 * Q16SLRV XRa, XRb, Rb
1294 * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
1295 * S32ALN XRa, XRb, XRc, Rb
1296 * S32ALNI XRa, XRb, XRc, s3
1297 * S32LUI XRa, s8, optn3 Move instructions
1298 * S32EXTR XRa, XRb, Rb, bits5 -----------------
1299 * S32EXTRV XRa, XRb, Rs, Rt
1300 * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
1301 * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
1304 * The opcode organization of MXU instructions
1305 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1307 * The bits 31..26 of all MXU instructions are equal to 0x1C (also referred
1308 * as opcode SPECIAL2 in the base MIPS ISA). The organization and meaning of
1309 * other bits up to the instruction level is as follows:
1311 * bits
1312 * 05..00
1314 * ┌─ 000000 ─ OPC_MXU_S32MADD
1315 * ├─ 000001 ─ OPC_MXU_S32MADDU
1316 * ├─ 000010 ─ <not assigned> (non-MXU OPC_MUL)
1317 * │
1318 * │ 20..18
1319 * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
1320 * │ ├─ 001 ─ OPC_MXU_S32MIN
1321 * │ ├─ 010 ─ OPC_MXU_D16MAX
1322 * │ ├─ 011 ─ OPC_MXU_D16MIN
1323 * │ ├─ 100 ─ OPC_MXU_Q8MAX
1324 * │ ├─ 101 ─ OPC_MXU_Q8MIN
1325 * │ ├─ 110 ─ OPC_MXU_Q8SLT
1326 * │ └─ 111 ─ OPC_MXU_Q8SLTU
1327 * ├─ 000100 ─ OPC_MXU_S32MSUB
1328 * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
1329 * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
1330 * │ ├─ 001 ─ OPC_MXU_D16SLT
1331 * │ ├─ 010 ─ OPC_MXU_D16AVG
1332 * │ ├─ 011 ─ OPC_MXU_D16AVGR
1333 * │ ├─ 100 ─ OPC_MXU_Q8AVG
1334 * │ ├─ 101 ─ OPC_MXU_Q8AVGR
1335 * │ └─ 111 ─ OPC_MXU_Q8ADD
1336 * │
1337 * │ 20..18
1338 * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
1339 * │ ├─ 010 ─ OPC_MXU_D16CPS
1340 * │ ├─ 100 ─ OPC_MXU_Q8ABD
1341 * │ └─ 110 ─ OPC_MXU_Q16SAT
1342 * ├─ 001000 ─ OPC_MXU_D16MUL
1343 * │ 25..24
1344 * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
1345 * │ └─ 01 ─ OPC_MXU_D16MULE
1346 * ├─ 001010 ─ OPC_MXU_D16MAC
1347 * ├─ 001011 ─ OPC_MXU_D16MACF
1348 * ├─ 001100 ─ OPC_MXU_D16MADL
1349 * ├─ 001101 ─ OPC_MXU_S16MAD
1350 * ├─ 001110 ─ OPC_MXU_Q16ADD
1351 * ├─ 001111 ─ OPC_MXU_D16MACE 23
1352 * │ ┌─ 0 ─ OPC_MXU_S32LDD
1353 * ├─ 010000 ─ OPC_MXU__POOL04 ─┴─ 1 ─ OPC_MXU_S32LDDR
1354 * │
1355 * │ 23
1356 * ├─ 010001 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32STD
1357 * │ └─ 1 ─ OPC_MXU_S32STDR
1358 * │
1359 * │ 13..10
1360 * ├─ 010010 ─ OPC_MXU__POOL06 ─┬─ 0000 ─ OPC_MXU_S32LDDV
1361 * │ └─ 0001 ─ OPC_MXU_S32LDDVR
1362 * │
1363 * │ 13..10
1364 * ├─ 010011 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32STDV
1365 * │ └─ 0001 ─ OPC_MXU_S32STDVR
1366 * │
1367 * │ 23
1368 * ├─ 010100 ─ OPC_MXU__POOL08 ─┬─ 0 ─ OPC_MXU_S32LDI
1369 * │ └─ 1 ─ OPC_MXU_S32LDIR
1370 * │
1371 * │ 23
1372 * ├─ 010101 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32SDI
1373 * │ └─ 1 ─ OPC_MXU_S32SDIR
1374 * │
1375 * │ 13..10
1376 * ├─ 010110 ─ OPC_MXU__POOL10 ─┬─ 0000 ─ OPC_MXU_S32LDIV
1377 * │ └─ 0001 ─ OPC_MXU_S32LDIVR
1378 * │
1379 * │ 13..10
1380 * ├─ 010111 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32SDIV
1381 * │ └─ 0001 ─ OPC_MXU_S32SDIVR
1382 * ├─ 011000 ─ OPC_MXU_D32ADD
1383 * │ 23..22
1384 * MXU ├─ 011001 ─ OPC_MXU__POOL12 ─┬─ 00 ─ OPC_MXU_D32ACC
1385 * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
1386 * │ └─ 10 ─ OPC_MXU_D32ASUM
1387 * ├─ 011010 ─ <not assigned>
1388 * │ 23..22
1389 * ├─ 011011 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_Q16ACC
1390 * │ ├─ 01 ─ OPC_MXU_Q16ACCM
1391 * │ └─ 10 ─ OPC_MXU_Q16ASUM
1392 * │
1393 * │ 23..22
1394 * ├─ 011100 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q8ADDE
1395 * │ ├─ 01 ─ OPC_MXU_D8SUM
1396 * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
1397 * ├─ 011110 ─ <not assigned>
1398 * ├─ 011111 ─ <not assigned>
1399 * ├─ 100000 ─ <not assigned> (overlaps with CLZ)
1400 * ├─ 100001 ─ <not assigned> (overlaps with CLO)
1401 * ├─ 100010 ─ OPC_MXU_S8LDD
1402 * ├─ 100011 ─ OPC_MXU_S8STD 15..14
1403 * ├─ 100100 ─ OPC_MXU_S8LDI ┌─ 00 ─ OPC_MXU_S32MUL
1404 * ├─ 100101 ─ OPC_MXU_S8SDI ├─ 00 ─ OPC_MXU_S32MULU
1405 * │ ├─ 00 ─ OPC_MXU_S32EXTR
1406 * ├─ 100110 ─ OPC_MXU__POOL15 ─┴─ 00 ─ OPC_MXU_S32EXTRV
1407 * │
1408 * │ 20..18
1409 * ├─ 100111 ─ OPC_MXU__POOL16 ─┬─ 000 ─ OPC_MXU_D32SARW
1410 * │ ├─ 001 ─ OPC_MXU_S32ALN
1411 * │ ├─ 010 ─ OPC_MXU_S32ALNI
1412 * │ ├─ 011 ─ OPC_MXU_S32LUI
1413 * │ ├─ 100 ─ OPC_MXU_S32NOR
1414 * │ ├─ 101 ─ OPC_MXU_S32AND
1415 * │ ├─ 110 ─ OPC_MXU_S32OR
1416 * │ └─ 111 ─ OPC_MXU_S32XOR
1417 * │
1418 * │ 7..5
1419 * ├─ 101000 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_LXB
1420 * │ ├─ 001 ─ OPC_MXU_LXH
1421 * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_LXW
1422 * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_LXBU
1423 * ├─ 101011 ─ OPC_MXU_S16STD └─ 101 ─ OPC_MXU_LXHU
1424 * ├─ 101100 ─ OPC_MXU_S16LDI
1425 * ├─ 101101 ─ OPC_MXU_S16SDI
1426 * ├─ 101110 ─ OPC_MXU_S32M2I
1427 * ├─ 101111 ─ OPC_MXU_S32I2M
1428 * ├─ 110000 ─ OPC_MXU_D32SLL
1429 * ├─ 110001 ─ OPC_MXU_D32SLR 20..18
1430 * ├─ 110010 ─ OPC_MXU_D32SARL ┌─ 000 ─ OPC_MXU_D32SLLV
1431 * ├─ 110011 ─ OPC_MXU_D32SAR ├─ 001 ─ OPC_MXU_D32SLRV
1432 * ├─ 110100 ─ OPC_MXU_Q16SLL ├─ 010 ─ OPC_MXU_D32SARV
1433 * ├─ 110101 ─ OPC_MXU_Q16SLR ├─ 011 ─ OPC_MXU_Q16SLLV
1434 * │ ├─ 100 ─ OPC_MXU_Q16SLRV
1435 * ├─ 110110 ─ OPC_MXU__POOL18 ─┴─ 101 ─ OPC_MXU_Q16SARV
1436 * │
1437 * ├─ 110111 ─ OPC_MXU_Q16SAR
1438 * │ 23..22
1439 * ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL
1440 * │ └─ 01 ─ OPC_MXU_Q8MULSU
1441 * │
1442 * │ 20..18
1443 * ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
1444 * │ ├─ 001 ─ OPC_MXU_Q8MOVN
1445 * │ ├─ 010 ─ OPC_MXU_D16MOVZ
1446 * │ ├─ 011 ─ OPC_MXU_D16MOVN
1447 * │ ├─ 100 ─ OPC_MXU_S32MOVZ
1448 * │ └─ 101 ─ OPC_MXU_S32MOVN
1449 * │
1450 * │ 23..22
1451 * ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC
1452 * │ └─ 10 ─ OPC_MXU_Q8MACSU
1453 * ├─ 111011 ─ OPC_MXU_Q16SCOP
1454 * ├─ 111100 ─ OPC_MXU_Q8MADL
1455 * ├─ 111101 ─ OPC_MXU_S32SFL
1456 * ├─ 111110 ─ OPC_MXU_Q8SAD
1457 * └─ 111111 ─ <not assigned> (overlaps with SDBBP)
1460 * Compiled after:
1462 * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
1463 * Programming Manual", Ingenic Semiconductor Co, Ltd., revision June 2, 2017
1466 enum {
1467 OPC_MXU_S32MADD = 0x00,
1468 OPC_MXU_S32MADDU = 0x01,
1469 OPC__MXU_MUL = 0x02,
1470 OPC_MXU__POOL00 = 0x03,
1471 OPC_MXU_S32MSUB = 0x04,
1472 OPC_MXU_S32MSUBU = 0x05,
1473 OPC_MXU__POOL01 = 0x06,
1474 OPC_MXU__POOL02 = 0x07,
1475 OPC_MXU_D16MUL = 0x08,
1476 OPC_MXU__POOL03 = 0x09,
1477 OPC_MXU_D16MAC = 0x0A,
1478 OPC_MXU_D16MACF = 0x0B,
1479 OPC_MXU_D16MADL = 0x0C,
1480 OPC_MXU_S16MAD = 0x0D,
1481 OPC_MXU_Q16ADD = 0x0E,
1482 OPC_MXU_D16MACE = 0x0F,
1483 OPC_MXU__POOL04 = 0x10,
1484 OPC_MXU__POOL05 = 0x11,
1485 OPC_MXU__POOL06 = 0x12,
1486 OPC_MXU__POOL07 = 0x13,
1487 OPC_MXU__POOL08 = 0x14,
1488 OPC_MXU__POOL09 = 0x15,
1489 OPC_MXU__POOL10 = 0x16,
1490 OPC_MXU__POOL11 = 0x17,
1491 OPC_MXU_D32ADD = 0x18,
1492 OPC_MXU__POOL12 = 0x19,
1493 /* not assigned 0x1A */
1494 OPC_MXU__POOL13 = 0x1B,
1495 OPC_MXU__POOL14 = 0x1C,
1496 OPC_MXU_Q8ACCE = 0x1D,
1497 /* not assigned 0x1E */
1498 /* not assigned 0x1F */
1499 /* not assigned 0x20 */
1500 /* not assigned 0x21 */
1501 OPC_MXU_S8LDD = 0x22,
1502 OPC_MXU_S8STD = 0x23,
1503 OPC_MXU_S8LDI = 0x24,
1504 OPC_MXU_S8SDI = 0x25,
1505 OPC_MXU__POOL15 = 0x26,
1506 OPC_MXU__POOL16 = 0x27,
1507 OPC_MXU__POOL17 = 0x28,
1508 /* not assigned 0x29 */
1509 OPC_MXU_S16LDD = 0x2A,
1510 OPC_MXU_S16STD = 0x2B,
1511 OPC_MXU_S16LDI = 0x2C,
1512 OPC_MXU_S16SDI = 0x2D,
1513 OPC_MXU_S32M2I = 0x2E,
1514 OPC_MXU_S32I2M = 0x2F,
1515 OPC_MXU_D32SLL = 0x30,
1516 OPC_MXU_D32SLR = 0x31,
1517 OPC_MXU_D32SARL = 0x32,
1518 OPC_MXU_D32SAR = 0x33,
1519 OPC_MXU_Q16SLL = 0x34,
1520 OPC_MXU_Q16SLR = 0x35,
1521 OPC_MXU__POOL18 = 0x36,
1522 OPC_MXU_Q16SAR = 0x37,
1523 OPC_MXU__POOL19 = 0x38,
1524 OPC_MXU__POOL20 = 0x39,
1525 OPC_MXU__POOL21 = 0x3A,
1526 OPC_MXU_Q16SCOP = 0x3B,
1527 OPC_MXU_Q8MADL = 0x3C,
1528 OPC_MXU_S32SFL = 0x3D,
1529 OPC_MXU_Q8SAD = 0x3E,
1530 /* not assigned 0x3F */
1535 * MXU pool 00
1537 enum {
1538 OPC_MXU_S32MAX = 0x00,
1539 OPC_MXU_S32MIN = 0x01,
1540 OPC_MXU_D16MAX = 0x02,
1541 OPC_MXU_D16MIN = 0x03,
1542 OPC_MXU_Q8MAX = 0x04,
1543 OPC_MXU_Q8MIN = 0x05,
1544 OPC_MXU_Q8SLT = 0x06,
1545 OPC_MXU_Q8SLTU = 0x07,
1549 * MXU pool 01
1551 enum {
1552 OPC_MXU_S32SLT = 0x00,
1553 OPC_MXU_D16SLT = 0x01,
1554 OPC_MXU_D16AVG = 0x02,
1555 OPC_MXU_D16AVGR = 0x03,
1556 OPC_MXU_Q8AVG = 0x04,
1557 OPC_MXU_Q8AVGR = 0x05,
1558 OPC_MXU_Q8ADD = 0x07,
1562 * MXU pool 02
1564 enum {
1565 OPC_MXU_S32CPS = 0x00,
1566 OPC_MXU_D16CPS = 0x02,
1567 OPC_MXU_Q8ABD = 0x04,
1568 OPC_MXU_Q16SAT = 0x06,
1572 * MXU pool 03
1574 enum {
1575 OPC_MXU_D16MULF = 0x00,
1576 OPC_MXU_D16MULE = 0x01,
1580 * MXU pool 04
1582 enum {
1583 OPC_MXU_S32LDD = 0x00,
1584 OPC_MXU_S32LDDR = 0x01,
1588 * MXU pool 05
1590 enum {
1591 OPC_MXU_S32STD = 0x00,
1592 OPC_MXU_S32STDR = 0x01,
1596 * MXU pool 06
1598 enum {
1599 OPC_MXU_S32LDDV = 0x00,
1600 OPC_MXU_S32LDDVR = 0x01,
1604 * MXU pool 07
1606 enum {
1607 OPC_MXU_S32STDV = 0x00,
1608 OPC_MXU_S32STDVR = 0x01,
1612 * MXU pool 08
1614 enum {
1615 OPC_MXU_S32LDI = 0x00,
1616 OPC_MXU_S32LDIR = 0x01,
1620 * MXU pool 09
1622 enum {
1623 OPC_MXU_S32SDI = 0x00,
1624 OPC_MXU_S32SDIR = 0x01,
1628 * MXU pool 10
1630 enum {
1631 OPC_MXU_S32LDIV = 0x00,
1632 OPC_MXU_S32LDIVR = 0x01,
1636 * MXU pool 11
1638 enum {
1639 OPC_MXU_S32SDIV = 0x00,
1640 OPC_MXU_S32SDIVR = 0x01,
1644 * MXU pool 12
1646 enum {
1647 OPC_MXU_D32ACC = 0x00,
1648 OPC_MXU_D32ACCM = 0x01,
1649 OPC_MXU_D32ASUM = 0x02,
1653 * MXU pool 13
1655 enum {
1656 OPC_MXU_Q16ACC = 0x00,
1657 OPC_MXU_Q16ACCM = 0x01,
1658 OPC_MXU_Q16ASUM = 0x02,
1662 * MXU pool 14
1664 enum {
1665 OPC_MXU_Q8ADDE = 0x00,
1666 OPC_MXU_D8SUM = 0x01,
1667 OPC_MXU_D8SUMC = 0x02,
1671 * MXU pool 15
1673 enum {
1674 OPC_MXU_S32MUL = 0x00,
1675 OPC_MXU_S32MULU = 0x01,
1676 OPC_MXU_S32EXTR = 0x02,
1677 OPC_MXU_S32EXTRV = 0x03,
1681 * MXU pool 16
1683 enum {
1684 OPC_MXU_D32SARW = 0x00,
1685 OPC_MXU_S32ALN = 0x01,
1686 OPC_MXU_S32ALNI = 0x02,
1687 OPC_MXU_S32LUI = 0x03,
1688 OPC_MXU_S32NOR = 0x04,
1689 OPC_MXU_S32AND = 0x05,
1690 OPC_MXU_S32OR = 0x06,
1691 OPC_MXU_S32XOR = 0x07,
1695 * MXU pool 17
1697 enum {
1698 OPC_MXU_LXB = 0x00,
1699 OPC_MXU_LXH = 0x01,
1700 OPC_MXU_LXW = 0x03,
1701 OPC_MXU_LXBU = 0x04,
1702 OPC_MXU_LXHU = 0x05,
1706 * MXU pool 18
1708 enum {
1709 OPC_MXU_D32SLLV = 0x00,
1710 OPC_MXU_D32SLRV = 0x01,
1711 OPC_MXU_D32SARV = 0x03,
1712 OPC_MXU_Q16SLLV = 0x04,
1713 OPC_MXU_Q16SLRV = 0x05,
1714 OPC_MXU_Q16SARV = 0x07,
1718 * MXU pool 19
1720 enum {
1721 OPC_MXU_Q8MUL = 0x00,
1722 OPC_MXU_Q8MULSU = 0x01,
1726 * MXU pool 20
1728 enum {
1729 OPC_MXU_Q8MOVZ = 0x00,
1730 OPC_MXU_Q8MOVN = 0x01,
1731 OPC_MXU_D16MOVZ = 0x02,
1732 OPC_MXU_D16MOVN = 0x03,
1733 OPC_MXU_S32MOVZ = 0x04,
1734 OPC_MXU_S32MOVN = 0x05,
1738 * MXU pool 21
1740 enum {
1741 OPC_MXU_Q8MAC = 0x00,
1742 OPC_MXU_Q8MACSU = 0x01,
1746 * Overview of the TX79-specific instruction set
1747 * =============================================
1749 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
1750 * are only used by the specific quadword (128-bit) LQ/SQ load/store
1751 * instructions and certain multimedia instructions (MMIs). These MMIs
1752 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
1753 * or sixteen 8-bit paths.
1755 * Reference:
1757 * The Toshiba TX System RISC TX79 Core Architecture manual,
1758 * https://wiki.qemu.org/File:C790.pdf
1760 * Three-Operand Multiply and Multiply-Add (4 instructions)
1761 * --------------------------------------------------------
1762 * MADD [rd,] rs, rt Multiply/Add
1763 * MADDU [rd,] rs, rt Multiply/Add Unsigned
1764 * MULT [rd,] rs, rt Multiply (3-operand)
1765 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
1767 * Multiply Instructions for Pipeline 1 (10 instructions)
1768 * ------------------------------------------------------
1769 * MULT1 [rd,] rs, rt Multiply Pipeline 1
1770 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
1771 * DIV1 rs, rt Divide Pipeline 1
1772 * DIVU1 rs, rt Divide Unsigned Pipeline 1
1773 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
1774 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
1775 * MFHI1 rd Move From HI1 Register
1776 * MFLO1 rd Move From LO1 Register
1777 * MTHI1 rs Move To HI1 Register
1778 * MTLO1 rs Move To LO1 Register
1780 * Arithmetic (19 instructions)
1781 * ----------------------------
1782 * PADDB rd, rs, rt Parallel Add Byte
1783 * PSUBB rd, rs, rt Parallel Subtract Byte
1784 * PADDH rd, rs, rt Parallel Add Halfword
1785 * PSUBH rd, rs, rt Parallel Subtract Halfword
1786 * PADDW rd, rs, rt Parallel Add Word
1787 * PSUBW rd, rs, rt Parallel Subtract Word
1788 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
1789 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
1790 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
1791 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
1792 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
1793 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
1794 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
1795 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
1796 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
1797 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
1798 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
1799 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
1800 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
1802 * Min/Max (4 instructions)
1803 * ------------------------
1804 * PMAXH rd, rs, rt Parallel Maximum Halfword
1805 * PMINH rd, rs, rt Parallel Minimum Halfword
1806 * PMAXW rd, rs, rt Parallel Maximum Word
1807 * PMINW rd, rs, rt Parallel Minimum Word
1809 * Absolute (2 instructions)
1810 * -------------------------
1811 * PABSH rd, rt Parallel Absolute Halfword
1812 * PABSW rd, rt Parallel Absolute Word
1814 * Logical (4 instructions)
1815 * ------------------------
1816 * PAND rd, rs, rt Parallel AND
1817 * POR rd, rs, rt Parallel OR
1818 * PXOR rd, rs, rt Parallel XOR
1819 * PNOR rd, rs, rt Parallel NOR
1821 * Shift (9 instructions)
1822 * ----------------------
1823 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
1824 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
1825 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
1826 * PSLLW rd, rt, sa Parallel Shift Left Logical Word
1827 * PSRLW rd, rt, sa Parallel Shift Right Logical Word
1828 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
1829 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
1830 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
1831 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
1833 * Compare (6 instructions)
1834 * ------------------------
1835 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
1836 * PCEQB rd, rs, rt Parallel Compare for Equal Byte
1837 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
1838 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
1839 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
1840 * PCEQW rd, rs, rt Parallel Compare for Equal Word
1842 * LZC (1 instruction)
1843 * -------------------
1844 * PLZCW rd, rs Parallel Leading Zero or One Count Word
1846 * Quadword Load and Store (2 instructions)
1847 * ----------------------------------------
1848 * LQ rt, offset(base) Load Quadword
1849 * SQ rt, offset(base) Store Quadword
1851 * Multiply and Divide (19 instructions)
1852 * -------------------------------------
1853 * PMULTW rd, rs, rt Parallel Multiply Word
1854 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
1855 * PDIVW rs, rt Parallel Divide Word
1856 * PDIVUW rs, rt Parallel Divide Unsigned Word
1857 * PMADDW rd, rs, rt Parallel Multiply-Add Word
1858 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
1859 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
1860 * PMULTH rd, rs, rt Parallel Multiply Halfword
1861 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
1862 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
1863 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
1864 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
1865 * PDIVBW rs, rt Parallel Divide Broadcast Word
1866 * PMFHI rd Parallel Move From HI Register
1867 * PMFLO rd Parallel Move From LO Register
1868 * PMTHI rs Parallel Move To HI Register
1869 * PMTLO rs Parallel Move To LO Register
1870 * PMFHL rd Parallel Move From HI/LO Register
1871 * PMTHL rs Parallel Move To HI/LO Register
1873 * Pack/Extend (11 instructions)
1874 * -----------------------------
1875 * PPAC5 rd, rt Parallel Pack to 5 bits
1876 * PPACB rd, rs, rt Parallel Pack to Byte
1877 * PPACH rd, rs, rt Parallel Pack to Halfword
1878 * PPACW rd, rs, rt Parallel Pack to Word
1879 * PEXT5 rd, rt Parallel Extend Upper from 5 bits
1880 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
1881 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
1882 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
1883 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
1884 * PEXTUW rd, rs, rt Parallel Extend Upper from Word
1885 * PEXTLW rd, rs, rt Parallel Extend Lower from Word
1887 * Others (16 instructions)
1888 * ------------------------
1889 * PCPYH rd, rt Parallel Copy Halfword
1890 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
1891 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
1892 * PREVH rd, rt Parallel Reverse Halfword
1893 * PINTH rd, rs, rt Parallel Interleave Halfword
1894 * PINTEH rd, rs, rt Parallel Interleave Even Halfword
1895 * PEXEH rd, rt Parallel Exchange Even Halfword
1896 * PEXCH rd, rt Parallel Exchange Center Halfword
1897 * PEXEW rd, rt Parallel Exchange Even Word
1898 * PEXCW rd, rt Parallel Exchange Center Word
1899 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
1900 * MFSA rd Move from Shift Amount Register
1901 * MTSA rs Move to Shift Amount Register
1902 * MTSAB rs, immediate Move Byte Count to Shift Amount Register
1903 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
1904 * PROT3W rd, rt Parallel Rotate 3 Words
1906 * MMI (MultiMedia Instruction) encodings
1907 * ======================================
1909 * MMI instructions encoding table keys:
1911 * * This code is reserved for future use. An attempt to execute it
1912 * causes a Reserved Instruction exception.
1913 * % This code indicates an instruction class. The instruction word
1914 * must be further decoded by examining additional tables that show
1915 * the values for other instruction fields.
1916 * # This code is reserved for the unsupported instructions DMULT,
1917 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
1918 * to execute it causes a Reserved Instruction exception.
1920 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
1922 * 31 26 0
1923 * +--------+----------------------------------------+
1924 * | opcode | |
1925 * +--------+----------------------------------------+
1927 * opcode bits 28..26
1928 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
1929 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
1930 * -------+-------+-------+-------+-------+-------+-------+-------+-------
1931 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
1932 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
1933 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
1934 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
1935 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
1936 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
1937 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
1938 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
1941 enum {
1942 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
1943 MMI_OPC_LQ = 0x1E << 26, /* Same as OPC_MSA */
1944 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
1948 * MMI instructions with opcode field = MMI:
1950 * 31 26 5 0
1951 * +--------+-------------------------------+--------+
1952 * | MMI | |function|
1953 * +--------+-------------------------------+--------+
1955 * function bits 2..0
1956 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
1957 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
1958 * -------+-------+-------+-------+-------+-------+-------+-------+-------
1959 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
1960 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
1961 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
1962 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
1963 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
1964 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
1965 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
1966 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
1969 #define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
1970 enum {
1971 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
1972 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
1973 MMI_OPC_PLZCW = 0x04 | MMI_OPC_CLASS_MMI,
1974 MMI_OPC_CLASS_MMI0 = 0x08 | MMI_OPC_CLASS_MMI,
1975 MMI_OPC_CLASS_MMI2 = 0x09 | MMI_OPC_CLASS_MMI,
1976 MMI_OPC_MFHI1 = 0x10 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFHI */
1977 MMI_OPC_MTHI1 = 0x11 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTHI */
1978 MMI_OPC_MFLO1 = 0x12 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFLO */
1979 MMI_OPC_MTLO1 = 0x13 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTLO */
1980 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
1981 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
1982 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
1983 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
1984 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
1985 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
1986 MMI_OPC_CLASS_MMI1 = 0x28 | MMI_OPC_CLASS_MMI,
1987 MMI_OPC_CLASS_MMI3 = 0x29 | MMI_OPC_CLASS_MMI,
1988 MMI_OPC_PMFHL = 0x30 | MMI_OPC_CLASS_MMI,
1989 MMI_OPC_PMTHL = 0x31 | MMI_OPC_CLASS_MMI,
1990 MMI_OPC_PSLLH = 0x34 | MMI_OPC_CLASS_MMI,
1991 MMI_OPC_PSRLH = 0x36 | MMI_OPC_CLASS_MMI,
1992 MMI_OPC_PSRAH = 0x37 | MMI_OPC_CLASS_MMI,
1993 MMI_OPC_PSLLW = 0x3C | MMI_OPC_CLASS_MMI,
1994 MMI_OPC_PSRLW = 0x3E | MMI_OPC_CLASS_MMI,
1995 MMI_OPC_PSRAW = 0x3F | MMI_OPC_CLASS_MMI,
1999 * MMI instructions with opcode field = MMI and bits 5..0 = MMI0:
2001 * 31 26 10 6 5 0
2002 * +--------+----------------------+--------+--------+
2003 * | MMI | |function| MMI0 |
2004 * +--------+----------------------+--------+--------+
2006 * function bits 7..6
2007 * bits | 0 | 1 | 2 | 3
2008 * 10..8 | 00 | 01 | 10 | 11
2009 * -------+-------+-------+-------+-------
2010 * 0 000 | PADDW | PSUBW | PCGTW | PMAXW
2011 * 1 001 | PADDH | PSUBH | PCGTH | PMAXH
2012 * 2 010 | PADDB | PSUBB | PCGTB | *
2013 * 3 011 | * | * | * | *
2014 * 4 100 | PADDSW| PSUBSW| PEXTLW| PPACW
2015 * 5 101 | PADDSH| PSUBSH| PEXTLH| PPACH
2016 * 6 110 | PADDSB| PSUBSB| PEXTLB| PPACB
2017 * 7 111 | * | * | PEXT5 | PPAC5
2020 #define MASK_MMI0(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2021 enum {
2022 MMI_OPC_0_PADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI0,
2023 MMI_OPC_0_PSUBW = (0x01 << 6) | MMI_OPC_CLASS_MMI0,
2024 MMI_OPC_0_PCGTW = (0x02 << 6) | MMI_OPC_CLASS_MMI0,
2025 MMI_OPC_0_PMAXW = (0x03 << 6) | MMI_OPC_CLASS_MMI0,
2026 MMI_OPC_0_PADDH = (0x04 << 6) | MMI_OPC_CLASS_MMI0,
2027 MMI_OPC_0_PSUBH = (0x05 << 6) | MMI_OPC_CLASS_MMI0,
2028 MMI_OPC_0_PCGTH = (0x06 << 6) | MMI_OPC_CLASS_MMI0,
2029 MMI_OPC_0_PMAXH = (0x07 << 6) | MMI_OPC_CLASS_MMI0,
2030 MMI_OPC_0_PADDB = (0x08 << 6) | MMI_OPC_CLASS_MMI0,
2031 MMI_OPC_0_PSUBB = (0x09 << 6) | MMI_OPC_CLASS_MMI0,
2032 MMI_OPC_0_PCGTB = (0x0A << 6) | MMI_OPC_CLASS_MMI0,
2033 MMI_OPC_0_PADDSW = (0x10 << 6) | MMI_OPC_CLASS_MMI0,
2034 MMI_OPC_0_PSUBSW = (0x11 << 6) | MMI_OPC_CLASS_MMI0,
2035 MMI_OPC_0_PEXTLW = (0x12 << 6) | MMI_OPC_CLASS_MMI0,
2036 MMI_OPC_0_PPACW = (0x13 << 6) | MMI_OPC_CLASS_MMI0,
2037 MMI_OPC_0_PADDSH = (0x14 << 6) | MMI_OPC_CLASS_MMI0,
2038 MMI_OPC_0_PSUBSH = (0x15 << 6) | MMI_OPC_CLASS_MMI0,
2039 MMI_OPC_0_PEXTLH = (0x16 << 6) | MMI_OPC_CLASS_MMI0,
2040 MMI_OPC_0_PPACH = (0x17 << 6) | MMI_OPC_CLASS_MMI0,
2041 MMI_OPC_0_PADDSB = (0x18 << 6) | MMI_OPC_CLASS_MMI0,
2042 MMI_OPC_0_PSUBSB = (0x19 << 6) | MMI_OPC_CLASS_MMI0,
2043 MMI_OPC_0_PEXTLB = (0x1A << 6) | MMI_OPC_CLASS_MMI0,
2044 MMI_OPC_0_PPACB = (0x1B << 6) | MMI_OPC_CLASS_MMI0,
2045 MMI_OPC_0_PEXT5 = (0x1E << 6) | MMI_OPC_CLASS_MMI0,
2046 MMI_OPC_0_PPAC5 = (0x1F << 6) | MMI_OPC_CLASS_MMI0,
2050 * MMI instructions with opcode field = MMI and bits 5..0 = MMI1:
2052 * 31 26 10 6 5 0
2053 * +--------+----------------------+--------+--------+
2054 * | MMI | |function| MMI1 |
2055 * +--------+----------------------+--------+--------+
2057 * function bits 7..6
2058 * bits | 0 | 1 | 2 | 3
2059 * 10..8 | 00 | 01 | 10 | 11
2060 * -------+-------+-------+-------+-------
2061 * 0 000 | * | PABSW | PCEQW | PMINW
2062 * 1 001 | PADSBH| PABSH | PCEQH | PMINH
2063 * 2 010 | * | * | PCEQB | *
2064 * 3 011 | * | * | * | *
2065 * 4 100 | PADDUW| PSUBUW| PEXTUW| *
2066 * 5 101 | PADDUH| PSUBUH| PEXTUH| *
2067 * 6 110 | PADDUB| PSUBUB| PEXTUB| QFSRV
2068 * 7 111 | * | * | * | *
2071 #define MASK_MMI1(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2072 enum {
2073 MMI_OPC_1_PABSW = (0x01 << 6) | MMI_OPC_CLASS_MMI1,
2074 MMI_OPC_1_PCEQW = (0x02 << 6) | MMI_OPC_CLASS_MMI1,
2075 MMI_OPC_1_PMINW = (0x03 << 6) | MMI_OPC_CLASS_MMI1,
2076 MMI_OPC_1_PADSBH = (0x04 << 6) | MMI_OPC_CLASS_MMI1,
2077 MMI_OPC_1_PABSH = (0x05 << 6) | MMI_OPC_CLASS_MMI1,
2078 MMI_OPC_1_PCEQH = (0x06 << 6) | MMI_OPC_CLASS_MMI1,
2079 MMI_OPC_1_PMINH = (0x07 << 6) | MMI_OPC_CLASS_MMI1,
2080 MMI_OPC_1_PCEQB = (0x0A << 6) | MMI_OPC_CLASS_MMI1,
2081 MMI_OPC_1_PADDUW = (0x10 << 6) | MMI_OPC_CLASS_MMI1,
2082 MMI_OPC_1_PSUBUW = (0x11 << 6) | MMI_OPC_CLASS_MMI1,
2083 MMI_OPC_1_PEXTUW = (0x12 << 6) | MMI_OPC_CLASS_MMI1,
2084 MMI_OPC_1_PADDUH = (0x14 << 6) | MMI_OPC_CLASS_MMI1,
2085 MMI_OPC_1_PSUBUH = (0x15 << 6) | MMI_OPC_CLASS_MMI1,
2086 MMI_OPC_1_PEXTUH = (0x16 << 6) | MMI_OPC_CLASS_MMI1,
2087 MMI_OPC_1_PADDUB = (0x18 << 6) | MMI_OPC_CLASS_MMI1,
2088 MMI_OPC_1_PSUBUB = (0x19 << 6) | MMI_OPC_CLASS_MMI1,
2089 MMI_OPC_1_PEXTUB = (0x1A << 6) | MMI_OPC_CLASS_MMI1,
2090 MMI_OPC_1_QFSRV = (0x1B << 6) | MMI_OPC_CLASS_MMI1,
2094 * MMI instructions with opcode field = MMI and bits 5..0 = MMI2:
2096 * 31 26 10 6 5 0
2097 * +--------+----------------------+--------+--------+
2098 * | MMI | |function| MMI2 |
2099 * +--------+----------------------+--------+--------+
2101 * function bits 7..6
2102 * bits | 0 | 1 | 2 | 3
2103 * 10..8 | 00 | 01 | 10 | 11
2104 * -------+-------+-------+-------+-------
2105 * 0 000 | PMADDW| * | PSLLVW| PSRLVW
2106 * 1 001 | PMSUBW| * | * | *
2107 * 2 010 | PMFHI | PMFLO | PINTH | *
2108 * 3 011 | PMULTW| PDIVW | PCPYLD| *
2109 * 4 100 | PMADDH| PHMADH| PAND | PXOR
2110 * 5 101 | PMSUBH| PHMSBH| * | *
2111 * 6 110 | * | * | PEXEH | PREVH
2112 * 7 111 | PMULTH| PDIVBW| PEXEW | PROT3W
2115 #define MASK_MMI2(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2116 enum {
2117 MMI_OPC_2_PMADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI2,
2118 MMI_OPC_2_PSLLVW = (0x02 << 6) | MMI_OPC_CLASS_MMI2,
2119 MMI_OPC_2_PSRLVW = (0x03 << 6) | MMI_OPC_CLASS_MMI2,
2120 MMI_OPC_2_PMSUBW = (0x04 << 6) | MMI_OPC_CLASS_MMI2,
2121 MMI_OPC_2_PMFHI = (0x08 << 6) | MMI_OPC_CLASS_MMI2,
2122 MMI_OPC_2_PMFLO = (0x09 << 6) | MMI_OPC_CLASS_MMI2,
2123 MMI_OPC_2_PINTH = (0x0A << 6) | MMI_OPC_CLASS_MMI2,
2124 MMI_OPC_2_PMULTW = (0x0C << 6) | MMI_OPC_CLASS_MMI2,
2125 MMI_OPC_2_PDIVW = (0x0D << 6) | MMI_OPC_CLASS_MMI2,
2126 MMI_OPC_2_PCPYLD = (0x0E << 6) | MMI_OPC_CLASS_MMI2,
2127 MMI_OPC_2_PMADDH = (0x10 << 6) | MMI_OPC_CLASS_MMI2,
2128 MMI_OPC_2_PHMADH = (0x11 << 6) | MMI_OPC_CLASS_MMI2,
2129 MMI_OPC_2_PAND = (0x12 << 6) | MMI_OPC_CLASS_MMI2,
2130 MMI_OPC_2_PXOR = (0x13 << 6) | MMI_OPC_CLASS_MMI2,
2131 MMI_OPC_2_PMSUBH = (0x14 << 6) | MMI_OPC_CLASS_MMI2,
2132 MMI_OPC_2_PHMSBH = (0x15 << 6) | MMI_OPC_CLASS_MMI2,
2133 MMI_OPC_2_PEXEH = (0x1A << 6) | MMI_OPC_CLASS_MMI2,
2134 MMI_OPC_2_PREVH = (0x1B << 6) | MMI_OPC_CLASS_MMI2,
2135 MMI_OPC_2_PMULTH = (0x1C << 6) | MMI_OPC_CLASS_MMI2,
2136 MMI_OPC_2_PDIVBW = (0x1D << 6) | MMI_OPC_CLASS_MMI2,
2137 MMI_OPC_2_PEXEW = (0x1E << 6) | MMI_OPC_CLASS_MMI2,
2138 MMI_OPC_2_PROT3W = (0x1F << 6) | MMI_OPC_CLASS_MMI2,
2142 * MMI instructions with opcode field = MMI and bits 5..0 = MMI3:
2144 * 31 26 10 6 5 0
2145 * +--------+----------------------+--------+--------+
2146 * | MMI | |function| MMI3 |
2147 * +--------+----------------------+--------+--------+
2149 * function bits 7..6
2150 * bits | 0 | 1 | 2 | 3
2151 * 10..8 | 00 | 01 | 10 | 11
2152 * -------+-------+-------+-------+-------
2153 * 0 000 |PMADDUW| * | * | PSRAVW
2154 * 1 001 | * | * | * | *
2155 * 2 010 | PMTHI | PMTLO | PINTEH| *
2156 * 3 011 |PMULTUW| PDIVUW| PCPYUD| *
2157 * 4 100 | * | * | POR | PNOR
2158 * 5 101 | * | * | * | *
2159 * 6 110 | * | * | PEXCH | PCPYH
2160 * 7 111 | * | * | PEXCW | *
2163 #define MASK_MMI3(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2164 enum {
2165 MMI_OPC_3_PMADDUW = (0x00 << 6) | MMI_OPC_CLASS_MMI3,
2166 MMI_OPC_3_PSRAVW = (0x03 << 6) | MMI_OPC_CLASS_MMI3,
2167 MMI_OPC_3_PMTHI = (0x08 << 6) | MMI_OPC_CLASS_MMI3,
2168 MMI_OPC_3_PMTLO = (0x09 << 6) | MMI_OPC_CLASS_MMI3,
2169 MMI_OPC_3_PINTEH = (0x0A << 6) | MMI_OPC_CLASS_MMI3,
2170 MMI_OPC_3_PMULTUW = (0x0C << 6) | MMI_OPC_CLASS_MMI3,
2171 MMI_OPC_3_PDIVUW = (0x0D << 6) | MMI_OPC_CLASS_MMI3,
2172 MMI_OPC_3_PCPYUD = (0x0E << 6) | MMI_OPC_CLASS_MMI3,
2173 MMI_OPC_3_POR = (0x12 << 6) | MMI_OPC_CLASS_MMI3,
2174 MMI_OPC_3_PNOR = (0x13 << 6) | MMI_OPC_CLASS_MMI3,
2175 MMI_OPC_3_PEXCH = (0x1A << 6) | MMI_OPC_CLASS_MMI3,
2176 MMI_OPC_3_PCPYH = (0x1B << 6) | MMI_OPC_CLASS_MMI3,
2177 MMI_OPC_3_PEXCW = (0x1E << 6) | MMI_OPC_CLASS_MMI3,
2180 /* global register indices */
2181 TCGv cpu_gpr[32], cpu_PC;
2183 * For CPUs using 128-bit GPR registers, we put the lower halves in cpu_gpr[])
2184 * and the upper halves in cpu_gpr_hi[].
2186 TCGv_i64 cpu_gpr_hi[32];
2187 TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
2188 static TCGv cpu_dspctrl, btarget;
2189 TCGv bcond;
2190 static TCGv cpu_lladdr, cpu_llval;
2191 static TCGv_i32 hflags;
2192 TCGv_i32 fpu_fcr0, fpu_fcr31;
2193 TCGv_i64 fpu_f64[32];
2195 #if !defined(TARGET_MIPS64)
2196 /* MXU registers */
2197 static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1];
2198 static TCGv mxu_CR;
2199 #endif
2201 #include "exec/gen-icount.h"
2203 #define gen_helper_0e0i(name, arg) do { \
2204 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
2205 gen_helper_##name(cpu_env, helper_tmp); \
2206 tcg_temp_free_i32(helper_tmp); \
2207 } while (0)
2209 #define gen_helper_0e1i(name, arg1, arg2) do { \
2210 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2211 gen_helper_##name(cpu_env, arg1, helper_tmp); \
2212 tcg_temp_free_i32(helper_tmp); \
2213 } while (0)
2215 #define gen_helper_1e0i(name, ret, arg1) do { \
2216 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
2217 gen_helper_##name(ret, cpu_env, helper_tmp); \
2218 tcg_temp_free_i32(helper_tmp); \
2219 } while (0)
2221 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
2222 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2223 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
2224 tcg_temp_free_i32(helper_tmp); \
2225 } while (0)
2227 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
2228 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2229 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
2230 tcg_temp_free_i32(helper_tmp); \
2231 } while (0)
2233 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
2234 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2235 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
2236 tcg_temp_free_i32(helper_tmp); \
2237 } while (0)
2239 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
2240 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
2241 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
2242 tcg_temp_free_i32(helper_tmp); \
2243 } while (0)
2245 #define DISAS_STOP DISAS_TARGET_0
2246 #define DISAS_EXIT DISAS_TARGET_1
2248 static const char * const regnames[] = {
2249 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2250 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2251 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2252 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2255 static const char * const regnames_HI[] = {
2256 "HI0", "HI1", "HI2", "HI3",
2259 static const char * const regnames_LO[] = {
2260 "LO0", "LO1", "LO2", "LO3",
2263 static const char * const fregnames[] = {
2264 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2265 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2266 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2267 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2270 #if !defined(TARGET_MIPS64)
2271 static const char * const mxuregnames[] = {
2272 "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8",
2273 "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR",
2275 #endif
2277 /* General purpose registers moves. */
2278 void gen_load_gpr(TCGv t, int reg)
2280 if (reg == 0) {
2281 tcg_gen_movi_tl(t, 0);
2282 } else {
2283 tcg_gen_mov_tl(t, cpu_gpr[reg]);
2287 void gen_store_gpr(TCGv t, int reg)
2289 if (reg != 0) {
2290 tcg_gen_mov_tl(cpu_gpr[reg], t);
2294 /* Moves to/from shadow registers. */
2295 static inline void gen_load_srsgpr(int from, int to)
2297 TCGv t0 = tcg_temp_new();
2299 if (from == 0) {
2300 tcg_gen_movi_tl(t0, 0);
2301 } else {
2302 TCGv_i32 t2 = tcg_temp_new_i32();
2303 TCGv_ptr addr = tcg_temp_new_ptr();
2305 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2306 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2307 tcg_gen_andi_i32(t2, t2, 0xf);
2308 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2309 tcg_gen_ext_i32_ptr(addr, t2);
2310 tcg_gen_add_ptr(addr, cpu_env, addr);
2312 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
2313 tcg_temp_free_ptr(addr);
2314 tcg_temp_free_i32(t2);
2316 gen_store_gpr(t0, to);
2317 tcg_temp_free(t0);
2320 static inline void gen_store_srsgpr(int from, int to)
2322 if (to != 0) {
2323 TCGv t0 = tcg_temp_new();
2324 TCGv_i32 t2 = tcg_temp_new_i32();
2325 TCGv_ptr addr = tcg_temp_new_ptr();
2327 gen_load_gpr(t0, from);
2328 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2329 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2330 tcg_gen_andi_i32(t2, t2, 0xf);
2331 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2332 tcg_gen_ext_i32_ptr(addr, t2);
2333 tcg_gen_add_ptr(addr, cpu_env, addr);
2335 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
2336 tcg_temp_free_ptr(addr);
2337 tcg_temp_free_i32(t2);
2338 tcg_temp_free(t0);
2342 #if !defined(TARGET_MIPS64)
2343 /* MXU General purpose registers moves. */
2344 static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg)
2346 if (reg == 0) {
2347 tcg_gen_movi_tl(t, 0);
2348 } else if (reg <= 15) {
2349 tcg_gen_mov_tl(t, mxu_gpr[reg - 1]);
2353 static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg)
2355 if (reg > 0 && reg <= 15) {
2356 tcg_gen_mov_tl(mxu_gpr[reg - 1], t);
2360 /* MXU control register moves. */
2361 static inline void gen_load_mxu_cr(TCGv t)
2363 tcg_gen_mov_tl(t, mxu_CR);
2366 static inline void gen_store_mxu_cr(TCGv t)
2368 /* TODO: Add handling of RW rules for MXU_CR. */
2369 tcg_gen_mov_tl(mxu_CR, t);
2371 #endif
2374 /* Tests */
2375 static inline void gen_save_pc(target_ulong pc)
2377 tcg_gen_movi_tl(cpu_PC, pc);
2380 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2382 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
2383 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2384 gen_save_pc(ctx->base.pc_next);
2385 ctx->saved_pc = ctx->base.pc_next;
2387 if (ctx->hflags != ctx->saved_hflags) {
2388 tcg_gen_movi_i32(hflags, ctx->hflags);
2389 ctx->saved_hflags = ctx->hflags;
2390 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2391 case MIPS_HFLAG_BR:
2392 break;
2393 case MIPS_HFLAG_BC:
2394 case MIPS_HFLAG_BL:
2395 case MIPS_HFLAG_B:
2396 tcg_gen_movi_tl(btarget, ctx->btarget);
2397 break;
2402 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2404 ctx->saved_hflags = ctx->hflags;
2405 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2406 case MIPS_HFLAG_BR:
2407 break;
2408 case MIPS_HFLAG_BC:
2409 case MIPS_HFLAG_BL:
2410 case MIPS_HFLAG_B:
2411 ctx->btarget = env->btarget;
2412 break;
2416 void generate_exception_err(DisasContext *ctx, int excp, int err)
2418 TCGv_i32 texcp = tcg_const_i32(excp);
2419 TCGv_i32 terr = tcg_const_i32(err);
2420 save_cpu_state(ctx, 1);
2421 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2422 tcg_temp_free_i32(terr);
2423 tcg_temp_free_i32(texcp);
2424 ctx->base.is_jmp = DISAS_NORETURN;
2427 void generate_exception(DisasContext *ctx, int excp)
2429 gen_helper_0e0i(raise_exception, excp);
2432 void generate_exception_end(DisasContext *ctx, int excp)
2434 generate_exception_err(ctx, excp, 0);
2437 void gen_reserved_instruction(DisasContext *ctx)
2439 generate_exception_end(ctx, EXCP_RI);
2442 /* Floating point register moves. */
2443 void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2445 if (ctx->hflags & MIPS_HFLAG_FRE) {
2446 generate_exception(ctx, EXCP_RI);
2448 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
2451 void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2453 TCGv_i64 t64;
2454 if (ctx->hflags & MIPS_HFLAG_FRE) {
2455 generate_exception(ctx, EXCP_RI);
2457 t64 = tcg_temp_new_i64();
2458 tcg_gen_extu_i32_i64(t64, t);
2459 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2460 tcg_temp_free_i64(t64);
2463 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2465 if (ctx->hflags & MIPS_HFLAG_F64) {
2466 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
2467 } else {
2468 gen_load_fpr32(ctx, t, reg | 1);
2472 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2474 if (ctx->hflags & MIPS_HFLAG_F64) {
2475 TCGv_i64 t64 = tcg_temp_new_i64();
2476 tcg_gen_extu_i32_i64(t64, t);
2477 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2478 tcg_temp_free_i64(t64);
2479 } else {
2480 gen_store_fpr32(ctx, t, reg | 1);
2484 void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2486 if (ctx->hflags & MIPS_HFLAG_F64) {
2487 tcg_gen_mov_i64(t, fpu_f64[reg]);
2488 } else {
2489 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
2493 void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2495 if (ctx->hflags & MIPS_HFLAG_F64) {
2496 tcg_gen_mov_i64(fpu_f64[reg], t);
2497 } else {
2498 TCGv_i64 t0;
2499 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2500 t0 = tcg_temp_new_i64();
2501 tcg_gen_shri_i64(t0, t, 32);
2502 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
2503 tcg_temp_free_i64(t0);
2507 int get_fp_bit(int cc)
2509 if (cc) {
2510 return 24 + cc;
2511 } else {
2512 return 23;
2516 /* Addresses computation */
2517 void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
2519 tcg_gen_add_tl(ret, arg0, arg1);
2521 #if defined(TARGET_MIPS64)
2522 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2523 tcg_gen_ext32s_i64(ret, ret);
2525 #endif
2528 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2529 target_long ofs)
2531 tcg_gen_addi_tl(ret, base, ofs);
2533 #if defined(TARGET_MIPS64)
2534 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2535 tcg_gen_ext32s_i64(ret, ret);
2537 #endif
2540 /* Addresses computation (translation time) */
2541 static target_long addr_add(DisasContext *ctx, target_long base,
2542 target_long offset)
2544 target_long sum = base + offset;
2546 #if defined(TARGET_MIPS64)
2547 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2548 sum = (int32_t)sum;
2550 #endif
2551 return sum;
2554 /* Sign-extract the low 32-bits to a target_long. */
2555 void gen_move_low32(TCGv ret, TCGv_i64 arg)
2557 #if defined(TARGET_MIPS64)
2558 tcg_gen_ext32s_i64(ret, arg);
2559 #else
2560 tcg_gen_extrl_i64_i32(ret, arg);
2561 #endif
2564 /* Sign-extract the high 32-bits to a target_long. */
2565 void gen_move_high32(TCGv ret, TCGv_i64 arg)
2567 #if defined(TARGET_MIPS64)
2568 tcg_gen_sari_i64(ret, arg, 32);
2569 #else
2570 tcg_gen_extrh_i64_i32(ret, arg);
2571 #endif
2574 void check_cp0_enabled(DisasContext *ctx)
2576 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
2577 generate_exception_end(ctx, EXCP_CpU);
2581 void check_cp1_enabled(DisasContext *ctx)
2583 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) {
2584 generate_exception_err(ctx, EXCP_CpU, 1);
2589 * Verify that the processor is running with COP1X instructions enabled.
2590 * This is associated with the nabla symbol in the MIPS32 and MIPS64
2591 * opcode tables.
2593 void check_cop1x(DisasContext *ctx)
2595 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) {
2596 gen_reserved_instruction(ctx);
2601 * Verify that the processor is running with 64-bit floating-point
2602 * operations enabled.
2604 void check_cp1_64bitmode(DisasContext *ctx)
2606 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) {
2607 gen_reserved_instruction(ctx);
2612 * Verify if floating point register is valid; an operation is not defined
2613 * if bit 0 of any register specification is set and the FR bit in the
2614 * Status register equals zero, since the register numbers specify an
2615 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2616 * in the Status register equals one, both even and odd register numbers
2617 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2619 * Multiple 64 bit wide registers can be checked by calling
2620 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2622 void check_cp1_registers(DisasContext *ctx, int regs)
2624 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) {
2625 gen_reserved_instruction(ctx);
2630 * Verify that the processor is running with DSP instructions enabled.
2631 * This is enabled by CP0 Status register MX(24) bit.
2633 static inline void check_dsp(DisasContext *ctx)
2635 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
2636 if (ctx->insn_flags & ASE_DSP) {
2637 generate_exception_end(ctx, EXCP_DSPDIS);
2638 } else {
2639 gen_reserved_instruction(ctx);
2644 static inline void check_dsp_r2(DisasContext *ctx)
2646 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
2647 if (ctx->insn_flags & ASE_DSP) {
2648 generate_exception_end(ctx, EXCP_DSPDIS);
2649 } else {
2650 gen_reserved_instruction(ctx);
2655 static inline void check_dsp_r3(DisasContext *ctx)
2657 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
2658 if (ctx->insn_flags & ASE_DSP) {
2659 generate_exception_end(ctx, EXCP_DSPDIS);
2660 } else {
2661 gen_reserved_instruction(ctx);
2667 * This code generates a "reserved instruction" exception if the
2668 * CPU does not support the instruction set corresponding to flags.
2670 void check_insn(DisasContext *ctx, uint64_t flags)
2672 if (unlikely(!(ctx->insn_flags & flags))) {
2673 gen_reserved_instruction(ctx);
2678 * This code generates a "reserved instruction" exception if the
2679 * CPU has corresponding flag set which indicates that the instruction
2680 * has been removed.
2682 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
2684 if (unlikely(ctx->insn_flags & flags)) {
2685 gen_reserved_instruction(ctx);
2690 * The Linux kernel traps certain reserved instruction exceptions to
2691 * emulate the corresponding instructions. QEMU is the kernel in user
2692 * mode, so those traps are emulated by accepting the instructions.
2694 * A reserved instruction exception is generated for flagged CPUs if
2695 * QEMU runs in system mode.
2697 static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
2699 #ifndef CONFIG_USER_ONLY
2700 check_insn_opc_removed(ctx, flags);
2701 #endif
2705 * This code generates a "reserved instruction" exception if the
2706 * CPU does not support 64-bit paired-single (PS) floating point data type.
2708 static inline void check_ps(DisasContext *ctx)
2710 if (unlikely(!ctx->ps)) {
2711 generate_exception(ctx, EXCP_RI);
2713 check_cp1_64bitmode(ctx);
2717 * This code generates a "reserved instruction" exception if cpu is not
2718 * 64-bit or 64-bit instructions are not enabled.
2720 void check_mips_64(DisasContext *ctx)
2722 if (unlikely((TARGET_LONG_BITS != 64) || !(ctx->hflags & MIPS_HFLAG_64))) {
2723 gen_reserved_instruction(ctx);
2727 #ifndef CONFIG_USER_ONLY
2728 static inline void check_mvh(DisasContext *ctx)
2730 if (unlikely(!ctx->mvh)) {
2731 generate_exception(ctx, EXCP_RI);
2734 #endif
2737 * This code generates a "reserved instruction" exception if the
2738 * Config5 XNP bit is set.
2740 static inline void check_xnp(DisasContext *ctx)
2742 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
2743 gen_reserved_instruction(ctx);
2747 #ifndef CONFIG_USER_ONLY
2749 * This code generates a "reserved instruction" exception if the
2750 * Config3 PW bit is NOT set.
2752 static inline void check_pw(DisasContext *ctx)
2754 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
2755 gen_reserved_instruction(ctx);
2758 #endif
2761 * This code generates a "reserved instruction" exception if the
2762 * Config3 MT bit is NOT set.
2764 static inline void check_mt(DisasContext *ctx)
2766 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
2767 gen_reserved_instruction(ctx);
2771 #ifndef CONFIG_USER_ONLY
2773 * This code generates a "coprocessor unusable" exception if CP0 is not
2774 * available, and, if that is not the case, generates a "reserved instruction"
2775 * exception if the Config5 MT bit is NOT set. This is needed for availability
2776 * control of some of MT ASE instructions.
2778 static inline void check_cp0_mt(DisasContext *ctx)
2780 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
2781 generate_exception_end(ctx, EXCP_CpU);
2782 } else {
2783 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
2784 gen_reserved_instruction(ctx);
2788 #endif
2791 * This code generates a "reserved instruction" exception if the
2792 * Config5 NMS bit is set.
2794 static inline void check_nms(DisasContext *ctx)
2796 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
2797 gen_reserved_instruction(ctx);
2802 * This code generates a "reserved instruction" exception if the
2803 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
2804 * Config2 TL, and Config5 L2C are unset.
2806 static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
2808 if (unlikely((ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
2809 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
2810 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
2811 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
2812 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
2813 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))) {
2814 gen_reserved_instruction(ctx);
2819 * This code generates a "reserved instruction" exception if the
2820 * Config5 EVA bit is NOT set.
2822 static inline void check_eva(DisasContext *ctx)
2824 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
2825 gen_reserved_instruction(ctx);
2831 * Define small wrappers for gen_load_fpr* so that we have a uniform
2832 * calling interface for 32 and 64-bit FPRs. No sense in changing
2833 * all callers for gen_load_fpr32 when we need the CTX parameter for
2834 * this one use.
2836 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
2837 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
2838 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
2839 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
2840 int ft, int fs, int cc) \
2842 TCGv_i##bits fp0 = tcg_temp_new_i##bits(); \
2843 TCGv_i##bits fp1 = tcg_temp_new_i##bits(); \
2844 switch (ifmt) { \
2845 case FMT_PS: \
2846 check_ps(ctx); \
2847 break; \
2848 case FMT_D: \
2849 if (abs) { \
2850 check_cop1x(ctx); \
2852 check_cp1_registers(ctx, fs | ft); \
2853 break; \
2854 case FMT_S: \
2855 if (abs) { \
2856 check_cop1x(ctx); \
2858 break; \
2860 gen_ldcmp_fpr##bits(ctx, fp0, fs); \
2861 gen_ldcmp_fpr##bits(ctx, fp1, ft); \
2862 switch (n) { \
2863 case 0: \
2864 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); \
2865 break; \
2866 case 1: \
2867 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); \
2868 break; \
2869 case 2: \
2870 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); \
2871 break; \
2872 case 3: \
2873 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); \
2874 break; \
2875 case 4: \
2876 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); \
2877 break; \
2878 case 5: \
2879 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); \
2880 break; \
2881 case 6: \
2882 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); \
2883 break; \
2884 case 7: \
2885 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); \
2886 break; \
2887 case 8: \
2888 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); \
2889 break; \
2890 case 9: \
2891 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); \
2892 break; \
2893 case 10: \
2894 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); \
2895 break; \
2896 case 11: \
2897 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); \
2898 break; \
2899 case 12: \
2900 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); \
2901 break; \
2902 case 13: \
2903 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); \
2904 break; \
2905 case 14: \
2906 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); \
2907 break; \
2908 case 15: \
2909 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); \
2910 break; \
2911 default: \
2912 abort(); \
2914 tcg_temp_free_i##bits(fp0); \
2915 tcg_temp_free_i##bits(fp1); \
2918 FOP_CONDS(, 0, d, FMT_D, 64)
2919 FOP_CONDS(abs, 1, d, FMT_D, 64)
2920 FOP_CONDS(, 0, s, FMT_S, 32)
2921 FOP_CONDS(abs, 1, s, FMT_S, 32)
2922 FOP_CONDS(, 0, ps, FMT_PS, 64)
2923 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
2924 #undef FOP_CONDS
2926 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
2927 static inline void gen_r6_cmp_ ## fmt(DisasContext *ctx, int n, \
2928 int ft, int fs, int fd) \
2930 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
2931 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
2932 if (ifmt == FMT_D) { \
2933 check_cp1_registers(ctx, fs | ft | fd); \
2935 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
2936 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
2937 switch (n) { \
2938 case 0: \
2939 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
2940 break; \
2941 case 1: \
2942 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
2943 break; \
2944 case 2: \
2945 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
2946 break; \
2947 case 3: \
2948 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
2949 break; \
2950 case 4: \
2951 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
2952 break; \
2953 case 5: \
2954 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
2955 break; \
2956 case 6: \
2957 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
2958 break; \
2959 case 7: \
2960 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
2961 break; \
2962 case 8: \
2963 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
2964 break; \
2965 case 9: \
2966 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
2967 break; \
2968 case 10: \
2969 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
2970 break; \
2971 case 11: \
2972 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
2973 break; \
2974 case 12: \
2975 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
2976 break; \
2977 case 13: \
2978 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
2979 break; \
2980 case 14: \
2981 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
2982 break; \
2983 case 15: \
2984 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
2985 break; \
2986 case 17: \
2987 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
2988 break; \
2989 case 18: \
2990 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
2991 break; \
2992 case 19: \
2993 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
2994 break; \
2995 case 25: \
2996 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
2997 break; \
2998 case 26: \
2999 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
3000 break; \
3001 case 27: \
3002 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
3003 break; \
3004 default: \
3005 abort(); \
3007 STORE; \
3008 tcg_temp_free_i ## bits(fp0); \
3009 tcg_temp_free_i ## bits(fp1); \
3012 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
3013 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3014 #undef FOP_CONDNS
3015 #undef gen_ldcmp_fpr32
3016 #undef gen_ldcmp_fpr64
3018 /* load/store instructions. */
3019 #ifdef CONFIG_USER_ONLY
3020 #define OP_LD_ATOMIC(insn, fname) \
3021 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3022 DisasContext *ctx) \
3024 TCGv t0 = tcg_temp_new(); \
3025 tcg_gen_mov_tl(t0, arg1); \
3026 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
3027 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3028 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
3029 tcg_temp_free(t0); \
3031 #else
3032 #define OP_LD_ATOMIC(insn, fname) \
3033 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3034 DisasContext *ctx) \
3036 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
3038 #endif
3039 OP_LD_ATOMIC(ll, ld32s);
3040 #if defined(TARGET_MIPS64)
3041 OP_LD_ATOMIC(lld, ld64);
3042 #endif
3043 #undef OP_LD_ATOMIC
3045 void gen_base_offset_addr(DisasContext *ctx, TCGv addr, int base, int offset)
3047 if (base == 0) {
3048 tcg_gen_movi_tl(addr, offset);
3049 } else if (offset == 0) {
3050 gen_load_gpr(addr, base);
3051 } else {
3052 tcg_gen_movi_tl(addr, offset);
3053 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
3057 static target_ulong pc_relative_pc(DisasContext *ctx)
3059 target_ulong pc = ctx->base.pc_next;
3061 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3062 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
3064 pc -= branch_bytes;
3067 pc &= ~(target_ulong)3;
3068 return pc;
3071 /* Load */
3072 static void gen_ld(DisasContext *ctx, uint32_t opc,
3073 int rt, int base, int offset)
3075 TCGv t0, t1, t2;
3076 int mem_idx = ctx->mem_idx;
3078 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F |
3079 INSN_LOONGSON3A)) {
3081 * Loongson CPU uses a load to zero register for prefetch.
3082 * We emulate it as a NOP. On other CPU we must perform the
3083 * actual memory access.
3085 return;
3088 t0 = tcg_temp_new();
3089 gen_base_offset_addr(ctx, t0, base, offset);
3091 switch (opc) {
3092 #if defined(TARGET_MIPS64)
3093 case OPC_LWU:
3094 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
3095 ctx->default_tcg_memop_mask);
3096 gen_store_gpr(t0, rt);
3097 break;
3098 case OPC_LD:
3099 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
3100 ctx->default_tcg_memop_mask);
3101 gen_store_gpr(t0, rt);
3102 break;
3103 case OPC_LLD:
3104 case R6_OPC_LLD:
3105 op_ld_lld(t0, t0, mem_idx, ctx);
3106 gen_store_gpr(t0, rt);
3107 break;
3108 case OPC_LDL:
3109 t1 = tcg_temp_new();
3111 * Do a byte access to possibly trigger a page
3112 * fault with the unaligned address.
3114 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3115 tcg_gen_andi_tl(t1, t0, 7);
3116 #ifndef TARGET_WORDS_BIGENDIAN
3117 tcg_gen_xori_tl(t1, t1, 7);
3118 #endif
3119 tcg_gen_shli_tl(t1, t1, 3);
3120 tcg_gen_andi_tl(t0, t0, ~7);
3121 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3122 tcg_gen_shl_tl(t0, t0, t1);
3123 t2 = tcg_const_tl(-1);
3124 tcg_gen_shl_tl(t2, t2, t1);
3125 gen_load_gpr(t1, rt);
3126 tcg_gen_andc_tl(t1, t1, t2);
3127 tcg_temp_free(t2);
3128 tcg_gen_or_tl(t0, t0, t1);
3129 tcg_temp_free(t1);
3130 gen_store_gpr(t0, rt);
3131 break;
3132 case OPC_LDR:
3133 t1 = tcg_temp_new();
3135 * Do a byte access to possibly trigger a page
3136 * fault with the unaligned address.
3138 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3139 tcg_gen_andi_tl(t1, t0, 7);
3140 #ifdef TARGET_WORDS_BIGENDIAN
3141 tcg_gen_xori_tl(t1, t1, 7);
3142 #endif
3143 tcg_gen_shli_tl(t1, t1, 3);
3144 tcg_gen_andi_tl(t0, t0, ~7);
3145 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3146 tcg_gen_shr_tl(t0, t0, t1);
3147 tcg_gen_xori_tl(t1, t1, 63);
3148 t2 = tcg_const_tl(0xfffffffffffffffeull);
3149 tcg_gen_shl_tl(t2, t2, t1);
3150 gen_load_gpr(t1, rt);
3151 tcg_gen_and_tl(t1, t1, t2);
3152 tcg_temp_free(t2);
3153 tcg_gen_or_tl(t0, t0, t1);
3154 tcg_temp_free(t1);
3155 gen_store_gpr(t0, rt);
3156 break;
3157 case OPC_LDPC:
3158 t1 = tcg_const_tl(pc_relative_pc(ctx));
3159 gen_op_addr_add(ctx, t0, t0, t1);
3160 tcg_temp_free(t1);
3161 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3162 gen_store_gpr(t0, rt);
3163 break;
3164 #endif
3165 case OPC_LWPC:
3166 t1 = tcg_const_tl(pc_relative_pc(ctx));
3167 gen_op_addr_add(ctx, t0, t0, t1);
3168 tcg_temp_free(t1);
3169 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
3170 gen_store_gpr(t0, rt);
3171 break;
3172 case OPC_LWE:
3173 mem_idx = MIPS_HFLAG_UM;
3174 /* fall through */
3175 case OPC_LW:
3176 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
3177 ctx->default_tcg_memop_mask);
3178 gen_store_gpr(t0, rt);
3179 break;
3180 case OPC_LHE:
3181 mem_idx = MIPS_HFLAG_UM;
3182 /* fall through */
3183 case OPC_LH:
3184 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
3185 ctx->default_tcg_memop_mask);
3186 gen_store_gpr(t0, rt);
3187 break;
3188 case OPC_LHUE:
3189 mem_idx = MIPS_HFLAG_UM;
3190 /* fall through */
3191 case OPC_LHU:
3192 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
3193 ctx->default_tcg_memop_mask);
3194 gen_store_gpr(t0, rt);
3195 break;
3196 case OPC_LBE:
3197 mem_idx = MIPS_HFLAG_UM;
3198 /* fall through */
3199 case OPC_LB:
3200 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
3201 gen_store_gpr(t0, rt);
3202 break;
3203 case OPC_LBUE:
3204 mem_idx = MIPS_HFLAG_UM;
3205 /* fall through */
3206 case OPC_LBU:
3207 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
3208 gen_store_gpr(t0, rt);
3209 break;
3210 case OPC_LWLE:
3211 mem_idx = MIPS_HFLAG_UM;
3212 /* fall through */
3213 case OPC_LWL:
3214 t1 = tcg_temp_new();
3216 * Do a byte access to possibly trigger a page
3217 * fault with the unaligned address.
3219 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3220 tcg_gen_andi_tl(t1, t0, 3);
3221 #ifndef TARGET_WORDS_BIGENDIAN
3222 tcg_gen_xori_tl(t1, t1, 3);
3223 #endif
3224 tcg_gen_shli_tl(t1, t1, 3);
3225 tcg_gen_andi_tl(t0, t0, ~3);
3226 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3227 tcg_gen_shl_tl(t0, t0, t1);
3228 t2 = tcg_const_tl(-1);
3229 tcg_gen_shl_tl(t2, t2, t1);
3230 gen_load_gpr(t1, rt);
3231 tcg_gen_andc_tl(t1, t1, t2);
3232 tcg_temp_free(t2);
3233 tcg_gen_or_tl(t0, t0, t1);
3234 tcg_temp_free(t1);
3235 tcg_gen_ext32s_tl(t0, t0);
3236 gen_store_gpr(t0, rt);
3237 break;
3238 case OPC_LWRE:
3239 mem_idx = MIPS_HFLAG_UM;
3240 /* fall through */
3241 case OPC_LWR:
3242 t1 = tcg_temp_new();
3244 * Do a byte access to possibly trigger a page
3245 * fault with the unaligned address.
3247 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3248 tcg_gen_andi_tl(t1, t0, 3);
3249 #ifdef TARGET_WORDS_BIGENDIAN
3250 tcg_gen_xori_tl(t1, t1, 3);
3251 #endif
3252 tcg_gen_shli_tl(t1, t1, 3);
3253 tcg_gen_andi_tl(t0, t0, ~3);
3254 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3255 tcg_gen_shr_tl(t0, t0, t1);
3256 tcg_gen_xori_tl(t1, t1, 31);
3257 t2 = tcg_const_tl(0xfffffffeull);
3258 tcg_gen_shl_tl(t2, t2, t1);
3259 gen_load_gpr(t1, rt);
3260 tcg_gen_and_tl(t1, t1, t2);
3261 tcg_temp_free(t2);
3262 tcg_gen_or_tl(t0, t0, t1);
3263 tcg_temp_free(t1);
3264 tcg_gen_ext32s_tl(t0, t0);
3265 gen_store_gpr(t0, rt);
3266 break;
3267 case OPC_LLE:
3268 mem_idx = MIPS_HFLAG_UM;
3269 /* fall through */
3270 case OPC_LL:
3271 case R6_OPC_LL:
3272 op_ld_ll(t0, t0, mem_idx, ctx);
3273 gen_store_gpr(t0, rt);
3274 break;
3276 tcg_temp_free(t0);
3279 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3280 uint32_t reg1, uint32_t reg2)
3282 TCGv taddr = tcg_temp_new();
3283 TCGv_i64 tval = tcg_temp_new_i64();
3284 TCGv tmp1 = tcg_temp_new();
3285 TCGv tmp2 = tcg_temp_new();
3287 gen_base_offset_addr(ctx, taddr, base, offset);
3288 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3289 #ifdef TARGET_WORDS_BIGENDIAN
3290 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3291 #else
3292 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3293 #endif
3294 gen_store_gpr(tmp1, reg1);
3295 tcg_temp_free(tmp1);
3296 gen_store_gpr(tmp2, reg2);
3297 tcg_temp_free(tmp2);
3298 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3299 tcg_temp_free_i64(tval);
3300 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3301 tcg_temp_free(taddr);
3304 /* Store */
3305 static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
3306 int base, int offset)
3308 TCGv t0 = tcg_temp_new();
3309 TCGv t1 = tcg_temp_new();
3310 int mem_idx = ctx->mem_idx;
3312 gen_base_offset_addr(ctx, t0, base, offset);
3313 gen_load_gpr(t1, rt);
3314 switch (opc) {
3315 #if defined(TARGET_MIPS64)
3316 case OPC_SD:
3317 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
3318 ctx->default_tcg_memop_mask);
3319 break;
3320 case OPC_SDL:
3321 gen_helper_0e2i(sdl, t1, t0, mem_idx);
3322 break;
3323 case OPC_SDR:
3324 gen_helper_0e2i(sdr, t1, t0, mem_idx);
3325 break;
3326 #endif
3327 case OPC_SWE:
3328 mem_idx = MIPS_HFLAG_UM;
3329 /* fall through */
3330 case OPC_SW:
3331 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
3332 ctx->default_tcg_memop_mask);
3333 break;
3334 case OPC_SHE:
3335 mem_idx = MIPS_HFLAG_UM;
3336 /* fall through */
3337 case OPC_SH:
3338 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
3339 ctx->default_tcg_memop_mask);
3340 break;
3341 case OPC_SBE:
3342 mem_idx = MIPS_HFLAG_UM;
3343 /* fall through */
3344 case OPC_SB:
3345 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
3346 break;
3347 case OPC_SWLE:
3348 mem_idx = MIPS_HFLAG_UM;
3349 /* fall through */
3350 case OPC_SWL:
3351 gen_helper_0e2i(swl, t1, t0, mem_idx);
3352 break;
3353 case OPC_SWRE:
3354 mem_idx = MIPS_HFLAG_UM;
3355 /* fall through */
3356 case OPC_SWR:
3357 gen_helper_0e2i(swr, t1, t0, mem_idx);
3358 break;
3360 tcg_temp_free(t0);
3361 tcg_temp_free(t1);
3365 /* Store conditional */
3366 static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
3367 MemOp tcg_mo, bool eva)
3369 TCGv addr, t0, val;
3370 TCGLabel *l1 = gen_new_label();
3371 TCGLabel *done = gen_new_label();
3373 t0 = tcg_temp_new();
3374 addr = tcg_temp_new();
3375 /* compare the address against that of the preceding LL */
3376 gen_base_offset_addr(ctx, addr, base, offset);
3377 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
3378 tcg_temp_free(addr);
3379 tcg_gen_movi_tl(t0, 0);
3380 gen_store_gpr(t0, rt);
3381 tcg_gen_br(done);
3383 gen_set_label(l1);
3384 /* generate cmpxchg */
3385 val = tcg_temp_new();
3386 gen_load_gpr(val, rt);
3387 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
3388 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
3389 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
3390 gen_store_gpr(t0, rt);
3391 tcg_temp_free(val);
3393 gen_set_label(done);
3394 tcg_temp_free(t0);
3398 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
3399 uint32_t reg1, uint32_t reg2, bool eva)
3401 TCGv taddr = tcg_temp_local_new();
3402 TCGv lladdr = tcg_temp_local_new();
3403 TCGv_i64 tval = tcg_temp_new_i64();
3404 TCGv_i64 llval = tcg_temp_new_i64();
3405 TCGv_i64 val = tcg_temp_new_i64();
3406 TCGv tmp1 = tcg_temp_new();
3407 TCGv tmp2 = tcg_temp_new();
3408 TCGLabel *lab_fail = gen_new_label();
3409 TCGLabel *lab_done = gen_new_label();
3411 gen_base_offset_addr(ctx, taddr, base, offset);
3413 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3414 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3416 gen_load_gpr(tmp1, reg1);
3417 gen_load_gpr(tmp2, reg2);
3419 #ifdef TARGET_WORDS_BIGENDIAN
3420 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3421 #else
3422 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3423 #endif
3425 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3426 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
3427 eva ? MIPS_HFLAG_UM : ctx->mem_idx, MO_64);
3428 if (reg1 != 0) {
3429 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3431 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3433 gen_set_label(lab_fail);
3435 if (reg1 != 0) {
3436 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3438 gen_set_label(lab_done);
3439 tcg_gen_movi_tl(lladdr, -1);
3440 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3443 /* Load and store */
3444 static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
3445 TCGv t0)
3448 * Don't do NOP if destination is zero: we must perform the actual
3449 * memory access.
3451 switch (opc) {
3452 case OPC_LWC1:
3454 TCGv_i32 fp0 = tcg_temp_new_i32();
3455 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3456 ctx->default_tcg_memop_mask);
3457 gen_store_fpr32(ctx, fp0, ft);
3458 tcg_temp_free_i32(fp0);
3460 break;
3461 case OPC_SWC1:
3463 TCGv_i32 fp0 = tcg_temp_new_i32();
3464 gen_load_fpr32(ctx, fp0, ft);
3465 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3466 ctx->default_tcg_memop_mask);
3467 tcg_temp_free_i32(fp0);
3469 break;
3470 case OPC_LDC1:
3472 TCGv_i64 fp0 = tcg_temp_new_i64();
3473 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3474 ctx->default_tcg_memop_mask);
3475 gen_store_fpr64(ctx, fp0, ft);
3476 tcg_temp_free_i64(fp0);
3478 break;
3479 case OPC_SDC1:
3481 TCGv_i64 fp0 = tcg_temp_new_i64();
3482 gen_load_fpr64(ctx, fp0, ft);
3483 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3484 ctx->default_tcg_memop_mask);
3485 tcg_temp_free_i64(fp0);
3487 break;
3488 default:
3489 MIPS_INVAL("flt_ldst");
3490 gen_reserved_instruction(ctx);
3491 break;
3495 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3496 int rs, int16_t imm)
3498 TCGv t0 = tcg_temp_new();
3500 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3501 check_cp1_enabled(ctx);
3502 switch (op) {
3503 case OPC_LDC1:
3504 case OPC_SDC1:
3505 check_insn(ctx, ISA_MIPS2);
3506 /* Fallthrough */
3507 default:
3508 gen_base_offset_addr(ctx, t0, rs, imm);
3509 gen_flt_ldst(ctx, op, rt, t0);
3511 } else {
3512 generate_exception_err(ctx, EXCP_CpU, 1);
3514 tcg_temp_free(t0);
3517 /* Arithmetic with immediate operand */
3518 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
3519 int rt, int rs, int imm)
3521 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3523 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
3525 * If no destination, treat it as a NOP.
3526 * For addi, we must generate the overflow exception when needed.
3528 return;
3530 switch (opc) {
3531 case OPC_ADDI:
3533 TCGv t0 = tcg_temp_local_new();
3534 TCGv t1 = tcg_temp_new();
3535 TCGv t2 = tcg_temp_new();
3536 TCGLabel *l1 = gen_new_label();
3538 gen_load_gpr(t1, rs);
3539 tcg_gen_addi_tl(t0, t1, uimm);
3540 tcg_gen_ext32s_tl(t0, t0);
3542 tcg_gen_xori_tl(t1, t1, ~uimm);
3543 tcg_gen_xori_tl(t2, t0, uimm);
3544 tcg_gen_and_tl(t1, t1, t2);
3545 tcg_temp_free(t2);
3546 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3547 tcg_temp_free(t1);
3548 /* operands of same sign, result different sign */
3549 generate_exception(ctx, EXCP_OVERFLOW);
3550 gen_set_label(l1);
3551 tcg_gen_ext32s_tl(t0, t0);
3552 gen_store_gpr(t0, rt);
3553 tcg_temp_free(t0);
3555 break;
3556 case OPC_ADDIU:
3557 if (rs != 0) {
3558 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3559 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3560 } else {
3561 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3563 break;
3564 #if defined(TARGET_MIPS64)
3565 case OPC_DADDI:
3567 TCGv t0 = tcg_temp_local_new();
3568 TCGv t1 = tcg_temp_new();
3569 TCGv t2 = tcg_temp_new();
3570 TCGLabel *l1 = gen_new_label();
3572 gen_load_gpr(t1, rs);
3573 tcg_gen_addi_tl(t0, t1, uimm);
3575 tcg_gen_xori_tl(t1, t1, ~uimm);
3576 tcg_gen_xori_tl(t2, t0, uimm);
3577 tcg_gen_and_tl(t1, t1, t2);
3578 tcg_temp_free(t2);
3579 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3580 tcg_temp_free(t1);
3581 /* operands of same sign, result different sign */
3582 generate_exception(ctx, EXCP_OVERFLOW);
3583 gen_set_label(l1);
3584 gen_store_gpr(t0, rt);
3585 tcg_temp_free(t0);
3587 break;
3588 case OPC_DADDIU:
3589 if (rs != 0) {
3590 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3591 } else {
3592 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3594 break;
3595 #endif
3599 /* Logic with immediate operand */
3600 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
3601 int rt, int rs, int16_t imm)
3603 target_ulong uimm;
3605 if (rt == 0) {
3606 /* If no destination, treat it as a NOP. */
3607 return;
3609 uimm = (uint16_t)imm;
3610 switch (opc) {
3611 case OPC_ANDI:
3612 if (likely(rs != 0)) {
3613 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3614 } else {
3615 tcg_gen_movi_tl(cpu_gpr[rt], 0);
3617 break;
3618 case OPC_ORI:
3619 if (rs != 0) {
3620 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3621 } else {
3622 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3624 break;
3625 case OPC_XORI:
3626 if (likely(rs != 0)) {
3627 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3628 } else {
3629 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3631 break;
3632 case OPC_LUI:
3633 if (rs != 0 && (ctx->insn_flags & ISA_MIPS_R6)) {
3634 /* OPC_AUI */
3635 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3636 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3637 } else {
3638 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
3640 break;
3642 default:
3643 break;
3647 /* Set on less than with immediate operand */
3648 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
3649 int rt, int rs, int16_t imm)
3651 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3652 TCGv t0;
3654 if (rt == 0) {
3655 /* If no destination, treat it as a NOP. */
3656 return;
3658 t0 = tcg_temp_new();
3659 gen_load_gpr(t0, rs);
3660 switch (opc) {
3661 case OPC_SLTI:
3662 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
3663 break;
3664 case OPC_SLTIU:
3665 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
3666 break;
3668 tcg_temp_free(t0);
3671 /* Shifts with immediate operand */
3672 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
3673 int rt, int rs, int16_t imm)
3675 target_ulong uimm = ((uint16_t)imm) & 0x1f;
3676 TCGv t0;
3678 if (rt == 0) {
3679 /* If no destination, treat it as a NOP. */
3680 return;
3683 t0 = tcg_temp_new();
3684 gen_load_gpr(t0, rs);
3685 switch (opc) {
3686 case OPC_SLL:
3687 tcg_gen_shli_tl(t0, t0, uimm);
3688 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3689 break;
3690 case OPC_SRA:
3691 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3692 break;
3693 case OPC_SRL:
3694 if (uimm != 0) {
3695 tcg_gen_ext32u_tl(t0, t0);
3696 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3697 } else {
3698 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3700 break;
3701 case OPC_ROTR:
3702 if (uimm != 0) {
3703 TCGv_i32 t1 = tcg_temp_new_i32();
3705 tcg_gen_trunc_tl_i32(t1, t0);
3706 tcg_gen_rotri_i32(t1, t1, uimm);
3707 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
3708 tcg_temp_free_i32(t1);
3709 } else {
3710 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3712 break;
3713 #if defined(TARGET_MIPS64)
3714 case OPC_DSLL:
3715 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
3716 break;
3717 case OPC_DSRA:
3718 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3719 break;
3720 case OPC_DSRL:
3721 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3722 break;
3723 case OPC_DROTR:
3724 if (uimm != 0) {
3725 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3726 } else {
3727 tcg_gen_mov_tl(cpu_gpr[rt], t0);
3729 break;
3730 case OPC_DSLL32:
3731 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
3732 break;
3733 case OPC_DSRA32:
3734 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
3735 break;
3736 case OPC_DSRL32:
3737 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
3738 break;
3739 case OPC_DROTR32:
3740 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
3741 break;
3742 #endif
3744 tcg_temp_free(t0);
3747 /* Arithmetic */
3748 static void gen_arith(DisasContext *ctx, uint32_t opc,
3749 int rd, int rs, int rt)
3751 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
3752 && opc != OPC_DADD && opc != OPC_DSUB) {
3754 * If no destination, treat it as a NOP.
3755 * For add & sub, we must generate the overflow exception when needed.
3757 return;
3760 switch (opc) {
3761 case OPC_ADD:
3763 TCGv t0 = tcg_temp_local_new();
3764 TCGv t1 = tcg_temp_new();
3765 TCGv t2 = tcg_temp_new();
3766 TCGLabel *l1 = gen_new_label();
3768 gen_load_gpr(t1, rs);
3769 gen_load_gpr(t2, rt);
3770 tcg_gen_add_tl(t0, t1, t2);
3771 tcg_gen_ext32s_tl(t0, t0);
3772 tcg_gen_xor_tl(t1, t1, t2);
3773 tcg_gen_xor_tl(t2, t0, t2);
3774 tcg_gen_andc_tl(t1, t2, t1);
3775 tcg_temp_free(t2);
3776 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3777 tcg_temp_free(t1);
3778 /* operands of same sign, result different sign */
3779 generate_exception(ctx, EXCP_OVERFLOW);
3780 gen_set_label(l1);
3781 gen_store_gpr(t0, rd);
3782 tcg_temp_free(t0);
3784 break;
3785 case OPC_ADDU:
3786 if (rs != 0 && rt != 0) {
3787 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3788 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3789 } else if (rs == 0 && rt != 0) {
3790 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3791 } else if (rs != 0 && rt == 0) {
3792 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3793 } else {
3794 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3796 break;
3797 case OPC_SUB:
3799 TCGv t0 = tcg_temp_local_new();
3800 TCGv t1 = tcg_temp_new();
3801 TCGv t2 = tcg_temp_new();
3802 TCGLabel *l1 = gen_new_label();
3804 gen_load_gpr(t1, rs);
3805 gen_load_gpr(t2, rt);
3806 tcg_gen_sub_tl(t0, t1, t2);
3807 tcg_gen_ext32s_tl(t0, t0);
3808 tcg_gen_xor_tl(t2, t1, t2);
3809 tcg_gen_xor_tl(t1, t0, t1);
3810 tcg_gen_and_tl(t1, t1, t2);
3811 tcg_temp_free(t2);
3812 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3813 tcg_temp_free(t1);
3815 * operands of different sign, first operand and the result
3816 * of different sign
3818 generate_exception(ctx, EXCP_OVERFLOW);
3819 gen_set_label(l1);
3820 gen_store_gpr(t0, rd);
3821 tcg_temp_free(t0);
3823 break;
3824 case OPC_SUBU:
3825 if (rs != 0 && rt != 0) {
3826 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3827 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3828 } else if (rs == 0 && rt != 0) {
3829 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
3830 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3831 } else if (rs != 0 && rt == 0) {
3832 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3833 } else {
3834 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3836 break;
3837 #if defined(TARGET_MIPS64)
3838 case OPC_DADD:
3840 TCGv t0 = tcg_temp_local_new();
3841 TCGv t1 = tcg_temp_new();
3842 TCGv t2 = tcg_temp_new();
3843 TCGLabel *l1 = gen_new_label();
3845 gen_load_gpr(t1, rs);
3846 gen_load_gpr(t2, rt);
3847 tcg_gen_add_tl(t0, t1, t2);
3848 tcg_gen_xor_tl(t1, t1, t2);
3849 tcg_gen_xor_tl(t2, t0, t2);
3850 tcg_gen_andc_tl(t1, t2, t1);
3851 tcg_temp_free(t2);
3852 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3853 tcg_temp_free(t1);
3854 /* operands of same sign, result different sign */
3855 generate_exception(ctx, EXCP_OVERFLOW);
3856 gen_set_label(l1);
3857 gen_store_gpr(t0, rd);
3858 tcg_temp_free(t0);
3860 break;
3861 case OPC_DADDU:
3862 if (rs != 0 && rt != 0) {
3863 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3864 } else if (rs == 0 && rt != 0) {
3865 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3866 } else if (rs != 0 && rt == 0) {
3867 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3868 } else {
3869 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3871 break;
3872 case OPC_DSUB:
3874 TCGv t0 = tcg_temp_local_new();
3875 TCGv t1 = tcg_temp_new();
3876 TCGv t2 = tcg_temp_new();
3877 TCGLabel *l1 = gen_new_label();
3879 gen_load_gpr(t1, rs);
3880 gen_load_gpr(t2, rt);
3881 tcg_gen_sub_tl(t0, t1, t2);
3882 tcg_gen_xor_tl(t2, t1, t2);
3883 tcg_gen_xor_tl(t1, t0, t1);
3884 tcg_gen_and_tl(t1, t1, t2);
3885 tcg_temp_free(t2);
3886 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3887 tcg_temp_free(t1);
3889 * Operands of different sign, first operand and result different
3890 * sign.
3892 generate_exception(ctx, EXCP_OVERFLOW);
3893 gen_set_label(l1);
3894 gen_store_gpr(t0, rd);
3895 tcg_temp_free(t0);
3897 break;
3898 case OPC_DSUBU:
3899 if (rs != 0 && rt != 0) {
3900 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3901 } else if (rs == 0 && rt != 0) {
3902 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
3903 } else if (rs != 0 && rt == 0) {
3904 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3905 } else {
3906 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3908 break;
3909 #endif
3910 case OPC_MUL:
3911 if (likely(rs != 0 && rt != 0)) {
3912 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3913 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3914 } else {
3915 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3917 break;
3921 /* Conditional move */
3922 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
3923 int rd, int rs, int rt)
3925 TCGv t0, t1, t2;
3927 if (rd == 0) {
3928 /* If no destination, treat it as a NOP. */
3929 return;
3932 t0 = tcg_temp_new();
3933 gen_load_gpr(t0, rt);
3934 t1 = tcg_const_tl(0);
3935 t2 = tcg_temp_new();
3936 gen_load_gpr(t2, rs);
3937 switch (opc) {
3938 case OPC_MOVN:
3939 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
3940 break;
3941 case OPC_MOVZ:
3942 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
3943 break;
3944 case OPC_SELNEZ:
3945 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
3946 break;
3947 case OPC_SELEQZ:
3948 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
3949 break;
3951 tcg_temp_free(t2);
3952 tcg_temp_free(t1);
3953 tcg_temp_free(t0);
3956 /* Logic */
3957 static void gen_logic(DisasContext *ctx, uint32_t opc,
3958 int rd, int rs, int rt)
3960 if (rd == 0) {
3961 /* If no destination, treat it as a NOP. */
3962 return;
3965 switch (opc) {
3966 case OPC_AND:
3967 if (likely(rs != 0 && rt != 0)) {
3968 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3969 } else {
3970 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3972 break;
3973 case OPC_NOR:
3974 if (rs != 0 && rt != 0) {
3975 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3976 } else if (rs == 0 && rt != 0) {
3977 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
3978 } else if (rs != 0 && rt == 0) {
3979 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
3980 } else {
3981 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
3983 break;
3984 case OPC_OR:
3985 if (likely(rs != 0 && rt != 0)) {
3986 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3987 } else if (rs == 0 && rt != 0) {
3988 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3989 } else if (rs != 0 && rt == 0) {
3990 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3991 } else {
3992 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3994 break;
3995 case OPC_XOR:
3996 if (likely(rs != 0 && rt != 0)) {
3997 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3998 } else if (rs == 0 && rt != 0) {
3999 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4000 } else if (rs != 0 && rt == 0) {
4001 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4002 } else {
4003 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4005 break;
4009 /* Set on lower than */
4010 static void gen_slt(DisasContext *ctx, uint32_t opc,
4011 int rd, int rs, int rt)
4013 TCGv t0, t1;
4015 if (rd == 0) {
4016 /* If no destination, treat it as a NOP. */
4017 return;
4020 t0 = tcg_temp_new();
4021 t1 = tcg_temp_new();
4022 gen_load_gpr(t0, rs);
4023 gen_load_gpr(t1, rt);
4024 switch (opc) {
4025 case OPC_SLT:
4026 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
4027 break;
4028 case OPC_SLTU:
4029 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
4030 break;
4032 tcg_temp_free(t0);
4033 tcg_temp_free(t1);
4036 /* Shifts */
4037 static void gen_shift(DisasContext *ctx, uint32_t opc,
4038 int rd, int rs, int rt)
4040 TCGv t0, t1;
4042 if (rd == 0) {
4044 * If no destination, treat it as a NOP.
4045 * For add & sub, we must generate the overflow exception when needed.
4047 return;
4050 t0 = tcg_temp_new();
4051 t1 = tcg_temp_new();
4052 gen_load_gpr(t0, rs);
4053 gen_load_gpr(t1, rt);
4054 switch (opc) {
4055 case OPC_SLLV:
4056 tcg_gen_andi_tl(t0, t0, 0x1f);
4057 tcg_gen_shl_tl(t0, t1, t0);
4058 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4059 break;
4060 case OPC_SRAV:
4061 tcg_gen_andi_tl(t0, t0, 0x1f);
4062 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4063 break;
4064 case OPC_SRLV:
4065 tcg_gen_ext32u_tl(t1, t1);
4066 tcg_gen_andi_tl(t0, t0, 0x1f);
4067 tcg_gen_shr_tl(t0, t1, t0);
4068 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4069 break;
4070 case OPC_ROTRV:
4072 TCGv_i32 t2 = tcg_temp_new_i32();
4073 TCGv_i32 t3 = tcg_temp_new_i32();
4075 tcg_gen_trunc_tl_i32(t2, t0);
4076 tcg_gen_trunc_tl_i32(t3, t1);
4077 tcg_gen_andi_i32(t2, t2, 0x1f);
4078 tcg_gen_rotr_i32(t2, t3, t2);
4079 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4080 tcg_temp_free_i32(t2);
4081 tcg_temp_free_i32(t3);
4083 break;
4084 #if defined(TARGET_MIPS64)
4085 case OPC_DSLLV:
4086 tcg_gen_andi_tl(t0, t0, 0x3f);
4087 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
4088 break;
4089 case OPC_DSRAV:
4090 tcg_gen_andi_tl(t0, t0, 0x3f);
4091 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4092 break;
4093 case OPC_DSRLV:
4094 tcg_gen_andi_tl(t0, t0, 0x3f);
4095 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
4096 break;
4097 case OPC_DROTRV:
4098 tcg_gen_andi_tl(t0, t0, 0x3f);
4099 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
4100 break;
4101 #endif
4103 tcg_temp_free(t0);
4104 tcg_temp_free(t1);
4107 #if defined(TARGET_MIPS64)
4108 /* Copy GPR to and from TX79 HI1/LO1 register. */
4109 static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg)
4111 if (reg == 0 && (opc == MMI_OPC_MFHI1 || opc == MMI_OPC_MFLO1)) {
4112 /* Treat as NOP. */
4113 return;
4116 switch (opc) {
4117 case MMI_OPC_MFHI1:
4118 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[1]);
4119 break;
4120 case MMI_OPC_MFLO1:
4121 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[1]);
4122 break;
4123 case MMI_OPC_MTHI1:
4124 if (reg != 0) {
4125 tcg_gen_mov_tl(cpu_HI[1], cpu_gpr[reg]);
4126 } else {
4127 tcg_gen_movi_tl(cpu_HI[1], 0);
4129 break;
4130 case MMI_OPC_MTLO1:
4131 if (reg != 0) {
4132 tcg_gen_mov_tl(cpu_LO[1], cpu_gpr[reg]);
4133 } else {
4134 tcg_gen_movi_tl(cpu_LO[1], 0);
4136 break;
4137 default:
4138 MIPS_INVAL("mfthilo1 TX79");
4139 gen_reserved_instruction(ctx);
4140 break;
4143 #endif
4145 /* Arithmetic on HI/LO registers */
4146 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
4148 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
4149 /* Treat as NOP. */
4150 return;
4153 if (acc != 0) {
4154 check_dsp(ctx);
4157 switch (opc) {
4158 case OPC_MFHI:
4159 #if defined(TARGET_MIPS64)
4160 if (acc != 0) {
4161 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
4162 } else
4163 #endif
4165 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
4167 break;
4168 case OPC_MFLO:
4169 #if defined(TARGET_MIPS64)
4170 if (acc != 0) {
4171 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
4172 } else
4173 #endif
4175 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
4177 break;
4178 case OPC_MTHI:
4179 if (reg != 0) {
4180 #if defined(TARGET_MIPS64)
4181 if (acc != 0) {
4182 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
4183 } else
4184 #endif
4186 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
4188 } else {
4189 tcg_gen_movi_tl(cpu_HI[acc], 0);
4191 break;
4192 case OPC_MTLO:
4193 if (reg != 0) {
4194 #if defined(TARGET_MIPS64)
4195 if (acc != 0) {
4196 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
4197 } else
4198 #endif
4200 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
4202 } else {
4203 tcg_gen_movi_tl(cpu_LO[acc], 0);
4205 break;
4209 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
4210 MemOp memop)
4212 TCGv t0 = tcg_const_tl(addr);
4213 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
4214 gen_store_gpr(t0, reg);
4215 tcg_temp_free(t0);
4218 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
4219 int rs)
4221 target_long offset;
4222 target_long addr;
4224 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
4225 case OPC_ADDIUPC:
4226 if (rs != 0) {
4227 offset = sextract32(ctx->opcode << 2, 0, 21);
4228 addr = addr_add(ctx, pc, offset);
4229 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4231 break;
4232 case R6_OPC_LWPC:
4233 offset = sextract32(ctx->opcode << 2, 0, 21);
4234 addr = addr_add(ctx, pc, offset);
4235 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4236 break;
4237 #if defined(TARGET_MIPS64)
4238 case OPC_LWUPC:
4239 check_mips_64(ctx);
4240 offset = sextract32(ctx->opcode << 2, 0, 21);
4241 addr = addr_add(ctx, pc, offset);
4242 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4243 break;
4244 #endif
4245 default:
4246 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
4247 case OPC_AUIPC:
4248 if (rs != 0) {
4249 offset = sextract32(ctx->opcode, 0, 16) << 16;
4250 addr = addr_add(ctx, pc, offset);
4251 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4253 break;
4254 case OPC_ALUIPC:
4255 if (rs != 0) {
4256 offset = sextract32(ctx->opcode, 0, 16) << 16;
4257 addr = ~0xFFFF & addr_add(ctx, pc, offset);
4258 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4260 break;
4261 #if defined(TARGET_MIPS64)
4262 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4263 case R6_OPC_LDPC + (1 << 16):
4264 case R6_OPC_LDPC + (2 << 16):
4265 case R6_OPC_LDPC + (3 << 16):
4266 check_mips_64(ctx);
4267 offset = sextract32(ctx->opcode << 3, 0, 21);
4268 addr = addr_add(ctx, (pc & ~0x7), offset);
4269 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4270 break;
4271 #endif
4272 default:
4273 MIPS_INVAL("OPC_PCREL");
4274 gen_reserved_instruction(ctx);
4275 break;
4277 break;
4281 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4283 TCGv t0, t1;
4285 if (rd == 0) {
4286 /* Treat as NOP. */
4287 return;
4290 t0 = tcg_temp_new();
4291 t1 = tcg_temp_new();
4293 gen_load_gpr(t0, rs);
4294 gen_load_gpr(t1, rt);
4296 switch (opc) {
4297 case R6_OPC_DIV:
4299 TCGv t2 = tcg_temp_new();
4300 TCGv t3 = tcg_temp_new();
4301 tcg_gen_ext32s_tl(t0, t0);
4302 tcg_gen_ext32s_tl(t1, t1);
4303 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4304 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4305 tcg_gen_and_tl(t2, t2, t3);
4306 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4307 tcg_gen_or_tl(t2, t2, t3);
4308 tcg_gen_movi_tl(t3, 0);
4309 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4310 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4311 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4312 tcg_temp_free(t3);
4313 tcg_temp_free(t2);
4315 break;
4316 case R6_OPC_MOD:
4318 TCGv t2 = tcg_temp_new();
4319 TCGv t3 = tcg_temp_new();
4320 tcg_gen_ext32s_tl(t0, t0);
4321 tcg_gen_ext32s_tl(t1, t1);
4322 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4323 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4324 tcg_gen_and_tl(t2, t2, t3);
4325 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4326 tcg_gen_or_tl(t2, t2, t3);
4327 tcg_gen_movi_tl(t3, 0);
4328 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4329 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4330 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4331 tcg_temp_free(t3);
4332 tcg_temp_free(t2);
4334 break;
4335 case R6_OPC_DIVU:
4337 TCGv t2 = tcg_const_tl(0);
4338 TCGv t3 = tcg_const_tl(1);
4339 tcg_gen_ext32u_tl(t0, t0);
4340 tcg_gen_ext32u_tl(t1, t1);
4341 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4342 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4343 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4344 tcg_temp_free(t3);
4345 tcg_temp_free(t2);
4347 break;
4348 case R6_OPC_MODU:
4350 TCGv t2 = tcg_const_tl(0);
4351 TCGv t3 = tcg_const_tl(1);
4352 tcg_gen_ext32u_tl(t0, t0);
4353 tcg_gen_ext32u_tl(t1, t1);
4354 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4355 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4356 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4357 tcg_temp_free(t3);
4358 tcg_temp_free(t2);
4360 break;
4361 case R6_OPC_MUL:
4363 TCGv_i32 t2 = tcg_temp_new_i32();
4364 TCGv_i32 t3 = tcg_temp_new_i32();
4365 tcg_gen_trunc_tl_i32(t2, t0);
4366 tcg_gen_trunc_tl_i32(t3, t1);
4367 tcg_gen_mul_i32(t2, t2, t3);
4368 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4369 tcg_temp_free_i32(t2);
4370 tcg_temp_free_i32(t3);
4372 break;
4373 case R6_OPC_MUH:
4375 TCGv_i32 t2 = tcg_temp_new_i32();
4376 TCGv_i32 t3 = tcg_temp_new_i32();
4377 tcg_gen_trunc_tl_i32(t2, t0);
4378 tcg_gen_trunc_tl_i32(t3, t1);
4379 tcg_gen_muls2_i32(t2, t3, t2, t3);
4380 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4381 tcg_temp_free_i32(t2);
4382 tcg_temp_free_i32(t3);
4384 break;
4385 case R6_OPC_MULU:
4387 TCGv_i32 t2 = tcg_temp_new_i32();
4388 TCGv_i32 t3 = tcg_temp_new_i32();
4389 tcg_gen_trunc_tl_i32(t2, t0);
4390 tcg_gen_trunc_tl_i32(t3, t1);
4391 tcg_gen_mul_i32(t2, t2, t3);
4392 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4393 tcg_temp_free_i32(t2);
4394 tcg_temp_free_i32(t3);
4396 break;
4397 case R6_OPC_MUHU:
4399 TCGv_i32 t2 = tcg_temp_new_i32();
4400 TCGv_i32 t3 = tcg_temp_new_i32();
4401 tcg_gen_trunc_tl_i32(t2, t0);
4402 tcg_gen_trunc_tl_i32(t3, t1);
4403 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4404 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4405 tcg_temp_free_i32(t2);
4406 tcg_temp_free_i32(t3);
4408 break;
4409 #if defined(TARGET_MIPS64)
4410 case R6_OPC_DDIV:
4412 TCGv t2 = tcg_temp_new();
4413 TCGv t3 = tcg_temp_new();
4414 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4415 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4416 tcg_gen_and_tl(t2, t2, t3);
4417 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4418 tcg_gen_or_tl(t2, t2, t3);
4419 tcg_gen_movi_tl(t3, 0);
4420 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4421 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4422 tcg_temp_free(t3);
4423 tcg_temp_free(t2);
4425 break;
4426 case R6_OPC_DMOD:
4428 TCGv t2 = tcg_temp_new();
4429 TCGv t3 = tcg_temp_new();
4430 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4431 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4432 tcg_gen_and_tl(t2, t2, t3);
4433 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4434 tcg_gen_or_tl(t2, t2, t3);
4435 tcg_gen_movi_tl(t3, 0);
4436 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4437 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4438 tcg_temp_free(t3);
4439 tcg_temp_free(t2);
4441 break;
4442 case R6_OPC_DDIVU:
4444 TCGv t2 = tcg_const_tl(0);
4445 TCGv t3 = tcg_const_tl(1);
4446 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4447 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4448 tcg_temp_free(t3);
4449 tcg_temp_free(t2);
4451 break;
4452 case R6_OPC_DMODU:
4454 TCGv t2 = tcg_const_tl(0);
4455 TCGv t3 = tcg_const_tl(1);
4456 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4457 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4458 tcg_temp_free(t3);
4459 tcg_temp_free(t2);
4461 break;
4462 case R6_OPC_DMUL:
4463 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4464 break;
4465 case R6_OPC_DMUH:
4467 TCGv t2 = tcg_temp_new();
4468 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4469 tcg_temp_free(t2);
4471 break;
4472 case R6_OPC_DMULU:
4473 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4474 break;
4475 case R6_OPC_DMUHU:
4477 TCGv t2 = tcg_temp_new();
4478 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4479 tcg_temp_free(t2);
4481 break;
4482 #endif
4483 default:
4484 MIPS_INVAL("r6 mul/div");
4485 gen_reserved_instruction(ctx);
4486 goto out;
4488 out:
4489 tcg_temp_free(t0);
4490 tcg_temp_free(t1);
4493 #if defined(TARGET_MIPS64)
4494 static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
4496 TCGv t0, t1;
4498 t0 = tcg_temp_new();
4499 t1 = tcg_temp_new();
4501 gen_load_gpr(t0, rs);
4502 gen_load_gpr(t1, rt);
4504 switch (opc) {
4505 case MMI_OPC_DIV1:
4507 TCGv t2 = tcg_temp_new();
4508 TCGv t3 = tcg_temp_new();
4509 tcg_gen_ext32s_tl(t0, t0);
4510 tcg_gen_ext32s_tl(t1, t1);
4511 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4512 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4513 tcg_gen_and_tl(t2, t2, t3);
4514 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4515 tcg_gen_or_tl(t2, t2, t3);
4516 tcg_gen_movi_tl(t3, 0);
4517 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4518 tcg_gen_div_tl(cpu_LO[1], t0, t1);
4519 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
4520 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4521 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4522 tcg_temp_free(t3);
4523 tcg_temp_free(t2);
4525 break;
4526 case MMI_OPC_DIVU1:
4528 TCGv t2 = tcg_const_tl(0);
4529 TCGv t3 = tcg_const_tl(1);
4530 tcg_gen_ext32u_tl(t0, t0);
4531 tcg_gen_ext32u_tl(t1, t1);
4532 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4533 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
4534 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
4535 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4536 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4537 tcg_temp_free(t3);
4538 tcg_temp_free(t2);
4540 break;
4541 default:
4542 MIPS_INVAL("div1 TX79");
4543 gen_reserved_instruction(ctx);
4544 goto out;
4546 out:
4547 tcg_temp_free(t0);
4548 tcg_temp_free(t1);
4550 #endif
4552 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4553 int acc, int rs, int rt)
4555 TCGv t0, t1;
4557 t0 = tcg_temp_new();
4558 t1 = tcg_temp_new();
4560 gen_load_gpr(t0, rs);
4561 gen_load_gpr(t1, rt);
4563 if (acc != 0) {
4564 check_dsp(ctx);
4567 switch (opc) {
4568 case OPC_DIV:
4570 TCGv t2 = tcg_temp_new();
4571 TCGv t3 = tcg_temp_new();
4572 tcg_gen_ext32s_tl(t0, t0);
4573 tcg_gen_ext32s_tl(t1, t1);
4574 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4575 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4576 tcg_gen_and_tl(t2, t2, t3);
4577 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4578 tcg_gen_or_tl(t2, t2, t3);
4579 tcg_gen_movi_tl(t3, 0);
4580 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4581 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4582 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4583 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4584 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4585 tcg_temp_free(t3);
4586 tcg_temp_free(t2);
4588 break;
4589 case OPC_DIVU:
4591 TCGv t2 = tcg_const_tl(0);
4592 TCGv t3 = tcg_const_tl(1);
4593 tcg_gen_ext32u_tl(t0, t0);
4594 tcg_gen_ext32u_tl(t1, t1);
4595 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4596 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4597 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4598 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4599 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4600 tcg_temp_free(t3);
4601 tcg_temp_free(t2);
4603 break;
4604 case OPC_MULT:
4606 TCGv_i32 t2 = tcg_temp_new_i32();
4607 TCGv_i32 t3 = tcg_temp_new_i32();
4608 tcg_gen_trunc_tl_i32(t2, t0);
4609 tcg_gen_trunc_tl_i32(t3, t1);
4610 tcg_gen_muls2_i32(t2, t3, t2, t3);
4611 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4612 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4613 tcg_temp_free_i32(t2);
4614 tcg_temp_free_i32(t3);
4616 break;
4617 case OPC_MULTU:
4619 TCGv_i32 t2 = tcg_temp_new_i32();
4620 TCGv_i32 t3 = tcg_temp_new_i32();
4621 tcg_gen_trunc_tl_i32(t2, t0);
4622 tcg_gen_trunc_tl_i32(t3, t1);
4623 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4624 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4625 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4626 tcg_temp_free_i32(t2);
4627 tcg_temp_free_i32(t3);
4629 break;
4630 #if defined(TARGET_MIPS64)
4631 case OPC_DDIV:
4633 TCGv t2 = tcg_temp_new();
4634 TCGv t3 = tcg_temp_new();
4635 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4636 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4637 tcg_gen_and_tl(t2, t2, t3);
4638 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4639 tcg_gen_or_tl(t2, t2, t3);
4640 tcg_gen_movi_tl(t3, 0);
4641 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4642 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4643 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4644 tcg_temp_free(t3);
4645 tcg_temp_free(t2);
4647 break;
4648 case OPC_DDIVU:
4650 TCGv t2 = tcg_const_tl(0);
4651 TCGv t3 = tcg_const_tl(1);
4652 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4653 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
4654 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
4655 tcg_temp_free(t3);
4656 tcg_temp_free(t2);
4658 break;
4659 case OPC_DMULT:
4660 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4661 break;
4662 case OPC_DMULTU:
4663 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4664 break;
4665 #endif
4666 case OPC_MADD:
4668 TCGv_i64 t2 = tcg_temp_new_i64();
4669 TCGv_i64 t3 = tcg_temp_new_i64();
4671 tcg_gen_ext_tl_i64(t2, t0);
4672 tcg_gen_ext_tl_i64(t3, t1);
4673 tcg_gen_mul_i64(t2, t2, t3);
4674 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4675 tcg_gen_add_i64(t2, t2, t3);
4676 tcg_temp_free_i64(t3);
4677 gen_move_low32(cpu_LO[acc], t2);
4678 gen_move_high32(cpu_HI[acc], t2);
4679 tcg_temp_free_i64(t2);
4681 break;
4682 case OPC_MADDU:
4684 TCGv_i64 t2 = tcg_temp_new_i64();
4685 TCGv_i64 t3 = tcg_temp_new_i64();
4687 tcg_gen_ext32u_tl(t0, t0);
4688 tcg_gen_ext32u_tl(t1, t1);
4689 tcg_gen_extu_tl_i64(t2, t0);
4690 tcg_gen_extu_tl_i64(t3, t1);
4691 tcg_gen_mul_i64(t2, t2, t3);
4692 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4693 tcg_gen_add_i64(t2, t2, t3);
4694 tcg_temp_free_i64(t3);
4695 gen_move_low32(cpu_LO[acc], t2);
4696 gen_move_high32(cpu_HI[acc], t2);
4697 tcg_temp_free_i64(t2);
4699 break;
4700 case OPC_MSUB:
4702 TCGv_i64 t2 = tcg_temp_new_i64();
4703 TCGv_i64 t3 = tcg_temp_new_i64();
4705 tcg_gen_ext_tl_i64(t2, t0);
4706 tcg_gen_ext_tl_i64(t3, t1);
4707 tcg_gen_mul_i64(t2, t2, t3);
4708 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4709 tcg_gen_sub_i64(t2, t3, t2);
4710 tcg_temp_free_i64(t3);
4711 gen_move_low32(cpu_LO[acc], t2);
4712 gen_move_high32(cpu_HI[acc], t2);
4713 tcg_temp_free_i64(t2);
4715 break;
4716 case OPC_MSUBU:
4718 TCGv_i64 t2 = tcg_temp_new_i64();
4719 TCGv_i64 t3 = tcg_temp_new_i64();
4721 tcg_gen_ext32u_tl(t0, t0);
4722 tcg_gen_ext32u_tl(t1, t1);
4723 tcg_gen_extu_tl_i64(t2, t0);
4724 tcg_gen_extu_tl_i64(t3, t1);
4725 tcg_gen_mul_i64(t2, t2, t3);
4726 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4727 tcg_gen_sub_i64(t2, t3, t2);
4728 tcg_temp_free_i64(t3);
4729 gen_move_low32(cpu_LO[acc], t2);
4730 gen_move_high32(cpu_HI[acc], t2);
4731 tcg_temp_free_i64(t2);
4733 break;
4734 default:
4735 MIPS_INVAL("mul/div");
4736 gen_reserved_instruction(ctx);
4737 goto out;
4739 out:
4740 tcg_temp_free(t0);
4741 tcg_temp_free(t1);
4745 * These MULT[U] and MADD[U] instructions implemented in for example
4746 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
4747 * architectures are special three-operand variants with the syntax
4749 * MULT[U][1] rd, rs, rt
4751 * such that
4753 * (rd, LO, HI) <- rs * rt
4755 * and
4757 * MADD[U][1] rd, rs, rt
4759 * such that
4761 * (rd, LO, HI) <- (LO, HI) + rs * rt
4763 * where the low-order 32-bits of the result is placed into both the
4764 * GPR rd and the special register LO. The high-order 32-bits of the
4765 * result is placed into the special register HI.
4767 * If the GPR rd is omitted in assembly language, it is taken to be 0,
4768 * which is the zero register that always reads as 0.
4770 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
4771 int rd, int rs, int rt)
4773 TCGv t0 = tcg_temp_new();
4774 TCGv t1 = tcg_temp_new();
4775 int acc = 0;
4777 gen_load_gpr(t0, rs);
4778 gen_load_gpr(t1, rt);
4780 switch (opc) {
4781 case MMI_OPC_MULT1:
4782 acc = 1;
4783 /* Fall through */
4784 case OPC_MULT:
4786 TCGv_i32 t2 = tcg_temp_new_i32();
4787 TCGv_i32 t3 = tcg_temp_new_i32();
4788 tcg_gen_trunc_tl_i32(t2, t0);
4789 tcg_gen_trunc_tl_i32(t3, t1);
4790 tcg_gen_muls2_i32(t2, t3, t2, t3);
4791 if (rd) {
4792 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4794 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4795 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4796 tcg_temp_free_i32(t2);
4797 tcg_temp_free_i32(t3);
4799 break;
4800 case MMI_OPC_MULTU1:
4801 acc = 1;
4802 /* Fall through */
4803 case OPC_MULTU:
4805 TCGv_i32 t2 = tcg_temp_new_i32();
4806 TCGv_i32 t3 = tcg_temp_new_i32();
4807 tcg_gen_trunc_tl_i32(t2, t0);
4808 tcg_gen_trunc_tl_i32(t3, t1);
4809 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4810 if (rd) {
4811 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4813 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4814 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4815 tcg_temp_free_i32(t2);
4816 tcg_temp_free_i32(t3);
4818 break;
4819 case MMI_OPC_MADD1:
4820 acc = 1;
4821 /* Fall through */
4822 case MMI_OPC_MADD:
4824 TCGv_i64 t2 = tcg_temp_new_i64();
4825 TCGv_i64 t3 = tcg_temp_new_i64();
4827 tcg_gen_ext_tl_i64(t2, t0);
4828 tcg_gen_ext_tl_i64(t3, t1);
4829 tcg_gen_mul_i64(t2, t2, t3);
4830 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4831 tcg_gen_add_i64(t2, t2, t3);
4832 tcg_temp_free_i64(t3);
4833 gen_move_low32(cpu_LO[acc], t2);
4834 gen_move_high32(cpu_HI[acc], t2);
4835 if (rd) {
4836 gen_move_low32(cpu_gpr[rd], t2);
4838 tcg_temp_free_i64(t2);
4840 break;
4841 case MMI_OPC_MADDU1:
4842 acc = 1;
4843 /* Fall through */
4844 case MMI_OPC_MADDU:
4846 TCGv_i64 t2 = tcg_temp_new_i64();
4847 TCGv_i64 t3 = tcg_temp_new_i64();
4849 tcg_gen_ext32u_tl(t0, t0);
4850 tcg_gen_ext32u_tl(t1, t1);
4851 tcg_gen_extu_tl_i64(t2, t0);
4852 tcg_gen_extu_tl_i64(t3, t1);
4853 tcg_gen_mul_i64(t2, t2, t3);
4854 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4855 tcg_gen_add_i64(t2, t2, t3);
4856 tcg_temp_free_i64(t3);
4857 gen_move_low32(cpu_LO[acc], t2);
4858 gen_move_high32(cpu_HI[acc], t2);
4859 if (rd) {
4860 gen_move_low32(cpu_gpr[rd], t2);
4862 tcg_temp_free_i64(t2);
4864 break;
4865 default:
4866 MIPS_INVAL("mul/madd TXx9");
4867 gen_reserved_instruction(ctx);
4868 goto out;
4871 out:
4872 tcg_temp_free(t0);
4873 tcg_temp_free(t1);
4876 static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc,
4877 int rd, int rs, int rt)
4879 TCGv t0 = tcg_temp_new();
4880 TCGv t1 = tcg_temp_new();
4882 gen_load_gpr(t0, rs);
4883 gen_load_gpr(t1, rt);
4885 switch (opc) {
4886 case OPC_VR54XX_MULS:
4887 gen_helper_muls(t0, cpu_env, t0, t1);
4888 break;
4889 case OPC_VR54XX_MULSU:
4890 gen_helper_mulsu(t0, cpu_env, t0, t1);
4891 break;
4892 case OPC_VR54XX_MACC:
4893 gen_helper_macc(t0, cpu_env, t0, t1);
4894 break;
4895 case OPC_VR54XX_MACCU:
4896 gen_helper_maccu(t0, cpu_env, t0, t1);
4897 break;
4898 case OPC_VR54XX_MSAC:
4899 gen_helper_msac(t0, cpu_env, t0, t1);
4900 break;
4901 case OPC_VR54XX_MSACU:
4902 gen_helper_msacu(t0, cpu_env, t0, t1);
4903 break;
4904 case OPC_VR54XX_MULHI:
4905 gen_helper_mulhi(t0, cpu_env, t0, t1);
4906 break;
4907 case OPC_VR54XX_MULHIU:
4908 gen_helper_mulhiu(t0, cpu_env, t0, t1);
4909 break;
4910 case OPC_VR54XX_MULSHI:
4911 gen_helper_mulshi(t0, cpu_env, t0, t1);
4912 break;
4913 case OPC_VR54XX_MULSHIU:
4914 gen_helper_mulshiu(t0, cpu_env, t0, t1);
4915 break;
4916 case OPC_VR54XX_MACCHI:
4917 gen_helper_macchi(t0, cpu_env, t0, t1);
4918 break;
4919 case OPC_VR54XX_MACCHIU:
4920 gen_helper_macchiu(t0, cpu_env, t0, t1);
4921 break;
4922 case OPC_VR54XX_MSACHI:
4923 gen_helper_msachi(t0, cpu_env, t0, t1);
4924 break;
4925 case OPC_VR54XX_MSACHIU:
4926 gen_helper_msachiu(t0, cpu_env, t0, t1);
4927 break;
4928 default:
4929 MIPS_INVAL("mul vr54xx");
4930 gen_reserved_instruction(ctx);
4931 goto out;
4933 gen_store_gpr(t0, rd);
4935 out:
4936 tcg_temp_free(t0);
4937 tcg_temp_free(t1);
4940 static void gen_cl(DisasContext *ctx, uint32_t opc,
4941 int rd, int rs)
4943 TCGv t0;
4945 if (rd == 0) {
4946 /* Treat as NOP. */
4947 return;
4949 t0 = cpu_gpr[rd];
4950 gen_load_gpr(t0, rs);
4952 switch (opc) {
4953 case OPC_CLO:
4954 case R6_OPC_CLO:
4955 #if defined(TARGET_MIPS64)
4956 case OPC_DCLO:
4957 case R6_OPC_DCLO:
4958 #endif
4959 tcg_gen_not_tl(t0, t0);
4960 break;
4963 switch (opc) {
4964 case OPC_CLO:
4965 case R6_OPC_CLO:
4966 case OPC_CLZ:
4967 case R6_OPC_CLZ:
4968 tcg_gen_ext32u_tl(t0, t0);
4969 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
4970 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
4971 break;
4972 #if defined(TARGET_MIPS64)
4973 case OPC_DCLO:
4974 case R6_OPC_DCLO:
4975 case OPC_DCLZ:
4976 case R6_OPC_DCLZ:
4977 tcg_gen_clzi_i64(t0, t0, 64);
4978 break;
4979 #endif
4983 /* Godson integer instructions */
4984 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
4985 int rd, int rs, int rt)
4987 TCGv t0, t1;
4989 if (rd == 0) {
4990 /* Treat as NOP. */
4991 return;
4994 switch (opc) {
4995 case OPC_MULT_G_2E:
4996 case OPC_MULT_G_2F:
4997 case OPC_MULTU_G_2E:
4998 case OPC_MULTU_G_2F:
4999 #if defined(TARGET_MIPS64)
5000 case OPC_DMULT_G_2E:
5001 case OPC_DMULT_G_2F:
5002 case OPC_DMULTU_G_2E:
5003 case OPC_DMULTU_G_2F:
5004 #endif
5005 t0 = tcg_temp_new();
5006 t1 = tcg_temp_new();
5007 break;
5008 default:
5009 t0 = tcg_temp_local_new();
5010 t1 = tcg_temp_local_new();
5011 break;
5014 gen_load_gpr(t0, rs);
5015 gen_load_gpr(t1, rt);
5017 switch (opc) {
5018 case OPC_MULT_G_2E:
5019 case OPC_MULT_G_2F:
5020 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5021 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5022 break;
5023 case OPC_MULTU_G_2E:
5024 case OPC_MULTU_G_2F:
5025 tcg_gen_ext32u_tl(t0, t0);
5026 tcg_gen_ext32u_tl(t1, t1);
5027 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5028 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5029 break;
5030 case OPC_DIV_G_2E:
5031 case OPC_DIV_G_2F:
5033 TCGLabel *l1 = gen_new_label();
5034 TCGLabel *l2 = gen_new_label();
5035 TCGLabel *l3 = gen_new_label();
5036 tcg_gen_ext32s_tl(t0, t0);
5037 tcg_gen_ext32s_tl(t1, t1);
5038 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5039 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5040 tcg_gen_br(l3);
5041 gen_set_label(l1);
5042 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5043 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5044 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5045 tcg_gen_br(l3);
5046 gen_set_label(l2);
5047 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5048 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5049 gen_set_label(l3);
5051 break;
5052 case OPC_DIVU_G_2E:
5053 case OPC_DIVU_G_2F:
5055 TCGLabel *l1 = gen_new_label();
5056 TCGLabel *l2 = gen_new_label();
5057 tcg_gen_ext32u_tl(t0, t0);
5058 tcg_gen_ext32u_tl(t1, t1);
5059 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5060 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5061 tcg_gen_br(l2);
5062 gen_set_label(l1);
5063 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5064 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5065 gen_set_label(l2);
5067 break;
5068 case OPC_MOD_G_2E:
5069 case OPC_MOD_G_2F:
5071 TCGLabel *l1 = gen_new_label();
5072 TCGLabel *l2 = gen_new_label();
5073 TCGLabel *l3 = gen_new_label();
5074 tcg_gen_ext32u_tl(t0, t0);
5075 tcg_gen_ext32u_tl(t1, t1);
5076 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5077 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5078 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5079 gen_set_label(l1);
5080 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5081 tcg_gen_br(l3);
5082 gen_set_label(l2);
5083 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5084 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5085 gen_set_label(l3);
5087 break;
5088 case OPC_MODU_G_2E:
5089 case OPC_MODU_G_2F:
5091 TCGLabel *l1 = gen_new_label();
5092 TCGLabel *l2 = gen_new_label();
5093 tcg_gen_ext32u_tl(t0, t0);
5094 tcg_gen_ext32u_tl(t1, t1);
5095 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5096 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5097 tcg_gen_br(l2);
5098 gen_set_label(l1);
5099 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5100 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5101 gen_set_label(l2);
5103 break;
5104 #if defined(TARGET_MIPS64)
5105 case OPC_DMULT_G_2E:
5106 case OPC_DMULT_G_2F:
5107 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5108 break;
5109 case OPC_DMULTU_G_2E:
5110 case OPC_DMULTU_G_2F:
5111 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5112 break;
5113 case OPC_DDIV_G_2E:
5114 case OPC_DDIV_G_2F:
5116 TCGLabel *l1 = gen_new_label();
5117 TCGLabel *l2 = gen_new_label();
5118 TCGLabel *l3 = gen_new_label();
5119 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5120 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5121 tcg_gen_br(l3);
5122 gen_set_label(l1);
5123 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5124 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5125 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5126 tcg_gen_br(l3);
5127 gen_set_label(l2);
5128 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5129 gen_set_label(l3);
5131 break;
5132 case OPC_DDIVU_G_2E:
5133 case OPC_DDIVU_G_2F:
5135 TCGLabel *l1 = gen_new_label();
5136 TCGLabel *l2 = gen_new_label();
5137 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5138 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5139 tcg_gen_br(l2);
5140 gen_set_label(l1);
5141 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5142 gen_set_label(l2);
5144 break;
5145 case OPC_DMOD_G_2E:
5146 case OPC_DMOD_G_2F:
5148 TCGLabel *l1 = gen_new_label();
5149 TCGLabel *l2 = gen_new_label();
5150 TCGLabel *l3 = gen_new_label();
5151 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5152 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5153 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5154 gen_set_label(l1);
5155 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5156 tcg_gen_br(l3);
5157 gen_set_label(l2);
5158 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5159 gen_set_label(l3);
5161 break;
5162 case OPC_DMODU_G_2E:
5163 case OPC_DMODU_G_2F:
5165 TCGLabel *l1 = gen_new_label();
5166 TCGLabel *l2 = gen_new_label();
5167 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5168 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5169 tcg_gen_br(l2);
5170 gen_set_label(l1);
5171 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5172 gen_set_label(l2);
5174 break;
5175 #endif
5178 tcg_temp_free(t0);
5179 tcg_temp_free(t1);
5182 /* Loongson multimedia instructions */
5183 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
5185 uint32_t opc, shift_max;
5186 TCGv_i64 t0, t1;
5187 TCGCond cond;
5189 opc = MASK_LMMI(ctx->opcode);
5190 switch (opc) {
5191 case OPC_ADD_CP2:
5192 case OPC_SUB_CP2:
5193 case OPC_DADD_CP2:
5194 case OPC_DSUB_CP2:
5195 t0 = tcg_temp_local_new_i64();
5196 t1 = tcg_temp_local_new_i64();
5197 break;
5198 default:
5199 t0 = tcg_temp_new_i64();
5200 t1 = tcg_temp_new_i64();
5201 break;
5204 check_cp1_enabled(ctx);
5205 gen_load_fpr64(ctx, t0, rs);
5206 gen_load_fpr64(ctx, t1, rt);
5208 switch (opc) {
5209 case OPC_PADDSH:
5210 gen_helper_paddsh(t0, t0, t1);
5211 break;
5212 case OPC_PADDUSH:
5213 gen_helper_paddush(t0, t0, t1);
5214 break;
5215 case OPC_PADDH:
5216 gen_helper_paddh(t0, t0, t1);
5217 break;
5218 case OPC_PADDW:
5219 gen_helper_paddw(t0, t0, t1);
5220 break;
5221 case OPC_PADDSB:
5222 gen_helper_paddsb(t0, t0, t1);
5223 break;
5224 case OPC_PADDUSB:
5225 gen_helper_paddusb(t0, t0, t1);
5226 break;
5227 case OPC_PADDB:
5228 gen_helper_paddb(t0, t0, t1);
5229 break;
5231 case OPC_PSUBSH:
5232 gen_helper_psubsh(t0, t0, t1);
5233 break;
5234 case OPC_PSUBUSH:
5235 gen_helper_psubush(t0, t0, t1);
5236 break;
5237 case OPC_PSUBH:
5238 gen_helper_psubh(t0, t0, t1);
5239 break;
5240 case OPC_PSUBW:
5241 gen_helper_psubw(t0, t0, t1);
5242 break;
5243 case OPC_PSUBSB:
5244 gen_helper_psubsb(t0, t0, t1);
5245 break;
5246 case OPC_PSUBUSB:
5247 gen_helper_psubusb(t0, t0, t1);
5248 break;
5249 case OPC_PSUBB:
5250 gen_helper_psubb(t0, t0, t1);
5251 break;
5253 case OPC_PSHUFH:
5254 gen_helper_pshufh(t0, t0, t1);
5255 break;
5256 case OPC_PACKSSWH:
5257 gen_helper_packsswh(t0, t0, t1);
5258 break;
5259 case OPC_PACKSSHB:
5260 gen_helper_packsshb(t0, t0, t1);
5261 break;
5262 case OPC_PACKUSHB:
5263 gen_helper_packushb(t0, t0, t1);
5264 break;
5266 case OPC_PUNPCKLHW:
5267 gen_helper_punpcklhw(t0, t0, t1);
5268 break;
5269 case OPC_PUNPCKHHW:
5270 gen_helper_punpckhhw(t0, t0, t1);
5271 break;
5272 case OPC_PUNPCKLBH:
5273 gen_helper_punpcklbh(t0, t0, t1);
5274 break;
5275 case OPC_PUNPCKHBH:
5276 gen_helper_punpckhbh(t0, t0, t1);
5277 break;
5278 case OPC_PUNPCKLWD:
5279 gen_helper_punpcklwd(t0, t0, t1);
5280 break;
5281 case OPC_PUNPCKHWD:
5282 gen_helper_punpckhwd(t0, t0, t1);
5283 break;
5285 case OPC_PAVGH:
5286 gen_helper_pavgh(t0, t0, t1);
5287 break;
5288 case OPC_PAVGB:
5289 gen_helper_pavgb(t0, t0, t1);
5290 break;
5291 case OPC_PMAXSH:
5292 gen_helper_pmaxsh(t0, t0, t1);
5293 break;
5294 case OPC_PMINSH:
5295 gen_helper_pminsh(t0, t0, t1);
5296 break;
5297 case OPC_PMAXUB:
5298 gen_helper_pmaxub(t0, t0, t1);
5299 break;
5300 case OPC_PMINUB:
5301 gen_helper_pminub(t0, t0, t1);
5302 break;
5304 case OPC_PCMPEQW:
5305 gen_helper_pcmpeqw(t0, t0, t1);
5306 break;
5307 case OPC_PCMPGTW:
5308 gen_helper_pcmpgtw(t0, t0, t1);
5309 break;
5310 case OPC_PCMPEQH:
5311 gen_helper_pcmpeqh(t0, t0, t1);
5312 break;
5313 case OPC_PCMPGTH:
5314 gen_helper_pcmpgth(t0, t0, t1);
5315 break;
5316 case OPC_PCMPEQB:
5317 gen_helper_pcmpeqb(t0, t0, t1);
5318 break;
5319 case OPC_PCMPGTB:
5320 gen_helper_pcmpgtb(t0, t0, t1);
5321 break;
5323 case OPC_PSLLW:
5324 gen_helper_psllw(t0, t0, t1);
5325 break;
5326 case OPC_PSLLH:
5327 gen_helper_psllh(t0, t0, t1);
5328 break;
5329 case OPC_PSRLW:
5330 gen_helper_psrlw(t0, t0, t1);
5331 break;
5332 case OPC_PSRLH:
5333 gen_helper_psrlh(t0, t0, t1);
5334 break;
5335 case OPC_PSRAW:
5336 gen_helper_psraw(t0, t0, t1);
5337 break;
5338 case OPC_PSRAH:
5339 gen_helper_psrah(t0, t0, t1);
5340 break;
5342 case OPC_PMULLH:
5343 gen_helper_pmullh(t0, t0, t1);
5344 break;
5345 case OPC_PMULHH:
5346 gen_helper_pmulhh(t0, t0, t1);
5347 break;
5348 case OPC_PMULHUH:
5349 gen_helper_pmulhuh(t0, t0, t1);
5350 break;
5351 case OPC_PMADDHW:
5352 gen_helper_pmaddhw(t0, t0, t1);
5353 break;
5355 case OPC_PASUBUB:
5356 gen_helper_pasubub(t0, t0, t1);
5357 break;
5358 case OPC_BIADD:
5359 gen_helper_biadd(t0, t0);
5360 break;
5361 case OPC_PMOVMSKB:
5362 gen_helper_pmovmskb(t0, t0);
5363 break;
5365 case OPC_PADDD:
5366 tcg_gen_add_i64(t0, t0, t1);
5367 break;
5368 case OPC_PSUBD:
5369 tcg_gen_sub_i64(t0, t0, t1);
5370 break;
5371 case OPC_XOR_CP2:
5372 tcg_gen_xor_i64(t0, t0, t1);
5373 break;
5374 case OPC_NOR_CP2:
5375 tcg_gen_nor_i64(t0, t0, t1);
5376 break;
5377 case OPC_AND_CP2:
5378 tcg_gen_and_i64(t0, t0, t1);
5379 break;
5380 case OPC_OR_CP2:
5381 tcg_gen_or_i64(t0, t0, t1);
5382 break;
5384 case OPC_PANDN:
5385 tcg_gen_andc_i64(t0, t1, t0);
5386 break;
5388 case OPC_PINSRH_0:
5389 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
5390 break;
5391 case OPC_PINSRH_1:
5392 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
5393 break;
5394 case OPC_PINSRH_2:
5395 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
5396 break;
5397 case OPC_PINSRH_3:
5398 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
5399 break;
5401 case OPC_PEXTRH:
5402 tcg_gen_andi_i64(t1, t1, 3);
5403 tcg_gen_shli_i64(t1, t1, 4);
5404 tcg_gen_shr_i64(t0, t0, t1);
5405 tcg_gen_ext16u_i64(t0, t0);
5406 break;
5408 case OPC_ADDU_CP2:
5409 tcg_gen_add_i64(t0, t0, t1);
5410 tcg_gen_ext32s_i64(t0, t0);
5411 break;
5412 case OPC_SUBU_CP2:
5413 tcg_gen_sub_i64(t0, t0, t1);
5414 tcg_gen_ext32s_i64(t0, t0);
5415 break;
5417 case OPC_SLL_CP2:
5418 shift_max = 32;
5419 goto do_shift;
5420 case OPC_SRL_CP2:
5421 shift_max = 32;
5422 goto do_shift;
5423 case OPC_SRA_CP2:
5424 shift_max = 32;
5425 goto do_shift;
5426 case OPC_DSLL_CP2:
5427 shift_max = 64;
5428 goto do_shift;
5429 case OPC_DSRL_CP2:
5430 shift_max = 64;
5431 goto do_shift;
5432 case OPC_DSRA_CP2:
5433 shift_max = 64;
5434 goto do_shift;
5435 do_shift:
5436 /* Make sure shift count isn't TCG undefined behaviour. */
5437 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5439 switch (opc) {
5440 case OPC_SLL_CP2:
5441 case OPC_DSLL_CP2:
5442 tcg_gen_shl_i64(t0, t0, t1);
5443 break;
5444 case OPC_SRA_CP2:
5445 case OPC_DSRA_CP2:
5447 * Since SRA is UndefinedResult without sign-extended inputs,
5448 * we can treat SRA and DSRA the same.
5450 tcg_gen_sar_i64(t0, t0, t1);
5451 break;
5452 case OPC_SRL_CP2:
5453 /* We want to shift in zeros for SRL; zero-extend first. */
5454 tcg_gen_ext32u_i64(t0, t0);
5455 /* FALLTHRU */
5456 case OPC_DSRL_CP2:
5457 tcg_gen_shr_i64(t0, t0, t1);
5458 break;
5461 if (shift_max == 32) {
5462 tcg_gen_ext32s_i64(t0, t0);
5465 /* Shifts larger than MAX produce zero. */
5466 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5467 tcg_gen_neg_i64(t1, t1);
5468 tcg_gen_and_i64(t0, t0, t1);
5469 break;
5471 case OPC_ADD_CP2:
5472 case OPC_DADD_CP2:
5474 TCGv_i64 t2 = tcg_temp_new_i64();
5475 TCGLabel *lab = gen_new_label();
5477 tcg_gen_mov_i64(t2, t0);
5478 tcg_gen_add_i64(t0, t1, t2);
5479 if (opc == OPC_ADD_CP2) {
5480 tcg_gen_ext32s_i64(t0, t0);
5482 tcg_gen_xor_i64(t1, t1, t2);
5483 tcg_gen_xor_i64(t2, t2, t0);
5484 tcg_gen_andc_i64(t1, t2, t1);
5485 tcg_temp_free_i64(t2);
5486 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5487 generate_exception(ctx, EXCP_OVERFLOW);
5488 gen_set_label(lab);
5489 break;
5492 case OPC_SUB_CP2:
5493 case OPC_DSUB_CP2:
5495 TCGv_i64 t2 = tcg_temp_new_i64();
5496 TCGLabel *lab = gen_new_label();
5498 tcg_gen_mov_i64(t2, t0);
5499 tcg_gen_sub_i64(t0, t1, t2);
5500 if (opc == OPC_SUB_CP2) {
5501 tcg_gen_ext32s_i64(t0, t0);
5503 tcg_gen_xor_i64(t1, t1, t2);
5504 tcg_gen_xor_i64(t2, t2, t0);
5505 tcg_gen_and_i64(t1, t1, t2);
5506 tcg_temp_free_i64(t2);
5507 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5508 generate_exception(ctx, EXCP_OVERFLOW);
5509 gen_set_label(lab);
5510 break;
5513 case OPC_PMULUW:
5514 tcg_gen_ext32u_i64(t0, t0);
5515 tcg_gen_ext32u_i64(t1, t1);
5516 tcg_gen_mul_i64(t0, t0, t1);
5517 break;
5519 case OPC_SEQU_CP2:
5520 case OPC_SEQ_CP2:
5521 cond = TCG_COND_EQ;
5522 goto do_cc_cond;
5523 break;
5524 case OPC_SLTU_CP2:
5525 cond = TCG_COND_LTU;
5526 goto do_cc_cond;
5527 break;
5528 case OPC_SLT_CP2:
5529 cond = TCG_COND_LT;
5530 goto do_cc_cond;
5531 break;
5532 case OPC_SLEU_CP2:
5533 cond = TCG_COND_LEU;
5534 goto do_cc_cond;
5535 break;
5536 case OPC_SLE_CP2:
5537 cond = TCG_COND_LE;
5538 do_cc_cond:
5540 int cc = (ctx->opcode >> 8) & 0x7;
5541 TCGv_i64 t64 = tcg_temp_new_i64();
5542 TCGv_i32 t32 = tcg_temp_new_i32();
5544 tcg_gen_setcond_i64(cond, t64, t0, t1);
5545 tcg_gen_extrl_i64_i32(t32, t64);
5546 tcg_gen_deposit_i32(fpu_fcr31, fpu_fcr31, t32,
5547 get_fp_bit(cc), 1);
5549 tcg_temp_free_i32(t32);
5550 tcg_temp_free_i64(t64);
5552 goto no_rd;
5553 break;
5554 default:
5555 MIPS_INVAL("loongson_cp2");
5556 gen_reserved_instruction(ctx);
5557 return;
5560 gen_store_fpr64(ctx, t0, rd);
5562 no_rd:
5563 tcg_temp_free_i64(t0);
5564 tcg_temp_free_i64(t1);
5567 static void gen_loongson_lswc2(DisasContext *ctx, int rt,
5568 int rs, int rd)
5570 TCGv t0, t1, t2;
5571 TCGv_i32 fp0;
5572 #if defined(TARGET_MIPS64)
5573 int lsq_rt1 = ctx->opcode & 0x1f;
5574 int lsq_offset = sextract32(ctx->opcode, 6, 9) << 4;
5575 #endif
5576 int shf_offset = sextract32(ctx->opcode, 6, 8);
5578 t0 = tcg_temp_new();
5580 switch (MASK_LOONGSON_GSLSQ(ctx->opcode)) {
5581 #if defined(TARGET_MIPS64)
5582 case OPC_GSLQ:
5583 t1 = tcg_temp_new();
5584 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5585 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5586 ctx->default_tcg_memop_mask);
5587 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5588 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
5589 ctx->default_tcg_memop_mask);
5590 gen_store_gpr(t1, rt);
5591 gen_store_gpr(t0, lsq_rt1);
5592 tcg_temp_free(t1);
5593 break;
5594 case OPC_GSLQC1:
5595 check_cp1_enabled(ctx);
5596 t1 = tcg_temp_new();
5597 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5598 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5599 ctx->default_tcg_memop_mask);
5600 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5601 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
5602 ctx->default_tcg_memop_mask);
5603 gen_store_fpr64(ctx, t1, rt);
5604 gen_store_fpr64(ctx, t0, lsq_rt1);
5605 tcg_temp_free(t1);
5606 break;
5607 case OPC_GSSQ:
5608 t1 = tcg_temp_new();
5609 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5610 gen_load_gpr(t1, rt);
5611 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5612 ctx->default_tcg_memop_mask);
5613 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5614 gen_load_gpr(t1, lsq_rt1);
5615 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5616 ctx->default_tcg_memop_mask);
5617 tcg_temp_free(t1);
5618 break;
5619 case OPC_GSSQC1:
5620 check_cp1_enabled(ctx);
5621 t1 = tcg_temp_new();
5622 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5623 gen_load_fpr64(ctx, t1, rt);
5624 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5625 ctx->default_tcg_memop_mask);
5626 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5627 gen_load_fpr64(ctx, t1, lsq_rt1);
5628 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5629 ctx->default_tcg_memop_mask);
5630 tcg_temp_free(t1);
5631 break;
5632 #endif
5633 case OPC_GSSHFL:
5634 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
5635 case OPC_GSLWLC1:
5636 check_cp1_enabled(ctx);
5637 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5638 t1 = tcg_temp_new();
5639 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
5640 tcg_gen_andi_tl(t1, t0, 3);
5641 #ifndef TARGET_WORDS_BIGENDIAN
5642 tcg_gen_xori_tl(t1, t1, 3);
5643 #endif
5644 tcg_gen_shli_tl(t1, t1, 3);
5645 tcg_gen_andi_tl(t0, t0, ~3);
5646 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
5647 tcg_gen_shl_tl(t0, t0, t1);
5648 t2 = tcg_const_tl(-1);
5649 tcg_gen_shl_tl(t2, t2, t1);
5650 fp0 = tcg_temp_new_i32();
5651 gen_load_fpr32(ctx, fp0, rt);
5652 tcg_gen_ext_i32_tl(t1, fp0);
5653 tcg_gen_andc_tl(t1, t1, t2);
5654 tcg_temp_free(t2);
5655 tcg_gen_or_tl(t0, t0, t1);
5656 tcg_temp_free(t1);
5657 #if defined(TARGET_MIPS64)
5658 tcg_gen_extrl_i64_i32(fp0, t0);
5659 #else
5660 tcg_gen_ext32s_tl(fp0, t0);
5661 #endif
5662 gen_store_fpr32(ctx, fp0, rt);
5663 tcg_temp_free_i32(fp0);
5664 break;
5665 case OPC_GSLWRC1:
5666 check_cp1_enabled(ctx);
5667 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5668 t1 = tcg_temp_new();
5669 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
5670 tcg_gen_andi_tl(t1, t0, 3);
5671 #ifdef TARGET_WORDS_BIGENDIAN
5672 tcg_gen_xori_tl(t1, t1, 3);
5673 #endif
5674 tcg_gen_shli_tl(t1, t1, 3);
5675 tcg_gen_andi_tl(t0, t0, ~3);
5676 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
5677 tcg_gen_shr_tl(t0, t0, t1);
5678 tcg_gen_xori_tl(t1, t1, 31);
5679 t2 = tcg_const_tl(0xfffffffeull);
5680 tcg_gen_shl_tl(t2, t2, t1);
5681 fp0 = tcg_temp_new_i32();
5682 gen_load_fpr32(ctx, fp0, rt);
5683 tcg_gen_ext_i32_tl(t1, fp0);
5684 tcg_gen_and_tl(t1, t1, t2);
5685 tcg_temp_free(t2);
5686 tcg_gen_or_tl(t0, t0, t1);
5687 tcg_temp_free(t1);
5688 #if defined(TARGET_MIPS64)
5689 tcg_gen_extrl_i64_i32(fp0, t0);
5690 #else
5691 tcg_gen_ext32s_tl(fp0, t0);
5692 #endif
5693 gen_store_fpr32(ctx, fp0, rt);
5694 tcg_temp_free_i32(fp0);
5695 break;
5696 #if defined(TARGET_MIPS64)
5697 case OPC_GSLDLC1:
5698 check_cp1_enabled(ctx);
5699 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5700 t1 = tcg_temp_new();
5701 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
5702 tcg_gen_andi_tl(t1, t0, 7);
5703 #ifndef TARGET_WORDS_BIGENDIAN
5704 tcg_gen_xori_tl(t1, t1, 7);
5705 #endif
5706 tcg_gen_shli_tl(t1, t1, 3);
5707 tcg_gen_andi_tl(t0, t0, ~7);
5708 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
5709 tcg_gen_shl_tl(t0, t0, t1);
5710 t2 = tcg_const_tl(-1);
5711 tcg_gen_shl_tl(t2, t2, t1);
5712 gen_load_fpr64(ctx, t1, rt);
5713 tcg_gen_andc_tl(t1, t1, t2);
5714 tcg_temp_free(t2);
5715 tcg_gen_or_tl(t0, t0, t1);
5716 tcg_temp_free(t1);
5717 gen_store_fpr64(ctx, t0, rt);
5718 break;
5719 case OPC_GSLDRC1:
5720 check_cp1_enabled(ctx);
5721 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5722 t1 = tcg_temp_new();
5723 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
5724 tcg_gen_andi_tl(t1, t0, 7);
5725 #ifdef TARGET_WORDS_BIGENDIAN
5726 tcg_gen_xori_tl(t1, t1, 7);
5727 #endif
5728 tcg_gen_shli_tl(t1, t1, 3);
5729 tcg_gen_andi_tl(t0, t0, ~7);
5730 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
5731 tcg_gen_shr_tl(t0, t0, t1);
5732 tcg_gen_xori_tl(t1, t1, 63);
5733 t2 = tcg_const_tl(0xfffffffffffffffeull);
5734 tcg_gen_shl_tl(t2, t2, t1);
5735 gen_load_fpr64(ctx, t1, rt);
5736 tcg_gen_and_tl(t1, t1, t2);
5737 tcg_temp_free(t2);
5738 tcg_gen_or_tl(t0, t0, t1);
5739 tcg_temp_free(t1);
5740 gen_store_fpr64(ctx, t0, rt);
5741 break;
5742 #endif
5743 default:
5744 MIPS_INVAL("loongson_gsshfl");
5745 gen_reserved_instruction(ctx);
5746 break;
5748 break;
5749 case OPC_GSSHFS:
5750 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
5751 case OPC_GSSWLC1:
5752 check_cp1_enabled(ctx);
5753 t1 = tcg_temp_new();
5754 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5755 fp0 = tcg_temp_new_i32();
5756 gen_load_fpr32(ctx, fp0, rt);
5757 tcg_gen_ext_i32_tl(t1, fp0);
5758 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
5759 tcg_temp_free_i32(fp0);
5760 tcg_temp_free(t1);
5761 break;
5762 case OPC_GSSWRC1:
5763 check_cp1_enabled(ctx);
5764 t1 = tcg_temp_new();
5765 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5766 fp0 = tcg_temp_new_i32();
5767 gen_load_fpr32(ctx, fp0, rt);
5768 tcg_gen_ext_i32_tl(t1, fp0);
5769 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
5770 tcg_temp_free_i32(fp0);
5771 tcg_temp_free(t1);
5772 break;
5773 #if defined(TARGET_MIPS64)
5774 case OPC_GSSDLC1:
5775 check_cp1_enabled(ctx);
5776 t1 = tcg_temp_new();
5777 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5778 gen_load_fpr64(ctx, t1, rt);
5779 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
5780 tcg_temp_free(t1);
5781 break;
5782 case OPC_GSSDRC1:
5783 check_cp1_enabled(ctx);
5784 t1 = tcg_temp_new();
5785 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5786 gen_load_fpr64(ctx, t1, rt);
5787 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
5788 tcg_temp_free(t1);
5789 break;
5790 #endif
5791 default:
5792 MIPS_INVAL("loongson_gsshfs");
5793 gen_reserved_instruction(ctx);
5794 break;
5796 break;
5797 default:
5798 MIPS_INVAL("loongson_gslsq");
5799 gen_reserved_instruction(ctx);
5800 break;
5802 tcg_temp_free(t0);
5805 /* Loongson EXT LDC2/SDC2 */
5806 static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
5807 int rs, int rd)
5809 int offset = sextract32(ctx->opcode, 3, 8);
5810 uint32_t opc = MASK_LOONGSON_LSDC2(ctx->opcode);
5811 TCGv t0, t1;
5812 TCGv_i32 fp0;
5814 /* Pre-conditions */
5815 switch (opc) {
5816 case OPC_GSLBX:
5817 case OPC_GSLHX:
5818 case OPC_GSLWX:
5819 case OPC_GSLDX:
5820 /* prefetch, implement as NOP */
5821 if (rt == 0) {
5822 return;
5824 break;
5825 case OPC_GSSBX:
5826 case OPC_GSSHX:
5827 case OPC_GSSWX:
5828 case OPC_GSSDX:
5829 break;
5830 case OPC_GSLWXC1:
5831 #if defined(TARGET_MIPS64)
5832 case OPC_GSLDXC1:
5833 #endif
5834 check_cp1_enabled(ctx);
5835 /* prefetch, implement as NOP */
5836 if (rt == 0) {
5837 return;
5839 break;
5840 case OPC_GSSWXC1:
5841 #if defined(TARGET_MIPS64)
5842 case OPC_GSSDXC1:
5843 #endif
5844 check_cp1_enabled(ctx);
5845 break;
5846 default:
5847 MIPS_INVAL("loongson_lsdc2");
5848 gen_reserved_instruction(ctx);
5849 return;
5850 break;
5853 t0 = tcg_temp_new();
5855 gen_base_offset_addr(ctx, t0, rs, offset);
5856 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
5858 switch (opc) {
5859 case OPC_GSLBX:
5860 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
5861 gen_store_gpr(t0, rt);
5862 break;
5863 case OPC_GSLHX:
5864 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
5865 ctx->default_tcg_memop_mask);
5866 gen_store_gpr(t0, rt);
5867 break;
5868 case OPC_GSLWX:
5869 gen_base_offset_addr(ctx, t0, rs, offset);
5870 if (rd) {
5871 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
5873 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
5874 ctx->default_tcg_memop_mask);
5875 gen_store_gpr(t0, rt);
5876 break;
5877 #if defined(TARGET_MIPS64)
5878 case OPC_GSLDX:
5879 gen_base_offset_addr(ctx, t0, rs, offset);
5880 if (rd) {
5881 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
5883 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
5884 ctx->default_tcg_memop_mask);
5885 gen_store_gpr(t0, rt);
5886 break;
5887 #endif
5888 case OPC_GSLWXC1:
5889 check_cp1_enabled(ctx);
5890 gen_base_offset_addr(ctx, t0, rs, offset);
5891 if (rd) {
5892 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
5894 fp0 = tcg_temp_new_i32();
5895 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
5896 ctx->default_tcg_memop_mask);
5897 gen_store_fpr32(ctx, fp0, rt);
5898 tcg_temp_free_i32(fp0);
5899 break;
5900 #if defined(TARGET_MIPS64)
5901 case OPC_GSLDXC1:
5902 check_cp1_enabled(ctx);
5903 gen_base_offset_addr(ctx, t0, rs, offset);
5904 if (rd) {
5905 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
5907 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
5908 ctx->default_tcg_memop_mask);
5909 gen_store_fpr64(ctx, t0, rt);
5910 break;
5911 #endif
5912 case OPC_GSSBX:
5913 t1 = tcg_temp_new();
5914 gen_load_gpr(t1, rt);
5915 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_SB);
5916 tcg_temp_free(t1);
5917 break;
5918 case OPC_GSSHX:
5919 t1 = tcg_temp_new();
5920 gen_load_gpr(t1, rt);
5921 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
5922 ctx->default_tcg_memop_mask);
5923 tcg_temp_free(t1);
5924 break;
5925 case OPC_GSSWX:
5926 t1 = tcg_temp_new();
5927 gen_load_gpr(t1, rt);
5928 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
5929 ctx->default_tcg_memop_mask);
5930 tcg_temp_free(t1);
5931 break;
5932 #if defined(TARGET_MIPS64)
5933 case OPC_GSSDX:
5934 t1 = tcg_temp_new();
5935 gen_load_gpr(t1, rt);
5936 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5937 ctx->default_tcg_memop_mask);
5938 tcg_temp_free(t1);
5939 break;
5940 #endif
5941 case OPC_GSSWXC1:
5942 fp0 = tcg_temp_new_i32();
5943 gen_load_fpr32(ctx, fp0, rt);
5944 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
5945 ctx->default_tcg_memop_mask);
5946 tcg_temp_free_i32(fp0);
5947 break;
5948 #if defined(TARGET_MIPS64)
5949 case OPC_GSSDXC1:
5950 t1 = tcg_temp_new();
5951 gen_load_fpr64(ctx, t1, rt);
5952 tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, MO_TEQ |
5953 ctx->default_tcg_memop_mask);
5954 tcg_temp_free(t1);
5955 break;
5956 #endif
5957 default:
5958 break;
5961 tcg_temp_free(t0);
5964 /* Traps */
5965 static void gen_trap(DisasContext *ctx, uint32_t opc,
5966 int rs, int rt, int16_t imm)
5968 int cond;
5969 TCGv t0 = tcg_temp_new();
5970 TCGv t1 = tcg_temp_new();
5972 cond = 0;
5973 /* Load needed operands */
5974 switch (opc) {
5975 case OPC_TEQ:
5976 case OPC_TGE:
5977 case OPC_TGEU:
5978 case OPC_TLT:
5979 case OPC_TLTU:
5980 case OPC_TNE:
5981 /* Compare two registers */
5982 if (rs != rt) {
5983 gen_load_gpr(t0, rs);
5984 gen_load_gpr(t1, rt);
5985 cond = 1;
5987 break;
5988 case OPC_TEQI:
5989 case OPC_TGEI:
5990 case OPC_TGEIU:
5991 case OPC_TLTI:
5992 case OPC_TLTIU:
5993 case OPC_TNEI:
5994 /* Compare register to immediate */
5995 if (rs != 0 || imm != 0) {
5996 gen_load_gpr(t0, rs);
5997 tcg_gen_movi_tl(t1, (int32_t)imm);
5998 cond = 1;
6000 break;
6002 if (cond == 0) {
6003 switch (opc) {
6004 case OPC_TEQ: /* rs == rs */
6005 case OPC_TEQI: /* r0 == 0 */
6006 case OPC_TGE: /* rs >= rs */
6007 case OPC_TGEI: /* r0 >= 0 */
6008 case OPC_TGEU: /* rs >= rs unsigned */
6009 case OPC_TGEIU: /* r0 >= 0 unsigned */
6010 /* Always trap */
6011 generate_exception_end(ctx, EXCP_TRAP);
6012 break;
6013 case OPC_TLT: /* rs < rs */
6014 case OPC_TLTI: /* r0 < 0 */
6015 case OPC_TLTU: /* rs < rs unsigned */
6016 case OPC_TLTIU: /* r0 < 0 unsigned */
6017 case OPC_TNE: /* rs != rs */
6018 case OPC_TNEI: /* r0 != 0 */
6019 /* Never trap: treat as NOP. */
6020 break;
6022 } else {
6023 TCGLabel *l1 = gen_new_label();
6025 switch (opc) {
6026 case OPC_TEQ:
6027 case OPC_TEQI:
6028 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
6029 break;
6030 case OPC_TGE:
6031 case OPC_TGEI:
6032 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
6033 break;
6034 case OPC_TGEU:
6035 case OPC_TGEIU:
6036 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
6037 break;
6038 case OPC_TLT:
6039 case OPC_TLTI:
6040 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
6041 break;
6042 case OPC_TLTU:
6043 case OPC_TLTIU:
6044 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
6045 break;
6046 case OPC_TNE:
6047 case OPC_TNEI:
6048 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
6049 break;
6051 generate_exception(ctx, EXCP_TRAP);
6052 gen_set_label(l1);
6054 tcg_temp_free(t0);
6055 tcg_temp_free(t1);
6058 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
6060 if (unlikely(ctx->base.singlestep_enabled)) {
6061 return false;
6064 #ifndef CONFIG_USER_ONLY
6065 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
6066 #else
6067 return true;
6068 #endif
6071 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
6073 if (use_goto_tb(ctx, dest)) {
6074 tcg_gen_goto_tb(n);
6075 gen_save_pc(dest);
6076 tcg_gen_exit_tb(ctx->base.tb, n);
6077 } else {
6078 gen_save_pc(dest);
6079 if (ctx->base.singlestep_enabled) {
6080 save_cpu_state(ctx, 0);
6081 gen_helper_raise_exception_debug(cpu_env);
6083 tcg_gen_lookup_and_goto_ptr();
6087 /* Branches (before delay slot) */
6088 static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
6089 int insn_bytes,
6090 int rs, int rt, int32_t offset,
6091 int delayslot_size)
6093 target_ulong btgt = -1;
6094 int blink = 0;
6095 int bcond_compute = 0;
6096 TCGv t0 = tcg_temp_new();
6097 TCGv t1 = tcg_temp_new();
6099 if (ctx->hflags & MIPS_HFLAG_BMASK) {
6100 #ifdef MIPS_DEBUG_DISAS
6101 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
6102 TARGET_FMT_lx "\n", ctx->base.pc_next);
6103 #endif
6104 gen_reserved_instruction(ctx);
6105 goto out;
6108 /* Load needed operands */
6109 switch (opc) {
6110 case OPC_BEQ:
6111 case OPC_BEQL:
6112 case OPC_BNE:
6113 case OPC_BNEL:
6114 /* Compare two registers */
6115 if (rs != rt) {
6116 gen_load_gpr(t0, rs);
6117 gen_load_gpr(t1, rt);
6118 bcond_compute = 1;
6120 btgt = ctx->base.pc_next + insn_bytes + offset;
6121 break;
6122 case OPC_BGEZ:
6123 case OPC_BGEZAL:
6124 case OPC_BGEZALL:
6125 case OPC_BGEZL:
6126 case OPC_BGTZ:
6127 case OPC_BGTZL:
6128 case OPC_BLEZ:
6129 case OPC_BLEZL:
6130 case OPC_BLTZ:
6131 case OPC_BLTZAL:
6132 case OPC_BLTZALL:
6133 case OPC_BLTZL:
6134 /* Compare to zero */
6135 if (rs != 0) {
6136 gen_load_gpr(t0, rs);
6137 bcond_compute = 1;
6139 btgt = ctx->base.pc_next + insn_bytes + offset;
6140 break;
6141 case OPC_BPOSGE32:
6142 #if defined(TARGET_MIPS64)
6143 case OPC_BPOSGE64:
6144 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
6145 #else
6146 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6147 #endif
6148 bcond_compute = 1;
6149 btgt = ctx->base.pc_next + insn_bytes + offset;
6150 break;
6151 case OPC_J:
6152 case OPC_JAL:
6153 case OPC_JALX:
6154 /* Jump to immediate */
6155 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
6156 (uint32_t)offset;
6157 break;
6158 case OPC_JR:
6159 case OPC_JALR:
6160 /* Jump to register */
6161 if (offset != 0 && offset != 16) {
6163 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6164 * others are reserved.
6166 MIPS_INVAL("jump hint");
6167 gen_reserved_instruction(ctx);
6168 goto out;
6170 gen_load_gpr(btarget, rs);
6171 break;
6172 default:
6173 MIPS_INVAL("branch/jump");
6174 gen_reserved_instruction(ctx);
6175 goto out;
6177 if (bcond_compute == 0) {
6178 /* No condition to be computed */
6179 switch (opc) {
6180 case OPC_BEQ: /* rx == rx */
6181 case OPC_BEQL: /* rx == rx likely */
6182 case OPC_BGEZ: /* 0 >= 0 */
6183 case OPC_BGEZL: /* 0 >= 0 likely */
6184 case OPC_BLEZ: /* 0 <= 0 */
6185 case OPC_BLEZL: /* 0 <= 0 likely */
6186 /* Always take */
6187 ctx->hflags |= MIPS_HFLAG_B;
6188 break;
6189 case OPC_BGEZAL: /* 0 >= 0 */
6190 case OPC_BGEZALL: /* 0 >= 0 likely */
6191 /* Always take and link */
6192 blink = 31;
6193 ctx->hflags |= MIPS_HFLAG_B;
6194 break;
6195 case OPC_BNE: /* rx != rx */
6196 case OPC_BGTZ: /* 0 > 0 */
6197 case OPC_BLTZ: /* 0 < 0 */
6198 /* Treat as NOP. */
6199 goto out;
6200 case OPC_BLTZAL: /* 0 < 0 */
6202 * Handle as an unconditional branch to get correct delay
6203 * slot checking.
6205 blink = 31;
6206 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
6207 ctx->hflags |= MIPS_HFLAG_B;
6208 break;
6209 case OPC_BLTZALL: /* 0 < 0 likely */
6210 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6211 /* Skip the instruction in the delay slot */
6212 ctx->base.pc_next += 4;
6213 goto out;
6214 case OPC_BNEL: /* rx != rx likely */
6215 case OPC_BGTZL: /* 0 > 0 likely */
6216 case OPC_BLTZL: /* 0 < 0 likely */
6217 /* Skip the instruction in the delay slot */
6218 ctx->base.pc_next += 4;
6219 goto out;
6220 case OPC_J:
6221 ctx->hflags |= MIPS_HFLAG_B;
6222 break;
6223 case OPC_JALX:
6224 ctx->hflags |= MIPS_HFLAG_BX;
6225 /* Fallthrough */
6226 case OPC_JAL:
6227 blink = 31;
6228 ctx->hflags |= MIPS_HFLAG_B;
6229 break;
6230 case OPC_JR:
6231 ctx->hflags |= MIPS_HFLAG_BR;
6232 break;
6233 case OPC_JALR:
6234 blink = rt;
6235 ctx->hflags |= MIPS_HFLAG_BR;
6236 break;
6237 default:
6238 MIPS_INVAL("branch/jump");
6239 gen_reserved_instruction(ctx);
6240 goto out;
6242 } else {
6243 switch (opc) {
6244 case OPC_BEQ:
6245 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6246 goto not_likely;
6247 case OPC_BEQL:
6248 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6249 goto likely;
6250 case OPC_BNE:
6251 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6252 goto not_likely;
6253 case OPC_BNEL:
6254 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6255 goto likely;
6256 case OPC_BGEZ:
6257 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6258 goto not_likely;
6259 case OPC_BGEZL:
6260 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6261 goto likely;
6262 case OPC_BGEZAL:
6263 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6264 blink = 31;
6265 goto not_likely;
6266 case OPC_BGEZALL:
6267 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6268 blink = 31;
6269 goto likely;
6270 case OPC_BGTZ:
6271 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6272 goto not_likely;
6273 case OPC_BGTZL:
6274 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6275 goto likely;
6276 case OPC_BLEZ:
6277 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6278 goto not_likely;
6279 case OPC_BLEZL:
6280 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6281 goto likely;
6282 case OPC_BLTZ:
6283 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6284 goto not_likely;
6285 case OPC_BLTZL:
6286 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6287 goto likely;
6288 case OPC_BPOSGE32:
6289 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6290 goto not_likely;
6291 #if defined(TARGET_MIPS64)
6292 case OPC_BPOSGE64:
6293 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
6294 goto not_likely;
6295 #endif
6296 case OPC_BLTZAL:
6297 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6298 blink = 31;
6299 not_likely:
6300 ctx->hflags |= MIPS_HFLAG_BC;
6301 break;
6302 case OPC_BLTZALL:
6303 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6304 blink = 31;
6305 likely:
6306 ctx->hflags |= MIPS_HFLAG_BL;
6307 break;
6308 default:
6309 MIPS_INVAL("conditional branch/jump");
6310 gen_reserved_instruction(ctx);
6311 goto out;
6315 ctx->btarget = btgt;
6317 switch (delayslot_size) {
6318 case 2:
6319 ctx->hflags |= MIPS_HFLAG_BDS16;
6320 break;
6321 case 4:
6322 ctx->hflags |= MIPS_HFLAG_BDS32;
6323 break;
6326 if (blink > 0) {
6327 int post_delay = insn_bytes + delayslot_size;
6328 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
6330 tcg_gen_movi_tl(cpu_gpr[blink],
6331 ctx->base.pc_next + post_delay + lowbit);
6334 out:
6335 if (insn_bytes == 2) {
6336 ctx->hflags |= MIPS_HFLAG_B16;
6338 tcg_temp_free(t0);
6339 tcg_temp_free(t1);
6343 /* nanoMIPS Branches */
6344 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
6345 int insn_bytes,
6346 int rs, int rt, int32_t offset)
6348 target_ulong btgt = -1;
6349 int bcond_compute = 0;
6350 TCGv t0 = tcg_temp_new();
6351 TCGv t1 = tcg_temp_new();
6353 /* Load needed operands */
6354 switch (opc) {
6355 case OPC_BEQ:
6356 case OPC_BNE:
6357 /* Compare two registers */
6358 if (rs != rt) {
6359 gen_load_gpr(t0, rs);
6360 gen_load_gpr(t1, rt);
6361 bcond_compute = 1;
6363 btgt = ctx->base.pc_next + insn_bytes + offset;
6364 break;
6365 case OPC_BGEZAL:
6366 /* Compare to zero */
6367 if (rs != 0) {
6368 gen_load_gpr(t0, rs);
6369 bcond_compute = 1;
6371 btgt = ctx->base.pc_next + insn_bytes + offset;
6372 break;
6373 case OPC_BPOSGE32:
6374 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6375 bcond_compute = 1;
6376 btgt = ctx->base.pc_next + insn_bytes + offset;
6377 break;
6378 case OPC_JR:
6379 case OPC_JALR:
6380 /* Jump to register */
6381 if (offset != 0 && offset != 16) {
6383 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6384 * others are reserved.
6386 MIPS_INVAL("jump hint");
6387 gen_reserved_instruction(ctx);
6388 goto out;
6390 gen_load_gpr(btarget, rs);
6391 break;
6392 default:
6393 MIPS_INVAL("branch/jump");
6394 gen_reserved_instruction(ctx);
6395 goto out;
6397 if (bcond_compute == 0) {
6398 /* No condition to be computed */
6399 switch (opc) {
6400 case OPC_BEQ: /* rx == rx */
6401 /* Always take */
6402 ctx->hflags |= MIPS_HFLAG_B;
6403 break;
6404 case OPC_BGEZAL: /* 0 >= 0 */
6405 /* Always take and link */
6406 tcg_gen_movi_tl(cpu_gpr[31],
6407 ctx->base.pc_next + insn_bytes);
6408 ctx->hflags |= MIPS_HFLAG_B;
6409 break;
6410 case OPC_BNE: /* rx != rx */
6411 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6412 /* Skip the instruction in the delay slot */
6413 ctx->base.pc_next += 4;
6414 goto out;
6415 case OPC_JR:
6416 ctx->hflags |= MIPS_HFLAG_BR;
6417 break;
6418 case OPC_JALR:
6419 if (rt > 0) {
6420 tcg_gen_movi_tl(cpu_gpr[rt],
6421 ctx->base.pc_next + insn_bytes);
6423 ctx->hflags |= MIPS_HFLAG_BR;
6424 break;
6425 default:
6426 MIPS_INVAL("branch/jump");
6427 gen_reserved_instruction(ctx);
6428 goto out;
6430 } else {
6431 switch (opc) {
6432 case OPC_BEQ:
6433 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6434 goto not_likely;
6435 case OPC_BNE:
6436 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6437 goto not_likely;
6438 case OPC_BGEZAL:
6439 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6440 tcg_gen_movi_tl(cpu_gpr[31],
6441 ctx->base.pc_next + insn_bytes);
6442 goto not_likely;
6443 case OPC_BPOSGE32:
6444 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6445 not_likely:
6446 ctx->hflags |= MIPS_HFLAG_BC;
6447 break;
6448 default:
6449 MIPS_INVAL("conditional branch/jump");
6450 gen_reserved_instruction(ctx);
6451 goto out;
6455 ctx->btarget = btgt;
6457 out:
6458 if (insn_bytes == 2) {
6459 ctx->hflags |= MIPS_HFLAG_B16;
6461 tcg_temp_free(t0);
6462 tcg_temp_free(t1);
6466 /* special3 bitfield operations */
6467 static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
6468 int rs, int lsb, int msb)
6470 TCGv t0 = tcg_temp_new();
6471 TCGv t1 = tcg_temp_new();
6473 gen_load_gpr(t1, rs);
6474 switch (opc) {
6475 case OPC_EXT:
6476 if (lsb + msb > 31) {
6477 goto fail;
6479 if (msb != 31) {
6480 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6481 } else {
6483 * The two checks together imply that lsb == 0,
6484 * so this is a simple sign-extension.
6486 tcg_gen_ext32s_tl(t0, t1);
6488 break;
6489 #if defined(TARGET_MIPS64)
6490 case OPC_DEXTU:
6491 lsb += 32;
6492 goto do_dext;
6493 case OPC_DEXTM:
6494 msb += 32;
6495 goto do_dext;
6496 case OPC_DEXT:
6497 do_dext:
6498 if (lsb + msb > 63) {
6499 goto fail;
6501 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6502 break;
6503 #endif
6504 case OPC_INS:
6505 if (lsb > msb) {
6506 goto fail;
6508 gen_load_gpr(t0, rt);
6509 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6510 tcg_gen_ext32s_tl(t0, t0);
6511 break;
6512 #if defined(TARGET_MIPS64)
6513 case OPC_DINSU:
6514 lsb += 32;
6515 /* FALLTHRU */
6516 case OPC_DINSM:
6517 msb += 32;
6518 /* FALLTHRU */
6519 case OPC_DINS:
6520 if (lsb > msb) {
6521 goto fail;
6523 gen_load_gpr(t0, rt);
6524 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6525 break;
6526 #endif
6527 default:
6528 fail:
6529 MIPS_INVAL("bitops");
6530 gen_reserved_instruction(ctx);
6531 tcg_temp_free(t0);
6532 tcg_temp_free(t1);
6533 return;
6535 gen_store_gpr(t0, rt);
6536 tcg_temp_free(t0);
6537 tcg_temp_free(t1);
6540 static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
6542 TCGv t0;
6544 if (rd == 0) {
6545 /* If no destination, treat it as a NOP. */
6546 return;
6549 t0 = tcg_temp_new();
6550 gen_load_gpr(t0, rt);
6551 switch (op2) {
6552 case OPC_WSBH:
6554 TCGv t1 = tcg_temp_new();
6555 TCGv t2 = tcg_const_tl(0x00FF00FF);
6557 tcg_gen_shri_tl(t1, t0, 8);
6558 tcg_gen_and_tl(t1, t1, t2);
6559 tcg_gen_and_tl(t0, t0, t2);
6560 tcg_gen_shli_tl(t0, t0, 8);
6561 tcg_gen_or_tl(t0, t0, t1);
6562 tcg_temp_free(t2);
6563 tcg_temp_free(t1);
6564 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6566 break;
6567 case OPC_SEB:
6568 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
6569 break;
6570 case OPC_SEH:
6571 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
6572 break;
6573 #if defined(TARGET_MIPS64)
6574 case OPC_DSBH:
6576 TCGv t1 = tcg_temp_new();
6577 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
6579 tcg_gen_shri_tl(t1, t0, 8);
6580 tcg_gen_and_tl(t1, t1, t2);
6581 tcg_gen_and_tl(t0, t0, t2);
6582 tcg_gen_shli_tl(t0, t0, 8);
6583 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6584 tcg_temp_free(t2);
6585 tcg_temp_free(t1);
6587 break;
6588 case OPC_DSHD:
6590 TCGv t1 = tcg_temp_new();
6591 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
6593 tcg_gen_shri_tl(t1, t0, 16);
6594 tcg_gen_and_tl(t1, t1, t2);
6595 tcg_gen_and_tl(t0, t0, t2);
6596 tcg_gen_shli_tl(t0, t0, 16);
6597 tcg_gen_or_tl(t0, t0, t1);
6598 tcg_gen_shri_tl(t1, t0, 32);
6599 tcg_gen_shli_tl(t0, t0, 32);
6600 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6601 tcg_temp_free(t2);
6602 tcg_temp_free(t1);
6604 break;
6605 #endif
6606 default:
6607 MIPS_INVAL("bsfhl");
6608 gen_reserved_instruction(ctx);
6609 tcg_temp_free(t0);
6610 return;
6612 tcg_temp_free(t0);
6615 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
6616 int rt, int bits)
6618 TCGv t0;
6619 if (rd == 0) {
6620 /* Treat as NOP. */
6621 return;
6623 t0 = tcg_temp_new();
6624 if (bits == 0 || bits == wordsz) {
6625 if (bits == 0) {
6626 gen_load_gpr(t0, rt);
6627 } else {
6628 gen_load_gpr(t0, rs);
6630 switch (wordsz) {
6631 case 32:
6632 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6633 break;
6634 #if defined(TARGET_MIPS64)
6635 case 64:
6636 tcg_gen_mov_tl(cpu_gpr[rd], t0);
6637 break;
6638 #endif
6640 } else {
6641 TCGv t1 = tcg_temp_new();
6642 gen_load_gpr(t0, rt);
6643 gen_load_gpr(t1, rs);
6644 switch (wordsz) {
6645 case 32:
6647 TCGv_i64 t2 = tcg_temp_new_i64();
6648 tcg_gen_concat_tl_i64(t2, t1, t0);
6649 tcg_gen_shri_i64(t2, t2, 32 - bits);
6650 gen_move_low32(cpu_gpr[rd], t2);
6651 tcg_temp_free_i64(t2);
6653 break;
6654 #if defined(TARGET_MIPS64)
6655 case 64:
6656 tcg_gen_shli_tl(t0, t0, bits);
6657 tcg_gen_shri_tl(t1, t1, 64 - bits);
6658 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
6659 break;
6660 #endif
6662 tcg_temp_free(t1);
6665 tcg_temp_free(t0);
6668 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6669 int bp)
6671 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
6674 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6675 int shift)
6677 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
6680 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
6682 TCGv t0;
6683 if (rd == 0) {
6684 /* Treat as NOP. */
6685 return;
6687 t0 = tcg_temp_new();
6688 gen_load_gpr(t0, rt);
6689 switch (opc) {
6690 case OPC_BITSWAP:
6691 gen_helper_bitswap(cpu_gpr[rd], t0);
6692 break;
6693 #if defined(TARGET_MIPS64)
6694 case OPC_DBITSWAP:
6695 gen_helper_dbitswap(cpu_gpr[rd], t0);
6696 break;
6697 #endif
6699 tcg_temp_free(t0);
6702 #ifndef CONFIG_USER_ONLY
6703 /* CP0 (MMU and control) */
6704 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
6706 TCGv_i64 t0 = tcg_temp_new_i64();
6707 TCGv_i64 t1 = tcg_temp_new_i64();
6709 tcg_gen_ext_tl_i64(t0, arg);
6710 tcg_gen_ld_i64(t1, cpu_env, off);
6711 #if defined(TARGET_MIPS64)
6712 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
6713 #else
6714 tcg_gen_concat32_i64(t1, t1, t0);
6715 #endif
6716 tcg_gen_st_i64(t1, cpu_env, off);
6717 tcg_temp_free_i64(t1);
6718 tcg_temp_free_i64(t0);
6721 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
6723 TCGv_i64 t0 = tcg_temp_new_i64();
6724 TCGv_i64 t1 = tcg_temp_new_i64();
6726 tcg_gen_ext_tl_i64(t0, arg);
6727 tcg_gen_ld_i64(t1, cpu_env, off);
6728 tcg_gen_concat32_i64(t1, t1, t0);
6729 tcg_gen_st_i64(t1, cpu_env, off);
6730 tcg_temp_free_i64(t1);
6731 tcg_temp_free_i64(t0);
6734 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
6736 TCGv_i64 t0 = tcg_temp_new_i64();
6738 tcg_gen_ld_i64(t0, cpu_env, off);
6739 #if defined(TARGET_MIPS64)
6740 tcg_gen_shri_i64(t0, t0, 30);
6741 #else
6742 tcg_gen_shri_i64(t0, t0, 32);
6743 #endif
6744 gen_move_low32(arg, t0);
6745 tcg_temp_free_i64(t0);
6748 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
6750 TCGv_i64 t0 = tcg_temp_new_i64();
6752 tcg_gen_ld_i64(t0, cpu_env, off);
6753 tcg_gen_shri_i64(t0, t0, 32 + shift);
6754 gen_move_low32(arg, t0);
6755 tcg_temp_free_i64(t0);
6758 static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
6760 TCGv_i32 t0 = tcg_temp_new_i32();
6762 tcg_gen_ld_i32(t0, cpu_env, off);
6763 tcg_gen_ext_i32_tl(arg, t0);
6764 tcg_temp_free_i32(t0);
6767 static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
6769 tcg_gen_ld_tl(arg, cpu_env, off);
6770 tcg_gen_ext32s_tl(arg, arg);
6773 static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
6775 TCGv_i32 t0 = tcg_temp_new_i32();
6777 tcg_gen_trunc_tl_i32(t0, arg);
6778 tcg_gen_st_i32(t0, cpu_env, off);
6779 tcg_temp_free_i32(t0);
6782 #define CP0_CHECK(c) \
6783 do { \
6784 if (!(c)) { \
6785 goto cp0_unimplemented; \
6787 } while (0)
6789 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6791 const char *register_name = "invalid";
6793 switch (reg) {
6794 case CP0_REGISTER_02:
6795 switch (sel) {
6796 case 0:
6797 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6798 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6799 register_name = "EntryLo0";
6800 break;
6801 default:
6802 goto cp0_unimplemented;
6804 break;
6805 case CP0_REGISTER_03:
6806 switch (sel) {
6807 case CP0_REG03__ENTRYLO1:
6808 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6809 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6810 register_name = "EntryLo1";
6811 break;
6812 default:
6813 goto cp0_unimplemented;
6815 break;
6816 case CP0_REGISTER_09:
6817 switch (sel) {
6818 case CP0_REG09__SAAR:
6819 CP0_CHECK(ctx->saar);
6820 gen_helper_mfhc0_saar(arg, cpu_env);
6821 register_name = "SAAR";
6822 break;
6823 default:
6824 goto cp0_unimplemented;
6826 break;
6827 case CP0_REGISTER_17:
6828 switch (sel) {
6829 case CP0_REG17__LLADDR:
6830 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
6831 ctx->CP0_LLAddr_shift);
6832 register_name = "LLAddr";
6833 break;
6834 case CP0_REG17__MAAR:
6835 CP0_CHECK(ctx->mrp);
6836 gen_helper_mfhc0_maar(arg, cpu_env);
6837 register_name = "MAAR";
6838 break;
6839 default:
6840 goto cp0_unimplemented;
6842 break;
6843 case CP0_REGISTER_19:
6844 switch (sel) {
6845 case CP0_REG19__WATCHHI0:
6846 case CP0_REG19__WATCHHI1:
6847 case CP0_REG19__WATCHHI2:
6848 case CP0_REG19__WATCHHI3:
6849 case CP0_REG19__WATCHHI4:
6850 case CP0_REG19__WATCHHI5:
6851 case CP0_REG19__WATCHHI6:
6852 case CP0_REG19__WATCHHI7:
6853 /* upper 32 bits are only available when Config5MI != 0 */
6854 CP0_CHECK(ctx->mi);
6855 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_WatchHi[sel]), 0);
6856 register_name = "WatchHi";
6857 break;
6858 default:
6859 goto cp0_unimplemented;
6861 break;
6862 case CP0_REGISTER_28:
6863 switch (sel) {
6864 case 0:
6865 case 2:
6866 case 4:
6867 case 6:
6868 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
6869 register_name = "TagLo";
6870 break;
6871 default:
6872 goto cp0_unimplemented;
6874 break;
6875 default:
6876 goto cp0_unimplemented;
6878 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
6879 return;
6881 cp0_unimplemented:
6882 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
6883 register_name, reg, sel);
6884 tcg_gen_movi_tl(arg, 0);
6887 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6889 const char *register_name = "invalid";
6890 uint64_t mask = ctx->PAMask >> 36;
6892 switch (reg) {
6893 case CP0_REGISTER_02:
6894 switch (sel) {
6895 case 0:
6896 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6897 tcg_gen_andi_tl(arg, arg, mask);
6898 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6899 register_name = "EntryLo0";
6900 break;
6901 default:
6902 goto cp0_unimplemented;
6904 break;
6905 case CP0_REGISTER_03:
6906 switch (sel) {
6907 case CP0_REG03__ENTRYLO1:
6908 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6909 tcg_gen_andi_tl(arg, arg, mask);
6910 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6911 register_name = "EntryLo1";
6912 break;
6913 default:
6914 goto cp0_unimplemented;
6916 break;
6917 case CP0_REGISTER_09:
6918 switch (sel) {
6919 case CP0_REG09__SAAR:
6920 CP0_CHECK(ctx->saar);
6921 gen_helper_mthc0_saar(cpu_env, arg);
6922 register_name = "SAAR";
6923 break;
6924 default:
6925 goto cp0_unimplemented;
6927 break;
6928 case CP0_REGISTER_17:
6929 switch (sel) {
6930 case CP0_REG17__LLADDR:
6932 * LLAddr is read-only (the only exception is bit 0 if LLB is
6933 * supported); the CP0_LLAddr_rw_bitmask does not seem to be
6934 * relevant for modern MIPS cores supporting MTHC0, therefore
6935 * treating MTHC0 to LLAddr as NOP.
6937 register_name = "LLAddr";
6938 break;
6939 case CP0_REG17__MAAR:
6940 CP0_CHECK(ctx->mrp);
6941 gen_helper_mthc0_maar(cpu_env, arg);
6942 register_name = "MAAR";
6943 break;
6944 default:
6945 goto cp0_unimplemented;
6947 break;
6948 case CP0_REGISTER_19:
6949 switch (sel) {
6950 case CP0_REG19__WATCHHI0:
6951 case CP0_REG19__WATCHHI1:
6952 case CP0_REG19__WATCHHI2:
6953 case CP0_REG19__WATCHHI3:
6954 case CP0_REG19__WATCHHI4:
6955 case CP0_REG19__WATCHHI5:
6956 case CP0_REG19__WATCHHI6:
6957 case CP0_REG19__WATCHHI7:
6958 /* upper 32 bits are only available when Config5MI != 0 */
6959 CP0_CHECK(ctx->mi);
6960 gen_helper_0e1i(mthc0_watchhi, arg, sel);
6961 register_name = "WatchHi";
6962 break;
6963 default:
6964 goto cp0_unimplemented;
6966 break;
6967 case CP0_REGISTER_28:
6968 switch (sel) {
6969 case 0:
6970 case 2:
6971 case 4:
6972 case 6:
6973 tcg_gen_andi_tl(arg, arg, mask);
6974 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
6975 register_name = "TagLo";
6976 break;
6977 default:
6978 goto cp0_unimplemented;
6980 break;
6981 default:
6982 goto cp0_unimplemented;
6984 trace_mips_translate_c0("mthc0", register_name, reg, sel);
6986 cp0_unimplemented:
6987 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
6988 register_name, reg, sel);
6991 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
6993 if (ctx->insn_flags & ISA_MIPS_R6) {
6994 tcg_gen_movi_tl(arg, 0);
6995 } else {
6996 tcg_gen_movi_tl(arg, ~0);
7000 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7002 const char *register_name = "invalid";
7004 if (sel != 0) {
7005 check_insn(ctx, ISA_MIPS_R1);
7008 switch (reg) {
7009 case CP0_REGISTER_00:
7010 switch (sel) {
7011 case CP0_REG00__INDEX:
7012 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
7013 register_name = "Index";
7014 break;
7015 case CP0_REG00__MVPCONTROL:
7016 CP0_CHECK(ctx->insn_flags & ASE_MT);
7017 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
7018 register_name = "MVPControl";
7019 break;
7020 case CP0_REG00__MVPCONF0:
7021 CP0_CHECK(ctx->insn_flags & ASE_MT);
7022 gen_helper_mfc0_mvpconf0(arg, cpu_env);
7023 register_name = "MVPConf0";
7024 break;
7025 case CP0_REG00__MVPCONF1:
7026 CP0_CHECK(ctx->insn_flags & ASE_MT);
7027 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7028 register_name = "MVPConf1";
7029 break;
7030 case CP0_REG00__VPCONTROL:
7031 CP0_CHECK(ctx->vp);
7032 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
7033 register_name = "VPControl";
7034 break;
7035 default:
7036 goto cp0_unimplemented;
7038 break;
7039 case CP0_REGISTER_01:
7040 switch (sel) {
7041 case CP0_REG01__RANDOM:
7042 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7043 gen_helper_mfc0_random(arg, cpu_env);
7044 register_name = "Random";
7045 break;
7046 case CP0_REG01__VPECONTROL:
7047 CP0_CHECK(ctx->insn_flags & ASE_MT);
7048 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7049 register_name = "VPEControl";
7050 break;
7051 case CP0_REG01__VPECONF0:
7052 CP0_CHECK(ctx->insn_flags & ASE_MT);
7053 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7054 register_name = "VPEConf0";
7055 break;
7056 case CP0_REG01__VPECONF1:
7057 CP0_CHECK(ctx->insn_flags & ASE_MT);
7058 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7059 register_name = "VPEConf1";
7060 break;
7061 case CP0_REG01__YQMASK:
7062 CP0_CHECK(ctx->insn_flags & ASE_MT);
7063 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
7064 register_name = "YQMask";
7065 break;
7066 case CP0_REG01__VPESCHEDULE:
7067 CP0_CHECK(ctx->insn_flags & ASE_MT);
7068 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
7069 register_name = "VPESchedule";
7070 break;
7071 case CP0_REG01__VPESCHEFBACK:
7072 CP0_CHECK(ctx->insn_flags & ASE_MT);
7073 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7074 register_name = "VPEScheFBack";
7075 break;
7076 case CP0_REG01__VPEOPT:
7077 CP0_CHECK(ctx->insn_flags & ASE_MT);
7078 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
7079 register_name = "VPEOpt";
7080 break;
7081 default:
7082 goto cp0_unimplemented;
7084 break;
7085 case CP0_REGISTER_02:
7086 switch (sel) {
7087 case CP0_REG02__ENTRYLO0:
7089 TCGv_i64 tmp = tcg_temp_new_i64();
7090 tcg_gen_ld_i64(tmp, cpu_env,
7091 offsetof(CPUMIPSState, CP0_EntryLo0));
7092 #if defined(TARGET_MIPS64)
7093 if (ctx->rxi) {
7094 /* Move RI/XI fields to bits 31:30 */
7095 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
7096 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
7098 #endif
7099 gen_move_low32(arg, tmp);
7100 tcg_temp_free_i64(tmp);
7102 register_name = "EntryLo0";
7103 break;
7104 case CP0_REG02__TCSTATUS:
7105 CP0_CHECK(ctx->insn_flags & ASE_MT);
7106 gen_helper_mfc0_tcstatus(arg, cpu_env);
7107 register_name = "TCStatus";
7108 break;
7109 case CP0_REG02__TCBIND:
7110 CP0_CHECK(ctx->insn_flags & ASE_MT);
7111 gen_helper_mfc0_tcbind(arg, cpu_env);
7112 register_name = "TCBind";
7113 break;
7114 case CP0_REG02__TCRESTART:
7115 CP0_CHECK(ctx->insn_flags & ASE_MT);
7116 gen_helper_mfc0_tcrestart(arg, cpu_env);
7117 register_name = "TCRestart";
7118 break;
7119 case CP0_REG02__TCHALT:
7120 CP0_CHECK(ctx->insn_flags & ASE_MT);
7121 gen_helper_mfc0_tchalt(arg, cpu_env);
7122 register_name = "TCHalt";
7123 break;
7124 case CP0_REG02__TCCONTEXT:
7125 CP0_CHECK(ctx->insn_flags & ASE_MT);
7126 gen_helper_mfc0_tccontext(arg, cpu_env);
7127 register_name = "TCContext";
7128 break;
7129 case CP0_REG02__TCSCHEDULE:
7130 CP0_CHECK(ctx->insn_flags & ASE_MT);
7131 gen_helper_mfc0_tcschedule(arg, cpu_env);
7132 register_name = "TCSchedule";
7133 break;
7134 case CP0_REG02__TCSCHEFBACK:
7135 CP0_CHECK(ctx->insn_flags & ASE_MT);
7136 gen_helper_mfc0_tcschefback(arg, cpu_env);
7137 register_name = "TCScheFBack";
7138 break;
7139 default:
7140 goto cp0_unimplemented;
7142 break;
7143 case CP0_REGISTER_03:
7144 switch (sel) {
7145 case CP0_REG03__ENTRYLO1:
7147 TCGv_i64 tmp = tcg_temp_new_i64();
7148 tcg_gen_ld_i64(tmp, cpu_env,
7149 offsetof(CPUMIPSState, CP0_EntryLo1));
7150 #if defined(TARGET_MIPS64)
7151 if (ctx->rxi) {
7152 /* Move RI/XI fields to bits 31:30 */
7153 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
7154 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
7156 #endif
7157 gen_move_low32(arg, tmp);
7158 tcg_temp_free_i64(tmp);
7160 register_name = "EntryLo1";
7161 break;
7162 case CP0_REG03__GLOBALNUM:
7163 CP0_CHECK(ctx->vp);
7164 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
7165 register_name = "GlobalNumber";
7166 break;
7167 default:
7168 goto cp0_unimplemented;
7170 break;
7171 case CP0_REGISTER_04:
7172 switch (sel) {
7173 case CP0_REG04__CONTEXT:
7174 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
7175 tcg_gen_ext32s_tl(arg, arg);
7176 register_name = "Context";
7177 break;
7178 case CP0_REG04__CONTEXTCONFIG:
7179 /* SmartMIPS ASE */
7180 /* gen_helper_mfc0_contextconfig(arg); */
7181 register_name = "ContextConfig";
7182 goto cp0_unimplemented;
7183 case CP0_REG04__USERLOCAL:
7184 CP0_CHECK(ctx->ulri);
7185 tcg_gen_ld_tl(arg, cpu_env,
7186 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7187 tcg_gen_ext32s_tl(arg, arg);
7188 register_name = "UserLocal";
7189 break;
7190 case CP0_REG04__MMID:
7191 CP0_CHECK(ctx->mi);
7192 gen_helper_mtc0_memorymapid(cpu_env, arg);
7193 register_name = "MMID";
7194 break;
7195 default:
7196 goto cp0_unimplemented;
7198 break;
7199 case CP0_REGISTER_05:
7200 switch (sel) {
7201 case CP0_REG05__PAGEMASK:
7202 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
7203 register_name = "PageMask";
7204 break;
7205 case CP0_REG05__PAGEGRAIN:
7206 check_insn(ctx, ISA_MIPS_R2);
7207 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
7208 register_name = "PageGrain";
7209 break;
7210 case CP0_REG05__SEGCTL0:
7211 CP0_CHECK(ctx->sc);
7212 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
7213 tcg_gen_ext32s_tl(arg, arg);
7214 register_name = "SegCtl0";
7215 break;
7216 case CP0_REG05__SEGCTL1:
7217 CP0_CHECK(ctx->sc);
7218 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
7219 tcg_gen_ext32s_tl(arg, arg);
7220 register_name = "SegCtl1";
7221 break;
7222 case CP0_REG05__SEGCTL2:
7223 CP0_CHECK(ctx->sc);
7224 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
7225 tcg_gen_ext32s_tl(arg, arg);
7226 register_name = "SegCtl2";
7227 break;
7228 case CP0_REG05__PWBASE:
7229 check_pw(ctx);
7230 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7231 register_name = "PWBase";
7232 break;
7233 case CP0_REG05__PWFIELD:
7234 check_pw(ctx);
7235 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
7236 register_name = "PWField";
7237 break;
7238 case CP0_REG05__PWSIZE:
7239 check_pw(ctx);
7240 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
7241 register_name = "PWSize";
7242 break;
7243 default:
7244 goto cp0_unimplemented;
7246 break;
7247 case CP0_REGISTER_06:
7248 switch (sel) {
7249 case CP0_REG06__WIRED:
7250 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
7251 register_name = "Wired";
7252 break;
7253 case CP0_REG06__SRSCONF0:
7254 check_insn(ctx, ISA_MIPS_R2);
7255 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
7256 register_name = "SRSConf0";
7257 break;
7258 case CP0_REG06__SRSCONF1:
7259 check_insn(ctx, ISA_MIPS_R2);
7260 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
7261 register_name = "SRSConf1";
7262 break;
7263 case CP0_REG06__SRSCONF2:
7264 check_insn(ctx, ISA_MIPS_R2);
7265 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
7266 register_name = "SRSConf2";
7267 break;
7268 case CP0_REG06__SRSCONF3:
7269 check_insn(ctx, ISA_MIPS_R2);
7270 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
7271 register_name = "SRSConf3";
7272 break;
7273 case CP0_REG06__SRSCONF4:
7274 check_insn(ctx, ISA_MIPS_R2);
7275 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
7276 register_name = "SRSConf4";
7277 break;
7278 case CP0_REG06__PWCTL:
7279 check_pw(ctx);
7280 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
7281 register_name = "PWCtl";
7282 break;
7283 default:
7284 goto cp0_unimplemented;
7286 break;
7287 case CP0_REGISTER_07:
7288 switch (sel) {
7289 case CP0_REG07__HWRENA:
7290 check_insn(ctx, ISA_MIPS_R2);
7291 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
7292 register_name = "HWREna";
7293 break;
7294 default:
7295 goto cp0_unimplemented;
7297 break;
7298 case CP0_REGISTER_08:
7299 switch (sel) {
7300 case CP0_REG08__BADVADDR:
7301 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
7302 tcg_gen_ext32s_tl(arg, arg);
7303 register_name = "BadVAddr";
7304 break;
7305 case CP0_REG08__BADINSTR:
7306 CP0_CHECK(ctx->bi);
7307 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
7308 register_name = "BadInstr";
7309 break;
7310 case CP0_REG08__BADINSTRP:
7311 CP0_CHECK(ctx->bp);
7312 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
7313 register_name = "BadInstrP";
7314 break;
7315 case CP0_REG08__BADINSTRX:
7316 CP0_CHECK(ctx->bi);
7317 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7318 tcg_gen_andi_tl(arg, arg, ~0xffff);
7319 register_name = "BadInstrX";
7320 break;
7321 default:
7322 goto cp0_unimplemented;
7324 break;
7325 case CP0_REGISTER_09:
7326 switch (sel) {
7327 case CP0_REG09__COUNT:
7328 /* Mark as an IO operation because we read the time. */
7329 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7330 gen_io_start();
7332 gen_helper_mfc0_count(arg, cpu_env);
7334 * Break the TB to be able to take timer interrupts immediately
7335 * after reading count. DISAS_STOP isn't sufficient, we need to
7336 * ensure we break completely out of translated code.
7338 gen_save_pc(ctx->base.pc_next + 4);
7339 ctx->base.is_jmp = DISAS_EXIT;
7340 register_name = "Count";
7341 break;
7342 case CP0_REG09__SAARI:
7343 CP0_CHECK(ctx->saar);
7344 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
7345 register_name = "SAARI";
7346 break;
7347 case CP0_REG09__SAAR:
7348 CP0_CHECK(ctx->saar);
7349 gen_helper_mfc0_saar(arg, cpu_env);
7350 register_name = "SAAR";
7351 break;
7352 default:
7353 goto cp0_unimplemented;
7355 break;
7356 case CP0_REGISTER_10:
7357 switch (sel) {
7358 case CP0_REG10__ENTRYHI:
7359 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
7360 tcg_gen_ext32s_tl(arg, arg);
7361 register_name = "EntryHi";
7362 break;
7363 default:
7364 goto cp0_unimplemented;
7366 break;
7367 case CP0_REGISTER_11:
7368 switch (sel) {
7369 case CP0_REG11__COMPARE:
7370 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
7371 register_name = "Compare";
7372 break;
7373 /* 6,7 are implementation dependent */
7374 default:
7375 goto cp0_unimplemented;
7377 break;
7378 case CP0_REGISTER_12:
7379 switch (sel) {
7380 case CP0_REG12__STATUS:
7381 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
7382 register_name = "Status";
7383 break;
7384 case CP0_REG12__INTCTL:
7385 check_insn(ctx, ISA_MIPS_R2);
7386 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
7387 register_name = "IntCtl";
7388 break;
7389 case CP0_REG12__SRSCTL:
7390 check_insn(ctx, ISA_MIPS_R2);
7391 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
7392 register_name = "SRSCtl";
7393 break;
7394 case CP0_REG12__SRSMAP:
7395 check_insn(ctx, ISA_MIPS_R2);
7396 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7397 register_name = "SRSMap";
7398 break;
7399 default:
7400 goto cp0_unimplemented;
7402 break;
7403 case CP0_REGISTER_13:
7404 switch (sel) {
7405 case CP0_REG13__CAUSE:
7406 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
7407 register_name = "Cause";
7408 break;
7409 default:
7410 goto cp0_unimplemented;
7412 break;
7413 case CP0_REGISTER_14:
7414 switch (sel) {
7415 case CP0_REG14__EPC:
7416 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7417 tcg_gen_ext32s_tl(arg, arg);
7418 register_name = "EPC";
7419 break;
7420 default:
7421 goto cp0_unimplemented;
7423 break;
7424 case CP0_REGISTER_15:
7425 switch (sel) {
7426 case CP0_REG15__PRID:
7427 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
7428 register_name = "PRid";
7429 break;
7430 case CP0_REG15__EBASE:
7431 check_insn(ctx, ISA_MIPS_R2);
7432 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7433 tcg_gen_ext32s_tl(arg, arg);
7434 register_name = "EBase";
7435 break;
7436 case CP0_REG15__CMGCRBASE:
7437 check_insn(ctx, ISA_MIPS_R2);
7438 CP0_CHECK(ctx->cmgcr);
7439 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7440 tcg_gen_ext32s_tl(arg, arg);
7441 register_name = "CMGCRBase";
7442 break;
7443 default:
7444 goto cp0_unimplemented;
7446 break;
7447 case CP0_REGISTER_16:
7448 switch (sel) {
7449 case CP0_REG16__CONFIG:
7450 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
7451 register_name = "Config";
7452 break;
7453 case CP0_REG16__CONFIG1:
7454 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
7455 register_name = "Config1";
7456 break;
7457 case CP0_REG16__CONFIG2:
7458 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7459 register_name = "Config2";
7460 break;
7461 case CP0_REG16__CONFIG3:
7462 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7463 register_name = "Config3";
7464 break;
7465 case CP0_REG16__CONFIG4:
7466 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7467 register_name = "Config4";
7468 break;
7469 case CP0_REG16__CONFIG5:
7470 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7471 register_name = "Config5";
7472 break;
7473 /* 6,7 are implementation dependent */
7474 case CP0_REG16__CONFIG6:
7475 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
7476 register_name = "Config6";
7477 break;
7478 case CP0_REG16__CONFIG7:
7479 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
7480 register_name = "Config7";
7481 break;
7482 default:
7483 goto cp0_unimplemented;
7485 break;
7486 case CP0_REGISTER_17:
7487 switch (sel) {
7488 case CP0_REG17__LLADDR:
7489 gen_helper_mfc0_lladdr(arg, cpu_env);
7490 register_name = "LLAddr";
7491 break;
7492 case CP0_REG17__MAAR:
7493 CP0_CHECK(ctx->mrp);
7494 gen_helper_mfc0_maar(arg, cpu_env);
7495 register_name = "MAAR";
7496 break;
7497 case CP0_REG17__MAARI:
7498 CP0_CHECK(ctx->mrp);
7499 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7500 register_name = "MAARI";
7501 break;
7502 default:
7503 goto cp0_unimplemented;
7505 break;
7506 case CP0_REGISTER_18:
7507 switch (sel) {
7508 case CP0_REG18__WATCHLO0:
7509 case CP0_REG18__WATCHLO1:
7510 case CP0_REG18__WATCHLO2:
7511 case CP0_REG18__WATCHLO3:
7512 case CP0_REG18__WATCHLO4:
7513 case CP0_REG18__WATCHLO5:
7514 case CP0_REG18__WATCHLO6:
7515 case CP0_REG18__WATCHLO7:
7516 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7517 gen_helper_1e0i(mfc0_watchlo, arg, sel);
7518 register_name = "WatchLo";
7519 break;
7520 default:
7521 goto cp0_unimplemented;
7523 break;
7524 case CP0_REGISTER_19:
7525 switch (sel) {
7526 case CP0_REG19__WATCHHI0:
7527 case CP0_REG19__WATCHHI1:
7528 case CP0_REG19__WATCHHI2:
7529 case CP0_REG19__WATCHHI3:
7530 case CP0_REG19__WATCHHI4:
7531 case CP0_REG19__WATCHHI5:
7532 case CP0_REG19__WATCHHI6:
7533 case CP0_REG19__WATCHHI7:
7534 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7535 gen_helper_1e0i(mfc0_watchhi, arg, sel);
7536 register_name = "WatchHi";
7537 break;
7538 default:
7539 goto cp0_unimplemented;
7541 break;
7542 case CP0_REGISTER_20:
7543 switch (sel) {
7544 case CP0_REG20__XCONTEXT:
7545 #if defined(TARGET_MIPS64)
7546 check_insn(ctx, ISA_MIPS3);
7547 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
7548 tcg_gen_ext32s_tl(arg, arg);
7549 register_name = "XContext";
7550 break;
7551 #endif
7552 default:
7553 goto cp0_unimplemented;
7555 break;
7556 case CP0_REGISTER_21:
7557 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7558 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7559 switch (sel) {
7560 case 0:
7561 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
7562 register_name = "Framemask";
7563 break;
7564 default:
7565 goto cp0_unimplemented;
7567 break;
7568 case CP0_REGISTER_22:
7569 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7570 register_name = "'Diagnostic"; /* implementation dependent */
7571 break;
7572 case CP0_REGISTER_23:
7573 switch (sel) {
7574 case CP0_REG23__DEBUG:
7575 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
7576 register_name = "Debug";
7577 break;
7578 case CP0_REG23__TRACECONTROL:
7579 /* PDtrace support */
7580 /* gen_helper_mfc0_tracecontrol(arg); */
7581 register_name = "TraceControl";
7582 goto cp0_unimplemented;
7583 case CP0_REG23__TRACECONTROL2:
7584 /* PDtrace support */
7585 /* gen_helper_mfc0_tracecontrol2(arg); */
7586 register_name = "TraceControl2";
7587 goto cp0_unimplemented;
7588 case CP0_REG23__USERTRACEDATA1:
7589 /* PDtrace support */
7590 /* gen_helper_mfc0_usertracedata1(arg);*/
7591 register_name = "UserTraceData1";
7592 goto cp0_unimplemented;
7593 case CP0_REG23__TRACEIBPC:
7594 /* PDtrace support */
7595 /* gen_helper_mfc0_traceibpc(arg); */
7596 register_name = "TraceIBPC";
7597 goto cp0_unimplemented;
7598 case CP0_REG23__TRACEDBPC:
7599 /* PDtrace support */
7600 /* gen_helper_mfc0_tracedbpc(arg); */
7601 register_name = "TraceDBPC";
7602 goto cp0_unimplemented;
7603 default:
7604 goto cp0_unimplemented;
7606 break;
7607 case CP0_REGISTER_24:
7608 switch (sel) {
7609 case CP0_REG24__DEPC:
7610 /* EJTAG support */
7611 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7612 tcg_gen_ext32s_tl(arg, arg);
7613 register_name = "DEPC";
7614 break;
7615 default:
7616 goto cp0_unimplemented;
7618 break;
7619 case CP0_REGISTER_25:
7620 switch (sel) {
7621 case CP0_REG25__PERFCTL0:
7622 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
7623 register_name = "Performance0";
7624 break;
7625 case CP0_REG25__PERFCNT0:
7626 /* gen_helper_mfc0_performance1(arg); */
7627 register_name = "Performance1";
7628 goto cp0_unimplemented;
7629 case CP0_REG25__PERFCTL1:
7630 /* gen_helper_mfc0_performance2(arg); */
7631 register_name = "Performance2";
7632 goto cp0_unimplemented;
7633 case CP0_REG25__PERFCNT1:
7634 /* gen_helper_mfc0_performance3(arg); */
7635 register_name = "Performance3";
7636 goto cp0_unimplemented;
7637 case CP0_REG25__PERFCTL2:
7638 /* gen_helper_mfc0_performance4(arg); */
7639 register_name = "Performance4";
7640 goto cp0_unimplemented;
7641 case CP0_REG25__PERFCNT2:
7642 /* gen_helper_mfc0_performance5(arg); */
7643 register_name = "Performance5";
7644 goto cp0_unimplemented;
7645 case CP0_REG25__PERFCTL3:
7646 /* gen_helper_mfc0_performance6(arg); */
7647 register_name = "Performance6";
7648 goto cp0_unimplemented;
7649 case CP0_REG25__PERFCNT3:
7650 /* gen_helper_mfc0_performance7(arg); */
7651 register_name = "Performance7";
7652 goto cp0_unimplemented;
7653 default:
7654 goto cp0_unimplemented;
7656 break;
7657 case CP0_REGISTER_26:
7658 switch (sel) {
7659 case CP0_REG26__ERRCTL:
7660 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7661 register_name = "ErrCtl";
7662 break;
7663 default:
7664 goto cp0_unimplemented;
7666 break;
7667 case CP0_REGISTER_27:
7668 switch (sel) {
7669 case CP0_REG27__CACHERR:
7670 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7671 register_name = "CacheErr";
7672 break;
7673 default:
7674 goto cp0_unimplemented;
7676 break;
7677 case CP0_REGISTER_28:
7678 switch (sel) {
7679 case CP0_REG28__TAGLO:
7680 case CP0_REG28__TAGLO1:
7681 case CP0_REG28__TAGLO2:
7682 case CP0_REG28__TAGLO3:
7684 TCGv_i64 tmp = tcg_temp_new_i64();
7685 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
7686 gen_move_low32(arg, tmp);
7687 tcg_temp_free_i64(tmp);
7689 register_name = "TagLo";
7690 break;
7691 case CP0_REG28__DATALO:
7692 case CP0_REG28__DATALO1:
7693 case CP0_REG28__DATALO2:
7694 case CP0_REG28__DATALO3:
7695 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7696 register_name = "DataLo";
7697 break;
7698 default:
7699 goto cp0_unimplemented;
7701 break;
7702 case CP0_REGISTER_29:
7703 switch (sel) {
7704 case CP0_REG29__TAGHI:
7705 case CP0_REG29__TAGHI1:
7706 case CP0_REG29__TAGHI2:
7707 case CP0_REG29__TAGHI3:
7708 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7709 register_name = "TagHi";
7710 break;
7711 case CP0_REG29__DATAHI:
7712 case CP0_REG29__DATAHI1:
7713 case CP0_REG29__DATAHI2:
7714 case CP0_REG29__DATAHI3:
7715 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7716 register_name = "DataHi";
7717 break;
7718 default:
7719 goto cp0_unimplemented;
7721 break;
7722 case CP0_REGISTER_30:
7723 switch (sel) {
7724 case CP0_REG30__ERROREPC:
7725 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7726 tcg_gen_ext32s_tl(arg, arg);
7727 register_name = "ErrorEPC";
7728 break;
7729 default:
7730 goto cp0_unimplemented;
7732 break;
7733 case CP0_REGISTER_31:
7734 switch (sel) {
7735 case CP0_REG31__DESAVE:
7736 /* EJTAG support */
7737 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7738 register_name = "DESAVE";
7739 break;
7740 case CP0_REG31__KSCRATCH1:
7741 case CP0_REG31__KSCRATCH2:
7742 case CP0_REG31__KSCRATCH3:
7743 case CP0_REG31__KSCRATCH4:
7744 case CP0_REG31__KSCRATCH5:
7745 case CP0_REG31__KSCRATCH6:
7746 CP0_CHECK(ctx->kscrexist & (1 << sel));
7747 tcg_gen_ld_tl(arg, cpu_env,
7748 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
7749 tcg_gen_ext32s_tl(arg, arg);
7750 register_name = "KScratch";
7751 break;
7752 default:
7753 goto cp0_unimplemented;
7755 break;
7756 default:
7757 goto cp0_unimplemented;
7759 trace_mips_translate_c0("mfc0", register_name, reg, sel);
7760 return;
7762 cp0_unimplemented:
7763 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
7764 register_name, reg, sel);
7765 gen_mfc0_unimplemented(ctx, arg);
7768 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7770 const char *register_name = "invalid";
7772 if (sel != 0) {
7773 check_insn(ctx, ISA_MIPS_R1);
7776 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7777 gen_io_start();
7780 switch (reg) {
7781 case CP0_REGISTER_00:
7782 switch (sel) {
7783 case CP0_REG00__INDEX:
7784 gen_helper_mtc0_index(cpu_env, arg);
7785 register_name = "Index";
7786 break;
7787 case CP0_REG00__MVPCONTROL:
7788 CP0_CHECK(ctx->insn_flags & ASE_MT);
7789 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7790 register_name = "MVPControl";
7791 break;
7792 case CP0_REG00__MVPCONF0:
7793 CP0_CHECK(ctx->insn_flags & ASE_MT);
7794 /* ignored */
7795 register_name = "MVPConf0";
7796 break;
7797 case CP0_REG00__MVPCONF1:
7798 CP0_CHECK(ctx->insn_flags & ASE_MT);
7799 /* ignored */
7800 register_name = "MVPConf1";
7801 break;
7802 case CP0_REG00__VPCONTROL:
7803 CP0_CHECK(ctx->vp);
7804 /* ignored */
7805 register_name = "VPControl";
7806 break;
7807 default:
7808 goto cp0_unimplemented;
7810 break;
7811 case CP0_REGISTER_01:
7812 switch (sel) {
7813 case CP0_REG01__RANDOM:
7814 /* ignored */
7815 register_name = "Random";
7816 break;
7817 case CP0_REG01__VPECONTROL:
7818 CP0_CHECK(ctx->insn_flags & ASE_MT);
7819 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7820 register_name = "VPEControl";
7821 break;
7822 case CP0_REG01__VPECONF0:
7823 CP0_CHECK(ctx->insn_flags & ASE_MT);
7824 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7825 register_name = "VPEConf0";
7826 break;
7827 case CP0_REG01__VPECONF1:
7828 CP0_CHECK(ctx->insn_flags & ASE_MT);
7829 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7830 register_name = "VPEConf1";
7831 break;
7832 case CP0_REG01__YQMASK:
7833 CP0_CHECK(ctx->insn_flags & ASE_MT);
7834 gen_helper_mtc0_yqmask(cpu_env, arg);
7835 register_name = "YQMask";
7836 break;
7837 case CP0_REG01__VPESCHEDULE:
7838 CP0_CHECK(ctx->insn_flags & ASE_MT);
7839 tcg_gen_st_tl(arg, cpu_env,
7840 offsetof(CPUMIPSState, CP0_VPESchedule));
7841 register_name = "VPESchedule";
7842 break;
7843 case CP0_REG01__VPESCHEFBACK:
7844 CP0_CHECK(ctx->insn_flags & ASE_MT);
7845 tcg_gen_st_tl(arg, cpu_env,
7846 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7847 register_name = "VPEScheFBack";
7848 break;
7849 case CP0_REG01__VPEOPT:
7850 CP0_CHECK(ctx->insn_flags & ASE_MT);
7851 gen_helper_mtc0_vpeopt(cpu_env, arg);
7852 register_name = "VPEOpt";
7853 break;
7854 default:
7855 goto cp0_unimplemented;
7857 break;
7858 case CP0_REGISTER_02:
7859 switch (sel) {
7860 case CP0_REG02__ENTRYLO0:
7861 gen_helper_mtc0_entrylo0(cpu_env, arg);
7862 register_name = "EntryLo0";
7863 break;
7864 case CP0_REG02__TCSTATUS:
7865 CP0_CHECK(ctx->insn_flags & ASE_MT);
7866 gen_helper_mtc0_tcstatus(cpu_env, arg);
7867 register_name = "TCStatus";
7868 break;
7869 case CP0_REG02__TCBIND:
7870 CP0_CHECK(ctx->insn_flags & ASE_MT);
7871 gen_helper_mtc0_tcbind(cpu_env, arg);
7872 register_name = "TCBind";
7873 break;
7874 case CP0_REG02__TCRESTART:
7875 CP0_CHECK(ctx->insn_flags & ASE_MT);
7876 gen_helper_mtc0_tcrestart(cpu_env, arg);
7877 register_name = "TCRestart";
7878 break;
7879 case CP0_REG02__TCHALT:
7880 CP0_CHECK(ctx->insn_flags & ASE_MT);
7881 gen_helper_mtc0_tchalt(cpu_env, arg);
7882 register_name = "TCHalt";
7883 break;
7884 case CP0_REG02__TCCONTEXT:
7885 CP0_CHECK(ctx->insn_flags & ASE_MT);
7886 gen_helper_mtc0_tccontext(cpu_env, arg);
7887 register_name = "TCContext";
7888 break;
7889 case CP0_REG02__TCSCHEDULE:
7890 CP0_CHECK(ctx->insn_flags & ASE_MT);
7891 gen_helper_mtc0_tcschedule(cpu_env, arg);
7892 register_name = "TCSchedule";
7893 break;
7894 case CP0_REG02__TCSCHEFBACK:
7895 CP0_CHECK(ctx->insn_flags & ASE_MT);
7896 gen_helper_mtc0_tcschefback(cpu_env, arg);
7897 register_name = "TCScheFBack";
7898 break;
7899 default:
7900 goto cp0_unimplemented;
7902 break;
7903 case CP0_REGISTER_03:
7904 switch (sel) {
7905 case CP0_REG03__ENTRYLO1:
7906 gen_helper_mtc0_entrylo1(cpu_env, arg);
7907 register_name = "EntryLo1";
7908 break;
7909 case CP0_REG03__GLOBALNUM:
7910 CP0_CHECK(ctx->vp);
7911 /* ignored */
7912 register_name = "GlobalNumber";
7913 break;
7914 default:
7915 goto cp0_unimplemented;
7917 break;
7918 case CP0_REGISTER_04:
7919 switch (sel) {
7920 case CP0_REG04__CONTEXT:
7921 gen_helper_mtc0_context(cpu_env, arg);
7922 register_name = "Context";
7923 break;
7924 case CP0_REG04__CONTEXTCONFIG:
7925 /* SmartMIPS ASE */
7926 /* gen_helper_mtc0_contextconfig(arg); */
7927 register_name = "ContextConfig";
7928 goto cp0_unimplemented;
7929 case CP0_REG04__USERLOCAL:
7930 CP0_CHECK(ctx->ulri);
7931 tcg_gen_st_tl(arg, cpu_env,
7932 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7933 register_name = "UserLocal";
7934 break;
7935 case CP0_REG04__MMID:
7936 CP0_CHECK(ctx->mi);
7937 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
7938 register_name = "MMID";
7939 break;
7940 default:
7941 goto cp0_unimplemented;
7943 break;
7944 case CP0_REGISTER_05:
7945 switch (sel) {
7946 case CP0_REG05__PAGEMASK:
7947 gen_helper_mtc0_pagemask(cpu_env, arg);
7948 register_name = "PageMask";
7949 break;
7950 case CP0_REG05__PAGEGRAIN:
7951 check_insn(ctx, ISA_MIPS_R2);
7952 gen_helper_mtc0_pagegrain(cpu_env, arg);
7953 register_name = "PageGrain";
7954 ctx->base.is_jmp = DISAS_STOP;
7955 break;
7956 case CP0_REG05__SEGCTL0:
7957 CP0_CHECK(ctx->sc);
7958 gen_helper_mtc0_segctl0(cpu_env, arg);
7959 register_name = "SegCtl0";
7960 break;
7961 case CP0_REG05__SEGCTL1:
7962 CP0_CHECK(ctx->sc);
7963 gen_helper_mtc0_segctl1(cpu_env, arg);
7964 register_name = "SegCtl1";
7965 break;
7966 case CP0_REG05__SEGCTL2:
7967 CP0_CHECK(ctx->sc);
7968 gen_helper_mtc0_segctl2(cpu_env, arg);
7969 register_name = "SegCtl2";
7970 break;
7971 case CP0_REG05__PWBASE:
7972 check_pw(ctx);
7973 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7974 register_name = "PWBase";
7975 break;
7976 case CP0_REG05__PWFIELD:
7977 check_pw(ctx);
7978 gen_helper_mtc0_pwfield(cpu_env, arg);
7979 register_name = "PWField";
7980 break;
7981 case CP0_REG05__PWSIZE:
7982 check_pw(ctx);
7983 gen_helper_mtc0_pwsize(cpu_env, arg);
7984 register_name = "PWSize";
7985 break;
7986 default:
7987 goto cp0_unimplemented;
7989 break;
7990 case CP0_REGISTER_06:
7991 switch (sel) {
7992 case CP0_REG06__WIRED:
7993 gen_helper_mtc0_wired(cpu_env, arg);
7994 register_name = "Wired";
7995 break;
7996 case CP0_REG06__SRSCONF0:
7997 check_insn(ctx, ISA_MIPS_R2);
7998 gen_helper_mtc0_srsconf0(cpu_env, arg);
7999 register_name = "SRSConf0";
8000 break;
8001 case CP0_REG06__SRSCONF1:
8002 check_insn(ctx, ISA_MIPS_R2);
8003 gen_helper_mtc0_srsconf1(cpu_env, arg);
8004 register_name = "SRSConf1";
8005 break;
8006 case CP0_REG06__SRSCONF2:
8007 check_insn(ctx, ISA_MIPS_R2);
8008 gen_helper_mtc0_srsconf2(cpu_env, arg);
8009 register_name = "SRSConf2";
8010 break;
8011 case CP0_REG06__SRSCONF3:
8012 check_insn(ctx, ISA_MIPS_R2);
8013 gen_helper_mtc0_srsconf3(cpu_env, arg);
8014 register_name = "SRSConf3";
8015 break;
8016 case CP0_REG06__SRSCONF4:
8017 check_insn(ctx, ISA_MIPS_R2);
8018 gen_helper_mtc0_srsconf4(cpu_env, arg);
8019 register_name = "SRSConf4";
8020 break;
8021 case CP0_REG06__PWCTL:
8022 check_pw(ctx);
8023 gen_helper_mtc0_pwctl(cpu_env, arg);
8024 register_name = "PWCtl";
8025 break;
8026 default:
8027 goto cp0_unimplemented;
8029 break;
8030 case CP0_REGISTER_07:
8031 switch (sel) {
8032 case CP0_REG07__HWRENA:
8033 check_insn(ctx, ISA_MIPS_R2);
8034 gen_helper_mtc0_hwrena(cpu_env, arg);
8035 ctx->base.is_jmp = DISAS_STOP;
8036 register_name = "HWREna";
8037 break;
8038 default:
8039 goto cp0_unimplemented;
8041 break;
8042 case CP0_REGISTER_08:
8043 switch (sel) {
8044 case CP0_REG08__BADVADDR:
8045 /* ignored */
8046 register_name = "BadVAddr";
8047 break;
8048 case CP0_REG08__BADINSTR:
8049 /* ignored */
8050 register_name = "BadInstr";
8051 break;
8052 case CP0_REG08__BADINSTRP:
8053 /* ignored */
8054 register_name = "BadInstrP";
8055 break;
8056 case CP0_REG08__BADINSTRX:
8057 /* ignored */
8058 register_name = "BadInstrX";
8059 break;
8060 default:
8061 goto cp0_unimplemented;
8063 break;
8064 case CP0_REGISTER_09:
8065 switch (sel) {
8066 case CP0_REG09__COUNT:
8067 gen_helper_mtc0_count(cpu_env, arg);
8068 register_name = "Count";
8069 break;
8070 case CP0_REG09__SAARI:
8071 CP0_CHECK(ctx->saar);
8072 gen_helper_mtc0_saari(cpu_env, arg);
8073 register_name = "SAARI";
8074 break;
8075 case CP0_REG09__SAAR:
8076 CP0_CHECK(ctx->saar);
8077 gen_helper_mtc0_saar(cpu_env, arg);
8078 register_name = "SAAR";
8079 break;
8080 default:
8081 goto cp0_unimplemented;
8083 break;
8084 case CP0_REGISTER_10:
8085 switch (sel) {
8086 case CP0_REG10__ENTRYHI:
8087 gen_helper_mtc0_entryhi(cpu_env, arg);
8088 register_name = "EntryHi";
8089 break;
8090 default:
8091 goto cp0_unimplemented;
8093 break;
8094 case CP0_REGISTER_11:
8095 switch (sel) {
8096 case CP0_REG11__COMPARE:
8097 gen_helper_mtc0_compare(cpu_env, arg);
8098 register_name = "Compare";
8099 break;
8100 /* 6,7 are implementation dependent */
8101 default:
8102 goto cp0_unimplemented;
8104 break;
8105 case CP0_REGISTER_12:
8106 switch (sel) {
8107 case CP0_REG12__STATUS:
8108 save_cpu_state(ctx, 1);
8109 gen_helper_mtc0_status(cpu_env, arg);
8110 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8111 gen_save_pc(ctx->base.pc_next + 4);
8112 ctx->base.is_jmp = DISAS_EXIT;
8113 register_name = "Status";
8114 break;
8115 case CP0_REG12__INTCTL:
8116 check_insn(ctx, ISA_MIPS_R2);
8117 gen_helper_mtc0_intctl(cpu_env, arg);
8118 /* Stop translation as we may have switched the execution mode */
8119 ctx->base.is_jmp = DISAS_STOP;
8120 register_name = "IntCtl";
8121 break;
8122 case CP0_REG12__SRSCTL:
8123 check_insn(ctx, ISA_MIPS_R2);
8124 gen_helper_mtc0_srsctl(cpu_env, arg);
8125 /* Stop translation as we may have switched the execution mode */
8126 ctx->base.is_jmp = DISAS_STOP;
8127 register_name = "SRSCtl";
8128 break;
8129 case CP0_REG12__SRSMAP:
8130 check_insn(ctx, ISA_MIPS_R2);
8131 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8132 /* Stop translation as we may have switched the execution mode */
8133 ctx->base.is_jmp = DISAS_STOP;
8134 register_name = "SRSMap";
8135 break;
8136 default:
8137 goto cp0_unimplemented;
8139 break;
8140 case CP0_REGISTER_13:
8141 switch (sel) {
8142 case CP0_REG13__CAUSE:
8143 save_cpu_state(ctx, 1);
8144 gen_helper_mtc0_cause(cpu_env, arg);
8146 * Stop translation as we may have triggered an interrupt.
8147 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8148 * translated code to check for pending interrupts.
8150 gen_save_pc(ctx->base.pc_next + 4);
8151 ctx->base.is_jmp = DISAS_EXIT;
8152 register_name = "Cause";
8153 break;
8154 default:
8155 goto cp0_unimplemented;
8157 break;
8158 case CP0_REGISTER_14:
8159 switch (sel) {
8160 case CP0_REG14__EPC:
8161 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8162 register_name = "EPC";
8163 break;
8164 default:
8165 goto cp0_unimplemented;
8167 break;
8168 case CP0_REGISTER_15:
8169 switch (sel) {
8170 case CP0_REG15__PRID:
8171 /* ignored */
8172 register_name = "PRid";
8173 break;
8174 case CP0_REG15__EBASE:
8175 check_insn(ctx, ISA_MIPS_R2);
8176 gen_helper_mtc0_ebase(cpu_env, arg);
8177 register_name = "EBase";
8178 break;
8179 default:
8180 goto cp0_unimplemented;
8182 break;
8183 case CP0_REGISTER_16:
8184 switch (sel) {
8185 case CP0_REG16__CONFIG:
8186 gen_helper_mtc0_config0(cpu_env, arg);
8187 register_name = "Config";
8188 /* Stop translation as we may have switched the execution mode */
8189 ctx->base.is_jmp = DISAS_STOP;
8190 break;
8191 case CP0_REG16__CONFIG1:
8192 /* ignored, read only */
8193 register_name = "Config1";
8194 break;
8195 case CP0_REG16__CONFIG2:
8196 gen_helper_mtc0_config2(cpu_env, arg);
8197 register_name = "Config2";
8198 /* Stop translation as we may have switched the execution mode */
8199 ctx->base.is_jmp = DISAS_STOP;
8200 break;
8201 case CP0_REG16__CONFIG3:
8202 gen_helper_mtc0_config3(cpu_env, arg);
8203 register_name = "Config3";
8204 /* Stop translation as we may have switched the execution mode */
8205 ctx->base.is_jmp = DISAS_STOP;
8206 break;
8207 case CP0_REG16__CONFIG4:
8208 gen_helper_mtc0_config4(cpu_env, arg);
8209 register_name = "Config4";
8210 ctx->base.is_jmp = DISAS_STOP;
8211 break;
8212 case CP0_REG16__CONFIG5:
8213 gen_helper_mtc0_config5(cpu_env, arg);
8214 register_name = "Config5";
8215 /* Stop translation as we may have switched the execution mode */
8216 ctx->base.is_jmp = DISAS_STOP;
8217 break;
8218 /* 6,7 are implementation dependent */
8219 case CP0_REG16__CONFIG6:
8220 /* ignored */
8221 register_name = "Config6";
8222 break;
8223 case CP0_REG16__CONFIG7:
8224 /* ignored */
8225 register_name = "Config7";
8226 break;
8227 default:
8228 register_name = "Invalid config selector";
8229 goto cp0_unimplemented;
8231 break;
8232 case CP0_REGISTER_17:
8233 switch (sel) {
8234 case CP0_REG17__LLADDR:
8235 gen_helper_mtc0_lladdr(cpu_env, arg);
8236 register_name = "LLAddr";
8237 break;
8238 case CP0_REG17__MAAR:
8239 CP0_CHECK(ctx->mrp);
8240 gen_helper_mtc0_maar(cpu_env, arg);
8241 register_name = "MAAR";
8242 break;
8243 case CP0_REG17__MAARI:
8244 CP0_CHECK(ctx->mrp);
8245 gen_helper_mtc0_maari(cpu_env, arg);
8246 register_name = "MAARI";
8247 break;
8248 default:
8249 goto cp0_unimplemented;
8251 break;
8252 case CP0_REGISTER_18:
8253 switch (sel) {
8254 case CP0_REG18__WATCHLO0:
8255 case CP0_REG18__WATCHLO1:
8256 case CP0_REG18__WATCHLO2:
8257 case CP0_REG18__WATCHLO3:
8258 case CP0_REG18__WATCHLO4:
8259 case CP0_REG18__WATCHLO5:
8260 case CP0_REG18__WATCHLO6:
8261 case CP0_REG18__WATCHLO7:
8262 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8263 gen_helper_0e1i(mtc0_watchlo, arg, sel);
8264 register_name = "WatchLo";
8265 break;
8266 default:
8267 goto cp0_unimplemented;
8269 break;
8270 case CP0_REGISTER_19:
8271 switch (sel) {
8272 case CP0_REG19__WATCHHI0:
8273 case CP0_REG19__WATCHHI1:
8274 case CP0_REG19__WATCHHI2:
8275 case CP0_REG19__WATCHHI3:
8276 case CP0_REG19__WATCHHI4:
8277 case CP0_REG19__WATCHHI5:
8278 case CP0_REG19__WATCHHI6:
8279 case CP0_REG19__WATCHHI7:
8280 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8281 gen_helper_0e1i(mtc0_watchhi, arg, sel);
8282 register_name = "WatchHi";
8283 break;
8284 default:
8285 goto cp0_unimplemented;
8287 break;
8288 case CP0_REGISTER_20:
8289 switch (sel) {
8290 case CP0_REG20__XCONTEXT:
8291 #if defined(TARGET_MIPS64)
8292 check_insn(ctx, ISA_MIPS3);
8293 gen_helper_mtc0_xcontext(cpu_env, arg);
8294 register_name = "XContext";
8295 break;
8296 #endif
8297 default:
8298 goto cp0_unimplemented;
8300 break;
8301 case CP0_REGISTER_21:
8302 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8303 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
8304 switch (sel) {
8305 case 0:
8306 gen_helper_mtc0_framemask(cpu_env, arg);
8307 register_name = "Framemask";
8308 break;
8309 default:
8310 goto cp0_unimplemented;
8312 break;
8313 case CP0_REGISTER_22:
8314 /* ignored */
8315 register_name = "Diagnostic"; /* implementation dependent */
8316 break;
8317 case CP0_REGISTER_23:
8318 switch (sel) {
8319 case CP0_REG23__DEBUG:
8320 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8321 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8322 gen_save_pc(ctx->base.pc_next + 4);
8323 ctx->base.is_jmp = DISAS_EXIT;
8324 register_name = "Debug";
8325 break;
8326 case CP0_REG23__TRACECONTROL:
8327 /* PDtrace support */
8328 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
8329 register_name = "TraceControl";
8330 /* Stop translation as we may have switched the execution mode */
8331 ctx->base.is_jmp = DISAS_STOP;
8332 goto cp0_unimplemented;
8333 case CP0_REG23__TRACECONTROL2:
8334 /* PDtrace support */
8335 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
8336 register_name = "TraceControl2";
8337 /* Stop translation as we may have switched the execution mode */
8338 ctx->base.is_jmp = DISAS_STOP;
8339 goto cp0_unimplemented;
8340 case CP0_REG23__USERTRACEDATA1:
8341 /* Stop translation as we may have switched the execution mode */
8342 ctx->base.is_jmp = DISAS_STOP;
8343 /* PDtrace support */
8344 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
8345 register_name = "UserTraceData";
8346 /* Stop translation as we may have switched the execution mode */
8347 ctx->base.is_jmp = DISAS_STOP;
8348 goto cp0_unimplemented;
8349 case CP0_REG23__TRACEIBPC:
8350 /* PDtrace support */
8351 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
8352 /* Stop translation as we may have switched the execution mode */
8353 ctx->base.is_jmp = DISAS_STOP;
8354 register_name = "TraceIBPC";
8355 goto cp0_unimplemented;
8356 case CP0_REG23__TRACEDBPC:
8357 /* PDtrace support */
8358 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
8359 /* Stop translation as we may have switched the execution mode */
8360 ctx->base.is_jmp = DISAS_STOP;
8361 register_name = "TraceDBPC";
8362 goto cp0_unimplemented;
8363 default:
8364 goto cp0_unimplemented;
8366 break;
8367 case CP0_REGISTER_24:
8368 switch (sel) {
8369 case CP0_REG24__DEPC:
8370 /* EJTAG support */
8371 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8372 register_name = "DEPC";
8373 break;
8374 default:
8375 goto cp0_unimplemented;
8377 break;
8378 case CP0_REGISTER_25:
8379 switch (sel) {
8380 case CP0_REG25__PERFCTL0:
8381 gen_helper_mtc0_performance0(cpu_env, arg);
8382 register_name = "Performance0";
8383 break;
8384 case CP0_REG25__PERFCNT0:
8385 /* gen_helper_mtc0_performance1(arg); */
8386 register_name = "Performance1";
8387 goto cp0_unimplemented;
8388 case CP0_REG25__PERFCTL1:
8389 /* gen_helper_mtc0_performance2(arg); */
8390 register_name = "Performance2";
8391 goto cp0_unimplemented;
8392 case CP0_REG25__PERFCNT1:
8393 /* gen_helper_mtc0_performance3(arg); */
8394 register_name = "Performance3";
8395 goto cp0_unimplemented;
8396 case CP0_REG25__PERFCTL2:
8397 /* gen_helper_mtc0_performance4(arg); */
8398 register_name = "Performance4";
8399 goto cp0_unimplemented;
8400 case CP0_REG25__PERFCNT2:
8401 /* gen_helper_mtc0_performance5(arg); */
8402 register_name = "Performance5";
8403 goto cp0_unimplemented;
8404 case CP0_REG25__PERFCTL3:
8405 /* gen_helper_mtc0_performance6(arg); */
8406 register_name = "Performance6";
8407 goto cp0_unimplemented;
8408 case CP0_REG25__PERFCNT3:
8409 /* gen_helper_mtc0_performance7(arg); */
8410 register_name = "Performance7";
8411 goto cp0_unimplemented;
8412 default:
8413 goto cp0_unimplemented;
8415 break;
8416 case CP0_REGISTER_26:
8417 switch (sel) {
8418 case CP0_REG26__ERRCTL:
8419 gen_helper_mtc0_errctl(cpu_env, arg);
8420 ctx->base.is_jmp = DISAS_STOP;
8421 register_name = "ErrCtl";
8422 break;
8423 default:
8424 goto cp0_unimplemented;
8426 break;
8427 case CP0_REGISTER_27:
8428 switch (sel) {
8429 case CP0_REG27__CACHERR:
8430 /* ignored */
8431 register_name = "CacheErr";
8432 break;
8433 default:
8434 goto cp0_unimplemented;
8436 break;
8437 case CP0_REGISTER_28:
8438 switch (sel) {
8439 case CP0_REG28__TAGLO:
8440 case CP0_REG28__TAGLO1:
8441 case CP0_REG28__TAGLO2:
8442 case CP0_REG28__TAGLO3:
8443 gen_helper_mtc0_taglo(cpu_env, arg);
8444 register_name = "TagLo";
8445 break;
8446 case CP0_REG28__DATALO:
8447 case CP0_REG28__DATALO1:
8448 case CP0_REG28__DATALO2:
8449 case CP0_REG28__DATALO3:
8450 gen_helper_mtc0_datalo(cpu_env, arg);
8451 register_name = "DataLo";
8452 break;
8453 default:
8454 goto cp0_unimplemented;
8456 break;
8457 case CP0_REGISTER_29:
8458 switch (sel) {
8459 case CP0_REG29__TAGHI:
8460 case CP0_REG29__TAGHI1:
8461 case CP0_REG29__TAGHI2:
8462 case CP0_REG29__TAGHI3:
8463 gen_helper_mtc0_taghi(cpu_env, arg);
8464 register_name = "TagHi";
8465 break;
8466 case CP0_REG29__DATAHI:
8467 case CP0_REG29__DATAHI1:
8468 case CP0_REG29__DATAHI2:
8469 case CP0_REG29__DATAHI3:
8470 gen_helper_mtc0_datahi(cpu_env, arg);
8471 register_name = "DataHi";
8472 break;
8473 default:
8474 register_name = "invalid sel";
8475 goto cp0_unimplemented;
8477 break;
8478 case CP0_REGISTER_30:
8479 switch (sel) {
8480 case CP0_REG30__ERROREPC:
8481 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8482 register_name = "ErrorEPC";
8483 break;
8484 default:
8485 goto cp0_unimplemented;
8487 break;
8488 case CP0_REGISTER_31:
8489 switch (sel) {
8490 case CP0_REG31__DESAVE:
8491 /* EJTAG support */
8492 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8493 register_name = "DESAVE";
8494 break;
8495 case CP0_REG31__KSCRATCH1:
8496 case CP0_REG31__KSCRATCH2:
8497 case CP0_REG31__KSCRATCH3:
8498 case CP0_REG31__KSCRATCH4:
8499 case CP0_REG31__KSCRATCH5:
8500 case CP0_REG31__KSCRATCH6:
8501 CP0_CHECK(ctx->kscrexist & (1 << sel));
8502 tcg_gen_st_tl(arg, cpu_env,
8503 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
8504 register_name = "KScratch";
8505 break;
8506 default:
8507 goto cp0_unimplemented;
8509 break;
8510 default:
8511 goto cp0_unimplemented;
8513 trace_mips_translate_c0("mtc0", register_name, reg, sel);
8515 /* For simplicity assume that all writes can cause interrupts. */
8516 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8518 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8519 * translated code to check for pending interrupts.
8521 gen_save_pc(ctx->base.pc_next + 4);
8522 ctx->base.is_jmp = DISAS_EXIT;
8524 return;
8526 cp0_unimplemented:
8527 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
8528 register_name, reg, sel);
8531 #if defined(TARGET_MIPS64)
8532 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8534 const char *register_name = "invalid";
8536 if (sel != 0) {
8537 check_insn(ctx, ISA_MIPS_R1);
8540 switch (reg) {
8541 case CP0_REGISTER_00:
8542 switch (sel) {
8543 case CP0_REG00__INDEX:
8544 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
8545 register_name = "Index";
8546 break;
8547 case CP0_REG00__MVPCONTROL:
8548 CP0_CHECK(ctx->insn_flags & ASE_MT);
8549 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
8550 register_name = "MVPControl";
8551 break;
8552 case CP0_REG00__MVPCONF0:
8553 CP0_CHECK(ctx->insn_flags & ASE_MT);
8554 gen_helper_mfc0_mvpconf0(arg, cpu_env);
8555 register_name = "MVPConf0";
8556 break;
8557 case CP0_REG00__MVPCONF1:
8558 CP0_CHECK(ctx->insn_flags & ASE_MT);
8559 gen_helper_mfc0_mvpconf1(arg, cpu_env);
8560 register_name = "MVPConf1";
8561 break;
8562 case CP0_REG00__VPCONTROL:
8563 CP0_CHECK(ctx->vp);
8564 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
8565 register_name = "VPControl";
8566 break;
8567 default:
8568 goto cp0_unimplemented;
8570 break;
8571 case CP0_REGISTER_01:
8572 switch (sel) {
8573 case CP0_REG01__RANDOM:
8574 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
8575 gen_helper_mfc0_random(arg, cpu_env);
8576 register_name = "Random";
8577 break;
8578 case CP0_REG01__VPECONTROL:
8579 CP0_CHECK(ctx->insn_flags & ASE_MT);
8580 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
8581 register_name = "VPEControl";
8582 break;
8583 case CP0_REG01__VPECONF0:
8584 CP0_CHECK(ctx->insn_flags & ASE_MT);
8585 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
8586 register_name = "VPEConf0";
8587 break;
8588 case CP0_REG01__VPECONF1:
8589 CP0_CHECK(ctx->insn_flags & ASE_MT);
8590 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
8591 register_name = "VPEConf1";
8592 break;
8593 case CP0_REG01__YQMASK:
8594 CP0_CHECK(ctx->insn_flags & ASE_MT);
8595 tcg_gen_ld_tl(arg, cpu_env,
8596 offsetof(CPUMIPSState, CP0_YQMask));
8597 register_name = "YQMask";
8598 break;
8599 case CP0_REG01__VPESCHEDULE:
8600 CP0_CHECK(ctx->insn_flags & ASE_MT);
8601 tcg_gen_ld_tl(arg, cpu_env,
8602 offsetof(CPUMIPSState, CP0_VPESchedule));
8603 register_name = "VPESchedule";
8604 break;
8605 case CP0_REG01__VPESCHEFBACK:
8606 CP0_CHECK(ctx->insn_flags & ASE_MT);
8607 tcg_gen_ld_tl(arg, cpu_env,
8608 offsetof(CPUMIPSState, CP0_VPEScheFBack));
8609 register_name = "VPEScheFBack";
8610 break;
8611 case CP0_REG01__VPEOPT:
8612 CP0_CHECK(ctx->insn_flags & ASE_MT);
8613 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
8614 register_name = "VPEOpt";
8615 break;
8616 default:
8617 goto cp0_unimplemented;
8619 break;
8620 case CP0_REGISTER_02:
8621 switch (sel) {
8622 case CP0_REG02__ENTRYLO0:
8623 tcg_gen_ld_tl(arg, cpu_env,
8624 offsetof(CPUMIPSState, CP0_EntryLo0));
8625 register_name = "EntryLo0";
8626 break;
8627 case CP0_REG02__TCSTATUS:
8628 CP0_CHECK(ctx->insn_flags & ASE_MT);
8629 gen_helper_mfc0_tcstatus(arg, cpu_env);
8630 register_name = "TCStatus";
8631 break;
8632 case CP0_REG02__TCBIND:
8633 CP0_CHECK(ctx->insn_flags & ASE_MT);
8634 gen_helper_mfc0_tcbind(arg, cpu_env);
8635 register_name = "TCBind";
8636 break;
8637 case CP0_REG02__TCRESTART:
8638 CP0_CHECK(ctx->insn_flags & ASE_MT);
8639 gen_helper_dmfc0_tcrestart(arg, cpu_env);
8640 register_name = "TCRestart";
8641 break;
8642 case CP0_REG02__TCHALT:
8643 CP0_CHECK(ctx->insn_flags & ASE_MT);
8644 gen_helper_dmfc0_tchalt(arg, cpu_env);
8645 register_name = "TCHalt";
8646 break;
8647 case CP0_REG02__TCCONTEXT:
8648 CP0_CHECK(ctx->insn_flags & ASE_MT);
8649 gen_helper_dmfc0_tccontext(arg, cpu_env);
8650 register_name = "TCContext";
8651 break;
8652 case CP0_REG02__TCSCHEDULE:
8653 CP0_CHECK(ctx->insn_flags & ASE_MT);
8654 gen_helper_dmfc0_tcschedule(arg, cpu_env);
8655 register_name = "TCSchedule";
8656 break;
8657 case CP0_REG02__TCSCHEFBACK:
8658 CP0_CHECK(ctx->insn_flags & ASE_MT);
8659 gen_helper_dmfc0_tcschefback(arg, cpu_env);
8660 register_name = "TCScheFBack";
8661 break;
8662 default:
8663 goto cp0_unimplemented;
8665 break;
8666 case CP0_REGISTER_03:
8667 switch (sel) {
8668 case CP0_REG03__ENTRYLO1:
8669 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
8670 register_name = "EntryLo1";
8671 break;
8672 case CP0_REG03__GLOBALNUM:
8673 CP0_CHECK(ctx->vp);
8674 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
8675 register_name = "GlobalNumber";
8676 break;
8677 default:
8678 goto cp0_unimplemented;
8680 break;
8681 case CP0_REGISTER_04:
8682 switch (sel) {
8683 case CP0_REG04__CONTEXT:
8684 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
8685 register_name = "Context";
8686 break;
8687 case CP0_REG04__CONTEXTCONFIG:
8688 /* SmartMIPS ASE */
8689 /* gen_helper_dmfc0_contextconfig(arg); */
8690 register_name = "ContextConfig";
8691 goto cp0_unimplemented;
8692 case CP0_REG04__USERLOCAL:
8693 CP0_CHECK(ctx->ulri);
8694 tcg_gen_ld_tl(arg, cpu_env,
8695 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8696 register_name = "UserLocal";
8697 break;
8698 case CP0_REG04__MMID:
8699 CP0_CHECK(ctx->mi);
8700 gen_helper_mtc0_memorymapid(cpu_env, arg);
8701 register_name = "MMID";
8702 break;
8703 default:
8704 goto cp0_unimplemented;
8706 break;
8707 case CP0_REGISTER_05:
8708 switch (sel) {
8709 case CP0_REG05__PAGEMASK:
8710 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
8711 register_name = "PageMask";
8712 break;
8713 case CP0_REG05__PAGEGRAIN:
8714 check_insn(ctx, ISA_MIPS_R2);
8715 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
8716 register_name = "PageGrain";
8717 break;
8718 case CP0_REG05__SEGCTL0:
8719 CP0_CHECK(ctx->sc);
8720 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
8721 register_name = "SegCtl0";
8722 break;
8723 case CP0_REG05__SEGCTL1:
8724 CP0_CHECK(ctx->sc);
8725 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
8726 register_name = "SegCtl1";
8727 break;
8728 case CP0_REG05__SEGCTL2:
8729 CP0_CHECK(ctx->sc);
8730 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
8731 register_name = "SegCtl2";
8732 break;
8733 case CP0_REG05__PWBASE:
8734 check_pw(ctx);
8735 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8736 register_name = "PWBase";
8737 break;
8738 case CP0_REG05__PWFIELD:
8739 check_pw(ctx);
8740 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
8741 register_name = "PWField";
8742 break;
8743 case CP0_REG05__PWSIZE:
8744 check_pw(ctx);
8745 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
8746 register_name = "PWSize";
8747 break;
8748 default:
8749 goto cp0_unimplemented;
8751 break;
8752 case CP0_REGISTER_06:
8753 switch (sel) {
8754 case CP0_REG06__WIRED:
8755 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
8756 register_name = "Wired";
8757 break;
8758 case CP0_REG06__SRSCONF0:
8759 check_insn(ctx, ISA_MIPS_R2);
8760 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
8761 register_name = "SRSConf0";
8762 break;
8763 case CP0_REG06__SRSCONF1:
8764 check_insn(ctx, ISA_MIPS_R2);
8765 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
8766 register_name = "SRSConf1";
8767 break;
8768 case CP0_REG06__SRSCONF2:
8769 check_insn(ctx, ISA_MIPS_R2);
8770 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
8771 register_name = "SRSConf2";
8772 break;
8773 case CP0_REG06__SRSCONF3:
8774 check_insn(ctx, ISA_MIPS_R2);
8775 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
8776 register_name = "SRSConf3";
8777 break;
8778 case CP0_REG06__SRSCONF4:
8779 check_insn(ctx, ISA_MIPS_R2);
8780 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
8781 register_name = "SRSConf4";
8782 break;
8783 case CP0_REG06__PWCTL:
8784 check_pw(ctx);
8785 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
8786 register_name = "PWCtl";
8787 break;
8788 default:
8789 goto cp0_unimplemented;
8791 break;
8792 case CP0_REGISTER_07:
8793 switch (sel) {
8794 case CP0_REG07__HWRENA:
8795 check_insn(ctx, ISA_MIPS_R2);
8796 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
8797 register_name = "HWREna";
8798 break;
8799 default:
8800 goto cp0_unimplemented;
8802 break;
8803 case CP0_REGISTER_08:
8804 switch (sel) {
8805 case CP0_REG08__BADVADDR:
8806 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
8807 register_name = "BadVAddr";
8808 break;
8809 case CP0_REG08__BADINSTR:
8810 CP0_CHECK(ctx->bi);
8811 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
8812 register_name = "BadInstr";
8813 break;
8814 case CP0_REG08__BADINSTRP:
8815 CP0_CHECK(ctx->bp);
8816 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
8817 register_name = "BadInstrP";
8818 break;
8819 case CP0_REG08__BADINSTRX:
8820 CP0_CHECK(ctx->bi);
8821 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
8822 tcg_gen_andi_tl(arg, arg, ~0xffff);
8823 register_name = "BadInstrX";
8824 break;
8825 default:
8826 goto cp0_unimplemented;
8828 break;
8829 case CP0_REGISTER_09:
8830 switch (sel) {
8831 case CP0_REG09__COUNT:
8832 /* Mark as an IO operation because we read the time. */
8833 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8834 gen_io_start();
8836 gen_helper_mfc0_count(arg, cpu_env);
8838 * Break the TB to be able to take timer interrupts immediately
8839 * after reading count. DISAS_STOP isn't sufficient, we need to
8840 * ensure we break completely out of translated code.
8842 gen_save_pc(ctx->base.pc_next + 4);
8843 ctx->base.is_jmp = DISAS_EXIT;
8844 register_name = "Count";
8845 break;
8846 case CP0_REG09__SAARI:
8847 CP0_CHECK(ctx->saar);
8848 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
8849 register_name = "SAARI";
8850 break;
8851 case CP0_REG09__SAAR:
8852 CP0_CHECK(ctx->saar);
8853 gen_helper_dmfc0_saar(arg, cpu_env);
8854 register_name = "SAAR";
8855 break;
8856 default:
8857 goto cp0_unimplemented;
8859 break;
8860 case CP0_REGISTER_10:
8861 switch (sel) {
8862 case CP0_REG10__ENTRYHI:
8863 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
8864 register_name = "EntryHi";
8865 break;
8866 default:
8867 goto cp0_unimplemented;
8869 break;
8870 case CP0_REGISTER_11:
8871 switch (sel) {
8872 case CP0_REG11__COMPARE:
8873 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
8874 register_name = "Compare";
8875 break;
8876 /* 6,7 are implementation dependent */
8877 default:
8878 goto cp0_unimplemented;
8880 break;
8881 case CP0_REGISTER_12:
8882 switch (sel) {
8883 case CP0_REG12__STATUS:
8884 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
8885 register_name = "Status";
8886 break;
8887 case CP0_REG12__INTCTL:
8888 check_insn(ctx, ISA_MIPS_R2);
8889 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
8890 register_name = "IntCtl";
8891 break;
8892 case CP0_REG12__SRSCTL:
8893 check_insn(ctx, ISA_MIPS_R2);
8894 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
8895 register_name = "SRSCtl";
8896 break;
8897 case CP0_REG12__SRSMAP:
8898 check_insn(ctx, ISA_MIPS_R2);
8899 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8900 register_name = "SRSMap";
8901 break;
8902 default:
8903 goto cp0_unimplemented;
8905 break;
8906 case CP0_REGISTER_13:
8907 switch (sel) {
8908 case CP0_REG13__CAUSE:
8909 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
8910 register_name = "Cause";
8911 break;
8912 default:
8913 goto cp0_unimplemented;
8915 break;
8916 case CP0_REGISTER_14:
8917 switch (sel) {
8918 case CP0_REG14__EPC:
8919 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8920 register_name = "EPC";
8921 break;
8922 default:
8923 goto cp0_unimplemented;
8925 break;
8926 case CP0_REGISTER_15:
8927 switch (sel) {
8928 case CP0_REG15__PRID:
8929 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
8930 register_name = "PRid";
8931 break;
8932 case CP0_REG15__EBASE:
8933 check_insn(ctx, ISA_MIPS_R2);
8934 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
8935 register_name = "EBase";
8936 break;
8937 case CP0_REG15__CMGCRBASE:
8938 check_insn(ctx, ISA_MIPS_R2);
8939 CP0_CHECK(ctx->cmgcr);
8940 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
8941 register_name = "CMGCRBase";
8942 break;
8943 default:
8944 goto cp0_unimplemented;
8946 break;
8947 case CP0_REGISTER_16:
8948 switch (sel) {
8949 case CP0_REG16__CONFIG:
8950 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
8951 register_name = "Config";
8952 break;
8953 case CP0_REG16__CONFIG1:
8954 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
8955 register_name = "Config1";
8956 break;
8957 case CP0_REG16__CONFIG2:
8958 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
8959 register_name = "Config2";
8960 break;
8961 case CP0_REG16__CONFIG3:
8962 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
8963 register_name = "Config3";
8964 break;
8965 case CP0_REG16__CONFIG4:
8966 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
8967 register_name = "Config4";
8968 break;
8969 case CP0_REG16__CONFIG5:
8970 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
8971 register_name = "Config5";
8972 break;
8973 /* 6,7 are implementation dependent */
8974 case CP0_REG16__CONFIG6:
8975 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
8976 register_name = "Config6";
8977 break;
8978 case CP0_REG16__CONFIG7:
8979 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
8980 register_name = "Config7";
8981 break;
8982 default:
8983 goto cp0_unimplemented;
8985 break;
8986 case CP0_REGISTER_17:
8987 switch (sel) {
8988 case CP0_REG17__LLADDR:
8989 gen_helper_dmfc0_lladdr(arg, cpu_env);
8990 register_name = "LLAddr";
8991 break;
8992 case CP0_REG17__MAAR:
8993 CP0_CHECK(ctx->mrp);
8994 gen_helper_dmfc0_maar(arg, cpu_env);
8995 register_name = "MAAR";
8996 break;
8997 case CP0_REG17__MAARI:
8998 CP0_CHECK(ctx->mrp);
8999 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
9000 register_name = "MAARI";
9001 break;
9002 default:
9003 goto cp0_unimplemented;
9005 break;
9006 case CP0_REGISTER_18:
9007 switch (sel) {
9008 case CP0_REG18__WATCHLO0:
9009 case CP0_REG18__WATCHLO1:
9010 case CP0_REG18__WATCHLO2:
9011 case CP0_REG18__WATCHLO3:
9012 case CP0_REG18__WATCHLO4:
9013 case CP0_REG18__WATCHLO5:
9014 case CP0_REG18__WATCHLO6:
9015 case CP0_REG18__WATCHLO7:
9016 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9017 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
9018 register_name = "WatchLo";
9019 break;
9020 default:
9021 goto cp0_unimplemented;
9023 break;
9024 case CP0_REGISTER_19:
9025 switch (sel) {
9026 case CP0_REG19__WATCHHI0:
9027 case CP0_REG19__WATCHHI1:
9028 case CP0_REG19__WATCHHI2:
9029 case CP0_REG19__WATCHHI3:
9030 case CP0_REG19__WATCHHI4:
9031 case CP0_REG19__WATCHHI5:
9032 case CP0_REG19__WATCHHI6:
9033 case CP0_REG19__WATCHHI7:
9034 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9035 gen_helper_1e0i(dmfc0_watchhi, arg, sel);
9036 register_name = "WatchHi";
9037 break;
9038 default:
9039 goto cp0_unimplemented;
9041 break;
9042 case CP0_REGISTER_20:
9043 switch (sel) {
9044 case CP0_REG20__XCONTEXT:
9045 check_insn(ctx, ISA_MIPS3);
9046 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
9047 register_name = "XContext";
9048 break;
9049 default:
9050 goto cp0_unimplemented;
9052 break;
9053 case CP0_REGISTER_21:
9054 /* Officially reserved, but sel 0 is used for R1x000 framemask */
9055 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
9056 switch (sel) {
9057 case 0:
9058 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
9059 register_name = "Framemask";
9060 break;
9061 default:
9062 goto cp0_unimplemented;
9064 break;
9065 case CP0_REGISTER_22:
9066 tcg_gen_movi_tl(arg, 0); /* unimplemented */
9067 register_name = "'Diagnostic"; /* implementation dependent */
9068 break;
9069 case CP0_REGISTER_23:
9070 switch (sel) {
9071 case CP0_REG23__DEBUG:
9072 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
9073 register_name = "Debug";
9074 break;
9075 case CP0_REG23__TRACECONTROL:
9076 /* PDtrace support */
9077 /* gen_helper_dmfc0_tracecontrol(arg, cpu_env); */
9078 register_name = "TraceControl";
9079 goto cp0_unimplemented;
9080 case CP0_REG23__TRACECONTROL2:
9081 /* PDtrace support */
9082 /* gen_helper_dmfc0_tracecontrol2(arg, cpu_env); */
9083 register_name = "TraceControl2";
9084 goto cp0_unimplemented;
9085 case CP0_REG23__USERTRACEDATA1:
9086 /* PDtrace support */
9087 /* gen_helper_dmfc0_usertracedata1(arg, cpu_env);*/
9088 register_name = "UserTraceData1";
9089 goto cp0_unimplemented;
9090 case CP0_REG23__TRACEIBPC:
9091 /* PDtrace support */
9092 /* gen_helper_dmfc0_traceibpc(arg, cpu_env); */
9093 register_name = "TraceIBPC";
9094 goto cp0_unimplemented;
9095 case CP0_REG23__TRACEDBPC:
9096 /* PDtrace support */
9097 /* gen_helper_dmfc0_tracedbpc(arg, cpu_env); */
9098 register_name = "TraceDBPC";
9099 goto cp0_unimplemented;
9100 default:
9101 goto cp0_unimplemented;
9103 break;
9104 case CP0_REGISTER_24:
9105 switch (sel) {
9106 case CP0_REG24__DEPC:
9107 /* EJTAG support */
9108 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
9109 register_name = "DEPC";
9110 break;
9111 default:
9112 goto cp0_unimplemented;
9114 break;
9115 case CP0_REGISTER_25:
9116 switch (sel) {
9117 case CP0_REG25__PERFCTL0:
9118 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
9119 register_name = "Performance0";
9120 break;
9121 case CP0_REG25__PERFCNT0:
9122 /* gen_helper_dmfc0_performance1(arg); */
9123 register_name = "Performance1";
9124 goto cp0_unimplemented;
9125 case CP0_REG25__PERFCTL1:
9126 /* gen_helper_dmfc0_performance2(arg); */
9127 register_name = "Performance2";
9128 goto cp0_unimplemented;
9129 case CP0_REG25__PERFCNT1:
9130 /* gen_helper_dmfc0_performance3(arg); */
9131 register_name = "Performance3";
9132 goto cp0_unimplemented;
9133 case CP0_REG25__PERFCTL2:
9134 /* gen_helper_dmfc0_performance4(arg); */
9135 register_name = "Performance4";
9136 goto cp0_unimplemented;
9137 case CP0_REG25__PERFCNT2:
9138 /* gen_helper_dmfc0_performance5(arg); */
9139 register_name = "Performance5";
9140 goto cp0_unimplemented;
9141 case CP0_REG25__PERFCTL3:
9142 /* gen_helper_dmfc0_performance6(arg); */
9143 register_name = "Performance6";
9144 goto cp0_unimplemented;
9145 case CP0_REG25__PERFCNT3:
9146 /* gen_helper_dmfc0_performance7(arg); */
9147 register_name = "Performance7";
9148 goto cp0_unimplemented;
9149 default:
9150 goto cp0_unimplemented;
9152 break;
9153 case CP0_REGISTER_26:
9154 switch (sel) {
9155 case CP0_REG26__ERRCTL:
9156 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
9157 register_name = "ErrCtl";
9158 break;
9159 default:
9160 goto cp0_unimplemented;
9162 break;
9163 case CP0_REGISTER_27:
9164 switch (sel) {
9165 /* ignored */
9166 case CP0_REG27__CACHERR:
9167 tcg_gen_movi_tl(arg, 0); /* unimplemented */
9168 register_name = "CacheErr";
9169 break;
9170 default:
9171 goto cp0_unimplemented;
9173 break;
9174 case CP0_REGISTER_28:
9175 switch (sel) {
9176 case CP0_REG28__TAGLO:
9177 case CP0_REG28__TAGLO1:
9178 case CP0_REG28__TAGLO2:
9179 case CP0_REG28__TAGLO3:
9180 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
9181 register_name = "TagLo";
9182 break;
9183 case CP0_REG28__DATALO:
9184 case CP0_REG28__DATALO1:
9185 case CP0_REG28__DATALO2:
9186 case CP0_REG28__DATALO3:
9187 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
9188 register_name = "DataLo";
9189 break;
9190 default:
9191 goto cp0_unimplemented;
9193 break;
9194 case CP0_REGISTER_29:
9195 switch (sel) {
9196 case CP0_REG29__TAGHI:
9197 case CP0_REG29__TAGHI1:
9198 case CP0_REG29__TAGHI2:
9199 case CP0_REG29__TAGHI3:
9200 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
9201 register_name = "TagHi";
9202 break;
9203 case CP0_REG29__DATAHI:
9204 case CP0_REG29__DATAHI1:
9205 case CP0_REG29__DATAHI2:
9206 case CP0_REG29__DATAHI3:
9207 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
9208 register_name = "DataHi";
9209 break;
9210 default:
9211 goto cp0_unimplemented;
9213 break;
9214 case CP0_REGISTER_30:
9215 switch (sel) {
9216 case CP0_REG30__ERROREPC:
9217 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9218 register_name = "ErrorEPC";
9219 break;
9220 default:
9221 goto cp0_unimplemented;
9223 break;
9224 case CP0_REGISTER_31:
9225 switch (sel) {
9226 case CP0_REG31__DESAVE:
9227 /* EJTAG support */
9228 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9229 register_name = "DESAVE";
9230 break;
9231 case CP0_REG31__KSCRATCH1:
9232 case CP0_REG31__KSCRATCH2:
9233 case CP0_REG31__KSCRATCH3:
9234 case CP0_REG31__KSCRATCH4:
9235 case CP0_REG31__KSCRATCH5:
9236 case CP0_REG31__KSCRATCH6:
9237 CP0_CHECK(ctx->kscrexist & (1 << sel));
9238 tcg_gen_ld_tl(arg, cpu_env,
9239 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
9240 register_name = "KScratch";
9241 break;
9242 default:
9243 goto cp0_unimplemented;
9245 break;
9246 default:
9247 goto cp0_unimplemented;
9249 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
9250 return;
9252 cp0_unimplemented:
9253 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
9254 register_name, reg, sel);
9255 gen_mfc0_unimplemented(ctx, arg);
9258 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9260 const char *register_name = "invalid";
9262 if (sel != 0) {
9263 check_insn(ctx, ISA_MIPS_R1);
9266 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9267 gen_io_start();
9270 switch (reg) {
9271 case CP0_REGISTER_00:
9272 switch (sel) {
9273 case CP0_REG00__INDEX:
9274 gen_helper_mtc0_index(cpu_env, arg);
9275 register_name = "Index";
9276 break;
9277 case CP0_REG00__MVPCONTROL:
9278 CP0_CHECK(ctx->insn_flags & ASE_MT);
9279 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
9280 register_name = "MVPControl";
9281 break;
9282 case CP0_REG00__MVPCONF0:
9283 CP0_CHECK(ctx->insn_flags & ASE_MT);
9284 /* ignored */
9285 register_name = "MVPConf0";
9286 break;
9287 case CP0_REG00__MVPCONF1:
9288 CP0_CHECK(ctx->insn_flags & ASE_MT);
9289 /* ignored */
9290 register_name = "MVPConf1";
9291 break;
9292 case CP0_REG00__VPCONTROL:
9293 CP0_CHECK(ctx->vp);
9294 /* ignored */
9295 register_name = "VPControl";
9296 break;
9297 default:
9298 goto cp0_unimplemented;
9300 break;
9301 case CP0_REGISTER_01:
9302 switch (sel) {
9303 case CP0_REG01__RANDOM:
9304 /* ignored */
9305 register_name = "Random";
9306 break;
9307 case CP0_REG01__VPECONTROL:
9308 CP0_CHECK(ctx->insn_flags & ASE_MT);
9309 gen_helper_mtc0_vpecontrol(cpu_env, arg);
9310 register_name = "VPEControl";
9311 break;
9312 case CP0_REG01__VPECONF0:
9313 CP0_CHECK(ctx->insn_flags & ASE_MT);
9314 gen_helper_mtc0_vpeconf0(cpu_env, arg);
9315 register_name = "VPEConf0";
9316 break;
9317 case CP0_REG01__VPECONF1:
9318 CP0_CHECK(ctx->insn_flags & ASE_MT);
9319 gen_helper_mtc0_vpeconf1(cpu_env, arg);
9320 register_name = "VPEConf1";
9321 break;
9322 case CP0_REG01__YQMASK:
9323 CP0_CHECK(ctx->insn_flags & ASE_MT);
9324 gen_helper_mtc0_yqmask(cpu_env, arg);
9325 register_name = "YQMask";
9326 break;
9327 case CP0_REG01__VPESCHEDULE:
9328 CP0_CHECK(ctx->insn_flags & ASE_MT);
9329 tcg_gen_st_tl(arg, cpu_env,
9330 offsetof(CPUMIPSState, CP0_VPESchedule));
9331 register_name = "VPESchedule";
9332 break;
9333 case CP0_REG01__VPESCHEFBACK:
9334 CP0_CHECK(ctx->insn_flags & ASE_MT);
9335 tcg_gen_st_tl(arg, cpu_env,
9336 offsetof(CPUMIPSState, CP0_VPEScheFBack));
9337 register_name = "VPEScheFBack";
9338 break;
9339 case CP0_REG01__VPEOPT:
9340 CP0_CHECK(ctx->insn_flags & ASE_MT);
9341 gen_helper_mtc0_vpeopt(cpu_env, arg);
9342 register_name = "VPEOpt";
9343 break;
9344 default:
9345 goto cp0_unimplemented;
9347 break;
9348 case CP0_REGISTER_02:
9349 switch (sel) {
9350 case CP0_REG02__ENTRYLO0:
9351 gen_helper_dmtc0_entrylo0(cpu_env, arg);
9352 register_name = "EntryLo0";
9353 break;
9354 case CP0_REG02__TCSTATUS:
9355 CP0_CHECK(ctx->insn_flags & ASE_MT);
9356 gen_helper_mtc0_tcstatus(cpu_env, arg);
9357 register_name = "TCStatus";
9358 break;
9359 case CP0_REG02__TCBIND:
9360 CP0_CHECK(ctx->insn_flags & ASE_MT);
9361 gen_helper_mtc0_tcbind(cpu_env, arg);
9362 register_name = "TCBind";
9363 break;
9364 case CP0_REG02__TCRESTART:
9365 CP0_CHECK(ctx->insn_flags & ASE_MT);
9366 gen_helper_mtc0_tcrestart(cpu_env, arg);
9367 register_name = "TCRestart";
9368 break;
9369 case CP0_REG02__TCHALT:
9370 CP0_CHECK(ctx->insn_flags & ASE_MT);
9371 gen_helper_mtc0_tchalt(cpu_env, arg);
9372 register_name = "TCHalt";
9373 break;
9374 case CP0_REG02__TCCONTEXT:
9375 CP0_CHECK(ctx->insn_flags & ASE_MT);
9376 gen_helper_mtc0_tccontext(cpu_env, arg);
9377 register_name = "TCContext";
9378 break;
9379 case CP0_REG02__TCSCHEDULE:
9380 CP0_CHECK(ctx->insn_flags & ASE_MT);
9381 gen_helper_mtc0_tcschedule(cpu_env, arg);
9382 register_name = "TCSchedule";
9383 break;
9384 case CP0_REG02__TCSCHEFBACK:
9385 CP0_CHECK(ctx->insn_flags & ASE_MT);
9386 gen_helper_mtc0_tcschefback(cpu_env, arg);
9387 register_name = "TCScheFBack";
9388 break;
9389 default:
9390 goto cp0_unimplemented;
9392 break;
9393 case CP0_REGISTER_03:
9394 switch (sel) {
9395 case CP0_REG03__ENTRYLO1:
9396 gen_helper_dmtc0_entrylo1(cpu_env, arg);
9397 register_name = "EntryLo1";
9398 break;
9399 case CP0_REG03__GLOBALNUM:
9400 CP0_CHECK(ctx->vp);
9401 /* ignored */
9402 register_name = "GlobalNumber";
9403 break;
9404 default:
9405 goto cp0_unimplemented;
9407 break;
9408 case CP0_REGISTER_04:
9409 switch (sel) {
9410 case CP0_REG04__CONTEXT:
9411 gen_helper_mtc0_context(cpu_env, arg);
9412 register_name = "Context";
9413 break;
9414 case CP0_REG04__CONTEXTCONFIG:
9415 /* SmartMIPS ASE */
9416 /* gen_helper_dmtc0_contextconfig(arg); */
9417 register_name = "ContextConfig";
9418 goto cp0_unimplemented;
9419 case CP0_REG04__USERLOCAL:
9420 CP0_CHECK(ctx->ulri);
9421 tcg_gen_st_tl(arg, cpu_env,
9422 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
9423 register_name = "UserLocal";
9424 break;
9425 case CP0_REG04__MMID:
9426 CP0_CHECK(ctx->mi);
9427 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
9428 register_name = "MMID";
9429 break;
9430 default:
9431 goto cp0_unimplemented;
9433 break;
9434 case CP0_REGISTER_05:
9435 switch (sel) {
9436 case CP0_REG05__PAGEMASK:
9437 gen_helper_mtc0_pagemask(cpu_env, arg);
9438 register_name = "PageMask";
9439 break;
9440 case CP0_REG05__PAGEGRAIN:
9441 check_insn(ctx, ISA_MIPS_R2);
9442 gen_helper_mtc0_pagegrain(cpu_env, arg);
9443 register_name = "PageGrain";
9444 break;
9445 case CP0_REG05__SEGCTL0:
9446 CP0_CHECK(ctx->sc);
9447 gen_helper_mtc0_segctl0(cpu_env, arg);
9448 register_name = "SegCtl0";
9449 break;
9450 case CP0_REG05__SEGCTL1:
9451 CP0_CHECK(ctx->sc);
9452 gen_helper_mtc0_segctl1(cpu_env, arg);
9453 register_name = "SegCtl1";
9454 break;
9455 case CP0_REG05__SEGCTL2:
9456 CP0_CHECK(ctx->sc);
9457 gen_helper_mtc0_segctl2(cpu_env, arg);
9458 register_name = "SegCtl2";
9459 break;
9460 case CP0_REG05__PWBASE:
9461 check_pw(ctx);
9462 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
9463 register_name = "PWBase";
9464 break;
9465 case CP0_REG05__PWFIELD:
9466 check_pw(ctx);
9467 gen_helper_mtc0_pwfield(cpu_env, arg);
9468 register_name = "PWField";
9469 break;
9470 case CP0_REG05__PWSIZE:
9471 check_pw(ctx);
9472 gen_helper_mtc0_pwsize(cpu_env, arg);
9473 register_name = "PWSize";
9474 break;
9475 default:
9476 goto cp0_unimplemented;
9478 break;
9479 case CP0_REGISTER_06:
9480 switch (sel) {
9481 case CP0_REG06__WIRED:
9482 gen_helper_mtc0_wired(cpu_env, arg);
9483 register_name = "Wired";
9484 break;
9485 case CP0_REG06__SRSCONF0:
9486 check_insn(ctx, ISA_MIPS_R2);
9487 gen_helper_mtc0_srsconf0(cpu_env, arg);
9488 register_name = "SRSConf0";
9489 break;
9490 case CP0_REG06__SRSCONF1:
9491 check_insn(ctx, ISA_MIPS_R2);
9492 gen_helper_mtc0_srsconf1(cpu_env, arg);
9493 register_name = "SRSConf1";
9494 break;
9495 case CP0_REG06__SRSCONF2:
9496 check_insn(ctx, ISA_MIPS_R2);
9497 gen_helper_mtc0_srsconf2(cpu_env, arg);
9498 register_name = "SRSConf2";
9499 break;
9500 case CP0_REG06__SRSCONF3:
9501 check_insn(ctx, ISA_MIPS_R2);
9502 gen_helper_mtc0_srsconf3(cpu_env, arg);
9503 register_name = "SRSConf3";
9504 break;
9505 case CP0_REG06__SRSCONF4:
9506 check_insn(ctx, ISA_MIPS_R2);
9507 gen_helper_mtc0_srsconf4(cpu_env, arg);
9508 register_name = "SRSConf4";
9509 break;
9510 case CP0_REG06__PWCTL:
9511 check_pw(ctx);
9512 gen_helper_mtc0_pwctl(cpu_env, arg);
9513 register_name = "PWCtl";
9514 break;
9515 default:
9516 goto cp0_unimplemented;
9518 break;
9519 case CP0_REGISTER_07:
9520 switch (sel) {
9521 case CP0_REG07__HWRENA:
9522 check_insn(ctx, ISA_MIPS_R2);
9523 gen_helper_mtc0_hwrena(cpu_env, arg);
9524 ctx->base.is_jmp = DISAS_STOP;
9525 register_name = "HWREna";
9526 break;
9527 default:
9528 goto cp0_unimplemented;
9530 break;
9531 case CP0_REGISTER_08:
9532 switch (sel) {
9533 case CP0_REG08__BADVADDR:
9534 /* ignored */
9535 register_name = "BadVAddr";
9536 break;
9537 case CP0_REG08__BADINSTR:
9538 /* ignored */
9539 register_name = "BadInstr";
9540 break;
9541 case CP0_REG08__BADINSTRP:
9542 /* ignored */
9543 register_name = "BadInstrP";
9544 break;
9545 case CP0_REG08__BADINSTRX:
9546 /* ignored */
9547 register_name = "BadInstrX";
9548 break;
9549 default:
9550 goto cp0_unimplemented;
9552 break;
9553 case CP0_REGISTER_09:
9554 switch (sel) {
9555 case CP0_REG09__COUNT:
9556 gen_helper_mtc0_count(cpu_env, arg);
9557 register_name = "Count";
9558 break;
9559 case CP0_REG09__SAARI:
9560 CP0_CHECK(ctx->saar);
9561 gen_helper_mtc0_saari(cpu_env, arg);
9562 register_name = "SAARI";
9563 break;
9564 case CP0_REG09__SAAR:
9565 CP0_CHECK(ctx->saar);
9566 gen_helper_mtc0_saar(cpu_env, arg);
9567 register_name = "SAAR";
9568 break;
9569 default:
9570 goto cp0_unimplemented;
9572 /* Stop translation as we may have switched the execution mode */
9573 ctx->base.is_jmp = DISAS_STOP;
9574 break;
9575 case CP0_REGISTER_10:
9576 switch (sel) {
9577 case CP0_REG10__ENTRYHI:
9578 gen_helper_mtc0_entryhi(cpu_env, arg);
9579 register_name = "EntryHi";
9580 break;
9581 default:
9582 goto cp0_unimplemented;
9584 break;
9585 case CP0_REGISTER_11:
9586 switch (sel) {
9587 case CP0_REG11__COMPARE:
9588 gen_helper_mtc0_compare(cpu_env, arg);
9589 register_name = "Compare";
9590 break;
9591 /* 6,7 are implementation dependent */
9592 default:
9593 goto cp0_unimplemented;
9595 /* Stop translation as we may have switched the execution mode */
9596 ctx->base.is_jmp = DISAS_STOP;
9597 break;
9598 case CP0_REGISTER_12:
9599 switch (sel) {
9600 case CP0_REG12__STATUS:
9601 save_cpu_state(ctx, 1);
9602 gen_helper_mtc0_status(cpu_env, arg);
9603 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9604 gen_save_pc(ctx->base.pc_next + 4);
9605 ctx->base.is_jmp = DISAS_EXIT;
9606 register_name = "Status";
9607 break;
9608 case CP0_REG12__INTCTL:
9609 check_insn(ctx, ISA_MIPS_R2);
9610 gen_helper_mtc0_intctl(cpu_env, arg);
9611 /* Stop translation as we may have switched the execution mode */
9612 ctx->base.is_jmp = DISAS_STOP;
9613 register_name = "IntCtl";
9614 break;
9615 case CP0_REG12__SRSCTL:
9616 check_insn(ctx, ISA_MIPS_R2);
9617 gen_helper_mtc0_srsctl(cpu_env, arg);
9618 /* Stop translation as we may have switched the execution mode */
9619 ctx->base.is_jmp = DISAS_STOP;
9620 register_name = "SRSCtl";
9621 break;
9622 case CP0_REG12__SRSMAP:
9623 check_insn(ctx, ISA_MIPS_R2);
9624 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
9625 /* Stop translation as we may have switched the execution mode */
9626 ctx->base.is_jmp = DISAS_STOP;
9627 register_name = "SRSMap";
9628 break;
9629 default:
9630 goto cp0_unimplemented;
9632 break;
9633 case CP0_REGISTER_13:
9634 switch (sel) {
9635 case CP0_REG13__CAUSE:
9636 save_cpu_state(ctx, 1);
9637 gen_helper_mtc0_cause(cpu_env, arg);
9639 * Stop translation as we may have triggered an interrupt.
9640 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9641 * translated code to check for pending interrupts.
9643 gen_save_pc(ctx->base.pc_next + 4);
9644 ctx->base.is_jmp = DISAS_EXIT;
9645 register_name = "Cause";
9646 break;
9647 default:
9648 goto cp0_unimplemented;
9650 break;
9651 case CP0_REGISTER_14:
9652 switch (sel) {
9653 case CP0_REG14__EPC:
9654 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
9655 register_name = "EPC";
9656 break;
9657 default:
9658 goto cp0_unimplemented;
9660 break;
9661 case CP0_REGISTER_15:
9662 switch (sel) {
9663 case CP0_REG15__PRID:
9664 /* ignored */
9665 register_name = "PRid";
9666 break;
9667 case CP0_REG15__EBASE:
9668 check_insn(ctx, ISA_MIPS_R2);
9669 gen_helper_mtc0_ebase(cpu_env, arg);
9670 register_name = "EBase";
9671 break;
9672 default:
9673 goto cp0_unimplemented;
9675 break;
9676 case CP0_REGISTER_16:
9677 switch (sel) {
9678 case CP0_REG16__CONFIG:
9679 gen_helper_mtc0_config0(cpu_env, arg);
9680 register_name = "Config";
9681 /* Stop translation as we may have switched the execution mode */
9682 ctx->base.is_jmp = DISAS_STOP;
9683 break;
9684 case CP0_REG16__CONFIG1:
9685 /* ignored, read only */
9686 register_name = "Config1";
9687 break;
9688 case CP0_REG16__CONFIG2:
9689 gen_helper_mtc0_config2(cpu_env, arg);
9690 register_name = "Config2";
9691 /* Stop translation as we may have switched the execution mode */
9692 ctx->base.is_jmp = DISAS_STOP;
9693 break;
9694 case CP0_REG16__CONFIG3:
9695 gen_helper_mtc0_config3(cpu_env, arg);
9696 register_name = "Config3";
9697 /* Stop translation as we may have switched the execution mode */
9698 ctx->base.is_jmp = DISAS_STOP;
9699 break;
9700 case CP0_REG16__CONFIG4:
9701 /* currently ignored */
9702 register_name = "Config4";
9703 break;
9704 case CP0_REG16__CONFIG5:
9705 gen_helper_mtc0_config5(cpu_env, arg);
9706 register_name = "Config5";
9707 /* Stop translation as we may have switched the execution mode */
9708 ctx->base.is_jmp = DISAS_STOP;
9709 break;
9710 /* 6,7 are implementation dependent */
9711 default:
9712 register_name = "Invalid config selector";
9713 goto cp0_unimplemented;
9715 break;
9716 case CP0_REGISTER_17:
9717 switch (sel) {
9718 case CP0_REG17__LLADDR:
9719 gen_helper_mtc0_lladdr(cpu_env, arg);
9720 register_name = "LLAddr";
9721 break;
9722 case CP0_REG17__MAAR:
9723 CP0_CHECK(ctx->mrp);
9724 gen_helper_mtc0_maar(cpu_env, arg);
9725 register_name = "MAAR";
9726 break;
9727 case CP0_REG17__MAARI:
9728 CP0_CHECK(ctx->mrp);
9729 gen_helper_mtc0_maari(cpu_env, arg);
9730 register_name = "MAARI";
9731 break;
9732 default:
9733 goto cp0_unimplemented;
9735 break;
9736 case CP0_REGISTER_18:
9737 switch (sel) {
9738 case CP0_REG18__WATCHLO0:
9739 case CP0_REG18__WATCHLO1:
9740 case CP0_REG18__WATCHLO2:
9741 case CP0_REG18__WATCHLO3:
9742 case CP0_REG18__WATCHLO4:
9743 case CP0_REG18__WATCHLO5:
9744 case CP0_REG18__WATCHLO6:
9745 case CP0_REG18__WATCHLO7:
9746 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9747 gen_helper_0e1i(mtc0_watchlo, arg, sel);
9748 register_name = "WatchLo";
9749 break;
9750 default:
9751 goto cp0_unimplemented;
9753 break;
9754 case CP0_REGISTER_19:
9755 switch (sel) {
9756 case CP0_REG19__WATCHHI0:
9757 case CP0_REG19__WATCHHI1:
9758 case CP0_REG19__WATCHHI2:
9759 case CP0_REG19__WATCHHI3:
9760 case CP0_REG19__WATCHHI4:
9761 case CP0_REG19__WATCHHI5:
9762 case CP0_REG19__WATCHHI6:
9763 case CP0_REG19__WATCHHI7:
9764 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9765 gen_helper_0e1i(mtc0_watchhi, arg, sel);
9766 register_name = "WatchHi";
9767 break;
9768 default:
9769 goto cp0_unimplemented;
9771 break;
9772 case CP0_REGISTER_20:
9773 switch (sel) {
9774 case CP0_REG20__XCONTEXT:
9775 check_insn(ctx, ISA_MIPS3);
9776 gen_helper_mtc0_xcontext(cpu_env, arg);
9777 register_name = "XContext";
9778 break;
9779 default:
9780 goto cp0_unimplemented;
9782 break;
9783 case CP0_REGISTER_21:
9784 /* Officially reserved, but sel 0 is used for R1x000 framemask */
9785 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
9786 switch (sel) {
9787 case 0:
9788 gen_helper_mtc0_framemask(cpu_env, arg);
9789 register_name = "Framemask";
9790 break;
9791 default:
9792 goto cp0_unimplemented;
9794 break;
9795 case CP0_REGISTER_22:
9796 /* ignored */
9797 register_name = "Diagnostic"; /* implementation dependent */
9798 break;
9799 case CP0_REGISTER_23:
9800 switch (sel) {
9801 case CP0_REG23__DEBUG:
9802 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
9803 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9804 gen_save_pc(ctx->base.pc_next + 4);
9805 ctx->base.is_jmp = DISAS_EXIT;
9806 register_name = "Debug";
9807 break;
9808 case CP0_REG23__TRACECONTROL:
9809 /* PDtrace support */
9810 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
9811 /* Stop translation as we may have switched the execution mode */
9812 ctx->base.is_jmp = DISAS_STOP;
9813 register_name = "TraceControl";
9814 goto cp0_unimplemented;
9815 case CP0_REG23__TRACECONTROL2:
9816 /* PDtrace support */
9817 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
9818 /* Stop translation as we may have switched the execution mode */
9819 ctx->base.is_jmp = DISAS_STOP;
9820 register_name = "TraceControl2";
9821 goto cp0_unimplemented;
9822 case CP0_REG23__USERTRACEDATA1:
9823 /* PDtrace support */
9824 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
9825 /* Stop translation as we may have switched the execution mode */
9826 ctx->base.is_jmp = DISAS_STOP;
9827 register_name = "UserTraceData1";
9828 goto cp0_unimplemented;
9829 case CP0_REG23__TRACEIBPC:
9830 /* PDtrace support */
9831 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
9832 /* Stop translation as we may have switched the execution mode */
9833 ctx->base.is_jmp = DISAS_STOP;
9834 register_name = "TraceIBPC";
9835 goto cp0_unimplemented;
9836 case CP0_REG23__TRACEDBPC:
9837 /* PDtrace support */
9838 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
9839 /* Stop translation as we may have switched the execution mode */
9840 ctx->base.is_jmp = DISAS_STOP;
9841 register_name = "TraceDBPC";
9842 goto cp0_unimplemented;
9843 default:
9844 goto cp0_unimplemented;
9846 break;
9847 case CP0_REGISTER_24:
9848 switch (sel) {
9849 case CP0_REG24__DEPC:
9850 /* EJTAG support */
9851 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
9852 register_name = "DEPC";
9853 break;
9854 default:
9855 goto cp0_unimplemented;
9857 break;
9858 case CP0_REGISTER_25:
9859 switch (sel) {
9860 case CP0_REG25__PERFCTL0:
9861 gen_helper_mtc0_performance0(cpu_env, arg);
9862 register_name = "Performance0";
9863 break;
9864 case CP0_REG25__PERFCNT0:
9865 /* gen_helper_mtc0_performance1(cpu_env, arg); */
9866 register_name = "Performance1";
9867 goto cp0_unimplemented;
9868 case CP0_REG25__PERFCTL1:
9869 /* gen_helper_mtc0_performance2(cpu_env, arg); */
9870 register_name = "Performance2";
9871 goto cp0_unimplemented;
9872 case CP0_REG25__PERFCNT1:
9873 /* gen_helper_mtc0_performance3(cpu_env, arg); */
9874 register_name = "Performance3";
9875 goto cp0_unimplemented;
9876 case CP0_REG25__PERFCTL2:
9877 /* gen_helper_mtc0_performance4(cpu_env, arg); */
9878 register_name = "Performance4";
9879 goto cp0_unimplemented;
9880 case CP0_REG25__PERFCNT2:
9881 /* gen_helper_mtc0_performance5(cpu_env, arg); */
9882 register_name = "Performance5";
9883 goto cp0_unimplemented;
9884 case CP0_REG25__PERFCTL3:
9885 /* gen_helper_mtc0_performance6(cpu_env, arg); */
9886 register_name = "Performance6";
9887 goto cp0_unimplemented;
9888 case CP0_REG25__PERFCNT3:
9889 /* gen_helper_mtc0_performance7(cpu_env, arg); */
9890 register_name = "Performance7";
9891 goto cp0_unimplemented;
9892 default:
9893 goto cp0_unimplemented;
9895 break;
9896 case CP0_REGISTER_26:
9897 switch (sel) {
9898 case CP0_REG26__ERRCTL:
9899 gen_helper_mtc0_errctl(cpu_env, arg);
9900 ctx->base.is_jmp = DISAS_STOP;
9901 register_name = "ErrCtl";
9902 break;
9903 default:
9904 goto cp0_unimplemented;
9906 break;
9907 case CP0_REGISTER_27:
9908 switch (sel) {
9909 case CP0_REG27__CACHERR:
9910 /* ignored */
9911 register_name = "CacheErr";
9912 break;
9913 default:
9914 goto cp0_unimplemented;
9916 break;
9917 case CP0_REGISTER_28:
9918 switch (sel) {
9919 case CP0_REG28__TAGLO:
9920 case CP0_REG28__TAGLO1:
9921 case CP0_REG28__TAGLO2:
9922 case CP0_REG28__TAGLO3:
9923 gen_helper_mtc0_taglo(cpu_env, arg);
9924 register_name = "TagLo";
9925 break;
9926 case CP0_REG28__DATALO:
9927 case CP0_REG28__DATALO1:
9928 case CP0_REG28__DATALO2:
9929 case CP0_REG28__DATALO3:
9930 gen_helper_mtc0_datalo(cpu_env, arg);
9931 register_name = "DataLo";
9932 break;
9933 default:
9934 goto cp0_unimplemented;
9936 break;
9937 case CP0_REGISTER_29:
9938 switch (sel) {
9939 case CP0_REG29__TAGHI:
9940 case CP0_REG29__TAGHI1:
9941 case CP0_REG29__TAGHI2:
9942 case CP0_REG29__TAGHI3:
9943 gen_helper_mtc0_taghi(cpu_env, arg);
9944 register_name = "TagHi";
9945 break;
9946 case CP0_REG29__DATAHI:
9947 case CP0_REG29__DATAHI1:
9948 case CP0_REG29__DATAHI2:
9949 case CP0_REG29__DATAHI3:
9950 gen_helper_mtc0_datahi(cpu_env, arg);
9951 register_name = "DataHi";
9952 break;
9953 default:
9954 register_name = "invalid sel";
9955 goto cp0_unimplemented;
9957 break;
9958 case CP0_REGISTER_30:
9959 switch (sel) {
9960 case CP0_REG30__ERROREPC:
9961 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9962 register_name = "ErrorEPC";
9963 break;
9964 default:
9965 goto cp0_unimplemented;
9967 break;
9968 case CP0_REGISTER_31:
9969 switch (sel) {
9970 case CP0_REG31__DESAVE:
9971 /* EJTAG support */
9972 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9973 register_name = "DESAVE";
9974 break;
9975 case CP0_REG31__KSCRATCH1:
9976 case CP0_REG31__KSCRATCH2:
9977 case CP0_REG31__KSCRATCH3:
9978 case CP0_REG31__KSCRATCH4:
9979 case CP0_REG31__KSCRATCH5:
9980 case CP0_REG31__KSCRATCH6:
9981 CP0_CHECK(ctx->kscrexist & (1 << sel));
9982 tcg_gen_st_tl(arg, cpu_env,
9983 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
9984 register_name = "KScratch";
9985 break;
9986 default:
9987 goto cp0_unimplemented;
9989 break;
9990 default:
9991 goto cp0_unimplemented;
9993 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
9995 /* For simplicity assume that all writes can cause interrupts. */
9996 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9998 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9999 * translated code to check for pending interrupts.
10001 gen_save_pc(ctx->base.pc_next + 4);
10002 ctx->base.is_jmp = DISAS_EXIT;
10004 return;
10006 cp0_unimplemented:
10007 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
10008 register_name, reg, sel);
10010 #endif /* TARGET_MIPS64 */
10012 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
10013 int u, int sel, int h)
10015 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
10016 TCGv t0 = tcg_temp_local_new();
10018 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
10019 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
10020 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
10021 tcg_gen_movi_tl(t0, -1);
10022 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
10023 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
10024 tcg_gen_movi_tl(t0, -1);
10025 } else if (u == 0) {
10026 switch (rt) {
10027 case 1:
10028 switch (sel) {
10029 case 1:
10030 gen_helper_mftc0_vpecontrol(t0, cpu_env);
10031 break;
10032 case 2:
10033 gen_helper_mftc0_vpeconf0(t0, cpu_env);
10034 break;
10035 default:
10036 goto die;
10037 break;
10039 break;
10040 case 2:
10041 switch (sel) {
10042 case 1:
10043 gen_helper_mftc0_tcstatus(t0, cpu_env);
10044 break;
10045 case 2:
10046 gen_helper_mftc0_tcbind(t0, cpu_env);
10047 break;
10048 case 3:
10049 gen_helper_mftc0_tcrestart(t0, cpu_env);
10050 break;
10051 case 4:
10052 gen_helper_mftc0_tchalt(t0, cpu_env);
10053 break;
10054 case 5:
10055 gen_helper_mftc0_tccontext(t0, cpu_env);
10056 break;
10057 case 6:
10058 gen_helper_mftc0_tcschedule(t0, cpu_env);
10059 break;
10060 case 7:
10061 gen_helper_mftc0_tcschefback(t0, cpu_env);
10062 break;
10063 default:
10064 gen_mfc0(ctx, t0, rt, sel);
10065 break;
10067 break;
10068 case 10:
10069 switch (sel) {
10070 case 0:
10071 gen_helper_mftc0_entryhi(t0, cpu_env);
10072 break;
10073 default:
10074 gen_mfc0(ctx, t0, rt, sel);
10075 break;
10077 break;
10078 case 12:
10079 switch (sel) {
10080 case 0:
10081 gen_helper_mftc0_status(t0, cpu_env);
10082 break;
10083 default:
10084 gen_mfc0(ctx, t0, rt, sel);
10085 break;
10087 break;
10088 case 13:
10089 switch (sel) {
10090 case 0:
10091 gen_helper_mftc0_cause(t0, cpu_env);
10092 break;
10093 default:
10094 goto die;
10095 break;
10097 break;
10098 case 14:
10099 switch (sel) {
10100 case 0:
10101 gen_helper_mftc0_epc(t0, cpu_env);
10102 break;
10103 default:
10104 goto die;
10105 break;
10107 break;
10108 case 15:
10109 switch (sel) {
10110 case 1:
10111 gen_helper_mftc0_ebase(t0, cpu_env);
10112 break;
10113 default:
10114 goto die;
10115 break;
10117 break;
10118 case 16:
10119 switch (sel) {
10120 case 0:
10121 case 1:
10122 case 2:
10123 case 3:
10124 case 4:
10125 case 5:
10126 case 6:
10127 case 7:
10128 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
10129 break;
10130 default:
10131 goto die;
10132 break;
10134 break;
10135 case 23:
10136 switch (sel) {
10137 case 0:
10138 gen_helper_mftc0_debug(t0, cpu_env);
10139 break;
10140 default:
10141 gen_mfc0(ctx, t0, rt, sel);
10142 break;
10144 break;
10145 default:
10146 gen_mfc0(ctx, t0, rt, sel);
10148 } else {
10149 switch (sel) {
10150 /* GPR registers. */
10151 case 0:
10152 gen_helper_1e0i(mftgpr, t0, rt);
10153 break;
10154 /* Auxiliary CPU registers */
10155 case 1:
10156 switch (rt) {
10157 case 0:
10158 gen_helper_1e0i(mftlo, t0, 0);
10159 break;
10160 case 1:
10161 gen_helper_1e0i(mfthi, t0, 0);
10162 break;
10163 case 2:
10164 gen_helper_1e0i(mftacx, t0, 0);
10165 break;
10166 case 4:
10167 gen_helper_1e0i(mftlo, t0, 1);
10168 break;
10169 case 5:
10170 gen_helper_1e0i(mfthi, t0, 1);
10171 break;
10172 case 6:
10173 gen_helper_1e0i(mftacx, t0, 1);
10174 break;
10175 case 8:
10176 gen_helper_1e0i(mftlo, t0, 2);
10177 break;
10178 case 9:
10179 gen_helper_1e0i(mfthi, t0, 2);
10180 break;
10181 case 10:
10182 gen_helper_1e0i(mftacx, t0, 2);
10183 break;
10184 case 12:
10185 gen_helper_1e0i(mftlo, t0, 3);
10186 break;
10187 case 13:
10188 gen_helper_1e0i(mfthi, t0, 3);
10189 break;
10190 case 14:
10191 gen_helper_1e0i(mftacx, t0, 3);
10192 break;
10193 case 16:
10194 gen_helper_mftdsp(t0, cpu_env);
10195 break;
10196 default:
10197 goto die;
10199 break;
10200 /* Floating point (COP1). */
10201 case 2:
10202 /* XXX: For now we support only a single FPU context. */
10203 if (h == 0) {
10204 TCGv_i32 fp0 = tcg_temp_new_i32();
10206 gen_load_fpr32(ctx, fp0, rt);
10207 tcg_gen_ext_i32_tl(t0, fp0);
10208 tcg_temp_free_i32(fp0);
10209 } else {
10210 TCGv_i32 fp0 = tcg_temp_new_i32();
10212 gen_load_fpr32h(ctx, fp0, rt);
10213 tcg_gen_ext_i32_tl(t0, fp0);
10214 tcg_temp_free_i32(fp0);
10216 break;
10217 case 3:
10218 /* XXX: For now we support only a single FPU context. */
10219 gen_helper_1e0i(cfc1, t0, rt);
10220 break;
10221 /* COP2: Not implemented. */
10222 case 4:
10223 case 5:
10224 /* fall through */
10225 default:
10226 goto die;
10229 trace_mips_translate_tr("mftr", rt, u, sel, h);
10230 gen_store_gpr(t0, rd);
10231 tcg_temp_free(t0);
10232 return;
10234 die:
10235 tcg_temp_free(t0);
10236 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
10237 gen_reserved_instruction(ctx);
10240 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
10241 int u, int sel, int h)
10243 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
10244 TCGv t0 = tcg_temp_local_new();
10246 gen_load_gpr(t0, rt);
10247 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
10248 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
10249 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
10250 /* NOP */
10252 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
10253 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
10254 /* NOP */
10256 } else if (u == 0) {
10257 switch (rd) {
10258 case 1:
10259 switch (sel) {
10260 case 1:
10261 gen_helper_mttc0_vpecontrol(cpu_env, t0);
10262 break;
10263 case 2:
10264 gen_helper_mttc0_vpeconf0(cpu_env, t0);
10265 break;
10266 default:
10267 goto die;
10268 break;
10270 break;
10271 case 2:
10272 switch (sel) {
10273 case 1:
10274 gen_helper_mttc0_tcstatus(cpu_env, t0);
10275 break;
10276 case 2:
10277 gen_helper_mttc0_tcbind(cpu_env, t0);
10278 break;
10279 case 3:
10280 gen_helper_mttc0_tcrestart(cpu_env, t0);
10281 break;
10282 case 4:
10283 gen_helper_mttc0_tchalt(cpu_env, t0);
10284 break;
10285 case 5:
10286 gen_helper_mttc0_tccontext(cpu_env, t0);
10287 break;
10288 case 6:
10289 gen_helper_mttc0_tcschedule(cpu_env, t0);
10290 break;
10291 case 7:
10292 gen_helper_mttc0_tcschefback(cpu_env, t0);
10293 break;
10294 default:
10295 gen_mtc0(ctx, t0, rd, sel);
10296 break;
10298 break;
10299 case 10:
10300 switch (sel) {
10301 case 0:
10302 gen_helper_mttc0_entryhi(cpu_env, t0);
10303 break;
10304 default:
10305 gen_mtc0(ctx, t0, rd, sel);
10306 break;
10308 break;
10309 case 12:
10310 switch (sel) {
10311 case 0:
10312 gen_helper_mttc0_status(cpu_env, t0);
10313 break;
10314 default:
10315 gen_mtc0(ctx, t0, rd, sel);
10316 break;
10318 break;
10319 case 13:
10320 switch (sel) {
10321 case 0:
10322 gen_helper_mttc0_cause(cpu_env, t0);
10323 break;
10324 default:
10325 goto die;
10326 break;
10328 break;
10329 case 15:
10330 switch (sel) {
10331 case 1:
10332 gen_helper_mttc0_ebase(cpu_env, t0);
10333 break;
10334 default:
10335 goto die;
10336 break;
10338 break;
10339 case 23:
10340 switch (sel) {
10341 case 0:
10342 gen_helper_mttc0_debug(cpu_env, t0);
10343 break;
10344 default:
10345 gen_mtc0(ctx, t0, rd, sel);
10346 break;
10348 break;
10349 default:
10350 gen_mtc0(ctx, t0, rd, sel);
10352 } else {
10353 switch (sel) {
10354 /* GPR registers. */
10355 case 0:
10356 gen_helper_0e1i(mttgpr, t0, rd);
10357 break;
10358 /* Auxiliary CPU registers */
10359 case 1:
10360 switch (rd) {
10361 case 0:
10362 gen_helper_0e1i(mttlo, t0, 0);
10363 break;
10364 case 1:
10365 gen_helper_0e1i(mtthi, t0, 0);
10366 break;
10367 case 2:
10368 gen_helper_0e1i(mttacx, t0, 0);
10369 break;
10370 case 4:
10371 gen_helper_0e1i(mttlo, t0, 1);
10372 break;
10373 case 5:
10374 gen_helper_0e1i(mtthi, t0, 1);
10375 break;
10376 case 6:
10377 gen_helper_0e1i(mttacx, t0, 1);
10378 break;
10379 case 8:
10380 gen_helper_0e1i(mttlo, t0, 2);
10381 break;
10382 case 9:
10383 gen_helper_0e1i(mtthi, t0, 2);
10384 break;
10385 case 10:
10386 gen_helper_0e1i(mttacx, t0, 2);
10387 break;
10388 case 12:
10389 gen_helper_0e1i(mttlo, t0, 3);
10390 break;
10391 case 13:
10392 gen_helper_0e1i(mtthi, t0, 3);
10393 break;
10394 case 14:
10395 gen_helper_0e1i(mttacx, t0, 3);
10396 break;
10397 case 16:
10398 gen_helper_mttdsp(cpu_env, t0);
10399 break;
10400 default:
10401 goto die;
10403 break;
10404 /* Floating point (COP1). */
10405 case 2:
10406 /* XXX: For now we support only a single FPU context. */
10407 if (h == 0) {
10408 TCGv_i32 fp0 = tcg_temp_new_i32();
10410 tcg_gen_trunc_tl_i32(fp0, t0);
10411 gen_store_fpr32(ctx, fp0, rd);
10412 tcg_temp_free_i32(fp0);
10413 } else {
10414 TCGv_i32 fp0 = tcg_temp_new_i32();
10416 tcg_gen_trunc_tl_i32(fp0, t0);
10417 gen_store_fpr32h(ctx, fp0, rd);
10418 tcg_temp_free_i32(fp0);
10420 break;
10421 case 3:
10422 /* XXX: For now we support only a single FPU context. */
10424 TCGv_i32 fs_tmp = tcg_const_i32(rd);
10426 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10427 tcg_temp_free_i32(fs_tmp);
10429 /* Stop translation as we may have changed hflags */
10430 ctx->base.is_jmp = DISAS_STOP;
10431 break;
10432 /* COP2: Not implemented. */
10433 case 4:
10434 case 5:
10435 /* fall through */
10436 default:
10437 goto die;
10440 trace_mips_translate_tr("mttr", rd, u, sel, h);
10441 tcg_temp_free(t0);
10442 return;
10444 die:
10445 tcg_temp_free(t0);
10446 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
10447 gen_reserved_instruction(ctx);
10450 static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
10451 int rt, int rd)
10453 const char *opn = "ldst";
10455 check_cp0_enabled(ctx);
10456 switch (opc) {
10457 case OPC_MFC0:
10458 if (rt == 0) {
10459 /* Treat as NOP. */
10460 return;
10462 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10463 opn = "mfc0";
10464 break;
10465 case OPC_MTC0:
10467 TCGv t0 = tcg_temp_new();
10469 gen_load_gpr(t0, rt);
10470 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
10471 tcg_temp_free(t0);
10473 opn = "mtc0";
10474 break;
10475 #if defined(TARGET_MIPS64)
10476 case OPC_DMFC0:
10477 check_insn(ctx, ISA_MIPS3);
10478 if (rt == 0) {
10479 /* Treat as NOP. */
10480 return;
10482 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10483 opn = "dmfc0";
10484 break;
10485 case OPC_DMTC0:
10486 check_insn(ctx, ISA_MIPS3);
10488 TCGv t0 = tcg_temp_new();
10490 gen_load_gpr(t0, rt);
10491 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
10492 tcg_temp_free(t0);
10494 opn = "dmtc0";
10495 break;
10496 #endif
10497 case OPC_MFHC0:
10498 check_mvh(ctx);
10499 if (rt == 0) {
10500 /* Treat as NOP. */
10501 return;
10503 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10504 opn = "mfhc0";
10505 break;
10506 case OPC_MTHC0:
10507 check_mvh(ctx);
10509 TCGv t0 = tcg_temp_new();
10510 gen_load_gpr(t0, rt);
10511 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
10512 tcg_temp_free(t0);
10514 opn = "mthc0";
10515 break;
10516 case OPC_MFTR:
10517 check_cp0_enabled(ctx);
10518 if (rd == 0) {
10519 /* Treat as NOP. */
10520 return;
10522 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
10523 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10524 opn = "mftr";
10525 break;
10526 case OPC_MTTR:
10527 check_cp0_enabled(ctx);
10528 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
10529 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10530 opn = "mttr";
10531 break;
10532 case OPC_TLBWI:
10533 opn = "tlbwi";
10534 if (!env->tlb->helper_tlbwi) {
10535 goto die;
10537 gen_helper_tlbwi(cpu_env);
10538 break;
10539 case OPC_TLBINV:
10540 opn = "tlbinv";
10541 if (ctx->ie >= 2) {
10542 if (!env->tlb->helper_tlbinv) {
10543 goto die;
10545 gen_helper_tlbinv(cpu_env);
10546 } /* treat as nop if TLBINV not supported */
10547 break;
10548 case OPC_TLBINVF:
10549 opn = "tlbinvf";
10550 if (ctx->ie >= 2) {
10551 if (!env->tlb->helper_tlbinvf) {
10552 goto die;
10554 gen_helper_tlbinvf(cpu_env);
10555 } /* treat as nop if TLBINV not supported */
10556 break;
10557 case OPC_TLBWR:
10558 opn = "tlbwr";
10559 if (!env->tlb->helper_tlbwr) {
10560 goto die;
10562 gen_helper_tlbwr(cpu_env);
10563 break;
10564 case OPC_TLBP:
10565 opn = "tlbp";
10566 if (!env->tlb->helper_tlbp) {
10567 goto die;
10569 gen_helper_tlbp(cpu_env);
10570 break;
10571 case OPC_TLBR:
10572 opn = "tlbr";
10573 if (!env->tlb->helper_tlbr) {
10574 goto die;
10576 gen_helper_tlbr(cpu_env);
10577 break;
10578 case OPC_ERET: /* OPC_ERETNC */
10579 if ((ctx->insn_flags & ISA_MIPS_R6) &&
10580 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10581 goto die;
10582 } else {
10583 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
10584 if (ctx->opcode & (1 << bit_shift)) {
10585 /* OPC_ERETNC */
10586 opn = "eretnc";
10587 check_insn(ctx, ISA_MIPS_R5);
10588 gen_helper_eretnc(cpu_env);
10589 } else {
10590 /* OPC_ERET */
10591 opn = "eret";
10592 check_insn(ctx, ISA_MIPS2);
10593 gen_helper_eret(cpu_env);
10595 ctx->base.is_jmp = DISAS_EXIT;
10597 break;
10598 case OPC_DERET:
10599 opn = "deret";
10600 check_insn(ctx, ISA_MIPS_R1);
10601 if ((ctx->insn_flags & ISA_MIPS_R6) &&
10602 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10603 goto die;
10605 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10606 MIPS_INVAL(opn);
10607 gen_reserved_instruction(ctx);
10608 } else {
10609 gen_helper_deret(cpu_env);
10610 ctx->base.is_jmp = DISAS_EXIT;
10612 break;
10613 case OPC_WAIT:
10614 opn = "wait";
10615 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
10616 if ((ctx->insn_flags & ISA_MIPS_R6) &&
10617 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10618 goto die;
10620 /* If we get an exception, we want to restart at next instruction */
10621 ctx->base.pc_next += 4;
10622 save_cpu_state(ctx, 1);
10623 ctx->base.pc_next -= 4;
10624 gen_helper_wait(cpu_env);
10625 ctx->base.is_jmp = DISAS_NORETURN;
10626 break;
10627 default:
10628 die:
10629 MIPS_INVAL(opn);
10630 gen_reserved_instruction(ctx);
10631 return;
10633 (void)opn; /* avoid a compiler warning */
10635 #endif /* !CONFIG_USER_ONLY */
10637 /* CP1 Branches (before delay slot) */
10638 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
10639 int32_t cc, int32_t offset)
10641 target_ulong btarget;
10642 TCGv_i32 t0 = tcg_temp_new_i32();
10644 if ((ctx->insn_flags & ISA_MIPS_R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
10645 gen_reserved_instruction(ctx);
10646 goto out;
10649 if (cc != 0) {
10650 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
10653 btarget = ctx->base.pc_next + 4 + offset;
10655 switch (op) {
10656 case OPC_BC1F:
10657 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10658 tcg_gen_not_i32(t0, t0);
10659 tcg_gen_andi_i32(t0, t0, 1);
10660 tcg_gen_extu_i32_tl(bcond, t0);
10661 goto not_likely;
10662 case OPC_BC1FL:
10663 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10664 tcg_gen_not_i32(t0, t0);
10665 tcg_gen_andi_i32(t0, t0, 1);
10666 tcg_gen_extu_i32_tl(bcond, t0);
10667 goto likely;
10668 case OPC_BC1T:
10669 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10670 tcg_gen_andi_i32(t0, t0, 1);
10671 tcg_gen_extu_i32_tl(bcond, t0);
10672 goto not_likely;
10673 case OPC_BC1TL:
10674 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10675 tcg_gen_andi_i32(t0, t0, 1);
10676 tcg_gen_extu_i32_tl(bcond, t0);
10677 likely:
10678 ctx->hflags |= MIPS_HFLAG_BL;
10679 break;
10680 case OPC_BC1FANY2:
10682 TCGv_i32 t1 = tcg_temp_new_i32();
10683 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10684 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10685 tcg_gen_nand_i32(t0, t0, t1);
10686 tcg_temp_free_i32(t1);
10687 tcg_gen_andi_i32(t0, t0, 1);
10688 tcg_gen_extu_i32_tl(bcond, t0);
10690 goto not_likely;
10691 case OPC_BC1TANY2:
10693 TCGv_i32 t1 = tcg_temp_new_i32();
10694 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10695 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10696 tcg_gen_or_i32(t0, t0, t1);
10697 tcg_temp_free_i32(t1);
10698 tcg_gen_andi_i32(t0, t0, 1);
10699 tcg_gen_extu_i32_tl(bcond, t0);
10701 goto not_likely;
10702 case OPC_BC1FANY4:
10704 TCGv_i32 t1 = tcg_temp_new_i32();
10705 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10706 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10707 tcg_gen_and_i32(t0, t0, t1);
10708 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
10709 tcg_gen_and_i32(t0, t0, t1);
10710 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
10711 tcg_gen_nand_i32(t0, t0, t1);
10712 tcg_temp_free_i32(t1);
10713 tcg_gen_andi_i32(t0, t0, 1);
10714 tcg_gen_extu_i32_tl(bcond, t0);
10716 goto not_likely;
10717 case OPC_BC1TANY4:
10719 TCGv_i32 t1 = tcg_temp_new_i32();
10720 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10721 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10722 tcg_gen_or_i32(t0, t0, t1);
10723 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
10724 tcg_gen_or_i32(t0, t0, t1);
10725 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
10726 tcg_gen_or_i32(t0, t0, t1);
10727 tcg_temp_free_i32(t1);
10728 tcg_gen_andi_i32(t0, t0, 1);
10729 tcg_gen_extu_i32_tl(bcond, t0);
10731 not_likely:
10732 ctx->hflags |= MIPS_HFLAG_BC;
10733 break;
10734 default:
10735 MIPS_INVAL("cp1 cond branch");
10736 gen_reserved_instruction(ctx);
10737 goto out;
10739 ctx->btarget = btarget;
10740 ctx->hflags |= MIPS_HFLAG_BDS32;
10741 out:
10742 tcg_temp_free_i32(t0);
10745 /* R6 CP1 Branches */
10746 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
10747 int32_t ft, int32_t offset,
10748 int delayslot_size)
10750 target_ulong btarget;
10751 TCGv_i64 t0 = tcg_temp_new_i64();
10753 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10754 #ifdef MIPS_DEBUG_DISAS
10755 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
10756 "\n", ctx->base.pc_next);
10757 #endif
10758 gen_reserved_instruction(ctx);
10759 goto out;
10762 gen_load_fpr64(ctx, t0, ft);
10763 tcg_gen_andi_i64(t0, t0, 1);
10765 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
10767 switch (op) {
10768 case OPC_BC1EQZ:
10769 tcg_gen_xori_i64(t0, t0, 1);
10770 ctx->hflags |= MIPS_HFLAG_BC;
10771 break;
10772 case OPC_BC1NEZ:
10773 /* t0 already set */
10774 ctx->hflags |= MIPS_HFLAG_BC;
10775 break;
10776 default:
10777 MIPS_INVAL("cp1 cond branch");
10778 gen_reserved_instruction(ctx);
10779 goto out;
10782 tcg_gen_trunc_i64_tl(bcond, t0);
10784 ctx->btarget = btarget;
10786 switch (delayslot_size) {
10787 case 2:
10788 ctx->hflags |= MIPS_HFLAG_BDS16;
10789 break;
10790 case 4:
10791 ctx->hflags |= MIPS_HFLAG_BDS32;
10792 break;
10795 out:
10796 tcg_temp_free_i64(t0);
10799 /* Coprocessor 1 (FPU) */
10801 #define FOP(func, fmt) (((fmt) << 21) | (func))
10803 enum fopcode {
10804 OPC_ADD_S = FOP(0, FMT_S),
10805 OPC_SUB_S = FOP(1, FMT_S),
10806 OPC_MUL_S = FOP(2, FMT_S),
10807 OPC_DIV_S = FOP(3, FMT_S),
10808 OPC_SQRT_S = FOP(4, FMT_S),
10809 OPC_ABS_S = FOP(5, FMT_S),
10810 OPC_MOV_S = FOP(6, FMT_S),
10811 OPC_NEG_S = FOP(7, FMT_S),
10812 OPC_ROUND_L_S = FOP(8, FMT_S),
10813 OPC_TRUNC_L_S = FOP(9, FMT_S),
10814 OPC_CEIL_L_S = FOP(10, FMT_S),
10815 OPC_FLOOR_L_S = FOP(11, FMT_S),
10816 OPC_ROUND_W_S = FOP(12, FMT_S),
10817 OPC_TRUNC_W_S = FOP(13, FMT_S),
10818 OPC_CEIL_W_S = FOP(14, FMT_S),
10819 OPC_FLOOR_W_S = FOP(15, FMT_S),
10820 OPC_SEL_S = FOP(16, FMT_S),
10821 OPC_MOVCF_S = FOP(17, FMT_S),
10822 OPC_MOVZ_S = FOP(18, FMT_S),
10823 OPC_MOVN_S = FOP(19, FMT_S),
10824 OPC_SELEQZ_S = FOP(20, FMT_S),
10825 OPC_RECIP_S = FOP(21, FMT_S),
10826 OPC_RSQRT_S = FOP(22, FMT_S),
10827 OPC_SELNEZ_S = FOP(23, FMT_S),
10828 OPC_MADDF_S = FOP(24, FMT_S),
10829 OPC_MSUBF_S = FOP(25, FMT_S),
10830 OPC_RINT_S = FOP(26, FMT_S),
10831 OPC_CLASS_S = FOP(27, FMT_S),
10832 OPC_MIN_S = FOP(28, FMT_S),
10833 OPC_RECIP2_S = FOP(28, FMT_S),
10834 OPC_MINA_S = FOP(29, FMT_S),
10835 OPC_RECIP1_S = FOP(29, FMT_S),
10836 OPC_MAX_S = FOP(30, FMT_S),
10837 OPC_RSQRT1_S = FOP(30, FMT_S),
10838 OPC_MAXA_S = FOP(31, FMT_S),
10839 OPC_RSQRT2_S = FOP(31, FMT_S),
10840 OPC_CVT_D_S = FOP(33, FMT_S),
10841 OPC_CVT_W_S = FOP(36, FMT_S),
10842 OPC_CVT_L_S = FOP(37, FMT_S),
10843 OPC_CVT_PS_S = FOP(38, FMT_S),
10844 OPC_CMP_F_S = FOP(48, FMT_S),
10845 OPC_CMP_UN_S = FOP(49, FMT_S),
10846 OPC_CMP_EQ_S = FOP(50, FMT_S),
10847 OPC_CMP_UEQ_S = FOP(51, FMT_S),
10848 OPC_CMP_OLT_S = FOP(52, FMT_S),
10849 OPC_CMP_ULT_S = FOP(53, FMT_S),
10850 OPC_CMP_OLE_S = FOP(54, FMT_S),
10851 OPC_CMP_ULE_S = FOP(55, FMT_S),
10852 OPC_CMP_SF_S = FOP(56, FMT_S),
10853 OPC_CMP_NGLE_S = FOP(57, FMT_S),
10854 OPC_CMP_SEQ_S = FOP(58, FMT_S),
10855 OPC_CMP_NGL_S = FOP(59, FMT_S),
10856 OPC_CMP_LT_S = FOP(60, FMT_S),
10857 OPC_CMP_NGE_S = FOP(61, FMT_S),
10858 OPC_CMP_LE_S = FOP(62, FMT_S),
10859 OPC_CMP_NGT_S = FOP(63, FMT_S),
10861 OPC_ADD_D = FOP(0, FMT_D),
10862 OPC_SUB_D = FOP(1, FMT_D),
10863 OPC_MUL_D = FOP(2, FMT_D),
10864 OPC_DIV_D = FOP(3, FMT_D),
10865 OPC_SQRT_D = FOP(4, FMT_D),
10866 OPC_ABS_D = FOP(5, FMT_D),
10867 OPC_MOV_D = FOP(6, FMT_D),
10868 OPC_NEG_D = FOP(7, FMT_D),
10869 OPC_ROUND_L_D = FOP(8, FMT_D),
10870 OPC_TRUNC_L_D = FOP(9, FMT_D),
10871 OPC_CEIL_L_D = FOP(10, FMT_D),
10872 OPC_FLOOR_L_D = FOP(11, FMT_D),
10873 OPC_ROUND_W_D = FOP(12, FMT_D),
10874 OPC_TRUNC_W_D = FOP(13, FMT_D),
10875 OPC_CEIL_W_D = FOP(14, FMT_D),
10876 OPC_FLOOR_W_D = FOP(15, FMT_D),
10877 OPC_SEL_D = FOP(16, FMT_D),
10878 OPC_MOVCF_D = FOP(17, FMT_D),
10879 OPC_MOVZ_D = FOP(18, FMT_D),
10880 OPC_MOVN_D = FOP(19, FMT_D),
10881 OPC_SELEQZ_D = FOP(20, FMT_D),
10882 OPC_RECIP_D = FOP(21, FMT_D),
10883 OPC_RSQRT_D = FOP(22, FMT_D),
10884 OPC_SELNEZ_D = FOP(23, FMT_D),
10885 OPC_MADDF_D = FOP(24, FMT_D),
10886 OPC_MSUBF_D = FOP(25, FMT_D),
10887 OPC_RINT_D = FOP(26, FMT_D),
10888 OPC_CLASS_D = FOP(27, FMT_D),
10889 OPC_MIN_D = FOP(28, FMT_D),
10890 OPC_RECIP2_D = FOP(28, FMT_D),
10891 OPC_MINA_D = FOP(29, FMT_D),
10892 OPC_RECIP1_D = FOP(29, FMT_D),
10893 OPC_MAX_D = FOP(30, FMT_D),
10894 OPC_RSQRT1_D = FOP(30, FMT_D),
10895 OPC_MAXA_D = FOP(31, FMT_D),
10896 OPC_RSQRT2_D = FOP(31, FMT_D),
10897 OPC_CVT_S_D = FOP(32, FMT_D),
10898 OPC_CVT_W_D = FOP(36, FMT_D),
10899 OPC_CVT_L_D = FOP(37, FMT_D),
10900 OPC_CMP_F_D = FOP(48, FMT_D),
10901 OPC_CMP_UN_D = FOP(49, FMT_D),
10902 OPC_CMP_EQ_D = FOP(50, FMT_D),
10903 OPC_CMP_UEQ_D = FOP(51, FMT_D),
10904 OPC_CMP_OLT_D = FOP(52, FMT_D),
10905 OPC_CMP_ULT_D = FOP(53, FMT_D),
10906 OPC_CMP_OLE_D = FOP(54, FMT_D),
10907 OPC_CMP_ULE_D = FOP(55, FMT_D),
10908 OPC_CMP_SF_D = FOP(56, FMT_D),
10909 OPC_CMP_NGLE_D = FOP(57, FMT_D),
10910 OPC_CMP_SEQ_D = FOP(58, FMT_D),
10911 OPC_CMP_NGL_D = FOP(59, FMT_D),
10912 OPC_CMP_LT_D = FOP(60, FMT_D),
10913 OPC_CMP_NGE_D = FOP(61, FMT_D),
10914 OPC_CMP_LE_D = FOP(62, FMT_D),
10915 OPC_CMP_NGT_D = FOP(63, FMT_D),
10917 OPC_CVT_S_W = FOP(32, FMT_W),
10918 OPC_CVT_D_W = FOP(33, FMT_W),
10919 OPC_CVT_S_L = FOP(32, FMT_L),
10920 OPC_CVT_D_L = FOP(33, FMT_L),
10921 OPC_CVT_PS_PW = FOP(38, FMT_W),
10923 OPC_ADD_PS = FOP(0, FMT_PS),
10924 OPC_SUB_PS = FOP(1, FMT_PS),
10925 OPC_MUL_PS = FOP(2, FMT_PS),
10926 OPC_DIV_PS = FOP(3, FMT_PS),
10927 OPC_ABS_PS = FOP(5, FMT_PS),
10928 OPC_MOV_PS = FOP(6, FMT_PS),
10929 OPC_NEG_PS = FOP(7, FMT_PS),
10930 OPC_MOVCF_PS = FOP(17, FMT_PS),
10931 OPC_MOVZ_PS = FOP(18, FMT_PS),
10932 OPC_MOVN_PS = FOP(19, FMT_PS),
10933 OPC_ADDR_PS = FOP(24, FMT_PS),
10934 OPC_MULR_PS = FOP(26, FMT_PS),
10935 OPC_RECIP2_PS = FOP(28, FMT_PS),
10936 OPC_RECIP1_PS = FOP(29, FMT_PS),
10937 OPC_RSQRT1_PS = FOP(30, FMT_PS),
10938 OPC_RSQRT2_PS = FOP(31, FMT_PS),
10940 OPC_CVT_S_PU = FOP(32, FMT_PS),
10941 OPC_CVT_PW_PS = FOP(36, FMT_PS),
10942 OPC_CVT_S_PL = FOP(40, FMT_PS),
10943 OPC_PLL_PS = FOP(44, FMT_PS),
10944 OPC_PLU_PS = FOP(45, FMT_PS),
10945 OPC_PUL_PS = FOP(46, FMT_PS),
10946 OPC_PUU_PS = FOP(47, FMT_PS),
10947 OPC_CMP_F_PS = FOP(48, FMT_PS),
10948 OPC_CMP_UN_PS = FOP(49, FMT_PS),
10949 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
10950 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
10951 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
10952 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
10953 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
10954 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
10955 OPC_CMP_SF_PS = FOP(56, FMT_PS),
10956 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
10957 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
10958 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
10959 OPC_CMP_LT_PS = FOP(60, FMT_PS),
10960 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
10961 OPC_CMP_LE_PS = FOP(62, FMT_PS),
10962 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
10965 enum r6_f_cmp_op {
10966 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
10967 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
10968 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
10969 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
10970 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
10971 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
10972 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
10973 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
10974 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
10975 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
10976 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
10977 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
10978 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
10979 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
10980 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
10981 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
10982 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
10983 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
10984 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
10985 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
10986 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
10987 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
10989 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
10990 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
10991 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
10992 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
10993 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
10994 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
10995 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
10996 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
10997 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
10998 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
10999 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
11000 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
11001 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
11002 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
11003 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
11004 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
11005 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
11006 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
11007 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
11008 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
11009 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
11010 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
11013 static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
11015 TCGv t0 = tcg_temp_new();
11017 switch (opc) {
11018 case OPC_MFC1:
11020 TCGv_i32 fp0 = tcg_temp_new_i32();
11022 gen_load_fpr32(ctx, fp0, fs);
11023 tcg_gen_ext_i32_tl(t0, fp0);
11024 tcg_temp_free_i32(fp0);
11026 gen_store_gpr(t0, rt);
11027 break;
11028 case OPC_MTC1:
11029 gen_load_gpr(t0, rt);
11031 TCGv_i32 fp0 = tcg_temp_new_i32();
11033 tcg_gen_trunc_tl_i32(fp0, t0);
11034 gen_store_fpr32(ctx, fp0, fs);
11035 tcg_temp_free_i32(fp0);
11037 break;
11038 case OPC_CFC1:
11039 gen_helper_1e0i(cfc1, t0, fs);
11040 gen_store_gpr(t0, rt);
11041 break;
11042 case OPC_CTC1:
11043 gen_load_gpr(t0, rt);
11044 save_cpu_state(ctx, 0);
11046 TCGv_i32 fs_tmp = tcg_const_i32(fs);
11048 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
11049 tcg_temp_free_i32(fs_tmp);
11051 /* Stop translation as we may have changed hflags */
11052 ctx->base.is_jmp = DISAS_STOP;
11053 break;
11054 #if defined(TARGET_MIPS64)
11055 case OPC_DMFC1:
11056 gen_load_fpr64(ctx, t0, fs);
11057 gen_store_gpr(t0, rt);
11058 break;
11059 case OPC_DMTC1:
11060 gen_load_gpr(t0, rt);
11061 gen_store_fpr64(ctx, t0, fs);
11062 break;
11063 #endif
11064 case OPC_MFHC1:
11066 TCGv_i32 fp0 = tcg_temp_new_i32();
11068 gen_load_fpr32h(ctx, fp0, fs);
11069 tcg_gen_ext_i32_tl(t0, fp0);
11070 tcg_temp_free_i32(fp0);
11072 gen_store_gpr(t0, rt);
11073 break;
11074 case OPC_MTHC1:
11075 gen_load_gpr(t0, rt);
11077 TCGv_i32 fp0 = tcg_temp_new_i32();
11079 tcg_gen_trunc_tl_i32(fp0, t0);
11080 gen_store_fpr32h(ctx, fp0, fs);
11081 tcg_temp_free_i32(fp0);
11083 break;
11084 default:
11085 MIPS_INVAL("cp1 move");
11086 gen_reserved_instruction(ctx);
11087 goto out;
11090 out:
11091 tcg_temp_free(t0);
11094 static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
11096 TCGLabel *l1;
11097 TCGCond cond;
11098 TCGv_i32 t0;
11100 if (rd == 0) {
11101 /* Treat as NOP. */
11102 return;
11105 if (tf) {
11106 cond = TCG_COND_EQ;
11107 } else {
11108 cond = TCG_COND_NE;
11111 l1 = gen_new_label();
11112 t0 = tcg_temp_new_i32();
11113 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11114 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11115 tcg_temp_free_i32(t0);
11116 if (rs == 0) {
11117 tcg_gen_movi_tl(cpu_gpr[rd], 0);
11118 } else {
11119 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
11121 gen_set_label(l1);
11124 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
11125 int tf)
11127 int cond;
11128 TCGv_i32 t0 = tcg_temp_new_i32();
11129 TCGLabel *l1 = gen_new_label();
11131 if (tf) {
11132 cond = TCG_COND_EQ;
11133 } else {
11134 cond = TCG_COND_NE;
11137 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11138 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11139 gen_load_fpr32(ctx, t0, fs);
11140 gen_store_fpr32(ctx, t0, fd);
11141 gen_set_label(l1);
11142 tcg_temp_free_i32(t0);
11145 static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
11146 int tf)
11148 int cond;
11149 TCGv_i32 t0 = tcg_temp_new_i32();
11150 TCGv_i64 fp0;
11151 TCGLabel *l1 = gen_new_label();
11153 if (tf) {
11154 cond = TCG_COND_EQ;
11155 } else {
11156 cond = TCG_COND_NE;
11159 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11160 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11161 tcg_temp_free_i32(t0);
11162 fp0 = tcg_temp_new_i64();
11163 gen_load_fpr64(ctx, fp0, fs);
11164 gen_store_fpr64(ctx, fp0, fd);
11165 tcg_temp_free_i64(fp0);
11166 gen_set_label(l1);
11169 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
11170 int cc, int tf)
11172 int cond;
11173 TCGv_i32 t0 = tcg_temp_new_i32();
11174 TCGLabel *l1 = gen_new_label();
11175 TCGLabel *l2 = gen_new_label();
11177 if (tf) {
11178 cond = TCG_COND_EQ;
11179 } else {
11180 cond = TCG_COND_NE;
11183 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11184 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11185 gen_load_fpr32(ctx, t0, fs);
11186 gen_store_fpr32(ctx, t0, fd);
11187 gen_set_label(l1);
11189 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc + 1));
11190 tcg_gen_brcondi_i32(cond, t0, 0, l2);
11191 gen_load_fpr32h(ctx, t0, fs);
11192 gen_store_fpr32h(ctx, t0, fd);
11193 tcg_temp_free_i32(t0);
11194 gen_set_label(l2);
11197 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
11198 int fs)
11200 TCGv_i32 t1 = tcg_const_i32(0);
11201 TCGv_i32 fp0 = tcg_temp_new_i32();
11202 TCGv_i32 fp1 = tcg_temp_new_i32();
11203 TCGv_i32 fp2 = tcg_temp_new_i32();
11204 gen_load_fpr32(ctx, fp0, fd);
11205 gen_load_fpr32(ctx, fp1, ft);
11206 gen_load_fpr32(ctx, fp2, fs);
11208 switch (op1) {
11209 case OPC_SEL_S:
11210 tcg_gen_andi_i32(fp0, fp0, 1);
11211 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11212 break;
11213 case OPC_SELEQZ_S:
11214 tcg_gen_andi_i32(fp1, fp1, 1);
11215 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11216 break;
11217 case OPC_SELNEZ_S:
11218 tcg_gen_andi_i32(fp1, fp1, 1);
11219 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11220 break;
11221 default:
11222 MIPS_INVAL("gen_sel_s");
11223 gen_reserved_instruction(ctx);
11224 break;
11227 gen_store_fpr32(ctx, fp0, fd);
11228 tcg_temp_free_i32(fp2);
11229 tcg_temp_free_i32(fp1);
11230 tcg_temp_free_i32(fp0);
11231 tcg_temp_free_i32(t1);
11234 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
11235 int fs)
11237 TCGv_i64 t1 = tcg_const_i64(0);
11238 TCGv_i64 fp0 = tcg_temp_new_i64();
11239 TCGv_i64 fp1 = tcg_temp_new_i64();
11240 TCGv_i64 fp2 = tcg_temp_new_i64();
11241 gen_load_fpr64(ctx, fp0, fd);
11242 gen_load_fpr64(ctx, fp1, ft);
11243 gen_load_fpr64(ctx, fp2, fs);
11245 switch (op1) {
11246 case OPC_SEL_D:
11247 tcg_gen_andi_i64(fp0, fp0, 1);
11248 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11249 break;
11250 case OPC_SELEQZ_D:
11251 tcg_gen_andi_i64(fp1, fp1, 1);
11252 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11253 break;
11254 case OPC_SELNEZ_D:
11255 tcg_gen_andi_i64(fp1, fp1, 1);
11256 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11257 break;
11258 default:
11259 MIPS_INVAL("gen_sel_d");
11260 gen_reserved_instruction(ctx);
11261 break;
11264 gen_store_fpr64(ctx, fp0, fd);
11265 tcg_temp_free_i64(fp2);
11266 tcg_temp_free_i64(fp1);
11267 tcg_temp_free_i64(fp0);
11268 tcg_temp_free_i64(t1);
11271 static void gen_farith(DisasContext *ctx, enum fopcode op1,
11272 int ft, int fs, int fd, int cc)
11274 uint32_t func = ctx->opcode & 0x3f;
11275 switch (op1) {
11276 case OPC_ADD_S:
11278 TCGv_i32 fp0 = tcg_temp_new_i32();
11279 TCGv_i32 fp1 = tcg_temp_new_i32();
11281 gen_load_fpr32(ctx, fp0, fs);
11282 gen_load_fpr32(ctx, fp1, ft);
11283 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
11284 tcg_temp_free_i32(fp1);
11285 gen_store_fpr32(ctx, fp0, fd);
11286 tcg_temp_free_i32(fp0);
11288 break;
11289 case OPC_SUB_S:
11291 TCGv_i32 fp0 = tcg_temp_new_i32();
11292 TCGv_i32 fp1 = tcg_temp_new_i32();
11294 gen_load_fpr32(ctx, fp0, fs);
11295 gen_load_fpr32(ctx, fp1, ft);
11296 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
11297 tcg_temp_free_i32(fp1);
11298 gen_store_fpr32(ctx, fp0, fd);
11299 tcg_temp_free_i32(fp0);
11301 break;
11302 case OPC_MUL_S:
11304 TCGv_i32 fp0 = tcg_temp_new_i32();
11305 TCGv_i32 fp1 = tcg_temp_new_i32();
11307 gen_load_fpr32(ctx, fp0, fs);
11308 gen_load_fpr32(ctx, fp1, ft);
11309 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
11310 tcg_temp_free_i32(fp1);
11311 gen_store_fpr32(ctx, fp0, fd);
11312 tcg_temp_free_i32(fp0);
11314 break;
11315 case OPC_DIV_S:
11317 TCGv_i32 fp0 = tcg_temp_new_i32();
11318 TCGv_i32 fp1 = tcg_temp_new_i32();
11320 gen_load_fpr32(ctx, fp0, fs);
11321 gen_load_fpr32(ctx, fp1, ft);
11322 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
11323 tcg_temp_free_i32(fp1);
11324 gen_store_fpr32(ctx, fp0, fd);
11325 tcg_temp_free_i32(fp0);
11327 break;
11328 case OPC_SQRT_S:
11330 TCGv_i32 fp0 = tcg_temp_new_i32();
11332 gen_load_fpr32(ctx, fp0, fs);
11333 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
11334 gen_store_fpr32(ctx, fp0, fd);
11335 tcg_temp_free_i32(fp0);
11337 break;
11338 case OPC_ABS_S:
11340 TCGv_i32 fp0 = tcg_temp_new_i32();
11342 gen_load_fpr32(ctx, fp0, fs);
11343 if (ctx->abs2008) {
11344 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
11345 } else {
11346 gen_helper_float_abs_s(fp0, fp0);
11348 gen_store_fpr32(ctx, fp0, fd);
11349 tcg_temp_free_i32(fp0);
11351 break;
11352 case OPC_MOV_S:
11354 TCGv_i32 fp0 = tcg_temp_new_i32();
11356 gen_load_fpr32(ctx, fp0, fs);
11357 gen_store_fpr32(ctx, fp0, fd);
11358 tcg_temp_free_i32(fp0);
11360 break;
11361 case OPC_NEG_S:
11363 TCGv_i32 fp0 = tcg_temp_new_i32();
11365 gen_load_fpr32(ctx, fp0, fs);
11366 if (ctx->abs2008) {
11367 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
11368 } else {
11369 gen_helper_float_chs_s(fp0, fp0);
11371 gen_store_fpr32(ctx, fp0, fd);
11372 tcg_temp_free_i32(fp0);
11374 break;
11375 case OPC_ROUND_L_S:
11376 check_cp1_64bitmode(ctx);
11378 TCGv_i32 fp32 = tcg_temp_new_i32();
11379 TCGv_i64 fp64 = tcg_temp_new_i64();
11381 gen_load_fpr32(ctx, fp32, fs);
11382 if (ctx->nan2008) {
11383 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
11384 } else {
11385 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
11387 tcg_temp_free_i32(fp32);
11388 gen_store_fpr64(ctx, fp64, fd);
11389 tcg_temp_free_i64(fp64);
11391 break;
11392 case OPC_TRUNC_L_S:
11393 check_cp1_64bitmode(ctx);
11395 TCGv_i32 fp32 = tcg_temp_new_i32();
11396 TCGv_i64 fp64 = tcg_temp_new_i64();
11398 gen_load_fpr32(ctx, fp32, fs);
11399 if (ctx->nan2008) {
11400 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
11401 } else {
11402 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
11404 tcg_temp_free_i32(fp32);
11405 gen_store_fpr64(ctx, fp64, fd);
11406 tcg_temp_free_i64(fp64);
11408 break;
11409 case OPC_CEIL_L_S:
11410 check_cp1_64bitmode(ctx);
11412 TCGv_i32 fp32 = tcg_temp_new_i32();
11413 TCGv_i64 fp64 = tcg_temp_new_i64();
11415 gen_load_fpr32(ctx, fp32, fs);
11416 if (ctx->nan2008) {
11417 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
11418 } else {
11419 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
11421 tcg_temp_free_i32(fp32);
11422 gen_store_fpr64(ctx, fp64, fd);
11423 tcg_temp_free_i64(fp64);
11425 break;
11426 case OPC_FLOOR_L_S:
11427 check_cp1_64bitmode(ctx);
11429 TCGv_i32 fp32 = tcg_temp_new_i32();
11430 TCGv_i64 fp64 = tcg_temp_new_i64();
11432 gen_load_fpr32(ctx, fp32, fs);
11433 if (ctx->nan2008) {
11434 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
11435 } else {
11436 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
11438 tcg_temp_free_i32(fp32);
11439 gen_store_fpr64(ctx, fp64, fd);
11440 tcg_temp_free_i64(fp64);
11442 break;
11443 case OPC_ROUND_W_S:
11445 TCGv_i32 fp0 = tcg_temp_new_i32();
11447 gen_load_fpr32(ctx, fp0, fs);
11448 if (ctx->nan2008) {
11449 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
11450 } else {
11451 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
11453 gen_store_fpr32(ctx, fp0, fd);
11454 tcg_temp_free_i32(fp0);
11456 break;
11457 case OPC_TRUNC_W_S:
11459 TCGv_i32 fp0 = tcg_temp_new_i32();
11461 gen_load_fpr32(ctx, fp0, fs);
11462 if (ctx->nan2008) {
11463 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
11464 } else {
11465 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
11467 gen_store_fpr32(ctx, fp0, fd);
11468 tcg_temp_free_i32(fp0);
11470 break;
11471 case OPC_CEIL_W_S:
11473 TCGv_i32 fp0 = tcg_temp_new_i32();
11475 gen_load_fpr32(ctx, fp0, fs);
11476 if (ctx->nan2008) {
11477 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
11478 } else {
11479 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
11481 gen_store_fpr32(ctx, fp0, fd);
11482 tcg_temp_free_i32(fp0);
11484 break;
11485 case OPC_FLOOR_W_S:
11487 TCGv_i32 fp0 = tcg_temp_new_i32();
11489 gen_load_fpr32(ctx, fp0, fs);
11490 if (ctx->nan2008) {
11491 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
11492 } else {
11493 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
11495 gen_store_fpr32(ctx, fp0, fd);
11496 tcg_temp_free_i32(fp0);
11498 break;
11499 case OPC_SEL_S:
11500 check_insn(ctx, ISA_MIPS_R6);
11501 gen_sel_s(ctx, op1, fd, ft, fs);
11502 break;
11503 case OPC_SELEQZ_S:
11504 check_insn(ctx, ISA_MIPS_R6);
11505 gen_sel_s(ctx, op1, fd, ft, fs);
11506 break;
11507 case OPC_SELNEZ_S:
11508 check_insn(ctx, ISA_MIPS_R6);
11509 gen_sel_s(ctx, op1, fd, ft, fs);
11510 break;
11511 case OPC_MOVCF_S:
11512 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11513 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11514 break;
11515 case OPC_MOVZ_S:
11516 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11518 TCGLabel *l1 = gen_new_label();
11519 TCGv_i32 fp0;
11521 if (ft != 0) {
11522 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11524 fp0 = tcg_temp_new_i32();
11525 gen_load_fpr32(ctx, fp0, fs);
11526 gen_store_fpr32(ctx, fp0, fd);
11527 tcg_temp_free_i32(fp0);
11528 gen_set_label(l1);
11530 break;
11531 case OPC_MOVN_S:
11532 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11534 TCGLabel *l1 = gen_new_label();
11535 TCGv_i32 fp0;
11537 if (ft != 0) {
11538 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11539 fp0 = tcg_temp_new_i32();
11540 gen_load_fpr32(ctx, fp0, fs);
11541 gen_store_fpr32(ctx, fp0, fd);
11542 tcg_temp_free_i32(fp0);
11543 gen_set_label(l1);
11546 break;
11547 case OPC_RECIP_S:
11549 TCGv_i32 fp0 = tcg_temp_new_i32();
11551 gen_load_fpr32(ctx, fp0, fs);
11552 gen_helper_float_recip_s(fp0, cpu_env, fp0);
11553 gen_store_fpr32(ctx, fp0, fd);
11554 tcg_temp_free_i32(fp0);
11556 break;
11557 case OPC_RSQRT_S:
11559 TCGv_i32 fp0 = tcg_temp_new_i32();
11561 gen_load_fpr32(ctx, fp0, fs);
11562 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
11563 gen_store_fpr32(ctx, fp0, fd);
11564 tcg_temp_free_i32(fp0);
11566 break;
11567 case OPC_MADDF_S:
11568 check_insn(ctx, ISA_MIPS_R6);
11570 TCGv_i32 fp0 = tcg_temp_new_i32();
11571 TCGv_i32 fp1 = tcg_temp_new_i32();
11572 TCGv_i32 fp2 = tcg_temp_new_i32();
11573 gen_load_fpr32(ctx, fp0, fs);
11574 gen_load_fpr32(ctx, fp1, ft);
11575 gen_load_fpr32(ctx, fp2, fd);
11576 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
11577 gen_store_fpr32(ctx, fp2, fd);
11578 tcg_temp_free_i32(fp2);
11579 tcg_temp_free_i32(fp1);
11580 tcg_temp_free_i32(fp0);
11582 break;
11583 case OPC_MSUBF_S:
11584 check_insn(ctx, ISA_MIPS_R6);
11586 TCGv_i32 fp0 = tcg_temp_new_i32();
11587 TCGv_i32 fp1 = tcg_temp_new_i32();
11588 TCGv_i32 fp2 = tcg_temp_new_i32();
11589 gen_load_fpr32(ctx, fp0, fs);
11590 gen_load_fpr32(ctx, fp1, ft);
11591 gen_load_fpr32(ctx, fp2, fd);
11592 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
11593 gen_store_fpr32(ctx, fp2, fd);
11594 tcg_temp_free_i32(fp2);
11595 tcg_temp_free_i32(fp1);
11596 tcg_temp_free_i32(fp0);
11598 break;
11599 case OPC_RINT_S:
11600 check_insn(ctx, ISA_MIPS_R6);
11602 TCGv_i32 fp0 = tcg_temp_new_i32();
11603 gen_load_fpr32(ctx, fp0, fs);
11604 gen_helper_float_rint_s(fp0, cpu_env, fp0);
11605 gen_store_fpr32(ctx, fp0, fd);
11606 tcg_temp_free_i32(fp0);
11608 break;
11609 case OPC_CLASS_S:
11610 check_insn(ctx, ISA_MIPS_R6);
11612 TCGv_i32 fp0 = tcg_temp_new_i32();
11613 gen_load_fpr32(ctx, fp0, fs);
11614 gen_helper_float_class_s(fp0, cpu_env, fp0);
11615 gen_store_fpr32(ctx, fp0, fd);
11616 tcg_temp_free_i32(fp0);
11618 break;
11619 case OPC_MIN_S: /* OPC_RECIP2_S */
11620 if (ctx->insn_flags & ISA_MIPS_R6) {
11621 /* OPC_MIN_S */
11622 TCGv_i32 fp0 = tcg_temp_new_i32();
11623 TCGv_i32 fp1 = tcg_temp_new_i32();
11624 TCGv_i32 fp2 = tcg_temp_new_i32();
11625 gen_load_fpr32(ctx, fp0, fs);
11626 gen_load_fpr32(ctx, fp1, ft);
11627 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
11628 gen_store_fpr32(ctx, fp2, fd);
11629 tcg_temp_free_i32(fp2);
11630 tcg_temp_free_i32(fp1);
11631 tcg_temp_free_i32(fp0);
11632 } else {
11633 /* OPC_RECIP2_S */
11634 check_cp1_64bitmode(ctx);
11636 TCGv_i32 fp0 = tcg_temp_new_i32();
11637 TCGv_i32 fp1 = tcg_temp_new_i32();
11639 gen_load_fpr32(ctx, fp0, fs);
11640 gen_load_fpr32(ctx, fp1, ft);
11641 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
11642 tcg_temp_free_i32(fp1);
11643 gen_store_fpr32(ctx, fp0, fd);
11644 tcg_temp_free_i32(fp0);
11647 break;
11648 case OPC_MINA_S: /* OPC_RECIP1_S */
11649 if (ctx->insn_flags & ISA_MIPS_R6) {
11650 /* OPC_MINA_S */
11651 TCGv_i32 fp0 = tcg_temp_new_i32();
11652 TCGv_i32 fp1 = tcg_temp_new_i32();
11653 TCGv_i32 fp2 = tcg_temp_new_i32();
11654 gen_load_fpr32(ctx, fp0, fs);
11655 gen_load_fpr32(ctx, fp1, ft);
11656 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
11657 gen_store_fpr32(ctx, fp2, fd);
11658 tcg_temp_free_i32(fp2);
11659 tcg_temp_free_i32(fp1);
11660 tcg_temp_free_i32(fp0);
11661 } else {
11662 /* OPC_RECIP1_S */
11663 check_cp1_64bitmode(ctx);
11665 TCGv_i32 fp0 = tcg_temp_new_i32();
11667 gen_load_fpr32(ctx, fp0, fs);
11668 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
11669 gen_store_fpr32(ctx, fp0, fd);
11670 tcg_temp_free_i32(fp0);
11673 break;
11674 case OPC_MAX_S: /* OPC_RSQRT1_S */
11675 if (ctx->insn_flags & ISA_MIPS_R6) {
11676 /* OPC_MAX_S */
11677 TCGv_i32 fp0 = tcg_temp_new_i32();
11678 TCGv_i32 fp1 = tcg_temp_new_i32();
11679 gen_load_fpr32(ctx, fp0, fs);
11680 gen_load_fpr32(ctx, fp1, ft);
11681 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
11682 gen_store_fpr32(ctx, fp1, fd);
11683 tcg_temp_free_i32(fp1);
11684 tcg_temp_free_i32(fp0);
11685 } else {
11686 /* OPC_RSQRT1_S */
11687 check_cp1_64bitmode(ctx);
11689 TCGv_i32 fp0 = tcg_temp_new_i32();
11691 gen_load_fpr32(ctx, fp0, fs);
11692 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
11693 gen_store_fpr32(ctx, fp0, fd);
11694 tcg_temp_free_i32(fp0);
11697 break;
11698 case OPC_MAXA_S: /* OPC_RSQRT2_S */
11699 if (ctx->insn_flags & ISA_MIPS_R6) {
11700 /* OPC_MAXA_S */
11701 TCGv_i32 fp0 = tcg_temp_new_i32();
11702 TCGv_i32 fp1 = tcg_temp_new_i32();
11703 gen_load_fpr32(ctx, fp0, fs);
11704 gen_load_fpr32(ctx, fp1, ft);
11705 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
11706 gen_store_fpr32(ctx, fp1, fd);
11707 tcg_temp_free_i32(fp1);
11708 tcg_temp_free_i32(fp0);
11709 } else {
11710 /* OPC_RSQRT2_S */
11711 check_cp1_64bitmode(ctx);
11713 TCGv_i32 fp0 = tcg_temp_new_i32();
11714 TCGv_i32 fp1 = tcg_temp_new_i32();
11716 gen_load_fpr32(ctx, fp0, fs);
11717 gen_load_fpr32(ctx, fp1, ft);
11718 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
11719 tcg_temp_free_i32(fp1);
11720 gen_store_fpr32(ctx, fp0, fd);
11721 tcg_temp_free_i32(fp0);
11724 break;
11725 case OPC_CVT_D_S:
11726 check_cp1_registers(ctx, fd);
11728 TCGv_i32 fp32 = tcg_temp_new_i32();
11729 TCGv_i64 fp64 = tcg_temp_new_i64();
11731 gen_load_fpr32(ctx, fp32, fs);
11732 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
11733 tcg_temp_free_i32(fp32);
11734 gen_store_fpr64(ctx, fp64, fd);
11735 tcg_temp_free_i64(fp64);
11737 break;
11738 case OPC_CVT_W_S:
11740 TCGv_i32 fp0 = tcg_temp_new_i32();
11742 gen_load_fpr32(ctx, fp0, fs);
11743 if (ctx->nan2008) {
11744 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
11745 } else {
11746 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
11748 gen_store_fpr32(ctx, fp0, fd);
11749 tcg_temp_free_i32(fp0);
11751 break;
11752 case OPC_CVT_L_S:
11753 check_cp1_64bitmode(ctx);
11755 TCGv_i32 fp32 = tcg_temp_new_i32();
11756 TCGv_i64 fp64 = tcg_temp_new_i64();
11758 gen_load_fpr32(ctx, fp32, fs);
11759 if (ctx->nan2008) {
11760 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
11761 } else {
11762 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
11764 tcg_temp_free_i32(fp32);
11765 gen_store_fpr64(ctx, fp64, fd);
11766 tcg_temp_free_i64(fp64);
11768 break;
11769 case OPC_CVT_PS_S:
11770 check_ps(ctx);
11772 TCGv_i64 fp64 = tcg_temp_new_i64();
11773 TCGv_i32 fp32_0 = tcg_temp_new_i32();
11774 TCGv_i32 fp32_1 = tcg_temp_new_i32();
11776 gen_load_fpr32(ctx, fp32_0, fs);
11777 gen_load_fpr32(ctx, fp32_1, ft);
11778 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
11779 tcg_temp_free_i32(fp32_1);
11780 tcg_temp_free_i32(fp32_0);
11781 gen_store_fpr64(ctx, fp64, fd);
11782 tcg_temp_free_i64(fp64);
11784 break;
11785 case OPC_CMP_F_S:
11786 case OPC_CMP_UN_S:
11787 case OPC_CMP_EQ_S:
11788 case OPC_CMP_UEQ_S:
11789 case OPC_CMP_OLT_S:
11790 case OPC_CMP_ULT_S:
11791 case OPC_CMP_OLE_S:
11792 case OPC_CMP_ULE_S:
11793 case OPC_CMP_SF_S:
11794 case OPC_CMP_NGLE_S:
11795 case OPC_CMP_SEQ_S:
11796 case OPC_CMP_NGL_S:
11797 case OPC_CMP_LT_S:
11798 case OPC_CMP_NGE_S:
11799 case OPC_CMP_LE_S:
11800 case OPC_CMP_NGT_S:
11801 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11802 if (ctx->opcode & (1 << 6)) {
11803 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
11804 } else {
11805 gen_cmp_s(ctx, func - 48, ft, fs, cc);
11807 break;
11808 case OPC_ADD_D:
11809 check_cp1_registers(ctx, fs | ft | fd);
11811 TCGv_i64 fp0 = tcg_temp_new_i64();
11812 TCGv_i64 fp1 = tcg_temp_new_i64();
11814 gen_load_fpr64(ctx, fp0, fs);
11815 gen_load_fpr64(ctx, fp1, ft);
11816 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
11817 tcg_temp_free_i64(fp1);
11818 gen_store_fpr64(ctx, fp0, fd);
11819 tcg_temp_free_i64(fp0);
11821 break;
11822 case OPC_SUB_D:
11823 check_cp1_registers(ctx, fs | ft | fd);
11825 TCGv_i64 fp0 = tcg_temp_new_i64();
11826 TCGv_i64 fp1 = tcg_temp_new_i64();
11828 gen_load_fpr64(ctx, fp0, fs);
11829 gen_load_fpr64(ctx, fp1, ft);
11830 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
11831 tcg_temp_free_i64(fp1);
11832 gen_store_fpr64(ctx, fp0, fd);
11833 tcg_temp_free_i64(fp0);
11835 break;
11836 case OPC_MUL_D:
11837 check_cp1_registers(ctx, fs | ft | fd);
11839 TCGv_i64 fp0 = tcg_temp_new_i64();
11840 TCGv_i64 fp1 = tcg_temp_new_i64();
11842 gen_load_fpr64(ctx, fp0, fs);
11843 gen_load_fpr64(ctx, fp1, ft);
11844 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
11845 tcg_temp_free_i64(fp1);
11846 gen_store_fpr64(ctx, fp0, fd);
11847 tcg_temp_free_i64(fp0);
11849 break;
11850 case OPC_DIV_D:
11851 check_cp1_registers(ctx, fs | ft | fd);
11853 TCGv_i64 fp0 = tcg_temp_new_i64();
11854 TCGv_i64 fp1 = tcg_temp_new_i64();
11856 gen_load_fpr64(ctx, fp0, fs);
11857 gen_load_fpr64(ctx, fp1, ft);
11858 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
11859 tcg_temp_free_i64(fp1);
11860 gen_store_fpr64(ctx, fp0, fd);
11861 tcg_temp_free_i64(fp0);
11863 break;
11864 case OPC_SQRT_D:
11865 check_cp1_registers(ctx, fs | fd);
11867 TCGv_i64 fp0 = tcg_temp_new_i64();
11869 gen_load_fpr64(ctx, fp0, fs);
11870 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
11871 gen_store_fpr64(ctx, fp0, fd);
11872 tcg_temp_free_i64(fp0);
11874 break;
11875 case OPC_ABS_D:
11876 check_cp1_registers(ctx, fs | fd);
11878 TCGv_i64 fp0 = tcg_temp_new_i64();
11880 gen_load_fpr64(ctx, fp0, fs);
11881 if (ctx->abs2008) {
11882 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
11883 } else {
11884 gen_helper_float_abs_d(fp0, fp0);
11886 gen_store_fpr64(ctx, fp0, fd);
11887 tcg_temp_free_i64(fp0);
11889 break;
11890 case OPC_MOV_D:
11891 check_cp1_registers(ctx, fs | fd);
11893 TCGv_i64 fp0 = tcg_temp_new_i64();
11895 gen_load_fpr64(ctx, fp0, fs);
11896 gen_store_fpr64(ctx, fp0, fd);
11897 tcg_temp_free_i64(fp0);
11899 break;
11900 case OPC_NEG_D:
11901 check_cp1_registers(ctx, fs | fd);
11903 TCGv_i64 fp0 = tcg_temp_new_i64();
11905 gen_load_fpr64(ctx, fp0, fs);
11906 if (ctx->abs2008) {
11907 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
11908 } else {
11909 gen_helper_float_chs_d(fp0, fp0);
11911 gen_store_fpr64(ctx, fp0, fd);
11912 tcg_temp_free_i64(fp0);
11914 break;
11915 case OPC_ROUND_L_D:
11916 check_cp1_64bitmode(ctx);
11918 TCGv_i64 fp0 = tcg_temp_new_i64();
11920 gen_load_fpr64(ctx, fp0, fs);
11921 if (ctx->nan2008) {
11922 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
11923 } else {
11924 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
11926 gen_store_fpr64(ctx, fp0, fd);
11927 tcg_temp_free_i64(fp0);
11929 break;
11930 case OPC_TRUNC_L_D:
11931 check_cp1_64bitmode(ctx);
11933 TCGv_i64 fp0 = tcg_temp_new_i64();
11935 gen_load_fpr64(ctx, fp0, fs);
11936 if (ctx->nan2008) {
11937 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
11938 } else {
11939 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
11941 gen_store_fpr64(ctx, fp0, fd);
11942 tcg_temp_free_i64(fp0);
11944 break;
11945 case OPC_CEIL_L_D:
11946 check_cp1_64bitmode(ctx);
11948 TCGv_i64 fp0 = tcg_temp_new_i64();
11950 gen_load_fpr64(ctx, fp0, fs);
11951 if (ctx->nan2008) {
11952 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
11953 } else {
11954 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
11956 gen_store_fpr64(ctx, fp0, fd);
11957 tcg_temp_free_i64(fp0);
11959 break;
11960 case OPC_FLOOR_L_D:
11961 check_cp1_64bitmode(ctx);
11963 TCGv_i64 fp0 = tcg_temp_new_i64();
11965 gen_load_fpr64(ctx, fp0, fs);
11966 if (ctx->nan2008) {
11967 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
11968 } else {
11969 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
11971 gen_store_fpr64(ctx, fp0, fd);
11972 tcg_temp_free_i64(fp0);
11974 break;
11975 case OPC_ROUND_W_D:
11976 check_cp1_registers(ctx, fs);
11978 TCGv_i32 fp32 = tcg_temp_new_i32();
11979 TCGv_i64 fp64 = tcg_temp_new_i64();
11981 gen_load_fpr64(ctx, fp64, fs);
11982 if (ctx->nan2008) {
11983 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
11984 } else {
11985 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
11987 tcg_temp_free_i64(fp64);
11988 gen_store_fpr32(ctx, fp32, fd);
11989 tcg_temp_free_i32(fp32);
11991 break;
11992 case OPC_TRUNC_W_D:
11993 check_cp1_registers(ctx, fs);
11995 TCGv_i32 fp32 = tcg_temp_new_i32();
11996 TCGv_i64 fp64 = tcg_temp_new_i64();
11998 gen_load_fpr64(ctx, fp64, fs);
11999 if (ctx->nan2008) {
12000 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
12001 } else {
12002 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
12004 tcg_temp_free_i64(fp64);
12005 gen_store_fpr32(ctx, fp32, fd);
12006 tcg_temp_free_i32(fp32);
12008 break;
12009 case OPC_CEIL_W_D:
12010 check_cp1_registers(ctx, fs);
12012 TCGv_i32 fp32 = tcg_temp_new_i32();
12013 TCGv_i64 fp64 = tcg_temp_new_i64();
12015 gen_load_fpr64(ctx, fp64, fs);
12016 if (ctx->nan2008) {
12017 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
12018 } else {
12019 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
12021 tcg_temp_free_i64(fp64);
12022 gen_store_fpr32(ctx, fp32, fd);
12023 tcg_temp_free_i32(fp32);
12025 break;
12026 case OPC_FLOOR_W_D:
12027 check_cp1_registers(ctx, fs);
12029 TCGv_i32 fp32 = tcg_temp_new_i32();
12030 TCGv_i64 fp64 = tcg_temp_new_i64();
12032 gen_load_fpr64(ctx, fp64, fs);
12033 if (ctx->nan2008) {
12034 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
12035 } else {
12036 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
12038 tcg_temp_free_i64(fp64);
12039 gen_store_fpr32(ctx, fp32, fd);
12040 tcg_temp_free_i32(fp32);
12042 break;
12043 case OPC_SEL_D:
12044 check_insn(ctx, ISA_MIPS_R6);
12045 gen_sel_d(ctx, op1, fd, ft, fs);
12046 break;
12047 case OPC_SELEQZ_D:
12048 check_insn(ctx, ISA_MIPS_R6);
12049 gen_sel_d(ctx, op1, fd, ft, fs);
12050 break;
12051 case OPC_SELNEZ_D:
12052 check_insn(ctx, ISA_MIPS_R6);
12053 gen_sel_d(ctx, op1, fd, ft, fs);
12054 break;
12055 case OPC_MOVCF_D:
12056 check_insn_opc_removed(ctx, ISA_MIPS_R6);
12057 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
12058 break;
12059 case OPC_MOVZ_D:
12060 check_insn_opc_removed(ctx, ISA_MIPS_R6);
12062 TCGLabel *l1 = gen_new_label();
12063 TCGv_i64 fp0;
12065 if (ft != 0) {
12066 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
12068 fp0 = tcg_temp_new_i64();
12069 gen_load_fpr64(ctx, fp0, fs);
12070 gen_store_fpr64(ctx, fp0, fd);
12071 tcg_temp_free_i64(fp0);
12072 gen_set_label(l1);
12074 break;
12075 case OPC_MOVN_D:
12076 check_insn_opc_removed(ctx, ISA_MIPS_R6);
12078 TCGLabel *l1 = gen_new_label();
12079 TCGv_i64 fp0;
12081 if (ft != 0) {
12082 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12083 fp0 = tcg_temp_new_i64();
12084 gen_load_fpr64(ctx, fp0, fs);
12085 gen_store_fpr64(ctx, fp0, fd);
12086 tcg_temp_free_i64(fp0);
12087 gen_set_label(l1);
12090 break;
12091 case OPC_RECIP_D:
12092 check_cp1_registers(ctx, fs | fd);
12094 TCGv_i64 fp0 = tcg_temp_new_i64();
12096 gen_load_fpr64(ctx, fp0, fs);
12097 gen_helper_float_recip_d(fp0, cpu_env, fp0);
12098 gen_store_fpr64(ctx, fp0, fd);
12099 tcg_temp_free_i64(fp0);
12101 break;
12102 case OPC_RSQRT_D:
12103 check_cp1_registers(ctx, fs | fd);
12105 TCGv_i64 fp0 = tcg_temp_new_i64();
12107 gen_load_fpr64(ctx, fp0, fs);
12108 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
12109 gen_store_fpr64(ctx, fp0, fd);
12110 tcg_temp_free_i64(fp0);
12112 break;
12113 case OPC_MADDF_D:
12114 check_insn(ctx, ISA_MIPS_R6);
12116 TCGv_i64 fp0 = tcg_temp_new_i64();
12117 TCGv_i64 fp1 = tcg_temp_new_i64();
12118 TCGv_i64 fp2 = tcg_temp_new_i64();
12119 gen_load_fpr64(ctx, fp0, fs);
12120 gen_load_fpr64(ctx, fp1, ft);
12121 gen_load_fpr64(ctx, fp2, fd);
12122 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
12123 gen_store_fpr64(ctx, fp2, fd);
12124 tcg_temp_free_i64(fp2);
12125 tcg_temp_free_i64(fp1);
12126 tcg_temp_free_i64(fp0);
12128 break;
12129 case OPC_MSUBF_D:
12130 check_insn(ctx, ISA_MIPS_R6);
12132 TCGv_i64 fp0 = tcg_temp_new_i64();
12133 TCGv_i64 fp1 = tcg_temp_new_i64();
12134 TCGv_i64 fp2 = tcg_temp_new_i64();
12135 gen_load_fpr64(ctx, fp0, fs);
12136 gen_load_fpr64(ctx, fp1, ft);
12137 gen_load_fpr64(ctx, fp2, fd);
12138 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
12139 gen_store_fpr64(ctx, fp2, fd);
12140 tcg_temp_free_i64(fp2);
12141 tcg_temp_free_i64(fp1);
12142 tcg_temp_free_i64(fp0);
12144 break;
12145 case OPC_RINT_D:
12146 check_insn(ctx, ISA_MIPS_R6);
12148 TCGv_i64 fp0 = tcg_temp_new_i64();
12149 gen_load_fpr64(ctx, fp0, fs);
12150 gen_helper_float_rint_d(fp0, cpu_env, fp0);
12151 gen_store_fpr64(ctx, fp0, fd);
12152 tcg_temp_free_i64(fp0);
12154 break;
12155 case OPC_CLASS_D:
12156 check_insn(ctx, ISA_MIPS_R6);
12158 TCGv_i64 fp0 = tcg_temp_new_i64();
12159 gen_load_fpr64(ctx, fp0, fs);
12160 gen_helper_float_class_d(fp0, cpu_env, fp0);
12161 gen_store_fpr64(ctx, fp0, fd);
12162 tcg_temp_free_i64(fp0);
12164 break;
12165 case OPC_MIN_D: /* OPC_RECIP2_D */
12166 if (ctx->insn_flags & ISA_MIPS_R6) {
12167 /* OPC_MIN_D */
12168 TCGv_i64 fp0 = tcg_temp_new_i64();
12169 TCGv_i64 fp1 = tcg_temp_new_i64();
12170 gen_load_fpr64(ctx, fp0, fs);
12171 gen_load_fpr64(ctx, fp1, ft);
12172 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
12173 gen_store_fpr64(ctx, fp1, fd);
12174 tcg_temp_free_i64(fp1);
12175 tcg_temp_free_i64(fp0);
12176 } else {
12177 /* OPC_RECIP2_D */
12178 check_cp1_64bitmode(ctx);
12180 TCGv_i64 fp0 = tcg_temp_new_i64();
12181 TCGv_i64 fp1 = tcg_temp_new_i64();
12183 gen_load_fpr64(ctx, fp0, fs);
12184 gen_load_fpr64(ctx, fp1, ft);
12185 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
12186 tcg_temp_free_i64(fp1);
12187 gen_store_fpr64(ctx, fp0, fd);
12188 tcg_temp_free_i64(fp0);
12191 break;
12192 case OPC_MINA_D: /* OPC_RECIP1_D */
12193 if (ctx->insn_flags & ISA_MIPS_R6) {
12194 /* OPC_MINA_D */
12195 TCGv_i64 fp0 = tcg_temp_new_i64();
12196 TCGv_i64 fp1 = tcg_temp_new_i64();
12197 gen_load_fpr64(ctx, fp0, fs);
12198 gen_load_fpr64(ctx, fp1, ft);
12199 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
12200 gen_store_fpr64(ctx, fp1, fd);
12201 tcg_temp_free_i64(fp1);
12202 tcg_temp_free_i64(fp0);
12203 } else {
12204 /* OPC_RECIP1_D */
12205 check_cp1_64bitmode(ctx);
12207 TCGv_i64 fp0 = tcg_temp_new_i64();
12209 gen_load_fpr64(ctx, fp0, fs);
12210 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
12211 gen_store_fpr64(ctx, fp0, fd);
12212 tcg_temp_free_i64(fp0);
12215 break;
12216 case OPC_MAX_D: /* OPC_RSQRT1_D */
12217 if (ctx->insn_flags & ISA_MIPS_R6) {
12218 /* OPC_MAX_D */
12219 TCGv_i64 fp0 = tcg_temp_new_i64();
12220 TCGv_i64 fp1 = tcg_temp_new_i64();
12221 gen_load_fpr64(ctx, fp0, fs);
12222 gen_load_fpr64(ctx, fp1, ft);
12223 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
12224 gen_store_fpr64(ctx, fp1, fd);
12225 tcg_temp_free_i64(fp1);
12226 tcg_temp_free_i64(fp0);
12227 } else {
12228 /* OPC_RSQRT1_D */
12229 check_cp1_64bitmode(ctx);
12231 TCGv_i64 fp0 = tcg_temp_new_i64();
12233 gen_load_fpr64(ctx, fp0, fs);
12234 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
12235 gen_store_fpr64(ctx, fp0, fd);
12236 tcg_temp_free_i64(fp0);
12239 break;
12240 case OPC_MAXA_D: /* OPC_RSQRT2_D */
12241 if (ctx->insn_flags & ISA_MIPS_R6) {
12242 /* OPC_MAXA_D */
12243 TCGv_i64 fp0 = tcg_temp_new_i64();
12244 TCGv_i64 fp1 = tcg_temp_new_i64();
12245 gen_load_fpr64(ctx, fp0, fs);
12246 gen_load_fpr64(ctx, fp1, ft);
12247 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
12248 gen_store_fpr64(ctx, fp1, fd);
12249 tcg_temp_free_i64(fp1);
12250 tcg_temp_free_i64(fp0);
12251 } else {
12252 /* OPC_RSQRT2_D */
12253 check_cp1_64bitmode(ctx);
12255 TCGv_i64 fp0 = tcg_temp_new_i64();
12256 TCGv_i64 fp1 = tcg_temp_new_i64();
12258 gen_load_fpr64(ctx, fp0, fs);
12259 gen_load_fpr64(ctx, fp1, ft);
12260 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
12261 tcg_temp_free_i64(fp1);
12262 gen_store_fpr64(ctx, fp0, fd);
12263 tcg_temp_free_i64(fp0);
12266 break;
12267 case OPC_CMP_F_D:
12268 case OPC_CMP_UN_D:
12269 case OPC_CMP_EQ_D:
12270 case OPC_CMP_UEQ_D:
12271 case OPC_CMP_OLT_D:
12272 case OPC_CMP_ULT_D:
12273 case OPC_CMP_OLE_D:
12274 case OPC_CMP_ULE_D:
12275 case OPC_CMP_SF_D:
12276 case OPC_CMP_NGLE_D:
12277 case OPC_CMP_SEQ_D:
12278 case OPC_CMP_NGL_D:
12279 case OPC_CMP_LT_D:
12280 case OPC_CMP_NGE_D:
12281 case OPC_CMP_LE_D:
12282 case OPC_CMP_NGT_D:
12283 check_insn_opc_removed(ctx, ISA_MIPS_R6);
12284 if (ctx->opcode & (1 << 6)) {
12285 gen_cmpabs_d(ctx, func - 48, ft, fs, cc);
12286 } else {
12287 gen_cmp_d(ctx, func - 48, ft, fs, cc);
12289 break;
12290 case OPC_CVT_S_D:
12291 check_cp1_registers(ctx, fs);
12293 TCGv_i32 fp32 = tcg_temp_new_i32();
12294 TCGv_i64 fp64 = tcg_temp_new_i64();
12296 gen_load_fpr64(ctx, fp64, fs);
12297 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
12298 tcg_temp_free_i64(fp64);
12299 gen_store_fpr32(ctx, fp32, fd);
12300 tcg_temp_free_i32(fp32);
12302 break;
12303 case OPC_CVT_W_D:
12304 check_cp1_registers(ctx, fs);
12306 TCGv_i32 fp32 = tcg_temp_new_i32();
12307 TCGv_i64 fp64 = tcg_temp_new_i64();
12309 gen_load_fpr64(ctx, fp64, fs);
12310 if (ctx->nan2008) {
12311 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
12312 } else {
12313 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
12315 tcg_temp_free_i64(fp64);
12316 gen_store_fpr32(ctx, fp32, fd);
12317 tcg_temp_free_i32(fp32);
12319 break;
12320 case OPC_CVT_L_D:
12321 check_cp1_64bitmode(ctx);
12323 TCGv_i64 fp0 = tcg_temp_new_i64();
12325 gen_load_fpr64(ctx, fp0, fs);
12326 if (ctx->nan2008) {
12327 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
12328 } else {
12329 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
12331 gen_store_fpr64(ctx, fp0, fd);
12332 tcg_temp_free_i64(fp0);
12334 break;
12335 case OPC_CVT_S_W:
12337 TCGv_i32 fp0 = tcg_temp_new_i32();
12339 gen_load_fpr32(ctx, fp0, fs);
12340 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
12341 gen_store_fpr32(ctx, fp0, fd);
12342 tcg_temp_free_i32(fp0);
12344 break;
12345 case OPC_CVT_D_W:
12346 check_cp1_registers(ctx, fd);
12348 TCGv_i32 fp32 = tcg_temp_new_i32();
12349 TCGv_i64 fp64 = tcg_temp_new_i64();
12351 gen_load_fpr32(ctx, fp32, fs);
12352 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
12353 tcg_temp_free_i32(fp32);
12354 gen_store_fpr64(ctx, fp64, fd);
12355 tcg_temp_free_i64(fp64);
12357 break;
12358 case OPC_CVT_S_L:
12359 check_cp1_64bitmode(ctx);
12361 TCGv_i32 fp32 = tcg_temp_new_i32();
12362 TCGv_i64 fp64 = tcg_temp_new_i64();
12364 gen_load_fpr64(ctx, fp64, fs);
12365 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
12366 tcg_temp_free_i64(fp64);
12367 gen_store_fpr32(ctx, fp32, fd);
12368 tcg_temp_free_i32(fp32);
12370 break;
12371 case OPC_CVT_D_L:
12372 check_cp1_64bitmode(ctx);
12374 TCGv_i64 fp0 = tcg_temp_new_i64();
12376 gen_load_fpr64(ctx, fp0, fs);
12377 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
12378 gen_store_fpr64(ctx, fp0, fd);
12379 tcg_temp_free_i64(fp0);
12381 break;
12382 case OPC_CVT_PS_PW:
12383 check_ps(ctx);
12385 TCGv_i64 fp0 = tcg_temp_new_i64();
12387 gen_load_fpr64(ctx, fp0, fs);
12388 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
12389 gen_store_fpr64(ctx, fp0, fd);
12390 tcg_temp_free_i64(fp0);
12392 break;
12393 case OPC_ADD_PS:
12394 check_ps(ctx);
12396 TCGv_i64 fp0 = tcg_temp_new_i64();
12397 TCGv_i64 fp1 = tcg_temp_new_i64();
12399 gen_load_fpr64(ctx, fp0, fs);
12400 gen_load_fpr64(ctx, fp1, ft);
12401 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
12402 tcg_temp_free_i64(fp1);
12403 gen_store_fpr64(ctx, fp0, fd);
12404 tcg_temp_free_i64(fp0);
12406 break;
12407 case OPC_SUB_PS:
12408 check_ps(ctx);
12410 TCGv_i64 fp0 = tcg_temp_new_i64();
12411 TCGv_i64 fp1 = tcg_temp_new_i64();
12413 gen_load_fpr64(ctx, fp0, fs);
12414 gen_load_fpr64(ctx, fp1, ft);
12415 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
12416 tcg_temp_free_i64(fp1);
12417 gen_store_fpr64(ctx, fp0, fd);
12418 tcg_temp_free_i64(fp0);
12420 break;
12421 case OPC_MUL_PS:
12422 check_ps(ctx);
12424 TCGv_i64 fp0 = tcg_temp_new_i64();
12425 TCGv_i64 fp1 = tcg_temp_new_i64();
12427 gen_load_fpr64(ctx, fp0, fs);
12428 gen_load_fpr64(ctx, fp1, ft);
12429 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
12430 tcg_temp_free_i64(fp1);
12431 gen_store_fpr64(ctx, fp0, fd);
12432 tcg_temp_free_i64(fp0);
12434 break;
12435 case OPC_ABS_PS:
12436 check_ps(ctx);
12438 TCGv_i64 fp0 = tcg_temp_new_i64();
12440 gen_load_fpr64(ctx, fp0, fs);
12441 gen_helper_float_abs_ps(fp0, fp0);
12442 gen_store_fpr64(ctx, fp0, fd);
12443 tcg_temp_free_i64(fp0);
12445 break;
12446 case OPC_MOV_PS:
12447 check_ps(ctx);
12449 TCGv_i64 fp0 = tcg_temp_new_i64();
12451 gen_load_fpr64(ctx, fp0, fs);
12452 gen_store_fpr64(ctx, fp0, fd);
12453 tcg_temp_free_i64(fp0);
12455 break;
12456 case OPC_NEG_PS:
12457 check_ps(ctx);
12459 TCGv_i64 fp0 = tcg_temp_new_i64();
12461 gen_load_fpr64(ctx, fp0, fs);
12462 gen_helper_float_chs_ps(fp0, fp0);
12463 gen_store_fpr64(ctx, fp0, fd);
12464 tcg_temp_free_i64(fp0);
12466 break;
12467 case OPC_MOVCF_PS:
12468 check_ps(ctx);
12469 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
12470 break;
12471 case OPC_MOVZ_PS:
12472 check_ps(ctx);
12474 TCGLabel *l1 = gen_new_label();
12475 TCGv_i64 fp0;
12477 if (ft != 0) {
12478 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
12480 fp0 = tcg_temp_new_i64();
12481 gen_load_fpr64(ctx, fp0, fs);
12482 gen_store_fpr64(ctx, fp0, fd);
12483 tcg_temp_free_i64(fp0);
12484 gen_set_label(l1);
12486 break;
12487 case OPC_MOVN_PS:
12488 check_ps(ctx);
12490 TCGLabel *l1 = gen_new_label();
12491 TCGv_i64 fp0;
12493 if (ft != 0) {
12494 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12495 fp0 = tcg_temp_new_i64();
12496 gen_load_fpr64(ctx, fp0, fs);
12497 gen_store_fpr64(ctx, fp0, fd);
12498 tcg_temp_free_i64(fp0);
12499 gen_set_label(l1);
12502 break;
12503 case OPC_ADDR_PS:
12504 check_ps(ctx);
12506 TCGv_i64 fp0 = tcg_temp_new_i64();
12507 TCGv_i64 fp1 = tcg_temp_new_i64();
12509 gen_load_fpr64(ctx, fp0, ft);
12510 gen_load_fpr64(ctx, fp1, fs);
12511 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
12512 tcg_temp_free_i64(fp1);
12513 gen_store_fpr64(ctx, fp0, fd);
12514 tcg_temp_free_i64(fp0);
12516 break;
12517 case OPC_MULR_PS:
12518 check_ps(ctx);
12520 TCGv_i64 fp0 = tcg_temp_new_i64();
12521 TCGv_i64 fp1 = tcg_temp_new_i64();
12523 gen_load_fpr64(ctx, fp0, ft);
12524 gen_load_fpr64(ctx, fp1, fs);
12525 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
12526 tcg_temp_free_i64(fp1);
12527 gen_store_fpr64(ctx, fp0, fd);
12528 tcg_temp_free_i64(fp0);
12530 break;
12531 case OPC_RECIP2_PS:
12532 check_ps(ctx);
12534 TCGv_i64 fp0 = tcg_temp_new_i64();
12535 TCGv_i64 fp1 = tcg_temp_new_i64();
12537 gen_load_fpr64(ctx, fp0, fs);
12538 gen_load_fpr64(ctx, fp1, ft);
12539 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
12540 tcg_temp_free_i64(fp1);
12541 gen_store_fpr64(ctx, fp0, fd);
12542 tcg_temp_free_i64(fp0);
12544 break;
12545 case OPC_RECIP1_PS:
12546 check_ps(ctx);
12548 TCGv_i64 fp0 = tcg_temp_new_i64();
12550 gen_load_fpr64(ctx, fp0, fs);
12551 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
12552 gen_store_fpr64(ctx, fp0, fd);
12553 tcg_temp_free_i64(fp0);
12555 break;
12556 case OPC_RSQRT1_PS:
12557 check_ps(ctx);
12559 TCGv_i64 fp0 = tcg_temp_new_i64();
12561 gen_load_fpr64(ctx, fp0, fs);
12562 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
12563 gen_store_fpr64(ctx, fp0, fd);
12564 tcg_temp_free_i64(fp0);
12566 break;
12567 case OPC_RSQRT2_PS:
12568 check_ps(ctx);
12570 TCGv_i64 fp0 = tcg_temp_new_i64();
12571 TCGv_i64 fp1 = tcg_temp_new_i64();
12573 gen_load_fpr64(ctx, fp0, fs);
12574 gen_load_fpr64(ctx, fp1, ft);
12575 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
12576 tcg_temp_free_i64(fp1);
12577 gen_store_fpr64(ctx, fp0, fd);
12578 tcg_temp_free_i64(fp0);
12580 break;
12581 case OPC_CVT_S_PU:
12582 check_cp1_64bitmode(ctx);
12584 TCGv_i32 fp0 = tcg_temp_new_i32();
12586 gen_load_fpr32h(ctx, fp0, fs);
12587 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
12588 gen_store_fpr32(ctx, fp0, fd);
12589 tcg_temp_free_i32(fp0);
12591 break;
12592 case OPC_CVT_PW_PS:
12593 check_ps(ctx);
12595 TCGv_i64 fp0 = tcg_temp_new_i64();
12597 gen_load_fpr64(ctx, fp0, fs);
12598 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
12599 gen_store_fpr64(ctx, fp0, fd);
12600 tcg_temp_free_i64(fp0);
12602 break;
12603 case OPC_CVT_S_PL:
12604 check_cp1_64bitmode(ctx);
12606 TCGv_i32 fp0 = tcg_temp_new_i32();
12608 gen_load_fpr32(ctx, fp0, fs);
12609 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
12610 gen_store_fpr32(ctx, fp0, fd);
12611 tcg_temp_free_i32(fp0);
12613 break;
12614 case OPC_PLL_PS:
12615 check_ps(ctx);
12617 TCGv_i32 fp0 = tcg_temp_new_i32();
12618 TCGv_i32 fp1 = tcg_temp_new_i32();
12620 gen_load_fpr32(ctx, fp0, fs);
12621 gen_load_fpr32(ctx, fp1, ft);
12622 gen_store_fpr32h(ctx, fp0, fd);
12623 gen_store_fpr32(ctx, fp1, fd);
12624 tcg_temp_free_i32(fp0);
12625 tcg_temp_free_i32(fp1);
12627 break;
12628 case OPC_PLU_PS:
12629 check_ps(ctx);
12631 TCGv_i32 fp0 = tcg_temp_new_i32();
12632 TCGv_i32 fp1 = tcg_temp_new_i32();
12634 gen_load_fpr32(ctx, fp0, fs);
12635 gen_load_fpr32h(ctx, fp1, ft);
12636 gen_store_fpr32(ctx, fp1, fd);
12637 gen_store_fpr32h(ctx, fp0, fd);
12638 tcg_temp_free_i32(fp0);
12639 tcg_temp_free_i32(fp1);
12641 break;
12642 case OPC_PUL_PS:
12643 check_ps(ctx);
12645 TCGv_i32 fp0 = tcg_temp_new_i32();
12646 TCGv_i32 fp1 = tcg_temp_new_i32();
12648 gen_load_fpr32h(ctx, fp0, fs);
12649 gen_load_fpr32(ctx, fp1, ft);
12650 gen_store_fpr32(ctx, fp1, fd);
12651 gen_store_fpr32h(ctx, fp0, fd);
12652 tcg_temp_free_i32(fp0);
12653 tcg_temp_free_i32(fp1);
12655 break;
12656 case OPC_PUU_PS:
12657 check_ps(ctx);
12659 TCGv_i32 fp0 = tcg_temp_new_i32();
12660 TCGv_i32 fp1 = tcg_temp_new_i32();
12662 gen_load_fpr32h(ctx, fp0, fs);
12663 gen_load_fpr32h(ctx, fp1, ft);
12664 gen_store_fpr32(ctx, fp1, fd);
12665 gen_store_fpr32h(ctx, fp0, fd);
12666 tcg_temp_free_i32(fp0);
12667 tcg_temp_free_i32(fp1);
12669 break;
12670 case OPC_CMP_F_PS:
12671 case OPC_CMP_UN_PS:
12672 case OPC_CMP_EQ_PS:
12673 case OPC_CMP_UEQ_PS:
12674 case OPC_CMP_OLT_PS:
12675 case OPC_CMP_ULT_PS:
12676 case OPC_CMP_OLE_PS:
12677 case OPC_CMP_ULE_PS:
12678 case OPC_CMP_SF_PS:
12679 case OPC_CMP_NGLE_PS:
12680 case OPC_CMP_SEQ_PS:
12681 case OPC_CMP_NGL_PS:
12682 case OPC_CMP_LT_PS:
12683 case OPC_CMP_NGE_PS:
12684 case OPC_CMP_LE_PS:
12685 case OPC_CMP_NGT_PS:
12686 if (ctx->opcode & (1 << 6)) {
12687 gen_cmpabs_ps(ctx, func - 48, ft, fs, cc);
12688 } else {
12689 gen_cmp_ps(ctx, func - 48, ft, fs, cc);
12691 break;
12692 default:
12693 MIPS_INVAL("farith");
12694 gen_reserved_instruction(ctx);
12695 return;
12699 /* Coprocessor 3 (FPU) */
12700 static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
12701 int fd, int fs, int base, int index)
12703 TCGv t0 = tcg_temp_new();
12705 if (base == 0) {
12706 gen_load_gpr(t0, index);
12707 } else if (index == 0) {
12708 gen_load_gpr(t0, base);
12709 } else {
12710 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
12713 * Don't do NOP if destination is zero: we must perform the actual
12714 * memory access.
12716 switch (opc) {
12717 case OPC_LWXC1:
12718 check_cop1x(ctx);
12720 TCGv_i32 fp0 = tcg_temp_new_i32();
12722 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
12723 tcg_gen_trunc_tl_i32(fp0, t0);
12724 gen_store_fpr32(ctx, fp0, fd);
12725 tcg_temp_free_i32(fp0);
12727 break;
12728 case OPC_LDXC1:
12729 check_cop1x(ctx);
12730 check_cp1_registers(ctx, fd);
12732 TCGv_i64 fp0 = tcg_temp_new_i64();
12733 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12734 gen_store_fpr64(ctx, fp0, fd);
12735 tcg_temp_free_i64(fp0);
12737 break;
12738 case OPC_LUXC1:
12739 check_cp1_64bitmode(ctx);
12740 tcg_gen_andi_tl(t0, t0, ~0x7);
12742 TCGv_i64 fp0 = tcg_temp_new_i64();
12744 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12745 gen_store_fpr64(ctx, fp0, fd);
12746 tcg_temp_free_i64(fp0);
12748 break;
12749 case OPC_SWXC1:
12750 check_cop1x(ctx);
12752 TCGv_i32 fp0 = tcg_temp_new_i32();
12753 gen_load_fpr32(ctx, fp0, fs);
12754 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
12755 tcg_temp_free_i32(fp0);
12757 break;
12758 case OPC_SDXC1:
12759 check_cop1x(ctx);
12760 check_cp1_registers(ctx, fs);
12762 TCGv_i64 fp0 = tcg_temp_new_i64();
12763 gen_load_fpr64(ctx, fp0, fs);
12764 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12765 tcg_temp_free_i64(fp0);
12767 break;
12768 case OPC_SUXC1:
12769 check_cp1_64bitmode(ctx);
12770 tcg_gen_andi_tl(t0, t0, ~0x7);
12772 TCGv_i64 fp0 = tcg_temp_new_i64();
12773 gen_load_fpr64(ctx, fp0, fs);
12774 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12775 tcg_temp_free_i64(fp0);
12777 break;
12779 tcg_temp_free(t0);
12782 static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
12783 int fd, int fr, int fs, int ft)
12785 switch (opc) {
12786 case OPC_ALNV_PS:
12787 check_ps(ctx);
12789 TCGv t0 = tcg_temp_local_new();
12790 TCGv_i32 fp = tcg_temp_new_i32();
12791 TCGv_i32 fph = tcg_temp_new_i32();
12792 TCGLabel *l1 = gen_new_label();
12793 TCGLabel *l2 = gen_new_label();
12795 gen_load_gpr(t0, fr);
12796 tcg_gen_andi_tl(t0, t0, 0x7);
12798 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
12799 gen_load_fpr32(ctx, fp, fs);
12800 gen_load_fpr32h(ctx, fph, fs);
12801 gen_store_fpr32(ctx, fp, fd);
12802 gen_store_fpr32h(ctx, fph, fd);
12803 tcg_gen_br(l2);
12804 gen_set_label(l1);
12805 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
12806 tcg_temp_free(t0);
12807 #ifdef TARGET_WORDS_BIGENDIAN
12808 gen_load_fpr32(ctx, fp, fs);
12809 gen_load_fpr32h(ctx, fph, ft);
12810 gen_store_fpr32h(ctx, fp, fd);
12811 gen_store_fpr32(ctx, fph, fd);
12812 #else
12813 gen_load_fpr32h(ctx, fph, fs);
12814 gen_load_fpr32(ctx, fp, ft);
12815 gen_store_fpr32(ctx, fph, fd);
12816 gen_store_fpr32h(ctx, fp, fd);
12817 #endif
12818 gen_set_label(l2);
12819 tcg_temp_free_i32(fp);
12820 tcg_temp_free_i32(fph);
12822 break;
12823 case OPC_MADD_S:
12824 check_cop1x(ctx);
12826 TCGv_i32 fp0 = tcg_temp_new_i32();
12827 TCGv_i32 fp1 = tcg_temp_new_i32();
12828 TCGv_i32 fp2 = tcg_temp_new_i32();
12830 gen_load_fpr32(ctx, fp0, fs);
12831 gen_load_fpr32(ctx, fp1, ft);
12832 gen_load_fpr32(ctx, fp2, fr);
12833 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
12834 tcg_temp_free_i32(fp0);
12835 tcg_temp_free_i32(fp1);
12836 gen_store_fpr32(ctx, fp2, fd);
12837 tcg_temp_free_i32(fp2);
12839 break;
12840 case OPC_MADD_D:
12841 check_cop1x(ctx);
12842 check_cp1_registers(ctx, fd | fs | ft | fr);
12844 TCGv_i64 fp0 = tcg_temp_new_i64();
12845 TCGv_i64 fp1 = tcg_temp_new_i64();
12846 TCGv_i64 fp2 = tcg_temp_new_i64();
12848 gen_load_fpr64(ctx, fp0, fs);
12849 gen_load_fpr64(ctx, fp1, ft);
12850 gen_load_fpr64(ctx, fp2, fr);
12851 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
12852 tcg_temp_free_i64(fp0);
12853 tcg_temp_free_i64(fp1);
12854 gen_store_fpr64(ctx, fp2, fd);
12855 tcg_temp_free_i64(fp2);
12857 break;
12858 case OPC_MADD_PS:
12859 check_ps(ctx);
12861 TCGv_i64 fp0 = tcg_temp_new_i64();
12862 TCGv_i64 fp1 = tcg_temp_new_i64();
12863 TCGv_i64 fp2 = tcg_temp_new_i64();
12865 gen_load_fpr64(ctx, fp0, fs);
12866 gen_load_fpr64(ctx, fp1, ft);
12867 gen_load_fpr64(ctx, fp2, fr);
12868 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
12869 tcg_temp_free_i64(fp0);
12870 tcg_temp_free_i64(fp1);
12871 gen_store_fpr64(ctx, fp2, fd);
12872 tcg_temp_free_i64(fp2);
12874 break;
12875 case OPC_MSUB_S:
12876 check_cop1x(ctx);
12878 TCGv_i32 fp0 = tcg_temp_new_i32();
12879 TCGv_i32 fp1 = tcg_temp_new_i32();
12880 TCGv_i32 fp2 = tcg_temp_new_i32();
12882 gen_load_fpr32(ctx, fp0, fs);
12883 gen_load_fpr32(ctx, fp1, ft);
12884 gen_load_fpr32(ctx, fp2, fr);
12885 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
12886 tcg_temp_free_i32(fp0);
12887 tcg_temp_free_i32(fp1);
12888 gen_store_fpr32(ctx, fp2, fd);
12889 tcg_temp_free_i32(fp2);
12891 break;
12892 case OPC_MSUB_D:
12893 check_cop1x(ctx);
12894 check_cp1_registers(ctx, fd | fs | ft | fr);
12896 TCGv_i64 fp0 = tcg_temp_new_i64();
12897 TCGv_i64 fp1 = tcg_temp_new_i64();
12898 TCGv_i64 fp2 = tcg_temp_new_i64();
12900 gen_load_fpr64(ctx, fp0, fs);
12901 gen_load_fpr64(ctx, fp1, ft);
12902 gen_load_fpr64(ctx, fp2, fr);
12903 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
12904 tcg_temp_free_i64(fp0);
12905 tcg_temp_free_i64(fp1);
12906 gen_store_fpr64(ctx, fp2, fd);
12907 tcg_temp_free_i64(fp2);
12909 break;
12910 case OPC_MSUB_PS:
12911 check_ps(ctx);
12913 TCGv_i64 fp0 = tcg_temp_new_i64();
12914 TCGv_i64 fp1 = tcg_temp_new_i64();
12915 TCGv_i64 fp2 = tcg_temp_new_i64();
12917 gen_load_fpr64(ctx, fp0, fs);
12918 gen_load_fpr64(ctx, fp1, ft);
12919 gen_load_fpr64(ctx, fp2, fr);
12920 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
12921 tcg_temp_free_i64(fp0);
12922 tcg_temp_free_i64(fp1);
12923 gen_store_fpr64(ctx, fp2, fd);
12924 tcg_temp_free_i64(fp2);
12926 break;
12927 case OPC_NMADD_S:
12928 check_cop1x(ctx);
12930 TCGv_i32 fp0 = tcg_temp_new_i32();
12931 TCGv_i32 fp1 = tcg_temp_new_i32();
12932 TCGv_i32 fp2 = tcg_temp_new_i32();
12934 gen_load_fpr32(ctx, fp0, fs);
12935 gen_load_fpr32(ctx, fp1, ft);
12936 gen_load_fpr32(ctx, fp2, fr);
12937 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
12938 tcg_temp_free_i32(fp0);
12939 tcg_temp_free_i32(fp1);
12940 gen_store_fpr32(ctx, fp2, fd);
12941 tcg_temp_free_i32(fp2);
12943 break;
12944 case OPC_NMADD_D:
12945 check_cop1x(ctx);
12946 check_cp1_registers(ctx, fd | fs | ft | fr);
12948 TCGv_i64 fp0 = tcg_temp_new_i64();
12949 TCGv_i64 fp1 = tcg_temp_new_i64();
12950 TCGv_i64 fp2 = tcg_temp_new_i64();
12952 gen_load_fpr64(ctx, fp0, fs);
12953 gen_load_fpr64(ctx, fp1, ft);
12954 gen_load_fpr64(ctx, fp2, fr);
12955 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
12956 tcg_temp_free_i64(fp0);
12957 tcg_temp_free_i64(fp1);
12958 gen_store_fpr64(ctx, fp2, fd);
12959 tcg_temp_free_i64(fp2);
12961 break;
12962 case OPC_NMADD_PS:
12963 check_ps(ctx);
12965 TCGv_i64 fp0 = tcg_temp_new_i64();
12966 TCGv_i64 fp1 = tcg_temp_new_i64();
12967 TCGv_i64 fp2 = tcg_temp_new_i64();
12969 gen_load_fpr64(ctx, fp0, fs);
12970 gen_load_fpr64(ctx, fp1, ft);
12971 gen_load_fpr64(ctx, fp2, fr);
12972 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
12973 tcg_temp_free_i64(fp0);
12974 tcg_temp_free_i64(fp1);
12975 gen_store_fpr64(ctx, fp2, fd);
12976 tcg_temp_free_i64(fp2);
12978 break;
12979 case OPC_NMSUB_S:
12980 check_cop1x(ctx);
12982 TCGv_i32 fp0 = tcg_temp_new_i32();
12983 TCGv_i32 fp1 = tcg_temp_new_i32();
12984 TCGv_i32 fp2 = tcg_temp_new_i32();
12986 gen_load_fpr32(ctx, fp0, fs);
12987 gen_load_fpr32(ctx, fp1, ft);
12988 gen_load_fpr32(ctx, fp2, fr);
12989 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
12990 tcg_temp_free_i32(fp0);
12991 tcg_temp_free_i32(fp1);
12992 gen_store_fpr32(ctx, fp2, fd);
12993 tcg_temp_free_i32(fp2);
12995 break;
12996 case OPC_NMSUB_D:
12997 check_cop1x(ctx);
12998 check_cp1_registers(ctx, fd | fs | ft | fr);
13000 TCGv_i64 fp0 = tcg_temp_new_i64();
13001 TCGv_i64 fp1 = tcg_temp_new_i64();
13002 TCGv_i64 fp2 = tcg_temp_new_i64();
13004 gen_load_fpr64(ctx, fp0, fs);
13005 gen_load_fpr64(ctx, fp1, ft);
13006 gen_load_fpr64(ctx, fp2, fr);
13007 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
13008 tcg_temp_free_i64(fp0);
13009 tcg_temp_free_i64(fp1);
13010 gen_store_fpr64(ctx, fp2, fd);
13011 tcg_temp_free_i64(fp2);
13013 break;
13014 case OPC_NMSUB_PS:
13015 check_ps(ctx);
13017 TCGv_i64 fp0 = tcg_temp_new_i64();
13018 TCGv_i64 fp1 = tcg_temp_new_i64();
13019 TCGv_i64 fp2 = tcg_temp_new_i64();
13021 gen_load_fpr64(ctx, fp0, fs);
13022 gen_load_fpr64(ctx, fp1, ft);
13023 gen_load_fpr64(ctx, fp2, fr);
13024 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
13025 tcg_temp_free_i64(fp0);
13026 tcg_temp_free_i64(fp1);
13027 gen_store_fpr64(ctx, fp2, fd);
13028 tcg_temp_free_i64(fp2);
13030 break;
13031 default:
13032 MIPS_INVAL("flt3_arith");
13033 gen_reserved_instruction(ctx);
13034 return;
13038 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
13040 TCGv t0;
13042 #if !defined(CONFIG_USER_ONLY)
13044 * The Linux kernel will emulate rdhwr if it's not supported natively.
13045 * Therefore only check the ISA in system mode.
13047 check_insn(ctx, ISA_MIPS_R2);
13048 #endif
13049 t0 = tcg_temp_new();
13051 switch (rd) {
13052 case 0:
13053 gen_helper_rdhwr_cpunum(t0, cpu_env);
13054 gen_store_gpr(t0, rt);
13055 break;
13056 case 1:
13057 gen_helper_rdhwr_synci_step(t0, cpu_env);
13058 gen_store_gpr(t0, rt);
13059 break;
13060 case 2:
13061 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
13062 gen_io_start();
13064 gen_helper_rdhwr_cc(t0, cpu_env);
13065 gen_store_gpr(t0, rt);
13067 * Break the TB to be able to take timer interrupts immediately
13068 * after reading count. DISAS_STOP isn't sufficient, we need to ensure
13069 * we break completely out of translated code.
13071 gen_save_pc(ctx->base.pc_next + 4);
13072 ctx->base.is_jmp = DISAS_EXIT;
13073 break;
13074 case 3:
13075 gen_helper_rdhwr_ccres(t0, cpu_env);
13076 gen_store_gpr(t0, rt);
13077 break;
13078 case 4:
13079 check_insn(ctx, ISA_MIPS_R6);
13080 if (sel != 0) {
13082 * Performance counter registers are not implemented other than
13083 * control register 0.
13085 generate_exception(ctx, EXCP_RI);
13087 gen_helper_rdhwr_performance(t0, cpu_env);
13088 gen_store_gpr(t0, rt);
13089 break;
13090 case 5:
13091 check_insn(ctx, ISA_MIPS_R6);
13092 gen_helper_rdhwr_xnp(t0, cpu_env);
13093 gen_store_gpr(t0, rt);
13094 break;
13095 case 29:
13096 #if defined(CONFIG_USER_ONLY)
13097 tcg_gen_ld_tl(t0, cpu_env,
13098 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
13099 gen_store_gpr(t0, rt);
13100 break;
13101 #else
13102 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
13103 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
13104 tcg_gen_ld_tl(t0, cpu_env,
13105 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
13106 gen_store_gpr(t0, rt);
13107 } else {
13108 gen_reserved_instruction(ctx);
13110 break;
13111 #endif
13112 default: /* Invalid */
13113 MIPS_INVAL("rdhwr");
13114 gen_reserved_instruction(ctx);
13115 break;
13117 tcg_temp_free(t0);
13120 static inline void clear_branch_hflags(DisasContext *ctx)
13122 ctx->hflags &= ~MIPS_HFLAG_BMASK;
13123 if (ctx->base.is_jmp == DISAS_NEXT) {
13124 save_cpu_state(ctx, 0);
13125 } else {
13127 * It is not safe to save ctx->hflags as hflags may be changed
13128 * in execution time by the instruction in delay / forbidden slot.
13130 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
13134 static void gen_branch(DisasContext *ctx, int insn_bytes)
13136 if (ctx->hflags & MIPS_HFLAG_BMASK) {
13137 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
13138 /* Branches completion */
13139 clear_branch_hflags(ctx);
13140 ctx->base.is_jmp = DISAS_NORETURN;
13141 /* FIXME: Need to clear can_do_io. */
13142 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
13143 case MIPS_HFLAG_FBNSLOT:
13144 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
13145 break;
13146 case MIPS_HFLAG_B:
13147 /* unconditional branch */
13148 if (proc_hflags & MIPS_HFLAG_BX) {
13149 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
13151 gen_goto_tb(ctx, 0, ctx->btarget);
13152 break;
13153 case MIPS_HFLAG_BL:
13154 /* blikely taken case */
13155 gen_goto_tb(ctx, 0, ctx->btarget);
13156 break;
13157 case MIPS_HFLAG_BC:
13158 /* Conditional branch */
13160 TCGLabel *l1 = gen_new_label();
13162 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
13163 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
13164 gen_set_label(l1);
13165 gen_goto_tb(ctx, 0, ctx->btarget);
13167 break;
13168 case MIPS_HFLAG_BR:
13169 /* unconditional branch to register */
13170 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
13171 TCGv t0 = tcg_temp_new();
13172 TCGv_i32 t1 = tcg_temp_new_i32();
13174 tcg_gen_andi_tl(t0, btarget, 0x1);
13175 tcg_gen_trunc_tl_i32(t1, t0);
13176 tcg_temp_free(t0);
13177 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
13178 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
13179 tcg_gen_or_i32(hflags, hflags, t1);
13180 tcg_temp_free_i32(t1);
13182 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
13183 } else {
13184 tcg_gen_mov_tl(cpu_PC, btarget);
13186 if (ctx->base.singlestep_enabled) {
13187 save_cpu_state(ctx, 0);
13188 gen_helper_raise_exception_debug(cpu_env);
13190 tcg_gen_lookup_and_goto_ptr();
13191 break;
13192 default:
13193 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
13194 abort();
13199 /* Compact Branches */
13200 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
13201 int rs, int rt, int32_t offset)
13203 int bcond_compute = 0;
13204 TCGv t0 = tcg_temp_new();
13205 TCGv t1 = tcg_temp_new();
13206 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
13208 if (ctx->hflags & MIPS_HFLAG_BMASK) {
13209 #ifdef MIPS_DEBUG_DISAS
13210 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
13211 "\n", ctx->base.pc_next);
13212 #endif
13213 gen_reserved_instruction(ctx);
13214 goto out;
13217 /* Load needed operands and calculate btarget */
13218 switch (opc) {
13219 /* compact branch */
13220 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13221 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13222 gen_load_gpr(t0, rs);
13223 gen_load_gpr(t1, rt);
13224 bcond_compute = 1;
13225 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13226 if (rs <= rt && rs == 0) {
13227 /* OPC_BEQZALC, OPC_BNEZALC */
13228 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13230 break;
13231 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13232 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13233 gen_load_gpr(t0, rs);
13234 gen_load_gpr(t1, rt);
13235 bcond_compute = 1;
13236 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13237 break;
13238 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13239 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13240 if (rs == 0 || rs == rt) {
13241 /* OPC_BLEZALC, OPC_BGEZALC */
13242 /* OPC_BGTZALC, OPC_BLTZALC */
13243 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13245 gen_load_gpr(t0, rs);
13246 gen_load_gpr(t1, rt);
13247 bcond_compute = 1;
13248 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13249 break;
13250 case OPC_BC:
13251 case OPC_BALC:
13252 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13253 break;
13254 case OPC_BEQZC:
13255 case OPC_BNEZC:
13256 if (rs != 0) {
13257 /* OPC_BEQZC, OPC_BNEZC */
13258 gen_load_gpr(t0, rs);
13259 bcond_compute = 1;
13260 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13261 } else {
13262 /* OPC_JIC, OPC_JIALC */
13263 TCGv tbase = tcg_temp_new();
13264 TCGv toffset = tcg_temp_new();
13266 gen_load_gpr(tbase, rt);
13267 tcg_gen_movi_tl(toffset, offset);
13268 gen_op_addr_add(ctx, btarget, tbase, toffset);
13269 tcg_temp_free(tbase);
13270 tcg_temp_free(toffset);
13272 break;
13273 default:
13274 MIPS_INVAL("Compact branch/jump");
13275 gen_reserved_instruction(ctx);
13276 goto out;
13279 if (bcond_compute == 0) {
13280 /* Uncoditional compact branch */
13281 switch (opc) {
13282 case OPC_JIALC:
13283 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13284 /* Fallthrough */
13285 case OPC_JIC:
13286 ctx->hflags |= MIPS_HFLAG_BR;
13287 break;
13288 case OPC_BALC:
13289 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13290 /* Fallthrough */
13291 case OPC_BC:
13292 ctx->hflags |= MIPS_HFLAG_B;
13293 break;
13294 default:
13295 MIPS_INVAL("Compact branch/jump");
13296 gen_reserved_instruction(ctx);
13297 goto out;
13300 /* Generating branch here as compact branches don't have delay slot */
13301 gen_branch(ctx, 4);
13302 } else {
13303 /* Conditional compact branch */
13304 TCGLabel *fs = gen_new_label();
13305 save_cpu_state(ctx, 0);
13307 switch (opc) {
13308 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13309 if (rs == 0 && rt != 0) {
13310 /* OPC_BLEZALC */
13311 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13312 } else if (rs != 0 && rt != 0 && rs == rt) {
13313 /* OPC_BGEZALC */
13314 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13315 } else {
13316 /* OPC_BGEUC */
13317 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
13319 break;
13320 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13321 if (rs == 0 && rt != 0) {
13322 /* OPC_BGTZALC */
13323 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13324 } else if (rs != 0 && rt != 0 && rs == rt) {
13325 /* OPC_BLTZALC */
13326 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13327 } else {
13328 /* OPC_BLTUC */
13329 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
13331 break;
13332 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13333 if (rs == 0 && rt != 0) {
13334 /* OPC_BLEZC */
13335 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13336 } else if (rs != 0 && rt != 0 && rs == rt) {
13337 /* OPC_BGEZC */
13338 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13339 } else {
13340 /* OPC_BGEC */
13341 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
13343 break;
13344 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13345 if (rs == 0 && rt != 0) {
13346 /* OPC_BGTZC */
13347 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13348 } else if (rs != 0 && rt != 0 && rs == rt) {
13349 /* OPC_BLTZC */
13350 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13351 } else {
13352 /* OPC_BLTC */
13353 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
13355 break;
13356 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13357 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13358 if (rs >= rt) {
13359 /* OPC_BOVC, OPC_BNVC */
13360 TCGv t2 = tcg_temp_new();
13361 TCGv t3 = tcg_temp_new();
13362 TCGv t4 = tcg_temp_new();
13363 TCGv input_overflow = tcg_temp_new();
13365 gen_load_gpr(t0, rs);
13366 gen_load_gpr(t1, rt);
13367 tcg_gen_ext32s_tl(t2, t0);
13368 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
13369 tcg_gen_ext32s_tl(t3, t1);
13370 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
13371 tcg_gen_or_tl(input_overflow, input_overflow, t4);
13373 tcg_gen_add_tl(t4, t2, t3);
13374 tcg_gen_ext32s_tl(t4, t4);
13375 tcg_gen_xor_tl(t2, t2, t3);
13376 tcg_gen_xor_tl(t3, t4, t3);
13377 tcg_gen_andc_tl(t2, t3, t2);
13378 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
13379 tcg_gen_or_tl(t4, t4, input_overflow);
13380 if (opc == OPC_BOVC) {
13381 /* OPC_BOVC */
13382 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
13383 } else {
13384 /* OPC_BNVC */
13385 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
13387 tcg_temp_free(input_overflow);
13388 tcg_temp_free(t4);
13389 tcg_temp_free(t3);
13390 tcg_temp_free(t2);
13391 } else if (rs < rt && rs == 0) {
13392 /* OPC_BEQZALC, OPC_BNEZALC */
13393 if (opc == OPC_BEQZALC) {
13394 /* OPC_BEQZALC */
13395 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
13396 } else {
13397 /* OPC_BNEZALC */
13398 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
13400 } else {
13401 /* OPC_BEQC, OPC_BNEC */
13402 if (opc == OPC_BEQC) {
13403 /* OPC_BEQC */
13404 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
13405 } else {
13406 /* OPC_BNEC */
13407 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
13410 break;
13411 case OPC_BEQZC:
13412 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
13413 break;
13414 case OPC_BNEZC:
13415 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
13416 break;
13417 default:
13418 MIPS_INVAL("Compact conditional branch/jump");
13419 gen_reserved_instruction(ctx);
13420 goto out;
13423 /* Generating branch here as compact branches don't have delay slot */
13424 gen_goto_tb(ctx, 1, ctx->btarget);
13425 gen_set_label(fs);
13427 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
13430 out:
13431 tcg_temp_free(t0);
13432 tcg_temp_free(t1);
13435 /* ISA extensions (ASEs) */
13436 /* MIPS16 extension to MIPS32 */
13438 /* MIPS16 major opcodes */
13439 enum {
13440 M16_OPC_ADDIUSP = 0x00,
13441 M16_OPC_ADDIUPC = 0x01,
13442 M16_OPC_B = 0x02,
13443 M16_OPC_JAL = 0x03,
13444 M16_OPC_BEQZ = 0x04,
13445 M16_OPC_BNEQZ = 0x05,
13446 M16_OPC_SHIFT = 0x06,
13447 M16_OPC_LD = 0x07,
13448 M16_OPC_RRIA = 0x08,
13449 M16_OPC_ADDIU8 = 0x09,
13450 M16_OPC_SLTI = 0x0a,
13451 M16_OPC_SLTIU = 0x0b,
13452 M16_OPC_I8 = 0x0c,
13453 M16_OPC_LI = 0x0d,
13454 M16_OPC_CMPI = 0x0e,
13455 M16_OPC_SD = 0x0f,
13456 M16_OPC_LB = 0x10,
13457 M16_OPC_LH = 0x11,
13458 M16_OPC_LWSP = 0x12,
13459 M16_OPC_LW = 0x13,
13460 M16_OPC_LBU = 0x14,
13461 M16_OPC_LHU = 0x15,
13462 M16_OPC_LWPC = 0x16,
13463 M16_OPC_LWU = 0x17,
13464 M16_OPC_SB = 0x18,
13465 M16_OPC_SH = 0x19,
13466 M16_OPC_SWSP = 0x1a,
13467 M16_OPC_SW = 0x1b,
13468 M16_OPC_RRR = 0x1c,
13469 M16_OPC_RR = 0x1d,
13470 M16_OPC_EXTEND = 0x1e,
13471 M16_OPC_I64 = 0x1f
13474 /* I8 funct field */
13475 enum {
13476 I8_BTEQZ = 0x0,
13477 I8_BTNEZ = 0x1,
13478 I8_SWRASP = 0x2,
13479 I8_ADJSP = 0x3,
13480 I8_SVRS = 0x4,
13481 I8_MOV32R = 0x5,
13482 I8_MOVR32 = 0x7
13485 /* RRR f field */
13486 enum {
13487 RRR_DADDU = 0x0,
13488 RRR_ADDU = 0x1,
13489 RRR_DSUBU = 0x2,
13490 RRR_SUBU = 0x3
13493 /* RR funct field */
13494 enum {
13495 RR_JR = 0x00,
13496 RR_SDBBP = 0x01,
13497 RR_SLT = 0x02,
13498 RR_SLTU = 0x03,
13499 RR_SLLV = 0x04,
13500 RR_BREAK = 0x05,
13501 RR_SRLV = 0x06,
13502 RR_SRAV = 0x07,
13503 RR_DSRL = 0x08,
13504 RR_CMP = 0x0a,
13505 RR_NEG = 0x0b,
13506 RR_AND = 0x0c,
13507 RR_OR = 0x0d,
13508 RR_XOR = 0x0e,
13509 RR_NOT = 0x0f,
13510 RR_MFHI = 0x10,
13511 RR_CNVT = 0x11,
13512 RR_MFLO = 0x12,
13513 RR_DSRA = 0x13,
13514 RR_DSLLV = 0x14,
13515 RR_DSRLV = 0x16,
13516 RR_DSRAV = 0x17,
13517 RR_MULT = 0x18,
13518 RR_MULTU = 0x19,
13519 RR_DIV = 0x1a,
13520 RR_DIVU = 0x1b,
13521 RR_DMULT = 0x1c,
13522 RR_DMULTU = 0x1d,
13523 RR_DDIV = 0x1e,
13524 RR_DDIVU = 0x1f
13527 /* I64 funct field */
13528 enum {
13529 I64_LDSP = 0x0,
13530 I64_SDSP = 0x1,
13531 I64_SDRASP = 0x2,
13532 I64_DADJSP = 0x3,
13533 I64_LDPC = 0x4,
13534 I64_DADDIU5 = 0x5,
13535 I64_DADDIUPC = 0x6,
13536 I64_DADDIUSP = 0x7
13539 /* RR ry field for CNVT */
13540 enum {
13541 RR_RY_CNVT_ZEB = 0x0,
13542 RR_RY_CNVT_ZEH = 0x1,
13543 RR_RY_CNVT_ZEW = 0x2,
13544 RR_RY_CNVT_SEB = 0x4,
13545 RR_RY_CNVT_SEH = 0x5,
13546 RR_RY_CNVT_SEW = 0x6,
13549 static int xlat(int r)
13551 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
13553 return map[r];
13556 static void gen_mips16_save(DisasContext *ctx,
13557 int xsregs, int aregs,
13558 int do_ra, int do_s0, int do_s1,
13559 int framesize)
13561 TCGv t0 = tcg_temp_new();
13562 TCGv t1 = tcg_temp_new();
13563 TCGv t2 = tcg_temp_new();
13564 int args, astatic;
13566 switch (aregs) {
13567 case 0:
13568 case 1:
13569 case 2:
13570 case 3:
13571 case 11:
13572 args = 0;
13573 break;
13574 case 4:
13575 case 5:
13576 case 6:
13577 case 7:
13578 args = 1;
13579 break;
13580 case 8:
13581 case 9:
13582 case 10:
13583 args = 2;
13584 break;
13585 case 12:
13586 case 13:
13587 args = 3;
13588 break;
13589 case 14:
13590 args = 4;
13591 break;
13592 default:
13593 gen_reserved_instruction(ctx);
13594 return;
13597 switch (args) {
13598 case 4:
13599 gen_base_offset_addr(ctx, t0, 29, 12);
13600 gen_load_gpr(t1, 7);
13601 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13602 /* Fall through */
13603 case 3:
13604 gen_base_offset_addr(ctx, t0, 29, 8);
13605 gen_load_gpr(t1, 6);
13606 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13607 /* Fall through */
13608 case 2:
13609 gen_base_offset_addr(ctx, t0, 29, 4);
13610 gen_load_gpr(t1, 5);
13611 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13612 /* Fall through */
13613 case 1:
13614 gen_base_offset_addr(ctx, t0, 29, 0);
13615 gen_load_gpr(t1, 4);
13616 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13619 gen_load_gpr(t0, 29);
13621 #define DECR_AND_STORE(reg) do { \
13622 tcg_gen_movi_tl(t2, -4); \
13623 gen_op_addr_add(ctx, t0, t0, t2); \
13624 gen_load_gpr(t1, reg); \
13625 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
13626 } while (0)
13628 if (do_ra) {
13629 DECR_AND_STORE(31);
13632 switch (xsregs) {
13633 case 7:
13634 DECR_AND_STORE(30);
13635 /* Fall through */
13636 case 6:
13637 DECR_AND_STORE(23);
13638 /* Fall through */
13639 case 5:
13640 DECR_AND_STORE(22);
13641 /* Fall through */
13642 case 4:
13643 DECR_AND_STORE(21);
13644 /* Fall through */
13645 case 3:
13646 DECR_AND_STORE(20);
13647 /* Fall through */
13648 case 2:
13649 DECR_AND_STORE(19);
13650 /* Fall through */
13651 case 1:
13652 DECR_AND_STORE(18);
13655 if (do_s1) {
13656 DECR_AND_STORE(17);
13658 if (do_s0) {
13659 DECR_AND_STORE(16);
13662 switch (aregs) {
13663 case 0:
13664 case 4:
13665 case 8:
13666 case 12:
13667 case 14:
13668 astatic = 0;
13669 break;
13670 case 1:
13671 case 5:
13672 case 9:
13673 case 13:
13674 astatic = 1;
13675 break;
13676 case 2:
13677 case 6:
13678 case 10:
13679 astatic = 2;
13680 break;
13681 case 3:
13682 case 7:
13683 astatic = 3;
13684 break;
13685 case 11:
13686 astatic = 4;
13687 break;
13688 default:
13689 gen_reserved_instruction(ctx);
13690 return;
13693 if (astatic > 0) {
13694 DECR_AND_STORE(7);
13695 if (astatic > 1) {
13696 DECR_AND_STORE(6);
13697 if (astatic > 2) {
13698 DECR_AND_STORE(5);
13699 if (astatic > 3) {
13700 DECR_AND_STORE(4);
13705 #undef DECR_AND_STORE
13707 tcg_gen_movi_tl(t2, -framesize);
13708 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13709 tcg_temp_free(t0);
13710 tcg_temp_free(t1);
13711 tcg_temp_free(t2);
13714 static void gen_mips16_restore(DisasContext *ctx,
13715 int xsregs, int aregs,
13716 int do_ra, int do_s0, int do_s1,
13717 int framesize)
13719 int astatic;
13720 TCGv t0 = tcg_temp_new();
13721 TCGv t1 = tcg_temp_new();
13722 TCGv t2 = tcg_temp_new();
13724 tcg_gen_movi_tl(t2, framesize);
13725 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
13727 #define DECR_AND_LOAD(reg) do { \
13728 tcg_gen_movi_tl(t2, -4); \
13729 gen_op_addr_add(ctx, t0, t0, t2); \
13730 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
13731 gen_store_gpr(t1, reg); \
13732 } while (0)
13734 if (do_ra) {
13735 DECR_AND_LOAD(31);
13738 switch (xsregs) {
13739 case 7:
13740 DECR_AND_LOAD(30);
13741 /* Fall through */
13742 case 6:
13743 DECR_AND_LOAD(23);
13744 /* Fall through */
13745 case 5:
13746 DECR_AND_LOAD(22);
13747 /* Fall through */
13748 case 4:
13749 DECR_AND_LOAD(21);
13750 /* Fall through */
13751 case 3:
13752 DECR_AND_LOAD(20);
13753 /* Fall through */
13754 case 2:
13755 DECR_AND_LOAD(19);
13756 /* Fall through */
13757 case 1:
13758 DECR_AND_LOAD(18);
13761 if (do_s1) {
13762 DECR_AND_LOAD(17);
13764 if (do_s0) {
13765 DECR_AND_LOAD(16);
13768 switch (aregs) {
13769 case 0:
13770 case 4:
13771 case 8:
13772 case 12:
13773 case 14:
13774 astatic = 0;
13775 break;
13776 case 1:
13777 case 5:
13778 case 9:
13779 case 13:
13780 astatic = 1;
13781 break;
13782 case 2:
13783 case 6:
13784 case 10:
13785 astatic = 2;
13786 break;
13787 case 3:
13788 case 7:
13789 astatic = 3;
13790 break;
13791 case 11:
13792 astatic = 4;
13793 break;
13794 default:
13795 gen_reserved_instruction(ctx);
13796 return;
13799 if (astatic > 0) {
13800 DECR_AND_LOAD(7);
13801 if (astatic > 1) {
13802 DECR_AND_LOAD(6);
13803 if (astatic > 2) {
13804 DECR_AND_LOAD(5);
13805 if (astatic > 3) {
13806 DECR_AND_LOAD(4);
13811 #undef DECR_AND_LOAD
13813 tcg_gen_movi_tl(t2, framesize);
13814 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13815 tcg_temp_free(t0);
13816 tcg_temp_free(t1);
13817 tcg_temp_free(t2);
13820 static void gen_addiupc(DisasContext *ctx, int rx, int imm,
13821 int is_64_bit, int extended)
13823 TCGv t0;
13825 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13826 gen_reserved_instruction(ctx);
13827 return;
13830 t0 = tcg_temp_new();
13832 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
13833 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
13834 if (!is_64_bit) {
13835 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13838 tcg_temp_free(t0);
13841 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
13842 int16_t offset)
13844 TCGv_i32 t0 = tcg_const_i32(op);
13845 TCGv t1 = tcg_temp_new();
13846 gen_base_offset_addr(ctx, t1, base, offset);
13847 gen_helper_cache(cpu_env, t1, t0);
13850 #if defined(TARGET_MIPS64)
13851 static void decode_i64_mips16(DisasContext *ctx,
13852 int ry, int funct, int16_t offset,
13853 int extended)
13855 switch (funct) {
13856 case I64_LDSP:
13857 check_insn(ctx, ISA_MIPS3);
13858 check_mips_64(ctx);
13859 offset = extended ? offset : offset << 3;
13860 gen_ld(ctx, OPC_LD, ry, 29, offset);
13861 break;
13862 case I64_SDSP:
13863 check_insn(ctx, ISA_MIPS3);
13864 check_mips_64(ctx);
13865 offset = extended ? offset : offset << 3;
13866 gen_st(ctx, OPC_SD, ry, 29, offset);
13867 break;
13868 case I64_SDRASP:
13869 check_insn(ctx, ISA_MIPS3);
13870 check_mips_64(ctx);
13871 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
13872 gen_st(ctx, OPC_SD, 31, 29, offset);
13873 break;
13874 case I64_DADJSP:
13875 check_insn(ctx, ISA_MIPS3);
13876 check_mips_64(ctx);
13877 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
13878 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
13879 break;
13880 case I64_LDPC:
13881 check_insn(ctx, ISA_MIPS3);
13882 check_mips_64(ctx);
13883 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13884 gen_reserved_instruction(ctx);
13885 } else {
13886 offset = extended ? offset : offset << 3;
13887 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
13889 break;
13890 case I64_DADDIU5:
13891 check_insn(ctx, ISA_MIPS3);
13892 check_mips_64(ctx);
13893 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
13894 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
13895 break;
13896 case I64_DADDIUPC:
13897 check_insn(ctx, ISA_MIPS3);
13898 check_mips_64(ctx);
13899 offset = extended ? offset : offset << 2;
13900 gen_addiupc(ctx, ry, offset, 1, extended);
13901 break;
13902 case I64_DADDIUSP:
13903 check_insn(ctx, ISA_MIPS3);
13904 check_mips_64(ctx);
13905 offset = extended ? offset : offset << 2;
13906 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
13907 break;
13910 #endif
13912 static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
13914 int extend = translator_lduw(env, ctx->base.pc_next + 2);
13915 int op, rx, ry, funct, sa;
13916 int16_t imm, offset;
13918 ctx->opcode = (ctx->opcode << 16) | extend;
13919 op = (ctx->opcode >> 11) & 0x1f;
13920 sa = (ctx->opcode >> 22) & 0x1f;
13921 funct = (ctx->opcode >> 8) & 0x7;
13922 rx = xlat((ctx->opcode >> 8) & 0x7);
13923 ry = xlat((ctx->opcode >> 5) & 0x7);
13924 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
13925 | ((ctx->opcode >> 21) & 0x3f) << 5
13926 | (ctx->opcode & 0x1f));
13929 * The extended opcodes cleverly reuse the opcodes from their 16-bit
13930 * counterparts.
13932 switch (op) {
13933 case M16_OPC_ADDIUSP:
13934 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13935 break;
13936 case M16_OPC_ADDIUPC:
13937 gen_addiupc(ctx, rx, imm, 0, 1);
13938 break;
13939 case M16_OPC_B:
13940 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
13941 /* No delay slot, so just process as a normal instruction */
13942 break;
13943 case M16_OPC_BEQZ:
13944 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
13945 /* No delay slot, so just process as a normal instruction */
13946 break;
13947 case M16_OPC_BNEQZ:
13948 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
13949 /* No delay slot, so just process as a normal instruction */
13950 break;
13951 case M16_OPC_SHIFT:
13952 switch (ctx->opcode & 0x3) {
13953 case 0x0:
13954 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13955 break;
13956 case 0x1:
13957 #if defined(TARGET_MIPS64)
13958 check_mips_64(ctx);
13959 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13960 #else
13961 gen_reserved_instruction(ctx);
13962 #endif
13963 break;
13964 case 0x2:
13965 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13966 break;
13967 case 0x3:
13968 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13969 break;
13971 break;
13972 #if defined(TARGET_MIPS64)
13973 case M16_OPC_LD:
13974 check_insn(ctx, ISA_MIPS3);
13975 check_mips_64(ctx);
13976 gen_ld(ctx, OPC_LD, ry, rx, offset);
13977 break;
13978 #endif
13979 case M16_OPC_RRIA:
13980 imm = ctx->opcode & 0xf;
13981 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
13982 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
13983 imm = (int16_t) (imm << 1) >> 1;
13984 if ((ctx->opcode >> 4) & 0x1) {
13985 #if defined(TARGET_MIPS64)
13986 check_mips_64(ctx);
13987 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13988 #else
13989 gen_reserved_instruction(ctx);
13990 #endif
13991 } else {
13992 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13994 break;
13995 case M16_OPC_ADDIU8:
13996 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13997 break;
13998 case M16_OPC_SLTI:
13999 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
14000 break;
14001 case M16_OPC_SLTIU:
14002 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
14003 break;
14004 case M16_OPC_I8:
14005 switch (funct) {
14006 case I8_BTEQZ:
14007 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
14008 break;
14009 case I8_BTNEZ:
14010 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
14011 break;
14012 case I8_SWRASP:
14013 gen_st(ctx, OPC_SW, 31, 29, imm);
14014 break;
14015 case I8_ADJSP:
14016 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
14017 break;
14018 case I8_SVRS:
14019 check_insn(ctx, ISA_MIPS_R1);
14021 int xsregs = (ctx->opcode >> 24) & 0x7;
14022 int aregs = (ctx->opcode >> 16) & 0xf;
14023 int do_ra = (ctx->opcode >> 6) & 0x1;
14024 int do_s0 = (ctx->opcode >> 5) & 0x1;
14025 int do_s1 = (ctx->opcode >> 4) & 0x1;
14026 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
14027 | (ctx->opcode & 0xf)) << 3;
14029 if (ctx->opcode & (1 << 7)) {
14030 gen_mips16_save(ctx, xsregs, aregs,
14031 do_ra, do_s0, do_s1,
14032 framesize);
14033 } else {
14034 gen_mips16_restore(ctx, xsregs, aregs,
14035 do_ra, do_s0, do_s1,
14036 framesize);
14039 break;
14040 default:
14041 gen_reserved_instruction(ctx);
14042 break;
14044 break;
14045 case M16_OPC_LI:
14046 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
14047 break;
14048 case M16_OPC_CMPI:
14049 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
14050 break;
14051 #if defined(TARGET_MIPS64)
14052 case M16_OPC_SD:
14053 check_insn(ctx, ISA_MIPS3);
14054 check_mips_64(ctx);
14055 gen_st(ctx, OPC_SD, ry, rx, offset);
14056 break;
14057 #endif
14058 case M16_OPC_LB:
14059 gen_ld(ctx, OPC_LB, ry, rx, offset);
14060 break;
14061 case M16_OPC_LH:
14062 gen_ld(ctx, OPC_LH, ry, rx, offset);
14063 break;
14064 case M16_OPC_LWSP:
14065 gen_ld(ctx, OPC_LW, rx, 29, offset);
14066 break;
14067 case M16_OPC_LW:
14068 gen_ld(ctx, OPC_LW, ry, rx, offset);
14069 break;
14070 case M16_OPC_LBU:
14071 gen_ld(ctx, OPC_LBU, ry, rx, offset);
14072 break;
14073 case M16_OPC_LHU:
14074 gen_ld(ctx, OPC_LHU, ry, rx, offset);
14075 break;
14076 case M16_OPC_LWPC:
14077 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
14078 break;
14079 #if defined(TARGET_MIPS64)
14080 case M16_OPC_LWU:
14081 check_insn(ctx, ISA_MIPS3);
14082 check_mips_64(ctx);
14083 gen_ld(ctx, OPC_LWU, ry, rx, offset);
14084 break;
14085 #endif
14086 case M16_OPC_SB:
14087 gen_st(ctx, OPC_SB, ry, rx, offset);
14088 break;
14089 case M16_OPC_SH:
14090 gen_st(ctx, OPC_SH, ry, rx, offset);
14091 break;
14092 case M16_OPC_SWSP:
14093 gen_st(ctx, OPC_SW, rx, 29, offset);
14094 break;
14095 case M16_OPC_SW:
14096 gen_st(ctx, OPC_SW, ry, rx, offset);
14097 break;
14098 #if defined(TARGET_MIPS64)
14099 case M16_OPC_I64:
14100 decode_i64_mips16(ctx, ry, funct, offset, 1);
14101 break;
14102 #endif
14103 default:
14104 gen_reserved_instruction(ctx);
14105 break;
14108 return 4;
14111 static inline bool is_uhi(int sdbbp_code)
14113 #ifdef CONFIG_USER_ONLY
14114 return false;
14115 #else
14116 return semihosting_enabled() && sdbbp_code == 1;
14117 #endif
14120 #ifdef CONFIG_USER_ONLY
14121 /* The above should dead-code away any calls to this..*/
14122 static inline void gen_helper_do_semihosting(void *env)
14124 g_assert_not_reached();
14126 #endif
14128 static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
14130 int rx, ry;
14131 int sa;
14132 int op, cnvt_op, op1, offset;
14133 int funct;
14134 int n_bytes;
14136 op = (ctx->opcode >> 11) & 0x1f;
14137 sa = (ctx->opcode >> 2) & 0x7;
14138 sa = sa == 0 ? 8 : sa;
14139 rx = xlat((ctx->opcode >> 8) & 0x7);
14140 cnvt_op = (ctx->opcode >> 5) & 0x7;
14141 ry = xlat((ctx->opcode >> 5) & 0x7);
14142 op1 = offset = ctx->opcode & 0x1f;
14144 n_bytes = 2;
14146 switch (op) {
14147 case M16_OPC_ADDIUSP:
14149 int16_t imm = ((uint8_t) ctx->opcode) << 2;
14151 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
14153 break;
14154 case M16_OPC_ADDIUPC:
14155 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
14156 break;
14157 case M16_OPC_B:
14158 offset = (ctx->opcode & 0x7ff) << 1;
14159 offset = (int16_t)(offset << 4) >> 4;
14160 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
14161 /* No delay slot, so just process as a normal instruction */
14162 break;
14163 case M16_OPC_JAL:
14164 offset = translator_lduw(env, ctx->base.pc_next + 2);
14165 offset = (((ctx->opcode & 0x1f) << 21)
14166 | ((ctx->opcode >> 5) & 0x1f) << 16
14167 | offset) << 2;
14168 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
14169 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
14170 n_bytes = 4;
14171 break;
14172 case M16_OPC_BEQZ:
14173 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
14174 ((int8_t)ctx->opcode) << 1, 0);
14175 /* No delay slot, so just process as a normal instruction */
14176 break;
14177 case M16_OPC_BNEQZ:
14178 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
14179 ((int8_t)ctx->opcode) << 1, 0);
14180 /* No delay slot, so just process as a normal instruction */
14181 break;
14182 case M16_OPC_SHIFT:
14183 switch (ctx->opcode & 0x3) {
14184 case 0x0:
14185 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
14186 break;
14187 case 0x1:
14188 #if defined(TARGET_MIPS64)
14189 check_insn(ctx, ISA_MIPS3);
14190 check_mips_64(ctx);
14191 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
14192 #else
14193 gen_reserved_instruction(ctx);
14194 #endif
14195 break;
14196 case 0x2:
14197 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
14198 break;
14199 case 0x3:
14200 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
14201 break;
14203 break;
14204 #if defined(TARGET_MIPS64)
14205 case M16_OPC_LD:
14206 check_insn(ctx, ISA_MIPS3);
14207 check_mips_64(ctx);
14208 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
14209 break;
14210 #endif
14211 case M16_OPC_RRIA:
14213 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
14215 if ((ctx->opcode >> 4) & 1) {
14216 #if defined(TARGET_MIPS64)
14217 check_insn(ctx, ISA_MIPS3);
14218 check_mips_64(ctx);
14219 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
14220 #else
14221 gen_reserved_instruction(ctx);
14222 #endif
14223 } else {
14224 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
14227 break;
14228 case M16_OPC_ADDIU8:
14230 int16_t imm = (int8_t) ctx->opcode;
14232 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
14234 break;
14235 case M16_OPC_SLTI:
14237 int16_t imm = (uint8_t) ctx->opcode;
14238 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
14240 break;
14241 case M16_OPC_SLTIU:
14243 int16_t imm = (uint8_t) ctx->opcode;
14244 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
14246 break;
14247 case M16_OPC_I8:
14249 int reg32;
14251 funct = (ctx->opcode >> 8) & 0x7;
14252 switch (funct) {
14253 case I8_BTEQZ:
14254 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
14255 ((int8_t)ctx->opcode) << 1, 0);
14256 break;
14257 case I8_BTNEZ:
14258 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
14259 ((int8_t)ctx->opcode) << 1, 0);
14260 break;
14261 case I8_SWRASP:
14262 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
14263 break;
14264 case I8_ADJSP:
14265 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
14266 ((int8_t)ctx->opcode) << 3);
14267 break;
14268 case I8_SVRS:
14269 check_insn(ctx, ISA_MIPS_R1);
14271 int do_ra = ctx->opcode & (1 << 6);
14272 int do_s0 = ctx->opcode & (1 << 5);
14273 int do_s1 = ctx->opcode & (1 << 4);
14274 int framesize = ctx->opcode & 0xf;
14276 if (framesize == 0) {
14277 framesize = 128;
14278 } else {
14279 framesize = framesize << 3;
14282 if (ctx->opcode & (1 << 7)) {
14283 gen_mips16_save(ctx, 0, 0,
14284 do_ra, do_s0, do_s1, framesize);
14285 } else {
14286 gen_mips16_restore(ctx, 0, 0,
14287 do_ra, do_s0, do_s1, framesize);
14290 break;
14291 case I8_MOV32R:
14293 int rz = xlat(ctx->opcode & 0x7);
14295 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
14296 ((ctx->opcode >> 5) & 0x7);
14297 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
14299 break;
14300 case I8_MOVR32:
14301 reg32 = ctx->opcode & 0x1f;
14302 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
14303 break;
14304 default:
14305 gen_reserved_instruction(ctx);
14306 break;
14309 break;
14310 case M16_OPC_LI:
14312 int16_t imm = (uint8_t) ctx->opcode;
14314 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
14316 break;
14317 case M16_OPC_CMPI:
14319 int16_t imm = (uint8_t) ctx->opcode;
14320 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
14322 break;
14323 #if defined(TARGET_MIPS64)
14324 case M16_OPC_SD:
14325 check_insn(ctx, ISA_MIPS3);
14326 check_mips_64(ctx);
14327 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
14328 break;
14329 #endif
14330 case M16_OPC_LB:
14331 gen_ld(ctx, OPC_LB, ry, rx, offset);
14332 break;
14333 case M16_OPC_LH:
14334 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
14335 break;
14336 case M16_OPC_LWSP:
14337 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14338 break;
14339 case M16_OPC_LW:
14340 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
14341 break;
14342 case M16_OPC_LBU:
14343 gen_ld(ctx, OPC_LBU, ry, rx, offset);
14344 break;
14345 case M16_OPC_LHU:
14346 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
14347 break;
14348 case M16_OPC_LWPC:
14349 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
14350 break;
14351 #if defined(TARGET_MIPS64)
14352 case M16_OPC_LWU:
14353 check_insn(ctx, ISA_MIPS3);
14354 check_mips_64(ctx);
14355 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
14356 break;
14357 #endif
14358 case M16_OPC_SB:
14359 gen_st(ctx, OPC_SB, ry, rx, offset);
14360 break;
14361 case M16_OPC_SH:
14362 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
14363 break;
14364 case M16_OPC_SWSP:
14365 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14366 break;
14367 case M16_OPC_SW:
14368 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
14369 break;
14370 case M16_OPC_RRR:
14372 int rz = xlat((ctx->opcode >> 2) & 0x7);
14373 int mips32_op;
14375 switch (ctx->opcode & 0x3) {
14376 case RRR_ADDU:
14377 mips32_op = OPC_ADDU;
14378 break;
14379 case RRR_SUBU:
14380 mips32_op = OPC_SUBU;
14381 break;
14382 #if defined(TARGET_MIPS64)
14383 case RRR_DADDU:
14384 mips32_op = OPC_DADDU;
14385 check_insn(ctx, ISA_MIPS3);
14386 check_mips_64(ctx);
14387 break;
14388 case RRR_DSUBU:
14389 mips32_op = OPC_DSUBU;
14390 check_insn(ctx, ISA_MIPS3);
14391 check_mips_64(ctx);
14392 break;
14393 #endif
14394 default:
14395 gen_reserved_instruction(ctx);
14396 goto done;
14399 gen_arith(ctx, mips32_op, rz, rx, ry);
14400 done:
14403 break;
14404 case M16_OPC_RR:
14405 switch (op1) {
14406 case RR_JR:
14408 int nd = (ctx->opcode >> 7) & 0x1;
14409 int link = (ctx->opcode >> 6) & 0x1;
14410 int ra = (ctx->opcode >> 5) & 0x1;
14412 if (nd) {
14413 check_insn(ctx, ISA_MIPS_R1);
14416 if (link) {
14417 op = OPC_JALR;
14418 } else {
14419 op = OPC_JR;
14422 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
14423 (nd ? 0 : 2));
14425 break;
14426 case RR_SDBBP:
14427 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
14428 gen_helper_do_semihosting(cpu_env);
14429 } else {
14431 * XXX: not clear which exception should be raised
14432 * when in debug mode...
14434 check_insn(ctx, ISA_MIPS_R1);
14435 generate_exception_end(ctx, EXCP_DBp);
14437 break;
14438 case RR_SLT:
14439 gen_slt(ctx, OPC_SLT, 24, rx, ry);
14440 break;
14441 case RR_SLTU:
14442 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
14443 break;
14444 case RR_BREAK:
14445 generate_exception_end(ctx, EXCP_BREAK);
14446 break;
14447 case RR_SLLV:
14448 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
14449 break;
14450 case RR_SRLV:
14451 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
14452 break;
14453 case RR_SRAV:
14454 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
14455 break;
14456 #if defined(TARGET_MIPS64)
14457 case RR_DSRL:
14458 check_insn(ctx, ISA_MIPS3);
14459 check_mips_64(ctx);
14460 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
14461 break;
14462 #endif
14463 case RR_CMP:
14464 gen_logic(ctx, OPC_XOR, 24, rx, ry);
14465 break;
14466 case RR_NEG:
14467 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
14468 break;
14469 case RR_AND:
14470 gen_logic(ctx, OPC_AND, rx, rx, ry);
14471 break;
14472 case RR_OR:
14473 gen_logic(ctx, OPC_OR, rx, rx, ry);
14474 break;
14475 case RR_XOR:
14476 gen_logic(ctx, OPC_XOR, rx, rx, ry);
14477 break;
14478 case RR_NOT:
14479 gen_logic(ctx, OPC_NOR, rx, ry, 0);
14480 break;
14481 case RR_MFHI:
14482 gen_HILO(ctx, OPC_MFHI, 0, rx);
14483 break;
14484 case RR_CNVT:
14485 check_insn(ctx, ISA_MIPS_R1);
14486 switch (cnvt_op) {
14487 case RR_RY_CNVT_ZEB:
14488 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14489 break;
14490 case RR_RY_CNVT_ZEH:
14491 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14492 break;
14493 case RR_RY_CNVT_SEB:
14494 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14495 break;
14496 case RR_RY_CNVT_SEH:
14497 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14498 break;
14499 #if defined(TARGET_MIPS64)
14500 case RR_RY_CNVT_ZEW:
14501 check_insn(ctx, ISA_MIPS_R1);
14502 check_mips_64(ctx);
14503 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14504 break;
14505 case RR_RY_CNVT_SEW:
14506 check_insn(ctx, ISA_MIPS_R1);
14507 check_mips_64(ctx);
14508 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14509 break;
14510 #endif
14511 default:
14512 gen_reserved_instruction(ctx);
14513 break;
14515 break;
14516 case RR_MFLO:
14517 gen_HILO(ctx, OPC_MFLO, 0, rx);
14518 break;
14519 #if defined(TARGET_MIPS64)
14520 case RR_DSRA:
14521 check_insn(ctx, ISA_MIPS3);
14522 check_mips_64(ctx);
14523 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
14524 break;
14525 case RR_DSLLV:
14526 check_insn(ctx, ISA_MIPS3);
14527 check_mips_64(ctx);
14528 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
14529 break;
14530 case RR_DSRLV:
14531 check_insn(ctx, ISA_MIPS3);
14532 check_mips_64(ctx);
14533 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
14534 break;
14535 case RR_DSRAV:
14536 check_insn(ctx, ISA_MIPS3);
14537 check_mips_64(ctx);
14538 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
14539 break;
14540 #endif
14541 case RR_MULT:
14542 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
14543 break;
14544 case RR_MULTU:
14545 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
14546 break;
14547 case RR_DIV:
14548 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
14549 break;
14550 case RR_DIVU:
14551 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
14552 break;
14553 #if defined(TARGET_MIPS64)
14554 case RR_DMULT:
14555 check_insn(ctx, ISA_MIPS3);
14556 check_mips_64(ctx);
14557 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
14558 break;
14559 case RR_DMULTU:
14560 check_insn(ctx, ISA_MIPS3);
14561 check_mips_64(ctx);
14562 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
14563 break;
14564 case RR_DDIV:
14565 check_insn(ctx, ISA_MIPS3);
14566 check_mips_64(ctx);
14567 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
14568 break;
14569 case RR_DDIVU:
14570 check_insn(ctx, ISA_MIPS3);
14571 check_mips_64(ctx);
14572 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
14573 break;
14574 #endif
14575 default:
14576 gen_reserved_instruction(ctx);
14577 break;
14579 break;
14580 case M16_OPC_EXTEND:
14581 decode_extended_mips16_opc(env, ctx);
14582 n_bytes = 4;
14583 break;
14584 #if defined(TARGET_MIPS64)
14585 case M16_OPC_I64:
14586 funct = (ctx->opcode >> 8) & 0x7;
14587 decode_i64_mips16(ctx, ry, funct, offset, 0);
14588 break;
14589 #endif
14590 default:
14591 gen_reserved_instruction(ctx);
14592 break;
14595 return n_bytes;
14598 /* microMIPS extension to MIPS32/MIPS64 */
14601 * microMIPS32/microMIPS64 major opcodes
14603 * 1. MIPS Architecture for Programmers Volume II-B:
14604 * The microMIPS32 Instruction Set (Revision 3.05)
14606 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
14608 * 2. MIPS Architecture For Programmers Volume II-A:
14609 * The MIPS64 Instruction Set (Revision 3.51)
14612 enum {
14613 POOL32A = 0x00,
14614 POOL16A = 0x01,
14615 LBU16 = 0x02,
14616 MOVE16 = 0x03,
14617 ADDI32 = 0x04,
14618 R6_LUI = 0x04,
14619 AUI = 0x04,
14620 LBU32 = 0x05,
14621 SB32 = 0x06,
14622 LB32 = 0x07,
14624 POOL32B = 0x08,
14625 POOL16B = 0x09,
14626 LHU16 = 0x0a,
14627 ANDI16 = 0x0b,
14628 ADDIU32 = 0x0c,
14629 LHU32 = 0x0d,
14630 SH32 = 0x0e,
14631 LH32 = 0x0f,
14633 POOL32I = 0x10,
14634 POOL16C = 0x11,
14635 LWSP16 = 0x12,
14636 POOL16D = 0x13,
14637 ORI32 = 0x14,
14638 POOL32F = 0x15,
14639 POOL32S = 0x16, /* MIPS64 */
14640 DADDIU32 = 0x17, /* MIPS64 */
14642 POOL32C = 0x18,
14643 LWGP16 = 0x19,
14644 LW16 = 0x1a,
14645 POOL16E = 0x1b,
14646 XORI32 = 0x1c,
14647 JALS32 = 0x1d,
14648 BOVC = 0x1d,
14649 BEQC = 0x1d,
14650 BEQZALC = 0x1d,
14651 ADDIUPC = 0x1e,
14652 PCREL = 0x1e,
14653 BNVC = 0x1f,
14654 BNEC = 0x1f,
14655 BNEZALC = 0x1f,
14657 R6_BEQZC = 0x20,
14658 JIC = 0x20,
14659 POOL16F = 0x21,
14660 SB16 = 0x22,
14661 BEQZ16 = 0x23,
14662 BEQZC16 = 0x23,
14663 SLTI32 = 0x24,
14664 BEQ32 = 0x25,
14665 BC = 0x25,
14666 SWC132 = 0x26,
14667 LWC132 = 0x27,
14669 /* 0x29 is reserved */
14670 RES_29 = 0x29,
14671 R6_BNEZC = 0x28,
14672 JIALC = 0x28,
14673 SH16 = 0x2a,
14674 BNEZ16 = 0x2b,
14675 BNEZC16 = 0x2b,
14676 SLTIU32 = 0x2c,
14677 BNE32 = 0x2d,
14678 BALC = 0x2d,
14679 SDC132 = 0x2e,
14680 LDC132 = 0x2f,
14682 /* 0x31 is reserved */
14683 RES_31 = 0x31,
14684 BLEZALC = 0x30,
14685 BGEZALC = 0x30,
14686 BGEUC = 0x30,
14687 SWSP16 = 0x32,
14688 B16 = 0x33,
14689 BC16 = 0x33,
14690 ANDI32 = 0x34,
14691 J32 = 0x35,
14692 BGTZC = 0x35,
14693 BLTZC = 0x35,
14694 BLTC = 0x35,
14695 SD32 = 0x36, /* MIPS64 */
14696 LD32 = 0x37, /* MIPS64 */
14698 /* 0x39 is reserved */
14699 RES_39 = 0x39,
14700 BGTZALC = 0x38,
14701 BLTZALC = 0x38,
14702 BLTUC = 0x38,
14703 SW16 = 0x3a,
14704 LI16 = 0x3b,
14705 JALX32 = 0x3c,
14706 JAL32 = 0x3d,
14707 BLEZC = 0x3d,
14708 BGEZC = 0x3d,
14709 BGEC = 0x3d,
14710 SW32 = 0x3e,
14711 LW32 = 0x3f
14714 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
14715 enum {
14716 ADDIUPC_00 = 0x00,
14717 ADDIUPC_01 = 0x01,
14718 ADDIUPC_02 = 0x02,
14719 ADDIUPC_03 = 0x03,
14720 ADDIUPC_04 = 0x04,
14721 ADDIUPC_05 = 0x05,
14722 ADDIUPC_06 = 0x06,
14723 ADDIUPC_07 = 0x07,
14724 AUIPC = 0x1e,
14725 ALUIPC = 0x1f,
14726 LWPC_08 = 0x08,
14727 LWPC_09 = 0x09,
14728 LWPC_0A = 0x0A,
14729 LWPC_0B = 0x0B,
14730 LWPC_0C = 0x0C,
14731 LWPC_0D = 0x0D,
14732 LWPC_0E = 0x0E,
14733 LWPC_0F = 0x0F,
14736 /* POOL32A encoding of minor opcode field */
14738 enum {
14740 * These opcodes are distinguished only by bits 9..6; those bits are
14741 * what are recorded below.
14743 SLL32 = 0x0,
14744 SRL32 = 0x1,
14745 SRA = 0x2,
14746 ROTR = 0x3,
14747 SELEQZ = 0x5,
14748 SELNEZ = 0x6,
14749 R6_RDHWR = 0x7,
14751 SLLV = 0x0,
14752 SRLV = 0x1,
14753 SRAV = 0x2,
14754 ROTRV = 0x3,
14755 ADD = 0x4,
14756 ADDU32 = 0x5,
14757 SUB = 0x6,
14758 SUBU32 = 0x7,
14759 MUL = 0x8,
14760 AND = 0x9,
14761 OR32 = 0xa,
14762 NOR = 0xb,
14763 XOR32 = 0xc,
14764 SLT = 0xd,
14765 SLTU = 0xe,
14767 MOVN = 0x0,
14768 R6_MUL = 0x0,
14769 MOVZ = 0x1,
14770 MUH = 0x1,
14771 MULU = 0x2,
14772 MUHU = 0x3,
14773 LWXS = 0x4,
14774 R6_DIV = 0x4,
14775 MOD = 0x5,
14776 R6_DIVU = 0x6,
14777 MODU = 0x7,
14779 /* The following can be distinguished by their lower 6 bits. */
14780 BREAK32 = 0x07,
14781 INS = 0x0c,
14782 LSA = 0x0f,
14783 ALIGN = 0x1f,
14784 EXT = 0x2c,
14785 POOL32AXF = 0x3c,
14786 SIGRIE = 0x3f
14789 /* POOL32AXF encoding of minor opcode field extension */
14792 * 1. MIPS Architecture for Programmers Volume II-B:
14793 * The microMIPS32 Instruction Set (Revision 3.05)
14795 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
14797 * 2. MIPS Architecture for Programmers VolumeIV-e:
14798 * The MIPS DSP Application-Specific Extension
14799 * to the microMIPS32 Architecture (Revision 2.34)
14801 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
14804 enum {
14805 /* bits 11..6 */
14806 TEQ = 0x00,
14807 TGE = 0x08,
14808 TGEU = 0x10,
14809 TLT = 0x20,
14810 TLTU = 0x28,
14811 TNE = 0x30,
14813 MFC0 = 0x03,
14814 MTC0 = 0x0b,
14816 /* begin of microMIPS32 DSP */
14818 /* bits 13..12 for 0x01 */
14819 MFHI_ACC = 0x0,
14820 MFLO_ACC = 0x1,
14821 MTHI_ACC = 0x2,
14822 MTLO_ACC = 0x3,
14824 /* bits 13..12 for 0x2a */
14825 MADD_ACC = 0x0,
14826 MADDU_ACC = 0x1,
14827 MSUB_ACC = 0x2,
14828 MSUBU_ACC = 0x3,
14830 /* bits 13..12 for 0x32 */
14831 MULT_ACC = 0x0,
14832 MULTU_ACC = 0x1,
14834 /* end of microMIPS32 DSP */
14836 /* bits 15..12 for 0x2c */
14837 BITSWAP = 0x0,
14838 SEB = 0x2,
14839 SEH = 0x3,
14840 CLO = 0x4,
14841 CLZ = 0x5,
14842 RDHWR = 0x6,
14843 WSBH = 0x7,
14844 MULT = 0x8,
14845 MULTU = 0x9,
14846 DIV = 0xa,
14847 DIVU = 0xb,
14848 MADD = 0xc,
14849 MADDU = 0xd,
14850 MSUB = 0xe,
14851 MSUBU = 0xf,
14853 /* bits 15..12 for 0x34 */
14854 MFC2 = 0x4,
14855 MTC2 = 0x5,
14856 MFHC2 = 0x8,
14857 MTHC2 = 0x9,
14858 CFC2 = 0xc,
14859 CTC2 = 0xd,
14861 /* bits 15..12 for 0x3c */
14862 JALR = 0x0,
14863 JR = 0x0, /* alias */
14864 JALRC = 0x0,
14865 JRC = 0x0,
14866 JALR_HB = 0x1,
14867 JALRC_HB = 0x1,
14868 JALRS = 0x4,
14869 JALRS_HB = 0x5,
14871 /* bits 15..12 for 0x05 */
14872 RDPGPR = 0xe,
14873 WRPGPR = 0xf,
14875 /* bits 15..12 for 0x0d */
14876 TLBP = 0x0,
14877 TLBR = 0x1,
14878 TLBWI = 0x2,
14879 TLBWR = 0x3,
14880 TLBINV = 0x4,
14881 TLBINVF = 0x5,
14882 WAIT = 0x9,
14883 IRET = 0xd,
14884 DERET = 0xe,
14885 ERET = 0xf,
14887 /* bits 15..12 for 0x15 */
14888 DMT = 0x0,
14889 DVPE = 0x1,
14890 EMT = 0x2,
14891 EVPE = 0x3,
14893 /* bits 15..12 for 0x1d */
14894 DI = 0x4,
14895 EI = 0x5,
14897 /* bits 15..12 for 0x2d */
14898 SYNC = 0x6,
14899 SYSCALL = 0x8,
14900 SDBBP = 0xd,
14902 /* bits 15..12 for 0x35 */
14903 MFHI32 = 0x0,
14904 MFLO32 = 0x1,
14905 MTHI32 = 0x2,
14906 MTLO32 = 0x3,
14909 /* POOL32B encoding of minor opcode field (bits 15..12) */
14911 enum {
14912 LWC2 = 0x0,
14913 LWP = 0x1,
14914 LDP = 0x4,
14915 LWM32 = 0x5,
14916 CACHE = 0x6,
14917 LDM = 0x7,
14918 SWC2 = 0x8,
14919 SWP = 0x9,
14920 SDP = 0xc,
14921 SWM32 = 0xd,
14922 SDM = 0xf
14925 /* POOL32C encoding of minor opcode field (bits 15..12) */
14927 enum {
14928 LWL = 0x0,
14929 SWL = 0x8,
14930 LWR = 0x1,
14931 SWR = 0x9,
14932 PREF = 0x2,
14933 ST_EVA = 0xa,
14934 LL = 0x3,
14935 SC = 0xb,
14936 LDL = 0x4,
14937 SDL = 0xc,
14938 LDR = 0x5,
14939 SDR = 0xd,
14940 LD_EVA = 0x6,
14941 LWU = 0xe,
14942 LLD = 0x7,
14943 SCD = 0xf
14946 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
14948 enum {
14949 LBUE = 0x0,
14950 LHUE = 0x1,
14951 LWLE = 0x2,
14952 LWRE = 0x3,
14953 LBE = 0x4,
14954 LHE = 0x5,
14955 LLE = 0x6,
14956 LWE = 0x7,
14959 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
14961 enum {
14962 SWLE = 0x0,
14963 SWRE = 0x1,
14964 PREFE = 0x2,
14965 CACHEE = 0x3,
14966 SBE = 0x4,
14967 SHE = 0x5,
14968 SCE = 0x6,
14969 SWE = 0x7,
14972 /* POOL32F encoding of minor opcode field (bits 5..0) */
14974 enum {
14975 /* These are the bit 7..6 values */
14976 ADD_FMT = 0x0,
14978 SUB_FMT = 0x1,
14980 MUL_FMT = 0x2,
14982 DIV_FMT = 0x3,
14984 /* These are the bit 8..6 values */
14985 MOVN_FMT = 0x0,
14986 RSQRT2_FMT = 0x0,
14987 MOVF_FMT = 0x0,
14988 RINT_FMT = 0x0,
14989 SELNEZ_FMT = 0x0,
14991 MOVZ_FMT = 0x1,
14992 LWXC1 = 0x1,
14993 MOVT_FMT = 0x1,
14994 CLASS_FMT = 0x1,
14995 SELEQZ_FMT = 0x1,
14997 PLL_PS = 0x2,
14998 SWXC1 = 0x2,
14999 SEL_FMT = 0x2,
15001 PLU_PS = 0x3,
15002 LDXC1 = 0x3,
15004 MOVN_FMT_04 = 0x4,
15005 PUL_PS = 0x4,
15006 SDXC1 = 0x4,
15007 RECIP2_FMT = 0x4,
15009 MOVZ_FMT_05 = 0x05,
15010 PUU_PS = 0x5,
15011 LUXC1 = 0x5,
15013 CVT_PS_S = 0x6,
15014 SUXC1 = 0x6,
15015 ADDR_PS = 0x6,
15016 PREFX = 0x6,
15017 MADDF_FMT = 0x6,
15019 MULR_PS = 0x7,
15020 MSUBF_FMT = 0x7,
15022 MADD_S = 0x01,
15023 MADD_D = 0x09,
15024 MADD_PS = 0x11,
15025 ALNV_PS = 0x19,
15026 MSUB_S = 0x21,
15027 MSUB_D = 0x29,
15028 MSUB_PS = 0x31,
15030 NMADD_S = 0x02,
15031 NMADD_D = 0x0a,
15032 NMADD_PS = 0x12,
15033 NMSUB_S = 0x22,
15034 NMSUB_D = 0x2a,
15035 NMSUB_PS = 0x32,
15037 MIN_FMT = 0x3,
15038 MAX_FMT = 0xb,
15039 MINA_FMT = 0x23,
15040 MAXA_FMT = 0x2b,
15041 POOL32FXF = 0x3b,
15043 CABS_COND_FMT = 0x1c, /* MIPS3D */
15044 C_COND_FMT = 0x3c,
15046 CMP_CONDN_S = 0x5,
15047 CMP_CONDN_D = 0x15
15050 /* POOL32Fxf encoding of minor opcode extension field */
15052 enum {
15053 CVT_L = 0x04,
15054 RSQRT_FMT = 0x08,
15055 FLOOR_L = 0x0c,
15056 CVT_PW_PS = 0x1c,
15057 CVT_W = 0x24,
15058 SQRT_FMT = 0x28,
15059 FLOOR_W = 0x2c,
15060 CVT_PS_PW = 0x3c,
15061 CFC1 = 0x40,
15062 RECIP_FMT = 0x48,
15063 CEIL_L = 0x4c,
15064 CTC1 = 0x60,
15065 CEIL_W = 0x6c,
15066 MFC1 = 0x80,
15067 CVT_S_PL = 0x84,
15068 TRUNC_L = 0x8c,
15069 MTC1 = 0xa0,
15070 CVT_S_PU = 0xa4,
15071 TRUNC_W = 0xac,
15072 MFHC1 = 0xc0,
15073 ROUND_L = 0xcc,
15074 MTHC1 = 0xe0,
15075 ROUND_W = 0xec,
15077 MOV_FMT = 0x01,
15078 MOVF = 0x05,
15079 ABS_FMT = 0x0d,
15080 RSQRT1_FMT = 0x1d,
15081 MOVT = 0x25,
15082 NEG_FMT = 0x2d,
15083 CVT_D = 0x4d,
15084 RECIP1_FMT = 0x5d,
15085 CVT_S = 0x6d
15088 /* POOL32I encoding of minor opcode field (bits 25..21) */
15090 enum {
15091 BLTZ = 0x00,
15092 BLTZAL = 0x01,
15093 BGEZ = 0x02,
15094 BGEZAL = 0x03,
15095 BLEZ = 0x04,
15096 BNEZC = 0x05,
15097 BGTZ = 0x06,
15098 BEQZC = 0x07,
15099 TLTI = 0x08,
15100 BC1EQZC = 0x08,
15101 TGEI = 0x09,
15102 BC1NEZC = 0x09,
15103 TLTIU = 0x0a,
15104 BC2EQZC = 0x0a,
15105 TGEIU = 0x0b,
15106 BC2NEZC = 0x0a,
15107 TNEI = 0x0c,
15108 R6_SYNCI = 0x0c,
15109 LUI = 0x0d,
15110 TEQI = 0x0e,
15111 SYNCI = 0x10,
15112 BLTZALS = 0x11,
15113 BGEZALS = 0x13,
15114 BC2F = 0x14,
15115 BC2T = 0x15,
15116 BPOSGE64 = 0x1a,
15117 BPOSGE32 = 0x1b,
15118 /* These overlap and are distinguished by bit16 of the instruction */
15119 BC1F = 0x1c,
15120 BC1T = 0x1d,
15121 BC1ANY2F = 0x1c,
15122 BC1ANY2T = 0x1d,
15123 BC1ANY4F = 0x1e,
15124 BC1ANY4T = 0x1f
15127 /* POOL16A encoding of minor opcode field */
15129 enum {
15130 ADDU16 = 0x0,
15131 SUBU16 = 0x1
15134 /* POOL16B encoding of minor opcode field */
15136 enum {
15137 SLL16 = 0x0,
15138 SRL16 = 0x1
15141 /* POOL16C encoding of minor opcode field */
15143 enum {
15144 NOT16 = 0x00,
15145 XOR16 = 0x04,
15146 AND16 = 0x08,
15147 OR16 = 0x0c,
15148 LWM16 = 0x10,
15149 SWM16 = 0x14,
15150 JR16 = 0x18,
15151 JRC16 = 0x1a,
15152 JALR16 = 0x1c,
15153 JALR16S = 0x1e,
15154 MFHI16 = 0x20,
15155 MFLO16 = 0x24,
15156 BREAK16 = 0x28,
15157 SDBBP16 = 0x2c,
15158 JRADDIUSP = 0x30
15161 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
15163 enum {
15164 R6_NOT16 = 0x00,
15165 R6_AND16 = 0x01,
15166 R6_LWM16 = 0x02,
15167 R6_JRC16 = 0x03,
15168 MOVEP = 0x04,
15169 MOVEP_05 = 0x05,
15170 MOVEP_06 = 0x06,
15171 MOVEP_07 = 0x07,
15172 R6_XOR16 = 0x08,
15173 R6_OR16 = 0x09,
15174 R6_SWM16 = 0x0a,
15175 JALRC16 = 0x0b,
15176 MOVEP_0C = 0x0c,
15177 MOVEP_0D = 0x0d,
15178 MOVEP_0E = 0x0e,
15179 MOVEP_0F = 0x0f,
15180 JRCADDIUSP = 0x13,
15181 R6_BREAK16 = 0x1b,
15182 R6_SDBBP16 = 0x3b
15185 /* POOL16D encoding of minor opcode field */
15187 enum {
15188 ADDIUS5 = 0x0,
15189 ADDIUSP = 0x1
15192 /* POOL16E encoding of minor opcode field */
15194 enum {
15195 ADDIUR2 = 0x0,
15196 ADDIUR1SP = 0x1
15199 static int mmreg(int r)
15201 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
15203 return map[r];
15206 /* Used for 16-bit store instructions. */
15207 static int mmreg2(int r)
15209 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
15211 return map[r];
15214 #define uMIPS_RD(op) ((op >> 7) & 0x7)
15215 #define uMIPS_RS(op) ((op >> 4) & 0x7)
15216 #define uMIPS_RS2(op) uMIPS_RS(op)
15217 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
15218 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
15219 #define uMIPS_RS5(op) (op & 0x1f)
15221 /* Signed immediate */
15222 #define SIMM(op, start, width) \
15223 ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \
15224 << (32 - width)) \
15225 >> (32 - width))
15226 /* Zero-extended immediate */
15227 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width)))
15229 static void gen_addiur1sp(DisasContext *ctx)
15231 int rd = mmreg(uMIPS_RD(ctx->opcode));
15233 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
15236 static void gen_addiur2(DisasContext *ctx)
15238 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
15239 int rd = mmreg(uMIPS_RD(ctx->opcode));
15240 int rs = mmreg(uMIPS_RS(ctx->opcode));
15242 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
15245 static void gen_addiusp(DisasContext *ctx)
15247 int encoded = ZIMM(ctx->opcode, 1, 9);
15248 int decoded;
15250 if (encoded <= 1) {
15251 decoded = 256 + encoded;
15252 } else if (encoded <= 255) {
15253 decoded = encoded;
15254 } else if (encoded <= 509) {
15255 decoded = encoded - 512;
15256 } else {
15257 decoded = encoded - 768;
15260 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
15263 static void gen_addius5(DisasContext *ctx)
15265 int imm = SIMM(ctx->opcode, 1, 4);
15266 int rd = (ctx->opcode >> 5) & 0x1f;
15268 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
15271 static void gen_andi16(DisasContext *ctx)
15273 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
15274 31, 32, 63, 64, 255, 32768, 65535 };
15275 int rd = mmreg(uMIPS_RD(ctx->opcode));
15276 int rs = mmreg(uMIPS_RS(ctx->opcode));
15277 int encoded = ZIMM(ctx->opcode, 0, 4);
15279 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
15282 static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist,
15283 int base, int16_t offset)
15285 TCGv t0, t1;
15286 TCGv_i32 t2;
15288 if (ctx->hflags & MIPS_HFLAG_BMASK) {
15289 gen_reserved_instruction(ctx);
15290 return;
15293 t0 = tcg_temp_new();
15295 gen_base_offset_addr(ctx, t0, base, offset);
15297 t1 = tcg_const_tl(reglist);
15298 t2 = tcg_const_i32(ctx->mem_idx);
15300 save_cpu_state(ctx, 1);
15301 switch (opc) {
15302 case LWM32:
15303 gen_helper_lwm(cpu_env, t0, t1, t2);
15304 break;
15305 case SWM32:
15306 gen_helper_swm(cpu_env, t0, t1, t2);
15307 break;
15308 #ifdef TARGET_MIPS64
15309 case LDM:
15310 gen_helper_ldm(cpu_env, t0, t1, t2);
15311 break;
15312 case SDM:
15313 gen_helper_sdm(cpu_env, t0, t1, t2);
15314 break;
15315 #endif
15317 tcg_temp_free(t0);
15318 tcg_temp_free(t1);
15319 tcg_temp_free_i32(t2);
15323 static void gen_pool16c_insn(DisasContext *ctx)
15325 int rd = mmreg((ctx->opcode >> 3) & 0x7);
15326 int rs = mmreg(ctx->opcode & 0x7);
15328 switch (((ctx->opcode) >> 4) & 0x3f) {
15329 case NOT16 + 0:
15330 case NOT16 + 1:
15331 case NOT16 + 2:
15332 case NOT16 + 3:
15333 gen_logic(ctx, OPC_NOR, rd, rs, 0);
15334 break;
15335 case XOR16 + 0:
15336 case XOR16 + 1:
15337 case XOR16 + 2:
15338 case XOR16 + 3:
15339 gen_logic(ctx, OPC_XOR, rd, rd, rs);
15340 break;
15341 case AND16 + 0:
15342 case AND16 + 1:
15343 case AND16 + 2:
15344 case AND16 + 3:
15345 gen_logic(ctx, OPC_AND, rd, rd, rs);
15346 break;
15347 case OR16 + 0:
15348 case OR16 + 1:
15349 case OR16 + 2:
15350 case OR16 + 3:
15351 gen_logic(ctx, OPC_OR, rd, rd, rs);
15352 break;
15353 case LWM16 + 0:
15354 case LWM16 + 1:
15355 case LWM16 + 2:
15356 case LWM16 + 3:
15358 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15359 int offset = ZIMM(ctx->opcode, 0, 4);
15361 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
15362 29, offset << 2);
15364 break;
15365 case SWM16 + 0:
15366 case SWM16 + 1:
15367 case SWM16 + 2:
15368 case SWM16 + 3:
15370 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15371 int offset = ZIMM(ctx->opcode, 0, 4);
15373 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
15374 29, offset << 2);
15376 break;
15377 case JR16 + 0:
15378 case JR16 + 1:
15380 int reg = ctx->opcode & 0x1f;
15382 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
15384 break;
15385 case JRC16 + 0:
15386 case JRC16 + 1:
15388 int reg = ctx->opcode & 0x1f;
15389 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
15391 * Let normal delay slot handling in our caller take us
15392 * to the branch target.
15395 break;
15396 case JALR16 + 0:
15397 case JALR16 + 1:
15398 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
15399 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15400 break;
15401 case JALR16S + 0:
15402 case JALR16S + 1:
15403 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
15404 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15405 break;
15406 case MFHI16 + 0:
15407 case MFHI16 + 1:
15408 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
15409 break;
15410 case MFLO16 + 0:
15411 case MFLO16 + 1:
15412 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
15413 break;
15414 case BREAK16:
15415 generate_exception_end(ctx, EXCP_BREAK);
15416 break;
15417 case SDBBP16:
15418 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
15419 gen_helper_do_semihosting(cpu_env);
15420 } else {
15422 * XXX: not clear which exception should be raised
15423 * when in debug mode...
15425 check_insn(ctx, ISA_MIPS_R1);
15426 generate_exception_end(ctx, EXCP_DBp);
15428 break;
15429 case JRADDIUSP + 0:
15430 case JRADDIUSP + 1:
15432 int imm = ZIMM(ctx->opcode, 0, 5);
15433 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15434 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15436 * Let normal delay slot handling in our caller take us
15437 * to the branch target.
15440 break;
15441 default:
15442 gen_reserved_instruction(ctx);
15443 break;
15447 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
15448 int enc_rs)
15450 int rd, rs, re, rt;
15451 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
15452 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
15453 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
15454 rd = rd_enc[enc_dest];
15455 re = re_enc[enc_dest];
15456 rs = rs_rt_enc[enc_rs];
15457 rt = rs_rt_enc[enc_rt];
15458 if (rs) {
15459 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
15460 } else {
15461 tcg_gen_movi_tl(cpu_gpr[rd], 0);
15463 if (rt) {
15464 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
15465 } else {
15466 tcg_gen_movi_tl(cpu_gpr[re], 0);
15470 static void gen_pool16c_r6_insn(DisasContext *ctx)
15472 int rt = mmreg((ctx->opcode >> 7) & 0x7);
15473 int rs = mmreg((ctx->opcode >> 4) & 0x7);
15475 switch (ctx->opcode & 0xf) {
15476 case R6_NOT16:
15477 gen_logic(ctx, OPC_NOR, rt, rs, 0);
15478 break;
15479 case R6_AND16:
15480 gen_logic(ctx, OPC_AND, rt, rt, rs);
15481 break;
15482 case R6_LWM16:
15484 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15485 int offset = extract32(ctx->opcode, 4, 4);
15486 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
15488 break;
15489 case R6_JRC16: /* JRCADDIUSP */
15490 if ((ctx->opcode >> 4) & 1) {
15491 /* JRCADDIUSP */
15492 int imm = extract32(ctx->opcode, 5, 5);
15493 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15494 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15495 } else {
15496 /* JRC16 */
15497 rs = extract32(ctx->opcode, 5, 5);
15498 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
15500 break;
15501 case MOVEP:
15502 case MOVEP_05:
15503 case MOVEP_06:
15504 case MOVEP_07:
15505 case MOVEP_0C:
15506 case MOVEP_0D:
15507 case MOVEP_0E:
15508 case MOVEP_0F:
15510 int enc_dest = uMIPS_RD(ctx->opcode);
15511 int enc_rt = uMIPS_RS2(ctx->opcode);
15512 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
15513 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15515 break;
15516 case R6_XOR16:
15517 gen_logic(ctx, OPC_XOR, rt, rt, rs);
15518 break;
15519 case R6_OR16:
15520 gen_logic(ctx, OPC_OR, rt, rt, rs);
15521 break;
15522 case R6_SWM16:
15524 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15525 int offset = extract32(ctx->opcode, 4, 4);
15526 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
15528 break;
15529 case JALRC16: /* BREAK16, SDBBP16 */
15530 switch (ctx->opcode & 0x3f) {
15531 case JALRC16:
15532 case JALRC16 + 0x20:
15533 /* JALRC16 */
15534 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
15535 31, 0, 0);
15536 break;
15537 case R6_BREAK16:
15538 /* BREAK16 */
15539 generate_exception(ctx, EXCP_BREAK);
15540 break;
15541 case R6_SDBBP16:
15542 /* SDBBP16 */
15543 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
15544 gen_helper_do_semihosting(cpu_env);
15545 } else {
15546 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15547 generate_exception(ctx, EXCP_RI);
15548 } else {
15549 generate_exception(ctx, EXCP_DBp);
15552 break;
15554 break;
15555 default:
15556 generate_exception(ctx, EXCP_RI);
15557 break;
15561 static void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
15563 TCGv t0 = tcg_temp_new();
15564 TCGv t1 = tcg_temp_new();
15566 gen_load_gpr(t0, base);
15568 if (index != 0) {
15569 gen_load_gpr(t1, index);
15570 tcg_gen_shli_tl(t1, t1, 2);
15571 gen_op_addr_add(ctx, t0, t1, t0);
15574 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15575 gen_store_gpr(t1, rd);
15577 tcg_temp_free(t0);
15578 tcg_temp_free(t1);
15581 static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd,
15582 int base, int16_t offset)
15584 TCGv t0, t1;
15586 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
15587 gen_reserved_instruction(ctx);
15588 return;
15591 t0 = tcg_temp_new();
15592 t1 = tcg_temp_new();
15594 gen_base_offset_addr(ctx, t0, base, offset);
15596 switch (opc) {
15597 case LWP:
15598 if (rd == base) {
15599 gen_reserved_instruction(ctx);
15600 return;
15602 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15603 gen_store_gpr(t1, rd);
15604 tcg_gen_movi_tl(t1, 4);
15605 gen_op_addr_add(ctx, t0, t0, t1);
15606 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15607 gen_store_gpr(t1, rd + 1);
15608 break;
15609 case SWP:
15610 gen_load_gpr(t1, rd);
15611 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15612 tcg_gen_movi_tl(t1, 4);
15613 gen_op_addr_add(ctx, t0, t0, t1);
15614 gen_load_gpr(t1, rd + 1);
15615 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15616 break;
15617 #ifdef TARGET_MIPS64
15618 case LDP:
15619 if (rd == base) {
15620 gen_reserved_instruction(ctx);
15621 return;
15623 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15624 gen_store_gpr(t1, rd);
15625 tcg_gen_movi_tl(t1, 8);
15626 gen_op_addr_add(ctx, t0, t0, t1);
15627 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15628 gen_store_gpr(t1, rd + 1);
15629 break;
15630 case SDP:
15631 gen_load_gpr(t1, rd);
15632 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15633 tcg_gen_movi_tl(t1, 8);
15634 gen_op_addr_add(ctx, t0, t0, t1);
15635 gen_load_gpr(t1, rd + 1);
15636 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15637 break;
15638 #endif
15640 tcg_temp_free(t0);
15641 tcg_temp_free(t1);
15644 static void gen_sync(int stype)
15646 TCGBar tcg_mo = TCG_BAR_SC;
15648 switch (stype) {
15649 case 0x4: /* SYNC_WMB */
15650 tcg_mo |= TCG_MO_ST_ST;
15651 break;
15652 case 0x10: /* SYNC_MB */
15653 tcg_mo |= TCG_MO_ALL;
15654 break;
15655 case 0x11: /* SYNC_ACQUIRE */
15656 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
15657 break;
15658 case 0x12: /* SYNC_RELEASE */
15659 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
15660 break;
15661 case 0x13: /* SYNC_RMB */
15662 tcg_mo |= TCG_MO_LD_LD;
15663 break;
15664 default:
15665 tcg_mo |= TCG_MO_ALL;
15666 break;
15669 tcg_gen_mb(tcg_mo);
15672 static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
15674 int extension = (ctx->opcode >> 6) & 0x3f;
15675 int minor = (ctx->opcode >> 12) & 0xf;
15676 uint32_t mips32_op;
15678 switch (extension) {
15679 case TEQ:
15680 mips32_op = OPC_TEQ;
15681 goto do_trap;
15682 case TGE:
15683 mips32_op = OPC_TGE;
15684 goto do_trap;
15685 case TGEU:
15686 mips32_op = OPC_TGEU;
15687 goto do_trap;
15688 case TLT:
15689 mips32_op = OPC_TLT;
15690 goto do_trap;
15691 case TLTU:
15692 mips32_op = OPC_TLTU;
15693 goto do_trap;
15694 case TNE:
15695 mips32_op = OPC_TNE;
15696 do_trap:
15697 gen_trap(ctx, mips32_op, rs, rt, -1);
15698 break;
15699 #ifndef CONFIG_USER_ONLY
15700 case MFC0:
15701 case MFC0 + 32:
15702 check_cp0_enabled(ctx);
15703 if (rt == 0) {
15704 /* Treat as NOP. */
15705 break;
15707 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
15708 break;
15709 case MTC0:
15710 case MTC0 + 32:
15711 check_cp0_enabled(ctx);
15713 TCGv t0 = tcg_temp_new();
15715 gen_load_gpr(t0, rt);
15716 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
15717 tcg_temp_free(t0);
15719 break;
15720 #endif
15721 case 0x2a:
15722 switch (minor & 3) {
15723 case MADD_ACC:
15724 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
15725 break;
15726 case MADDU_ACC:
15727 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
15728 break;
15729 case MSUB_ACC:
15730 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
15731 break;
15732 case MSUBU_ACC:
15733 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
15734 break;
15735 default:
15736 goto pool32axf_invalid;
15738 break;
15739 case 0x32:
15740 switch (minor & 3) {
15741 case MULT_ACC:
15742 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
15743 break;
15744 case MULTU_ACC:
15745 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
15746 break;
15747 default:
15748 goto pool32axf_invalid;
15750 break;
15751 case 0x2c:
15752 switch (minor) {
15753 case BITSWAP:
15754 check_insn(ctx, ISA_MIPS_R6);
15755 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
15756 break;
15757 case SEB:
15758 gen_bshfl(ctx, OPC_SEB, rs, rt);
15759 break;
15760 case SEH:
15761 gen_bshfl(ctx, OPC_SEH, rs, rt);
15762 break;
15763 case CLO:
15764 mips32_op = OPC_CLO;
15765 goto do_cl;
15766 case CLZ:
15767 mips32_op = OPC_CLZ;
15768 do_cl:
15769 check_insn(ctx, ISA_MIPS_R1);
15770 gen_cl(ctx, mips32_op, rt, rs);
15771 break;
15772 case RDHWR:
15773 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15774 gen_rdhwr(ctx, rt, rs, 0);
15775 break;
15776 case WSBH:
15777 gen_bshfl(ctx, OPC_WSBH, rs, rt);
15778 break;
15779 case MULT:
15780 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15781 mips32_op = OPC_MULT;
15782 goto do_mul;
15783 case MULTU:
15784 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15785 mips32_op = OPC_MULTU;
15786 goto do_mul;
15787 case DIV:
15788 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15789 mips32_op = OPC_DIV;
15790 goto do_div;
15791 case DIVU:
15792 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15793 mips32_op = OPC_DIVU;
15794 goto do_div;
15795 do_div:
15796 check_insn(ctx, ISA_MIPS_R1);
15797 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15798 break;
15799 case MADD:
15800 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15801 mips32_op = OPC_MADD;
15802 goto do_mul;
15803 case MADDU:
15804 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15805 mips32_op = OPC_MADDU;
15806 goto do_mul;
15807 case MSUB:
15808 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15809 mips32_op = OPC_MSUB;
15810 goto do_mul;
15811 case MSUBU:
15812 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15813 mips32_op = OPC_MSUBU;
15814 do_mul:
15815 check_insn(ctx, ISA_MIPS_R1);
15816 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15817 break;
15818 default:
15819 goto pool32axf_invalid;
15821 break;
15822 case 0x34:
15823 switch (minor) {
15824 case MFC2:
15825 case MTC2:
15826 case MFHC2:
15827 case MTHC2:
15828 case CFC2:
15829 case CTC2:
15830 generate_exception_err(ctx, EXCP_CpU, 2);
15831 break;
15832 default:
15833 goto pool32axf_invalid;
15835 break;
15836 case 0x3c:
15837 switch (minor) {
15838 case JALR: /* JALRC */
15839 case JALR_HB: /* JALRC_HB */
15840 if (ctx->insn_flags & ISA_MIPS_R6) {
15841 /* JALRC, JALRC_HB */
15842 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
15843 } else {
15844 /* JALR, JALR_HB */
15845 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
15846 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15848 break;
15849 case JALRS:
15850 case JALRS_HB:
15851 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15852 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
15853 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15854 break;
15855 default:
15856 goto pool32axf_invalid;
15858 break;
15859 case 0x05:
15860 switch (minor) {
15861 case RDPGPR:
15862 check_cp0_enabled(ctx);
15863 check_insn(ctx, ISA_MIPS_R2);
15864 gen_load_srsgpr(rs, rt);
15865 break;
15866 case WRPGPR:
15867 check_cp0_enabled(ctx);
15868 check_insn(ctx, ISA_MIPS_R2);
15869 gen_store_srsgpr(rs, rt);
15870 break;
15871 default:
15872 goto pool32axf_invalid;
15874 break;
15875 #ifndef CONFIG_USER_ONLY
15876 case 0x0d:
15877 switch (minor) {
15878 case TLBP:
15879 mips32_op = OPC_TLBP;
15880 goto do_cp0;
15881 case TLBR:
15882 mips32_op = OPC_TLBR;
15883 goto do_cp0;
15884 case TLBWI:
15885 mips32_op = OPC_TLBWI;
15886 goto do_cp0;
15887 case TLBWR:
15888 mips32_op = OPC_TLBWR;
15889 goto do_cp0;
15890 case TLBINV:
15891 mips32_op = OPC_TLBINV;
15892 goto do_cp0;
15893 case TLBINVF:
15894 mips32_op = OPC_TLBINVF;
15895 goto do_cp0;
15896 case WAIT:
15897 mips32_op = OPC_WAIT;
15898 goto do_cp0;
15899 case DERET:
15900 mips32_op = OPC_DERET;
15901 goto do_cp0;
15902 case ERET:
15903 mips32_op = OPC_ERET;
15904 do_cp0:
15905 gen_cp0(env, ctx, mips32_op, rt, rs);
15906 break;
15907 default:
15908 goto pool32axf_invalid;
15910 break;
15911 case 0x1d:
15912 switch (minor) {
15913 case DI:
15914 check_cp0_enabled(ctx);
15916 TCGv t0 = tcg_temp_new();
15918 save_cpu_state(ctx, 1);
15919 gen_helper_di(t0, cpu_env);
15920 gen_store_gpr(t0, rs);
15922 * Stop translation as we may have switched the execution
15923 * mode.
15925 ctx->base.is_jmp = DISAS_STOP;
15926 tcg_temp_free(t0);
15928 break;
15929 case EI:
15930 check_cp0_enabled(ctx);
15932 TCGv t0 = tcg_temp_new();
15934 save_cpu_state(ctx, 1);
15935 gen_helper_ei(t0, cpu_env);
15936 gen_store_gpr(t0, rs);
15938 * DISAS_STOP isn't sufficient, we need to ensure we break out
15939 * of translated code to check for pending interrupts.
15941 gen_save_pc(ctx->base.pc_next + 4);
15942 ctx->base.is_jmp = DISAS_EXIT;
15943 tcg_temp_free(t0);
15945 break;
15946 default:
15947 goto pool32axf_invalid;
15949 break;
15950 #endif
15951 case 0x2d:
15952 switch (minor) {
15953 case SYNC:
15954 gen_sync(extract32(ctx->opcode, 16, 5));
15955 break;
15956 case SYSCALL:
15957 generate_exception_end(ctx, EXCP_SYSCALL);
15958 break;
15959 case SDBBP:
15960 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
15961 gen_helper_do_semihosting(cpu_env);
15962 } else {
15963 check_insn(ctx, ISA_MIPS_R1);
15964 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15965 gen_reserved_instruction(ctx);
15966 } else {
15967 generate_exception_end(ctx, EXCP_DBp);
15970 break;
15971 default:
15972 goto pool32axf_invalid;
15974 break;
15975 case 0x01:
15976 switch (minor & 3) {
15977 case MFHI_ACC:
15978 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
15979 break;
15980 case MFLO_ACC:
15981 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
15982 break;
15983 case MTHI_ACC:
15984 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
15985 break;
15986 case MTLO_ACC:
15987 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
15988 break;
15989 default:
15990 goto pool32axf_invalid;
15992 break;
15993 case 0x35:
15994 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15995 switch (minor) {
15996 case MFHI32:
15997 gen_HILO(ctx, OPC_MFHI, 0, rs);
15998 break;
15999 case MFLO32:
16000 gen_HILO(ctx, OPC_MFLO, 0, rs);
16001 break;
16002 case MTHI32:
16003 gen_HILO(ctx, OPC_MTHI, 0, rs);
16004 break;
16005 case MTLO32:
16006 gen_HILO(ctx, OPC_MTLO, 0, rs);
16007 break;
16008 default:
16009 goto pool32axf_invalid;
16011 break;
16012 default:
16013 pool32axf_invalid:
16014 MIPS_INVAL("pool32axf");
16015 gen_reserved_instruction(ctx);
16016 break;
16021 * Values for microMIPS fmt field. Variable-width, depending on which
16022 * formats the instruction supports.
16024 enum {
16025 FMT_SD_S = 0,
16026 FMT_SD_D = 1,
16028 FMT_SDPS_S = 0,
16029 FMT_SDPS_D = 1,
16030 FMT_SDPS_PS = 2,
16032 FMT_SWL_S = 0,
16033 FMT_SWL_W = 1,
16034 FMT_SWL_L = 2,
16036 FMT_DWL_D = 0,
16037 FMT_DWL_W = 1,
16038 FMT_DWL_L = 2
16041 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
16043 int extension = (ctx->opcode >> 6) & 0x3ff;
16044 uint32_t mips32_op;
16046 #define FLOAT_1BIT_FMT(opc, fmt) ((fmt << 8) | opc)
16047 #define FLOAT_2BIT_FMT(opc, fmt) ((fmt << 7) | opc)
16048 #define COND_FLOAT_MOV(opc, cond) ((cond << 7) | opc)
16050 switch (extension) {
16051 case FLOAT_1BIT_FMT(CFC1, 0):
16052 mips32_op = OPC_CFC1;
16053 goto do_cp1;
16054 case FLOAT_1BIT_FMT(CTC1, 0):
16055 mips32_op = OPC_CTC1;
16056 goto do_cp1;
16057 case FLOAT_1BIT_FMT(MFC1, 0):
16058 mips32_op = OPC_MFC1;
16059 goto do_cp1;
16060 case FLOAT_1BIT_FMT(MTC1, 0):
16061 mips32_op = OPC_MTC1;
16062 goto do_cp1;
16063 case FLOAT_1BIT_FMT(MFHC1, 0):
16064 mips32_op = OPC_MFHC1;
16065 goto do_cp1;
16066 case FLOAT_1BIT_FMT(MTHC1, 0):
16067 mips32_op = OPC_MTHC1;
16068 do_cp1:
16069 gen_cp1(ctx, mips32_op, rt, rs);
16070 break;
16072 /* Reciprocal square root */
16073 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
16074 mips32_op = OPC_RSQRT_S;
16075 goto do_unaryfp;
16076 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
16077 mips32_op = OPC_RSQRT_D;
16078 goto do_unaryfp;
16080 /* Square root */
16081 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
16082 mips32_op = OPC_SQRT_S;
16083 goto do_unaryfp;
16084 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
16085 mips32_op = OPC_SQRT_D;
16086 goto do_unaryfp;
16088 /* Reciprocal */
16089 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
16090 mips32_op = OPC_RECIP_S;
16091 goto do_unaryfp;
16092 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
16093 mips32_op = OPC_RECIP_D;
16094 goto do_unaryfp;
16096 /* Floor */
16097 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
16098 mips32_op = OPC_FLOOR_L_S;
16099 goto do_unaryfp;
16100 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
16101 mips32_op = OPC_FLOOR_L_D;
16102 goto do_unaryfp;
16103 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
16104 mips32_op = OPC_FLOOR_W_S;
16105 goto do_unaryfp;
16106 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
16107 mips32_op = OPC_FLOOR_W_D;
16108 goto do_unaryfp;
16110 /* Ceiling */
16111 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
16112 mips32_op = OPC_CEIL_L_S;
16113 goto do_unaryfp;
16114 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
16115 mips32_op = OPC_CEIL_L_D;
16116 goto do_unaryfp;
16117 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
16118 mips32_op = OPC_CEIL_W_S;
16119 goto do_unaryfp;
16120 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
16121 mips32_op = OPC_CEIL_W_D;
16122 goto do_unaryfp;
16124 /* Truncation */
16125 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
16126 mips32_op = OPC_TRUNC_L_S;
16127 goto do_unaryfp;
16128 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
16129 mips32_op = OPC_TRUNC_L_D;
16130 goto do_unaryfp;
16131 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
16132 mips32_op = OPC_TRUNC_W_S;
16133 goto do_unaryfp;
16134 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
16135 mips32_op = OPC_TRUNC_W_D;
16136 goto do_unaryfp;
16138 /* Round */
16139 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
16140 mips32_op = OPC_ROUND_L_S;
16141 goto do_unaryfp;
16142 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
16143 mips32_op = OPC_ROUND_L_D;
16144 goto do_unaryfp;
16145 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
16146 mips32_op = OPC_ROUND_W_S;
16147 goto do_unaryfp;
16148 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
16149 mips32_op = OPC_ROUND_W_D;
16150 goto do_unaryfp;
16152 /* Integer to floating-point conversion */
16153 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
16154 mips32_op = OPC_CVT_L_S;
16155 goto do_unaryfp;
16156 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
16157 mips32_op = OPC_CVT_L_D;
16158 goto do_unaryfp;
16159 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
16160 mips32_op = OPC_CVT_W_S;
16161 goto do_unaryfp;
16162 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
16163 mips32_op = OPC_CVT_W_D;
16164 goto do_unaryfp;
16166 /* Paired-foo conversions */
16167 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
16168 mips32_op = OPC_CVT_S_PL;
16169 goto do_unaryfp;
16170 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
16171 mips32_op = OPC_CVT_S_PU;
16172 goto do_unaryfp;
16173 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
16174 mips32_op = OPC_CVT_PW_PS;
16175 goto do_unaryfp;
16176 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
16177 mips32_op = OPC_CVT_PS_PW;
16178 goto do_unaryfp;
16180 /* Floating-point moves */
16181 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
16182 mips32_op = OPC_MOV_S;
16183 goto do_unaryfp;
16184 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
16185 mips32_op = OPC_MOV_D;
16186 goto do_unaryfp;
16187 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
16188 mips32_op = OPC_MOV_PS;
16189 goto do_unaryfp;
16191 /* Absolute value */
16192 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
16193 mips32_op = OPC_ABS_S;
16194 goto do_unaryfp;
16195 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
16196 mips32_op = OPC_ABS_D;
16197 goto do_unaryfp;
16198 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
16199 mips32_op = OPC_ABS_PS;
16200 goto do_unaryfp;
16202 /* Negation */
16203 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
16204 mips32_op = OPC_NEG_S;
16205 goto do_unaryfp;
16206 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
16207 mips32_op = OPC_NEG_D;
16208 goto do_unaryfp;
16209 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
16210 mips32_op = OPC_NEG_PS;
16211 goto do_unaryfp;
16213 /* Reciprocal square root step */
16214 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
16215 mips32_op = OPC_RSQRT1_S;
16216 goto do_unaryfp;
16217 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
16218 mips32_op = OPC_RSQRT1_D;
16219 goto do_unaryfp;
16220 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
16221 mips32_op = OPC_RSQRT1_PS;
16222 goto do_unaryfp;
16224 /* Reciprocal step */
16225 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
16226 mips32_op = OPC_RECIP1_S;
16227 goto do_unaryfp;
16228 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
16229 mips32_op = OPC_RECIP1_S;
16230 goto do_unaryfp;
16231 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
16232 mips32_op = OPC_RECIP1_PS;
16233 goto do_unaryfp;
16235 /* Conversions from double */
16236 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
16237 mips32_op = OPC_CVT_D_S;
16238 goto do_unaryfp;
16239 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
16240 mips32_op = OPC_CVT_D_W;
16241 goto do_unaryfp;
16242 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
16243 mips32_op = OPC_CVT_D_L;
16244 goto do_unaryfp;
16246 /* Conversions from single */
16247 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
16248 mips32_op = OPC_CVT_S_D;
16249 goto do_unaryfp;
16250 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
16251 mips32_op = OPC_CVT_S_W;
16252 goto do_unaryfp;
16253 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
16254 mips32_op = OPC_CVT_S_L;
16255 do_unaryfp:
16256 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
16257 break;
16259 /* Conditional moves on floating-point codes */
16260 case COND_FLOAT_MOV(MOVT, 0):
16261 case COND_FLOAT_MOV(MOVT, 1):
16262 case COND_FLOAT_MOV(MOVT, 2):
16263 case COND_FLOAT_MOV(MOVT, 3):
16264 case COND_FLOAT_MOV(MOVT, 4):
16265 case COND_FLOAT_MOV(MOVT, 5):
16266 case COND_FLOAT_MOV(MOVT, 6):
16267 case COND_FLOAT_MOV(MOVT, 7):
16268 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16269 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
16270 break;
16271 case COND_FLOAT_MOV(MOVF, 0):
16272 case COND_FLOAT_MOV(MOVF, 1):
16273 case COND_FLOAT_MOV(MOVF, 2):
16274 case COND_FLOAT_MOV(MOVF, 3):
16275 case COND_FLOAT_MOV(MOVF, 4):
16276 case COND_FLOAT_MOV(MOVF, 5):
16277 case COND_FLOAT_MOV(MOVF, 6):
16278 case COND_FLOAT_MOV(MOVF, 7):
16279 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16280 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
16281 break;
16282 default:
16283 MIPS_INVAL("pool32fxf");
16284 gen_reserved_instruction(ctx);
16285 break;
16289 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
16291 int32_t offset;
16292 uint16_t insn;
16293 int rt, rs, rd, rr;
16294 int16_t imm;
16295 uint32_t op, minor, minor2, mips32_op;
16296 uint32_t cond, fmt, cc;
16298 insn = translator_lduw(env, ctx->base.pc_next + 2);
16299 ctx->opcode = (ctx->opcode << 16) | insn;
16301 rt = (ctx->opcode >> 21) & 0x1f;
16302 rs = (ctx->opcode >> 16) & 0x1f;
16303 rd = (ctx->opcode >> 11) & 0x1f;
16304 rr = (ctx->opcode >> 6) & 0x1f;
16305 imm = (int16_t) ctx->opcode;
16307 op = (ctx->opcode >> 26) & 0x3f;
16308 switch (op) {
16309 case POOL32A:
16310 minor = ctx->opcode & 0x3f;
16311 switch (minor) {
16312 case 0x00:
16313 minor = (ctx->opcode >> 6) & 0xf;
16314 switch (minor) {
16315 case SLL32:
16316 mips32_op = OPC_SLL;
16317 goto do_shifti;
16318 case SRA:
16319 mips32_op = OPC_SRA;
16320 goto do_shifti;
16321 case SRL32:
16322 mips32_op = OPC_SRL;
16323 goto do_shifti;
16324 case ROTR:
16325 mips32_op = OPC_ROTR;
16326 do_shifti:
16327 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
16328 break;
16329 case SELEQZ:
16330 check_insn(ctx, ISA_MIPS_R6);
16331 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
16332 break;
16333 case SELNEZ:
16334 check_insn(ctx, ISA_MIPS_R6);
16335 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
16336 break;
16337 case R6_RDHWR:
16338 check_insn(ctx, ISA_MIPS_R6);
16339 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
16340 break;
16341 default:
16342 goto pool32a_invalid;
16344 break;
16345 case 0x10:
16346 minor = (ctx->opcode >> 6) & 0xf;
16347 switch (minor) {
16348 /* Arithmetic */
16349 case ADD:
16350 mips32_op = OPC_ADD;
16351 goto do_arith;
16352 case ADDU32:
16353 mips32_op = OPC_ADDU;
16354 goto do_arith;
16355 case SUB:
16356 mips32_op = OPC_SUB;
16357 goto do_arith;
16358 case SUBU32:
16359 mips32_op = OPC_SUBU;
16360 goto do_arith;
16361 case MUL:
16362 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16363 mips32_op = OPC_MUL;
16364 do_arith:
16365 gen_arith(ctx, mips32_op, rd, rs, rt);
16366 break;
16367 /* Shifts */
16368 case SLLV:
16369 mips32_op = OPC_SLLV;
16370 goto do_shift;
16371 case SRLV:
16372 mips32_op = OPC_SRLV;
16373 goto do_shift;
16374 case SRAV:
16375 mips32_op = OPC_SRAV;
16376 goto do_shift;
16377 case ROTRV:
16378 mips32_op = OPC_ROTRV;
16379 do_shift:
16380 gen_shift(ctx, mips32_op, rd, rs, rt);
16381 break;
16382 /* Logical operations */
16383 case AND:
16384 mips32_op = OPC_AND;
16385 goto do_logic;
16386 case OR32:
16387 mips32_op = OPC_OR;
16388 goto do_logic;
16389 case NOR:
16390 mips32_op = OPC_NOR;
16391 goto do_logic;
16392 case XOR32:
16393 mips32_op = OPC_XOR;
16394 do_logic:
16395 gen_logic(ctx, mips32_op, rd, rs, rt);
16396 break;
16397 /* Set less than */
16398 case SLT:
16399 mips32_op = OPC_SLT;
16400 goto do_slt;
16401 case SLTU:
16402 mips32_op = OPC_SLTU;
16403 do_slt:
16404 gen_slt(ctx, mips32_op, rd, rs, rt);
16405 break;
16406 default:
16407 goto pool32a_invalid;
16409 break;
16410 case 0x18:
16411 minor = (ctx->opcode >> 6) & 0xf;
16412 switch (minor) {
16413 /* Conditional moves */
16414 case MOVN: /* MUL */
16415 if (ctx->insn_flags & ISA_MIPS_R6) {
16416 /* MUL */
16417 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
16418 } else {
16419 /* MOVN */
16420 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
16422 break;
16423 case MOVZ: /* MUH */
16424 if (ctx->insn_flags & ISA_MIPS_R6) {
16425 /* MUH */
16426 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
16427 } else {
16428 /* MOVZ */
16429 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
16431 break;
16432 case MULU:
16433 check_insn(ctx, ISA_MIPS_R6);
16434 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
16435 break;
16436 case MUHU:
16437 check_insn(ctx, ISA_MIPS_R6);
16438 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
16439 break;
16440 case LWXS: /* DIV */
16441 if (ctx->insn_flags & ISA_MIPS_R6) {
16442 /* DIV */
16443 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
16444 } else {
16445 /* LWXS */
16446 gen_ldxs(ctx, rs, rt, rd);
16448 break;
16449 case MOD:
16450 check_insn(ctx, ISA_MIPS_R6);
16451 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
16452 break;
16453 case R6_DIVU:
16454 check_insn(ctx, ISA_MIPS_R6);
16455 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
16456 break;
16457 case MODU:
16458 check_insn(ctx, ISA_MIPS_R6);
16459 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
16460 break;
16461 default:
16462 goto pool32a_invalid;
16464 break;
16465 case INS:
16466 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
16467 return;
16468 case LSA:
16469 check_insn(ctx, ISA_MIPS_R6);
16470 gen_lsa(ctx, rd, rt, rs, extract32(ctx->opcode, 9, 2));
16471 break;
16472 case ALIGN:
16473 check_insn(ctx, ISA_MIPS_R6);
16474 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
16475 break;
16476 case EXT:
16477 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
16478 return;
16479 case POOL32AXF:
16480 gen_pool32axf(env, ctx, rt, rs);
16481 break;
16482 case BREAK32:
16483 generate_exception_end(ctx, EXCP_BREAK);
16484 break;
16485 case SIGRIE:
16486 check_insn(ctx, ISA_MIPS_R6);
16487 gen_reserved_instruction(ctx);
16488 break;
16489 default:
16490 pool32a_invalid:
16491 MIPS_INVAL("pool32a");
16492 gen_reserved_instruction(ctx);
16493 break;
16495 break;
16496 case POOL32B:
16497 minor = (ctx->opcode >> 12) & 0xf;
16498 switch (minor) {
16499 case CACHE:
16500 check_cp0_enabled(ctx);
16501 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16502 gen_cache_operation(ctx, rt, rs, imm);
16504 break;
16505 case LWC2:
16506 case SWC2:
16507 /* COP2: Not implemented. */
16508 generate_exception_err(ctx, EXCP_CpU, 2);
16509 break;
16510 #ifdef TARGET_MIPS64
16511 case LDP:
16512 case SDP:
16513 check_insn(ctx, ISA_MIPS3);
16514 check_mips_64(ctx);
16515 #endif
16516 /* fall through */
16517 case LWP:
16518 case SWP:
16519 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16520 break;
16521 #ifdef TARGET_MIPS64
16522 case LDM:
16523 case SDM:
16524 check_insn(ctx, ISA_MIPS3);
16525 check_mips_64(ctx);
16526 #endif
16527 /* fall through */
16528 case LWM32:
16529 case SWM32:
16530 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16531 break;
16532 default:
16533 MIPS_INVAL("pool32b");
16534 gen_reserved_instruction(ctx);
16535 break;
16537 break;
16538 case POOL32F:
16539 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
16540 minor = ctx->opcode & 0x3f;
16541 check_cp1_enabled(ctx);
16542 switch (minor) {
16543 case ALNV_PS:
16544 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16545 mips32_op = OPC_ALNV_PS;
16546 goto do_madd;
16547 case MADD_S:
16548 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16549 mips32_op = OPC_MADD_S;
16550 goto do_madd;
16551 case MADD_D:
16552 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16553 mips32_op = OPC_MADD_D;
16554 goto do_madd;
16555 case MADD_PS:
16556 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16557 mips32_op = OPC_MADD_PS;
16558 goto do_madd;
16559 case MSUB_S:
16560 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16561 mips32_op = OPC_MSUB_S;
16562 goto do_madd;
16563 case MSUB_D:
16564 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16565 mips32_op = OPC_MSUB_D;
16566 goto do_madd;
16567 case MSUB_PS:
16568 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16569 mips32_op = OPC_MSUB_PS;
16570 goto do_madd;
16571 case NMADD_S:
16572 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16573 mips32_op = OPC_NMADD_S;
16574 goto do_madd;
16575 case NMADD_D:
16576 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16577 mips32_op = OPC_NMADD_D;
16578 goto do_madd;
16579 case NMADD_PS:
16580 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16581 mips32_op = OPC_NMADD_PS;
16582 goto do_madd;
16583 case NMSUB_S:
16584 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16585 mips32_op = OPC_NMSUB_S;
16586 goto do_madd;
16587 case NMSUB_D:
16588 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16589 mips32_op = OPC_NMSUB_D;
16590 goto do_madd;
16591 case NMSUB_PS:
16592 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16593 mips32_op = OPC_NMSUB_PS;
16594 do_madd:
16595 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
16596 break;
16597 case CABS_COND_FMT:
16598 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16599 cond = (ctx->opcode >> 6) & 0xf;
16600 cc = (ctx->opcode >> 13) & 0x7;
16601 fmt = (ctx->opcode >> 10) & 0x3;
16602 switch (fmt) {
16603 case 0x0:
16604 gen_cmpabs_s(ctx, cond, rt, rs, cc);
16605 break;
16606 case 0x1:
16607 gen_cmpabs_d(ctx, cond, rt, rs, cc);
16608 break;
16609 case 0x2:
16610 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
16611 break;
16612 default:
16613 goto pool32f_invalid;
16615 break;
16616 case C_COND_FMT:
16617 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16618 cond = (ctx->opcode >> 6) & 0xf;
16619 cc = (ctx->opcode >> 13) & 0x7;
16620 fmt = (ctx->opcode >> 10) & 0x3;
16621 switch (fmt) {
16622 case 0x0:
16623 gen_cmp_s(ctx, cond, rt, rs, cc);
16624 break;
16625 case 0x1:
16626 gen_cmp_d(ctx, cond, rt, rs, cc);
16627 break;
16628 case 0x2:
16629 gen_cmp_ps(ctx, cond, rt, rs, cc);
16630 break;
16631 default:
16632 goto pool32f_invalid;
16634 break;
16635 case CMP_CONDN_S:
16636 check_insn(ctx, ISA_MIPS_R6);
16637 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16638 break;
16639 case CMP_CONDN_D:
16640 check_insn(ctx, ISA_MIPS_R6);
16641 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16642 break;
16643 case POOL32FXF:
16644 gen_pool32fxf(ctx, rt, rs);
16645 break;
16646 case 0x00:
16647 /* PLL foo */
16648 switch ((ctx->opcode >> 6) & 0x7) {
16649 case PLL_PS:
16650 mips32_op = OPC_PLL_PS;
16651 goto do_ps;
16652 case PLU_PS:
16653 mips32_op = OPC_PLU_PS;
16654 goto do_ps;
16655 case PUL_PS:
16656 mips32_op = OPC_PUL_PS;
16657 goto do_ps;
16658 case PUU_PS:
16659 mips32_op = OPC_PUU_PS;
16660 goto do_ps;
16661 case CVT_PS_S:
16662 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16663 mips32_op = OPC_CVT_PS_S;
16664 do_ps:
16665 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16666 break;
16667 default:
16668 goto pool32f_invalid;
16670 break;
16671 case MIN_FMT:
16672 check_insn(ctx, ISA_MIPS_R6);
16673 switch ((ctx->opcode >> 9) & 0x3) {
16674 case FMT_SDPS_S:
16675 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
16676 break;
16677 case FMT_SDPS_D:
16678 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
16679 break;
16680 default:
16681 goto pool32f_invalid;
16683 break;
16684 case 0x08:
16685 /* [LS][WDU]XC1 */
16686 switch ((ctx->opcode >> 6) & 0x7) {
16687 case LWXC1:
16688 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16689 mips32_op = OPC_LWXC1;
16690 goto do_ldst_cp1;
16691 case SWXC1:
16692 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16693 mips32_op = OPC_SWXC1;
16694 goto do_ldst_cp1;
16695 case LDXC1:
16696 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16697 mips32_op = OPC_LDXC1;
16698 goto do_ldst_cp1;
16699 case SDXC1:
16700 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16701 mips32_op = OPC_SDXC1;
16702 goto do_ldst_cp1;
16703 case LUXC1:
16704 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16705 mips32_op = OPC_LUXC1;
16706 goto do_ldst_cp1;
16707 case SUXC1:
16708 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16709 mips32_op = OPC_SUXC1;
16710 do_ldst_cp1:
16711 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
16712 break;
16713 default:
16714 goto pool32f_invalid;
16716 break;
16717 case MAX_FMT:
16718 check_insn(ctx, ISA_MIPS_R6);
16719 switch ((ctx->opcode >> 9) & 0x3) {
16720 case FMT_SDPS_S:
16721 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
16722 break;
16723 case FMT_SDPS_D:
16724 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
16725 break;
16726 default:
16727 goto pool32f_invalid;
16729 break;
16730 case 0x18:
16731 /* 3D insns */
16732 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16733 fmt = (ctx->opcode >> 9) & 0x3;
16734 switch ((ctx->opcode >> 6) & 0x7) {
16735 case RSQRT2_FMT:
16736 switch (fmt) {
16737 case FMT_SDPS_S:
16738 mips32_op = OPC_RSQRT2_S;
16739 goto do_3d;
16740 case FMT_SDPS_D:
16741 mips32_op = OPC_RSQRT2_D;
16742 goto do_3d;
16743 case FMT_SDPS_PS:
16744 mips32_op = OPC_RSQRT2_PS;
16745 goto do_3d;
16746 default:
16747 goto pool32f_invalid;
16749 break;
16750 case RECIP2_FMT:
16751 switch (fmt) {
16752 case FMT_SDPS_S:
16753 mips32_op = OPC_RECIP2_S;
16754 goto do_3d;
16755 case FMT_SDPS_D:
16756 mips32_op = OPC_RECIP2_D;
16757 goto do_3d;
16758 case FMT_SDPS_PS:
16759 mips32_op = OPC_RECIP2_PS;
16760 goto do_3d;
16761 default:
16762 goto pool32f_invalid;
16764 break;
16765 case ADDR_PS:
16766 mips32_op = OPC_ADDR_PS;
16767 goto do_3d;
16768 case MULR_PS:
16769 mips32_op = OPC_MULR_PS;
16770 do_3d:
16771 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16772 break;
16773 default:
16774 goto pool32f_invalid;
16776 break;
16777 case 0x20:
16778 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
16779 cc = (ctx->opcode >> 13) & 0x7;
16780 fmt = (ctx->opcode >> 9) & 0x3;
16781 switch ((ctx->opcode >> 6) & 0x7) {
16782 case MOVF_FMT: /* RINT_FMT */
16783 if (ctx->insn_flags & ISA_MIPS_R6) {
16784 /* RINT_FMT */
16785 switch (fmt) {
16786 case FMT_SDPS_S:
16787 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
16788 break;
16789 case FMT_SDPS_D:
16790 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
16791 break;
16792 default:
16793 goto pool32f_invalid;
16795 } else {
16796 /* MOVF_FMT */
16797 switch (fmt) {
16798 case FMT_SDPS_S:
16799 gen_movcf_s(ctx, rs, rt, cc, 0);
16800 break;
16801 case FMT_SDPS_D:
16802 gen_movcf_d(ctx, rs, rt, cc, 0);
16803 break;
16804 case FMT_SDPS_PS:
16805 check_ps(ctx);
16806 gen_movcf_ps(ctx, rs, rt, cc, 0);
16807 break;
16808 default:
16809 goto pool32f_invalid;
16812 break;
16813 case MOVT_FMT: /* CLASS_FMT */
16814 if (ctx->insn_flags & ISA_MIPS_R6) {
16815 /* CLASS_FMT */
16816 switch (fmt) {
16817 case FMT_SDPS_S:
16818 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
16819 break;
16820 case FMT_SDPS_D:
16821 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
16822 break;
16823 default:
16824 goto pool32f_invalid;
16826 } else {
16827 /* MOVT_FMT */
16828 switch (fmt) {
16829 case FMT_SDPS_S:
16830 gen_movcf_s(ctx, rs, rt, cc, 1);
16831 break;
16832 case FMT_SDPS_D:
16833 gen_movcf_d(ctx, rs, rt, cc, 1);
16834 break;
16835 case FMT_SDPS_PS:
16836 check_ps(ctx);
16837 gen_movcf_ps(ctx, rs, rt, cc, 1);
16838 break;
16839 default:
16840 goto pool32f_invalid;
16843 break;
16844 case PREFX:
16845 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16846 break;
16847 default:
16848 goto pool32f_invalid;
16850 break;
16851 #define FINSN_3ARG_SDPS(prfx) \
16852 switch ((ctx->opcode >> 8) & 0x3) { \
16853 case FMT_SDPS_S: \
16854 mips32_op = OPC_##prfx##_S; \
16855 goto do_fpop; \
16856 case FMT_SDPS_D: \
16857 mips32_op = OPC_##prfx##_D; \
16858 goto do_fpop; \
16859 case FMT_SDPS_PS: \
16860 check_ps(ctx); \
16861 mips32_op = OPC_##prfx##_PS; \
16862 goto do_fpop; \
16863 default: \
16864 goto pool32f_invalid; \
16866 case MINA_FMT:
16867 check_insn(ctx, ISA_MIPS_R6);
16868 switch ((ctx->opcode >> 9) & 0x3) {
16869 case FMT_SDPS_S:
16870 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
16871 break;
16872 case FMT_SDPS_D:
16873 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
16874 break;
16875 default:
16876 goto pool32f_invalid;
16878 break;
16879 case MAXA_FMT:
16880 check_insn(ctx, ISA_MIPS_R6);
16881 switch ((ctx->opcode >> 9) & 0x3) {
16882 case FMT_SDPS_S:
16883 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
16884 break;
16885 case FMT_SDPS_D:
16886 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
16887 break;
16888 default:
16889 goto pool32f_invalid;
16891 break;
16892 case 0x30:
16893 /* regular FP ops */
16894 switch ((ctx->opcode >> 6) & 0x3) {
16895 case ADD_FMT:
16896 FINSN_3ARG_SDPS(ADD);
16897 break;
16898 case SUB_FMT:
16899 FINSN_3ARG_SDPS(SUB);
16900 break;
16901 case MUL_FMT:
16902 FINSN_3ARG_SDPS(MUL);
16903 break;
16904 case DIV_FMT:
16905 fmt = (ctx->opcode >> 8) & 0x3;
16906 if (fmt == 1) {
16907 mips32_op = OPC_DIV_D;
16908 } else if (fmt == 0) {
16909 mips32_op = OPC_DIV_S;
16910 } else {
16911 goto pool32f_invalid;
16913 goto do_fpop;
16914 default:
16915 goto pool32f_invalid;
16917 break;
16918 case 0x38:
16919 /* cmovs */
16920 switch ((ctx->opcode >> 6) & 0x7) {
16921 case MOVN_FMT: /* SELEQZ_FMT */
16922 if (ctx->insn_flags & ISA_MIPS_R6) {
16923 /* SELEQZ_FMT */
16924 switch ((ctx->opcode >> 9) & 0x3) {
16925 case FMT_SDPS_S:
16926 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
16927 break;
16928 case FMT_SDPS_D:
16929 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
16930 break;
16931 default:
16932 goto pool32f_invalid;
16934 } else {
16935 /* MOVN_FMT */
16936 FINSN_3ARG_SDPS(MOVN);
16938 break;
16939 case MOVN_FMT_04:
16940 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16941 FINSN_3ARG_SDPS(MOVN);
16942 break;
16943 case MOVZ_FMT: /* SELNEZ_FMT */
16944 if (ctx->insn_flags & ISA_MIPS_R6) {
16945 /* SELNEZ_FMT */
16946 switch ((ctx->opcode >> 9) & 0x3) {
16947 case FMT_SDPS_S:
16948 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
16949 break;
16950 case FMT_SDPS_D:
16951 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
16952 break;
16953 default:
16954 goto pool32f_invalid;
16956 } else {
16957 /* MOVZ_FMT */
16958 FINSN_3ARG_SDPS(MOVZ);
16960 break;
16961 case MOVZ_FMT_05:
16962 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16963 FINSN_3ARG_SDPS(MOVZ);
16964 break;
16965 case SEL_FMT:
16966 check_insn(ctx, ISA_MIPS_R6);
16967 switch ((ctx->opcode >> 9) & 0x3) {
16968 case FMT_SDPS_S:
16969 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
16970 break;
16971 case FMT_SDPS_D:
16972 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
16973 break;
16974 default:
16975 goto pool32f_invalid;
16977 break;
16978 case MADDF_FMT:
16979 check_insn(ctx, ISA_MIPS_R6);
16980 switch ((ctx->opcode >> 9) & 0x3) {
16981 case FMT_SDPS_S:
16982 mips32_op = OPC_MADDF_S;
16983 goto do_fpop;
16984 case FMT_SDPS_D:
16985 mips32_op = OPC_MADDF_D;
16986 goto do_fpop;
16987 default:
16988 goto pool32f_invalid;
16990 break;
16991 case MSUBF_FMT:
16992 check_insn(ctx, ISA_MIPS_R6);
16993 switch ((ctx->opcode >> 9) & 0x3) {
16994 case FMT_SDPS_S:
16995 mips32_op = OPC_MSUBF_S;
16996 goto do_fpop;
16997 case FMT_SDPS_D:
16998 mips32_op = OPC_MSUBF_D;
16999 goto do_fpop;
17000 default:
17001 goto pool32f_invalid;
17003 break;
17004 default:
17005 goto pool32f_invalid;
17007 break;
17008 do_fpop:
17009 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
17010 break;
17011 default:
17012 pool32f_invalid:
17013 MIPS_INVAL("pool32f");
17014 gen_reserved_instruction(ctx);
17015 break;
17017 } else {
17018 generate_exception_err(ctx, EXCP_CpU, 1);
17020 break;
17021 case POOL32I:
17022 minor = (ctx->opcode >> 21) & 0x1f;
17023 switch (minor) {
17024 case BLTZ:
17025 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17026 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
17027 break;
17028 case BLTZAL:
17029 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17030 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
17031 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17032 break;
17033 case BLTZALS:
17034 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17035 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
17036 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17037 break;
17038 case BGEZ:
17039 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17040 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
17041 break;
17042 case BGEZAL:
17043 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17044 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
17045 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17046 break;
17047 case BGEZALS:
17048 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17049 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
17050 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17051 break;
17052 case BLEZ:
17053 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17054 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
17055 break;
17056 case BGTZ:
17057 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17058 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
17059 break;
17061 /* Traps */
17062 case TLTI: /* BC1EQZC */
17063 if (ctx->insn_flags & ISA_MIPS_R6) {
17064 /* BC1EQZC */
17065 check_cp1_enabled(ctx);
17066 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
17067 } else {
17068 /* TLTI */
17069 mips32_op = OPC_TLTI;
17070 goto do_trapi;
17072 break;
17073 case TGEI: /* BC1NEZC */
17074 if (ctx->insn_flags & ISA_MIPS_R6) {
17075 /* BC1NEZC */
17076 check_cp1_enabled(ctx);
17077 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
17078 } else {
17079 /* TGEI */
17080 mips32_op = OPC_TGEI;
17081 goto do_trapi;
17083 break;
17084 case TLTIU:
17085 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17086 mips32_op = OPC_TLTIU;
17087 goto do_trapi;
17088 case TGEIU:
17089 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17090 mips32_op = OPC_TGEIU;
17091 goto do_trapi;
17092 case TNEI: /* SYNCI */
17093 if (ctx->insn_flags & ISA_MIPS_R6) {
17094 /* SYNCI */
17096 * Break the TB to be able to sync copied instructions
17097 * immediately.
17099 ctx->base.is_jmp = DISAS_STOP;
17100 } else {
17101 /* TNEI */
17102 mips32_op = OPC_TNEI;
17103 goto do_trapi;
17105 break;
17106 case TEQI:
17107 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17108 mips32_op = OPC_TEQI;
17109 do_trapi:
17110 gen_trap(ctx, mips32_op, rs, -1, imm);
17111 break;
17113 case BNEZC:
17114 case BEQZC:
17115 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17116 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
17117 4, rs, 0, imm << 1, 0);
17119 * Compact branches don't have a delay slot, so just let
17120 * the normal delay slot handling take us to the branch
17121 * target.
17123 break;
17124 case LUI:
17125 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17126 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
17127 break;
17128 case SYNCI:
17129 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17131 * Break the TB to be able to sync copied instructions
17132 * immediately.
17134 ctx->base.is_jmp = DISAS_STOP;
17135 break;
17136 case BC2F:
17137 case BC2T:
17138 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17139 /* COP2: Not implemented. */
17140 generate_exception_err(ctx, EXCP_CpU, 2);
17141 break;
17142 case BC1F:
17143 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17144 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
17145 goto do_cp1branch;
17146 case BC1T:
17147 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17148 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
17149 goto do_cp1branch;
17150 case BC1ANY4F:
17151 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17152 mips32_op = OPC_BC1FANY4;
17153 goto do_cp1mips3d;
17154 case BC1ANY4T:
17155 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17156 mips32_op = OPC_BC1TANY4;
17157 do_cp1mips3d:
17158 check_cop1x(ctx);
17159 check_insn(ctx, ASE_MIPS3D);
17160 /* Fall through */
17161 do_cp1branch:
17162 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
17163 check_cp1_enabled(ctx);
17164 gen_compute_branch1(ctx, mips32_op,
17165 (ctx->opcode >> 18) & 0x7, imm << 1);
17166 } else {
17167 generate_exception_err(ctx, EXCP_CpU, 1);
17169 break;
17170 case BPOSGE64:
17171 case BPOSGE32:
17172 /* MIPS DSP: not implemented */
17173 /* Fall through */
17174 default:
17175 MIPS_INVAL("pool32i");
17176 gen_reserved_instruction(ctx);
17177 break;
17179 break;
17180 case POOL32C:
17181 minor = (ctx->opcode >> 12) & 0xf;
17182 offset = sextract32(ctx->opcode, 0,
17183 (ctx->insn_flags & ISA_MIPS_R6) ? 9 : 12);
17184 switch (minor) {
17185 case LWL:
17186 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17187 mips32_op = OPC_LWL;
17188 goto do_ld_lr;
17189 case SWL:
17190 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17191 mips32_op = OPC_SWL;
17192 goto do_st_lr;
17193 case LWR:
17194 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17195 mips32_op = OPC_LWR;
17196 goto do_ld_lr;
17197 case SWR:
17198 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17199 mips32_op = OPC_SWR;
17200 goto do_st_lr;
17201 #if defined(TARGET_MIPS64)
17202 case LDL:
17203 check_insn(ctx, ISA_MIPS3);
17204 check_mips_64(ctx);
17205 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17206 mips32_op = OPC_LDL;
17207 goto do_ld_lr;
17208 case SDL:
17209 check_insn(ctx, ISA_MIPS3);
17210 check_mips_64(ctx);
17211 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17212 mips32_op = OPC_SDL;
17213 goto do_st_lr;
17214 case LDR:
17215 check_insn(ctx, ISA_MIPS3);
17216 check_mips_64(ctx);
17217 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17218 mips32_op = OPC_LDR;
17219 goto do_ld_lr;
17220 case SDR:
17221 check_insn(ctx, ISA_MIPS3);
17222 check_mips_64(ctx);
17223 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17224 mips32_op = OPC_SDR;
17225 goto do_st_lr;
17226 case LWU:
17227 check_insn(ctx, ISA_MIPS3);
17228 check_mips_64(ctx);
17229 mips32_op = OPC_LWU;
17230 goto do_ld_lr;
17231 case LLD:
17232 check_insn(ctx, ISA_MIPS3);
17233 check_mips_64(ctx);
17234 mips32_op = OPC_LLD;
17235 goto do_ld_lr;
17236 #endif
17237 case LL:
17238 mips32_op = OPC_LL;
17239 goto do_ld_lr;
17240 do_ld_lr:
17241 gen_ld(ctx, mips32_op, rt, rs, offset);
17242 break;
17243 do_st_lr:
17244 gen_st(ctx, mips32_op, rt, rs, offset);
17245 break;
17246 case SC:
17247 gen_st_cond(ctx, rt, rs, offset, MO_TESL, false);
17248 break;
17249 #if defined(TARGET_MIPS64)
17250 case SCD:
17251 check_insn(ctx, ISA_MIPS3);
17252 check_mips_64(ctx);
17253 gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false);
17254 break;
17255 #endif
17256 case LD_EVA:
17257 if (!ctx->eva) {
17258 MIPS_INVAL("pool32c ld-eva");
17259 gen_reserved_instruction(ctx);
17260 break;
17262 check_cp0_enabled(ctx);
17264 minor2 = (ctx->opcode >> 9) & 0x7;
17265 offset = sextract32(ctx->opcode, 0, 9);
17266 switch (minor2) {
17267 case LBUE:
17268 mips32_op = OPC_LBUE;
17269 goto do_ld_lr;
17270 case LHUE:
17271 mips32_op = OPC_LHUE;
17272 goto do_ld_lr;
17273 case LWLE:
17274 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17275 mips32_op = OPC_LWLE;
17276 goto do_ld_lr;
17277 case LWRE:
17278 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17279 mips32_op = OPC_LWRE;
17280 goto do_ld_lr;
17281 case LBE:
17282 mips32_op = OPC_LBE;
17283 goto do_ld_lr;
17284 case LHE:
17285 mips32_op = OPC_LHE;
17286 goto do_ld_lr;
17287 case LLE:
17288 mips32_op = OPC_LLE;
17289 goto do_ld_lr;
17290 case LWE:
17291 mips32_op = OPC_LWE;
17292 goto do_ld_lr;
17294 break;
17295 case ST_EVA:
17296 if (!ctx->eva) {
17297 MIPS_INVAL("pool32c st-eva");
17298 gen_reserved_instruction(ctx);
17299 break;
17301 check_cp0_enabled(ctx);
17303 minor2 = (ctx->opcode >> 9) & 0x7;
17304 offset = sextract32(ctx->opcode, 0, 9);
17305 switch (minor2) {
17306 case SWLE:
17307 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17308 mips32_op = OPC_SWLE;
17309 goto do_st_lr;
17310 case SWRE:
17311 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17312 mips32_op = OPC_SWRE;
17313 goto do_st_lr;
17314 case PREFE:
17315 /* Treat as no-op */
17316 if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >= 24)) {
17317 /* hint codes 24-31 are reserved and signal RI */
17318 generate_exception(ctx, EXCP_RI);
17320 break;
17321 case CACHEE:
17322 /* Treat as no-op */
17323 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
17324 gen_cache_operation(ctx, rt, rs, offset);
17326 break;
17327 case SBE:
17328 mips32_op = OPC_SBE;
17329 goto do_st_lr;
17330 case SHE:
17331 mips32_op = OPC_SHE;
17332 goto do_st_lr;
17333 case SCE:
17334 gen_st_cond(ctx, rt, rs, offset, MO_TESL, true);
17335 break;
17336 case SWE:
17337 mips32_op = OPC_SWE;
17338 goto do_st_lr;
17340 break;
17341 case PREF:
17342 /* Treat as no-op */
17343 if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >= 24)) {
17344 /* hint codes 24-31 are reserved and signal RI */
17345 generate_exception(ctx, EXCP_RI);
17347 break;
17348 default:
17349 MIPS_INVAL("pool32c");
17350 gen_reserved_instruction(ctx);
17351 break;
17353 break;
17354 case ADDI32: /* AUI, LUI */
17355 if (ctx->insn_flags & ISA_MIPS_R6) {
17356 /* AUI, LUI */
17357 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
17358 } else {
17359 /* ADDI32 */
17360 mips32_op = OPC_ADDI;
17361 goto do_addi;
17363 break;
17364 case ADDIU32:
17365 mips32_op = OPC_ADDIU;
17366 do_addi:
17367 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
17368 break;
17370 /* Logical operations */
17371 case ORI32:
17372 mips32_op = OPC_ORI;
17373 goto do_logici;
17374 case XORI32:
17375 mips32_op = OPC_XORI;
17376 goto do_logici;
17377 case ANDI32:
17378 mips32_op = OPC_ANDI;
17379 do_logici:
17380 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
17381 break;
17383 /* Set less than immediate */
17384 case SLTI32:
17385 mips32_op = OPC_SLTI;
17386 goto do_slti;
17387 case SLTIU32:
17388 mips32_op = OPC_SLTIU;
17389 do_slti:
17390 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
17391 break;
17392 case JALX32:
17393 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17394 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
17395 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
17396 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17397 break;
17398 case JALS32: /* BOVC, BEQC, BEQZALC */
17399 if (ctx->insn_flags & ISA_MIPS_R6) {
17400 if (rs >= rt) {
17401 /* BOVC */
17402 mips32_op = OPC_BOVC;
17403 } else if (rs < rt && rs == 0) {
17404 /* BEQZALC */
17405 mips32_op = OPC_BEQZALC;
17406 } else {
17407 /* BEQC */
17408 mips32_op = OPC_BEQC;
17410 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17411 } else {
17412 /* JALS32 */
17413 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
17414 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
17415 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17417 break;
17418 case BEQ32: /* BC */
17419 if (ctx->insn_flags & ISA_MIPS_R6) {
17420 /* BC */
17421 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
17422 sextract32(ctx->opcode << 1, 0, 27));
17423 } else {
17424 /* BEQ32 */
17425 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
17427 break;
17428 case BNE32: /* BALC */
17429 if (ctx->insn_flags & ISA_MIPS_R6) {
17430 /* BALC */
17431 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
17432 sextract32(ctx->opcode << 1, 0, 27));
17433 } else {
17434 /* BNE32 */
17435 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
17437 break;
17438 case J32: /* BGTZC, BLTZC, BLTC */
17439 if (ctx->insn_flags & ISA_MIPS_R6) {
17440 if (rs == 0 && rt != 0) {
17441 /* BGTZC */
17442 mips32_op = OPC_BGTZC;
17443 } else if (rs != 0 && rt != 0 && rs == rt) {
17444 /* BLTZC */
17445 mips32_op = OPC_BLTZC;
17446 } else {
17447 /* BLTC */
17448 mips32_op = OPC_BLTC;
17450 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17451 } else {
17452 /* J32 */
17453 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
17454 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17456 break;
17457 case JAL32: /* BLEZC, BGEZC, BGEC */
17458 if (ctx->insn_flags & ISA_MIPS_R6) {
17459 if (rs == 0 && rt != 0) {
17460 /* BLEZC */
17461 mips32_op = OPC_BLEZC;
17462 } else if (rs != 0 && rt != 0 && rs == rt) {
17463 /* BGEZC */
17464 mips32_op = OPC_BGEZC;
17465 } else {
17466 /* BGEC */
17467 mips32_op = OPC_BGEC;
17469 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17470 } else {
17471 /* JAL32 */
17472 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
17473 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17474 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17476 break;
17477 /* Floating point (COP1) */
17478 case LWC132:
17479 mips32_op = OPC_LWC1;
17480 goto do_cop1;
17481 case LDC132:
17482 mips32_op = OPC_LDC1;
17483 goto do_cop1;
17484 case SWC132:
17485 mips32_op = OPC_SWC1;
17486 goto do_cop1;
17487 case SDC132:
17488 mips32_op = OPC_SDC1;
17489 do_cop1:
17490 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
17491 break;
17492 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17493 if (ctx->insn_flags & ISA_MIPS_R6) {
17494 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17495 switch ((ctx->opcode >> 16) & 0x1f) {
17496 case ADDIUPC_00:
17497 case ADDIUPC_01:
17498 case ADDIUPC_02:
17499 case ADDIUPC_03:
17500 case ADDIUPC_04:
17501 case ADDIUPC_05:
17502 case ADDIUPC_06:
17503 case ADDIUPC_07:
17504 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
17505 break;
17506 case AUIPC:
17507 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
17508 break;
17509 case ALUIPC:
17510 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
17511 break;
17512 case LWPC_08:
17513 case LWPC_09:
17514 case LWPC_0A:
17515 case LWPC_0B:
17516 case LWPC_0C:
17517 case LWPC_0D:
17518 case LWPC_0E:
17519 case LWPC_0F:
17520 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
17521 break;
17522 default:
17523 generate_exception(ctx, EXCP_RI);
17524 break;
17526 } else {
17527 /* ADDIUPC */
17528 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
17529 offset = SIMM(ctx->opcode, 0, 23) << 2;
17531 gen_addiupc(ctx, reg, offset, 0, 0);
17533 break;
17534 case BNVC: /* BNEC, BNEZALC */
17535 check_insn(ctx, ISA_MIPS_R6);
17536 if (rs >= rt) {
17537 /* BNVC */
17538 mips32_op = OPC_BNVC;
17539 } else if (rs < rt && rs == 0) {
17540 /* BNEZALC */
17541 mips32_op = OPC_BNEZALC;
17542 } else {
17543 /* BNEC */
17544 mips32_op = OPC_BNEC;
17546 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17547 break;
17548 case R6_BNEZC: /* JIALC */
17549 check_insn(ctx, ISA_MIPS_R6);
17550 if (rt != 0) {
17551 /* BNEZC */
17552 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
17553 sextract32(ctx->opcode << 1, 0, 22));
17554 } else {
17555 /* JIALC */
17556 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
17558 break;
17559 case R6_BEQZC: /* JIC */
17560 check_insn(ctx, ISA_MIPS_R6);
17561 if (rt != 0) {
17562 /* BEQZC */
17563 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
17564 sextract32(ctx->opcode << 1, 0, 22));
17565 } else {
17566 /* JIC */
17567 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
17569 break;
17570 case BLEZALC: /* BGEZALC, BGEUC */
17571 check_insn(ctx, ISA_MIPS_R6);
17572 if (rs == 0 && rt != 0) {
17573 /* BLEZALC */
17574 mips32_op = OPC_BLEZALC;
17575 } else if (rs != 0 && rt != 0 && rs == rt) {
17576 /* BGEZALC */
17577 mips32_op = OPC_BGEZALC;
17578 } else {
17579 /* BGEUC */
17580 mips32_op = OPC_BGEUC;
17582 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17583 break;
17584 case BGTZALC: /* BLTZALC, BLTUC */
17585 check_insn(ctx, ISA_MIPS_R6);
17586 if (rs == 0 && rt != 0) {
17587 /* BGTZALC */
17588 mips32_op = OPC_BGTZALC;
17589 } else if (rs != 0 && rt != 0 && rs == rt) {
17590 /* BLTZALC */
17591 mips32_op = OPC_BLTZALC;
17592 } else {
17593 /* BLTUC */
17594 mips32_op = OPC_BLTUC;
17596 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17597 break;
17598 /* Loads and stores */
17599 case LB32:
17600 mips32_op = OPC_LB;
17601 goto do_ld;
17602 case LBU32:
17603 mips32_op = OPC_LBU;
17604 goto do_ld;
17605 case LH32:
17606 mips32_op = OPC_LH;
17607 goto do_ld;
17608 case LHU32:
17609 mips32_op = OPC_LHU;
17610 goto do_ld;
17611 case LW32:
17612 mips32_op = OPC_LW;
17613 goto do_ld;
17614 #ifdef TARGET_MIPS64
17615 case LD32:
17616 check_insn(ctx, ISA_MIPS3);
17617 check_mips_64(ctx);
17618 mips32_op = OPC_LD;
17619 goto do_ld;
17620 case SD32:
17621 check_insn(ctx, ISA_MIPS3);
17622 check_mips_64(ctx);
17623 mips32_op = OPC_SD;
17624 goto do_st;
17625 #endif
17626 case SB32:
17627 mips32_op = OPC_SB;
17628 goto do_st;
17629 case SH32:
17630 mips32_op = OPC_SH;
17631 goto do_st;
17632 case SW32:
17633 mips32_op = OPC_SW;
17634 goto do_st;
17635 do_ld:
17636 gen_ld(ctx, mips32_op, rt, rs, imm);
17637 break;
17638 do_st:
17639 gen_st(ctx, mips32_op, rt, rs, imm);
17640 break;
17641 default:
17642 gen_reserved_instruction(ctx);
17643 break;
17647 static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx)
17649 uint32_t op;
17651 /* make sure instructions are on a halfword boundary */
17652 if (ctx->base.pc_next & 0x1) {
17653 env->CP0_BadVAddr = ctx->base.pc_next;
17654 generate_exception_end(ctx, EXCP_AdEL);
17655 return 2;
17658 op = (ctx->opcode >> 10) & 0x3f;
17659 /* Enforce properly-sized instructions in a delay slot */
17660 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
17661 switch (op & 0x7) { /* MSB-3..MSB-5 */
17662 case 0:
17663 /* POOL32A, POOL32B, POOL32I, POOL32C */
17664 case 4:
17665 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
17666 case 5:
17667 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
17668 case 6:
17669 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
17670 case 7:
17671 /* LB32, LH32, LWC132, LDC132, LW32 */
17672 if (ctx->hflags & MIPS_HFLAG_BDS16) {
17673 gen_reserved_instruction(ctx);
17674 return 2;
17676 break;
17677 case 1:
17678 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
17679 case 2:
17680 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
17681 case 3:
17682 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
17683 if (ctx->hflags & MIPS_HFLAG_BDS32) {
17684 gen_reserved_instruction(ctx);
17685 return 2;
17687 break;
17691 switch (op) {
17692 case POOL16A:
17694 int rd = mmreg(uMIPS_RD(ctx->opcode));
17695 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
17696 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
17697 uint32_t opc = 0;
17699 switch (ctx->opcode & 0x1) {
17700 case ADDU16:
17701 opc = OPC_ADDU;
17702 break;
17703 case SUBU16:
17704 opc = OPC_SUBU;
17705 break;
17707 if (ctx->insn_flags & ISA_MIPS_R6) {
17709 * In the Release 6, the register number location in
17710 * the instruction encoding has changed.
17712 gen_arith(ctx, opc, rs1, rd, rs2);
17713 } else {
17714 gen_arith(ctx, opc, rd, rs1, rs2);
17717 break;
17718 case POOL16B:
17720 int rd = mmreg(uMIPS_RD(ctx->opcode));
17721 int rs = mmreg(uMIPS_RS(ctx->opcode));
17722 int amount = (ctx->opcode >> 1) & 0x7;
17723 uint32_t opc = 0;
17724 amount = amount == 0 ? 8 : amount;
17726 switch (ctx->opcode & 0x1) {
17727 case SLL16:
17728 opc = OPC_SLL;
17729 break;
17730 case SRL16:
17731 opc = OPC_SRL;
17732 break;
17735 gen_shift_imm(ctx, opc, rd, rs, amount);
17737 break;
17738 case POOL16C:
17739 if (ctx->insn_flags & ISA_MIPS_R6) {
17740 gen_pool16c_r6_insn(ctx);
17741 } else {
17742 gen_pool16c_insn(ctx);
17744 break;
17745 case LWGP16:
17747 int rd = mmreg(uMIPS_RD(ctx->opcode));
17748 int rb = 28; /* GP */
17749 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
17751 gen_ld(ctx, OPC_LW, rd, rb, offset);
17753 break;
17754 case POOL16F:
17755 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17756 if (ctx->opcode & 1) {
17757 gen_reserved_instruction(ctx);
17758 } else {
17759 /* MOVEP */
17760 int enc_dest = uMIPS_RD(ctx->opcode);
17761 int enc_rt = uMIPS_RS2(ctx->opcode);
17762 int enc_rs = uMIPS_RS1(ctx->opcode);
17763 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
17765 break;
17766 case LBU16:
17768 int rd = mmreg(uMIPS_RD(ctx->opcode));
17769 int rb = mmreg(uMIPS_RS(ctx->opcode));
17770 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17771 offset = (offset == 0xf ? -1 : offset);
17773 gen_ld(ctx, OPC_LBU, rd, rb, offset);
17775 break;
17776 case LHU16:
17778 int rd = mmreg(uMIPS_RD(ctx->opcode));
17779 int rb = mmreg(uMIPS_RS(ctx->opcode));
17780 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17782 gen_ld(ctx, OPC_LHU, rd, rb, offset);
17784 break;
17785 case LWSP16:
17787 int rd = (ctx->opcode >> 5) & 0x1f;
17788 int rb = 29; /* SP */
17789 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17791 gen_ld(ctx, OPC_LW, rd, rb, offset);
17793 break;
17794 case LW16:
17796 int rd = mmreg(uMIPS_RD(ctx->opcode));
17797 int rb = mmreg(uMIPS_RS(ctx->opcode));
17798 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17800 gen_ld(ctx, OPC_LW, rd, rb, offset);
17802 break;
17803 case SB16:
17805 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17806 int rb = mmreg(uMIPS_RS(ctx->opcode));
17807 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17809 gen_st(ctx, OPC_SB, rd, rb, offset);
17811 break;
17812 case SH16:
17814 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17815 int rb = mmreg(uMIPS_RS(ctx->opcode));
17816 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17818 gen_st(ctx, OPC_SH, rd, rb, offset);
17820 break;
17821 case SWSP16:
17823 int rd = (ctx->opcode >> 5) & 0x1f;
17824 int rb = 29; /* SP */
17825 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17827 gen_st(ctx, OPC_SW, rd, rb, offset);
17829 break;
17830 case SW16:
17832 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17833 int rb = mmreg(uMIPS_RS(ctx->opcode));
17834 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17836 gen_st(ctx, OPC_SW, rd, rb, offset);
17838 break;
17839 case MOVE16:
17841 int rd = uMIPS_RD5(ctx->opcode);
17842 int rs = uMIPS_RS5(ctx->opcode);
17844 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
17846 break;
17847 case ANDI16:
17848 gen_andi16(ctx);
17849 break;
17850 case POOL16D:
17851 switch (ctx->opcode & 0x1) {
17852 case ADDIUS5:
17853 gen_addius5(ctx);
17854 break;
17855 case ADDIUSP:
17856 gen_addiusp(ctx);
17857 break;
17859 break;
17860 case POOL16E:
17861 switch (ctx->opcode & 0x1) {
17862 case ADDIUR2:
17863 gen_addiur2(ctx);
17864 break;
17865 case ADDIUR1SP:
17866 gen_addiur1sp(ctx);
17867 break;
17869 break;
17870 case B16: /* BC16 */
17871 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
17872 sextract32(ctx->opcode, 0, 10) << 1,
17873 (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4);
17874 break;
17875 case BNEZ16: /* BNEZC16 */
17876 case BEQZ16: /* BEQZC16 */
17877 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
17878 mmreg(uMIPS_RD(ctx->opcode)),
17879 0, sextract32(ctx->opcode, 0, 7) << 1,
17880 (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4);
17882 break;
17883 case LI16:
17885 int reg = mmreg(uMIPS_RD(ctx->opcode));
17886 int imm = ZIMM(ctx->opcode, 0, 7);
17888 imm = (imm == 0x7f ? -1 : imm);
17889 tcg_gen_movi_tl(cpu_gpr[reg], imm);
17891 break;
17892 case RES_29:
17893 case RES_31:
17894 case RES_39:
17895 gen_reserved_instruction(ctx);
17896 break;
17897 default:
17898 decode_micromips32_opc(env, ctx);
17899 return 4;
17902 return 2;
17907 * nanoMIPS opcodes
17911 /* MAJOR, P16, and P32 pools opcodes */
17912 enum {
17913 NM_P_ADDIU = 0x00,
17914 NM_ADDIUPC = 0x01,
17915 NM_MOVE_BALC = 0x02,
17916 NM_P16_MV = 0x04,
17917 NM_LW16 = 0x05,
17918 NM_BC16 = 0x06,
17919 NM_P16_SR = 0x07,
17921 NM_POOL32A = 0x08,
17922 NM_P_BAL = 0x0a,
17923 NM_P16_SHIFT = 0x0c,
17924 NM_LWSP16 = 0x0d,
17925 NM_BALC16 = 0x0e,
17926 NM_P16_4X4 = 0x0f,
17928 NM_P_GP_W = 0x10,
17929 NM_P_GP_BH = 0x11,
17930 NM_P_J = 0x12,
17931 NM_P16C = 0x14,
17932 NM_LWGP16 = 0x15,
17933 NM_P16_LB = 0x17,
17935 NM_P48I = 0x18,
17936 NM_P16_A1 = 0x1c,
17937 NM_LW4X4 = 0x1d,
17938 NM_P16_LH = 0x1f,
17940 NM_P_U12 = 0x20,
17941 NM_P_LS_U12 = 0x21,
17942 NM_P_BR1 = 0x22,
17943 NM_P16_A2 = 0x24,
17944 NM_SW16 = 0x25,
17945 NM_BEQZC16 = 0x26,
17947 NM_POOL32F = 0x28,
17948 NM_P_LS_S9 = 0x29,
17949 NM_P_BR2 = 0x2a,
17951 NM_P16_ADDU = 0x2c,
17952 NM_SWSP16 = 0x2d,
17953 NM_BNEZC16 = 0x2e,
17954 NM_MOVEP = 0x2f,
17956 NM_POOL32S = 0x30,
17957 NM_P_BRI = 0x32,
17958 NM_LI16 = 0x34,
17959 NM_SWGP16 = 0x35,
17960 NM_P16_BR = 0x36,
17962 NM_P_LUI = 0x38,
17963 NM_ANDI16 = 0x3c,
17964 NM_SW4X4 = 0x3d,
17965 NM_MOVEPREV = 0x3f,
17968 /* POOL32A instruction pool */
17969 enum {
17970 NM_POOL32A0 = 0x00,
17971 NM_SPECIAL2 = 0x01,
17972 NM_COP2_1 = 0x02,
17973 NM_UDI = 0x03,
17974 NM_POOL32A5 = 0x05,
17975 NM_POOL32A7 = 0x07,
17978 /* P.GP.W instruction pool */
17979 enum {
17980 NM_ADDIUGP_W = 0x00,
17981 NM_LWGP = 0x02,
17982 NM_SWGP = 0x03,
17985 /* P48I instruction pool */
17986 enum {
17987 NM_LI48 = 0x00,
17988 NM_ADDIU48 = 0x01,
17989 NM_ADDIUGP48 = 0x02,
17990 NM_ADDIUPC48 = 0x03,
17991 NM_LWPC48 = 0x0b,
17992 NM_SWPC48 = 0x0f,
17995 /* P.U12 instruction pool */
17996 enum {
17997 NM_ORI = 0x00,
17998 NM_XORI = 0x01,
17999 NM_ANDI = 0x02,
18000 NM_P_SR = 0x03,
18001 NM_SLTI = 0x04,
18002 NM_SLTIU = 0x05,
18003 NM_SEQI = 0x06,
18004 NM_ADDIUNEG = 0x08,
18005 NM_P_SHIFT = 0x0c,
18006 NM_P_ROTX = 0x0d,
18007 NM_P_INS = 0x0e,
18008 NM_P_EXT = 0x0f,
18011 /* POOL32F instruction pool */
18012 enum {
18013 NM_POOL32F_0 = 0x00,
18014 NM_POOL32F_3 = 0x03,
18015 NM_POOL32F_5 = 0x05,
18018 /* POOL32S instruction pool */
18019 enum {
18020 NM_POOL32S_0 = 0x00,
18021 NM_POOL32S_4 = 0x04,
18024 /* P.LUI instruction pool */
18025 enum {
18026 NM_LUI = 0x00,
18027 NM_ALUIPC = 0x01,
18030 /* P.GP.BH instruction pool */
18031 enum {
18032 NM_LBGP = 0x00,
18033 NM_SBGP = 0x01,
18034 NM_LBUGP = 0x02,
18035 NM_ADDIUGP_B = 0x03,
18036 NM_P_GP_LH = 0x04,
18037 NM_P_GP_SH = 0x05,
18038 NM_P_GP_CP1 = 0x06,
18041 /* P.LS.U12 instruction pool */
18042 enum {
18043 NM_LB = 0x00,
18044 NM_SB = 0x01,
18045 NM_LBU = 0x02,
18046 NM_P_PREFU12 = 0x03,
18047 NM_LH = 0x04,
18048 NM_SH = 0x05,
18049 NM_LHU = 0x06,
18050 NM_LWU = 0x07,
18051 NM_LW = 0x08,
18052 NM_SW = 0x09,
18053 NM_LWC1 = 0x0a,
18054 NM_SWC1 = 0x0b,
18055 NM_LDC1 = 0x0e,
18056 NM_SDC1 = 0x0f,
18059 /* P.LS.S9 instruction pool */
18060 enum {
18061 NM_P_LS_S0 = 0x00,
18062 NM_P_LS_S1 = 0x01,
18063 NM_P_LS_E0 = 0x02,
18064 NM_P_LS_WM = 0x04,
18065 NM_P_LS_UAWM = 0x05,
18068 /* P.BAL instruction pool */
18069 enum {
18070 NM_BC = 0x00,
18071 NM_BALC = 0x01,
18074 /* P.J instruction pool */
18075 enum {
18076 NM_JALRC = 0x00,
18077 NM_JALRC_HB = 0x01,
18078 NM_P_BALRSC = 0x08,
18081 /* P.BR1 instruction pool */
18082 enum {
18083 NM_BEQC = 0x00,
18084 NM_P_BR3A = 0x01,
18085 NM_BGEC = 0x02,
18086 NM_BGEUC = 0x03,
18089 /* P.BR2 instruction pool */
18090 enum {
18091 NM_BNEC = 0x00,
18092 NM_BLTC = 0x02,
18093 NM_BLTUC = 0x03,
18096 /* P.BRI instruction pool */
18097 enum {
18098 NM_BEQIC = 0x00,
18099 NM_BBEQZC = 0x01,
18100 NM_BGEIC = 0x02,
18101 NM_BGEIUC = 0x03,
18102 NM_BNEIC = 0x04,
18103 NM_BBNEZC = 0x05,
18104 NM_BLTIC = 0x06,
18105 NM_BLTIUC = 0x07,
18108 /* P16.SHIFT instruction pool */
18109 enum {
18110 NM_SLL16 = 0x00,
18111 NM_SRL16 = 0x01,
18114 /* POOL16C instruction pool */
18115 enum {
18116 NM_POOL16C_0 = 0x00,
18117 NM_LWXS16 = 0x01,
18120 /* P16.A1 instruction pool */
18121 enum {
18122 NM_ADDIUR1SP = 0x01,
18125 /* P16.A2 instruction pool */
18126 enum {
18127 NM_ADDIUR2 = 0x00,
18128 NM_P_ADDIURS5 = 0x01,
18131 /* P16.ADDU instruction pool */
18132 enum {
18133 NM_ADDU16 = 0x00,
18134 NM_SUBU16 = 0x01,
18137 /* P16.SR instruction pool */
18138 enum {
18139 NM_SAVE16 = 0x00,
18140 NM_RESTORE_JRC16 = 0x01,
18143 /* P16.4X4 instruction pool */
18144 enum {
18145 NM_ADDU4X4 = 0x00,
18146 NM_MUL4X4 = 0x01,
18149 /* P16.LB instruction pool */
18150 enum {
18151 NM_LB16 = 0x00,
18152 NM_SB16 = 0x01,
18153 NM_LBU16 = 0x02,
18156 /* P16.LH instruction pool */
18157 enum {
18158 NM_LH16 = 0x00,
18159 NM_SH16 = 0x01,
18160 NM_LHU16 = 0x02,
18163 /* P.RI instruction pool */
18164 enum {
18165 NM_SIGRIE = 0x00,
18166 NM_P_SYSCALL = 0x01,
18167 NM_BREAK = 0x02,
18168 NM_SDBBP = 0x03,
18171 /* POOL32A0 instruction pool */
18172 enum {
18173 NM_P_TRAP = 0x00,
18174 NM_SEB = 0x01,
18175 NM_SLLV = 0x02,
18176 NM_MUL = 0x03,
18177 NM_MFC0 = 0x06,
18178 NM_MFHC0 = 0x07,
18179 NM_SEH = 0x09,
18180 NM_SRLV = 0x0a,
18181 NM_MUH = 0x0b,
18182 NM_MTC0 = 0x0e,
18183 NM_MTHC0 = 0x0f,
18184 NM_SRAV = 0x12,
18185 NM_MULU = 0x13,
18186 NM_ROTRV = 0x1a,
18187 NM_MUHU = 0x1b,
18188 NM_ADD = 0x22,
18189 NM_DIV = 0x23,
18190 NM_ADDU = 0x2a,
18191 NM_MOD = 0x2b,
18192 NM_SUB = 0x32,
18193 NM_DIVU = 0x33,
18194 NM_RDHWR = 0x38,
18195 NM_SUBU = 0x3a,
18196 NM_MODU = 0x3b,
18197 NM_P_CMOVE = 0x42,
18198 NM_FORK = 0x45,
18199 NM_MFTR = 0x46,
18200 NM_MFHTR = 0x47,
18201 NM_AND = 0x4a,
18202 NM_YIELD = 0x4d,
18203 NM_MTTR = 0x4e,
18204 NM_MTHTR = 0x4f,
18205 NM_OR = 0x52,
18206 NM_D_E_MT_VPE = 0x56,
18207 NM_NOR = 0x5a,
18208 NM_XOR = 0x62,
18209 NM_SLT = 0x6a,
18210 NM_P_SLTU = 0x72,
18211 NM_SOV = 0x7a,
18214 /* CRC32 instruction pool */
18215 enum {
18216 NM_CRC32B = 0x00,
18217 NM_CRC32H = 0x01,
18218 NM_CRC32W = 0x02,
18219 NM_CRC32CB = 0x04,
18220 NM_CRC32CH = 0x05,
18221 NM_CRC32CW = 0x06,
18224 /* POOL32A5 instruction pool */
18225 enum {
18226 NM_CMP_EQ_PH = 0x00,
18227 NM_CMP_LT_PH = 0x08,
18228 NM_CMP_LE_PH = 0x10,
18229 NM_CMPGU_EQ_QB = 0x18,
18230 NM_CMPGU_LT_QB = 0x20,
18231 NM_CMPGU_LE_QB = 0x28,
18232 NM_CMPGDU_EQ_QB = 0x30,
18233 NM_CMPGDU_LT_QB = 0x38,
18234 NM_CMPGDU_LE_QB = 0x40,
18235 NM_CMPU_EQ_QB = 0x48,
18236 NM_CMPU_LT_QB = 0x50,
18237 NM_CMPU_LE_QB = 0x58,
18238 NM_ADDQ_S_W = 0x60,
18239 NM_SUBQ_S_W = 0x68,
18240 NM_ADDSC = 0x70,
18241 NM_ADDWC = 0x78,
18243 NM_ADDQ_S_PH = 0x01,
18244 NM_ADDQH_R_PH = 0x09,
18245 NM_ADDQH_R_W = 0x11,
18246 NM_ADDU_S_QB = 0x19,
18247 NM_ADDU_S_PH = 0x21,
18248 NM_ADDUH_R_QB = 0x29,
18249 NM_SHRAV_R_PH = 0x31,
18250 NM_SHRAV_R_QB = 0x39,
18251 NM_SUBQ_S_PH = 0x41,
18252 NM_SUBQH_R_PH = 0x49,
18253 NM_SUBQH_R_W = 0x51,
18254 NM_SUBU_S_QB = 0x59,
18255 NM_SUBU_S_PH = 0x61,
18256 NM_SUBUH_R_QB = 0x69,
18257 NM_SHLLV_S_PH = 0x71,
18258 NM_PRECR_SRA_R_PH_W = 0x79,
18260 NM_MULEU_S_PH_QBL = 0x12,
18261 NM_MULEU_S_PH_QBR = 0x1a,
18262 NM_MULQ_RS_PH = 0x22,
18263 NM_MULQ_S_PH = 0x2a,
18264 NM_MULQ_RS_W = 0x32,
18265 NM_MULQ_S_W = 0x3a,
18266 NM_APPEND = 0x42,
18267 NM_MODSUB = 0x52,
18268 NM_SHRAV_R_W = 0x5a,
18269 NM_SHRLV_PH = 0x62,
18270 NM_SHRLV_QB = 0x6a,
18271 NM_SHLLV_QB = 0x72,
18272 NM_SHLLV_S_W = 0x7a,
18274 NM_SHILO = 0x03,
18276 NM_MULEQ_S_W_PHL = 0x04,
18277 NM_MULEQ_S_W_PHR = 0x0c,
18279 NM_MUL_S_PH = 0x05,
18280 NM_PRECR_QB_PH = 0x0d,
18281 NM_PRECRQ_QB_PH = 0x15,
18282 NM_PRECRQ_PH_W = 0x1d,
18283 NM_PRECRQ_RS_PH_W = 0x25,
18284 NM_PRECRQU_S_QB_PH = 0x2d,
18285 NM_PACKRL_PH = 0x35,
18286 NM_PICK_QB = 0x3d,
18287 NM_PICK_PH = 0x45,
18289 NM_SHRA_R_W = 0x5e,
18290 NM_SHRA_R_PH = 0x66,
18291 NM_SHLL_S_PH = 0x76,
18292 NM_SHLL_S_W = 0x7e,
18294 NM_REPL_PH = 0x07
18297 /* POOL32A7 instruction pool */
18298 enum {
18299 NM_P_LSX = 0x00,
18300 NM_LSA = 0x01,
18301 NM_EXTW = 0x03,
18302 NM_POOL32AXF = 0x07,
18305 /* P.SR instruction pool */
18306 enum {
18307 NM_PP_SR = 0x00,
18308 NM_P_SR_F = 0x01,
18311 /* P.SHIFT instruction pool */
18312 enum {
18313 NM_P_SLL = 0x00,
18314 NM_SRL = 0x02,
18315 NM_SRA = 0x04,
18316 NM_ROTR = 0x06,
18319 /* P.ROTX instruction pool */
18320 enum {
18321 NM_ROTX = 0x00,
18324 /* P.INS instruction pool */
18325 enum {
18326 NM_INS = 0x00,
18329 /* P.EXT instruction pool */
18330 enum {
18331 NM_EXT = 0x00,
18334 /* POOL32F_0 (fmt) instruction pool */
18335 enum {
18336 NM_RINT_S = 0x04,
18337 NM_RINT_D = 0x44,
18338 NM_ADD_S = 0x06,
18339 NM_SELEQZ_S = 0x07,
18340 NM_SELEQZ_D = 0x47,
18341 NM_CLASS_S = 0x0c,
18342 NM_CLASS_D = 0x4c,
18343 NM_SUB_S = 0x0e,
18344 NM_SELNEZ_S = 0x0f,
18345 NM_SELNEZ_D = 0x4f,
18346 NM_MUL_S = 0x16,
18347 NM_SEL_S = 0x17,
18348 NM_SEL_D = 0x57,
18349 NM_DIV_S = 0x1e,
18350 NM_ADD_D = 0x26,
18351 NM_SUB_D = 0x2e,
18352 NM_MUL_D = 0x36,
18353 NM_MADDF_S = 0x37,
18354 NM_MADDF_D = 0x77,
18355 NM_DIV_D = 0x3e,
18356 NM_MSUBF_S = 0x3f,
18357 NM_MSUBF_D = 0x7f,
18360 /* POOL32F_3 instruction pool */
18361 enum {
18362 NM_MIN_FMT = 0x00,
18363 NM_MAX_FMT = 0x01,
18364 NM_MINA_FMT = 0x04,
18365 NM_MAXA_FMT = 0x05,
18366 NM_POOL32FXF = 0x07,
18369 /* POOL32F_5 instruction pool */
18370 enum {
18371 NM_CMP_CONDN_S = 0x00,
18372 NM_CMP_CONDN_D = 0x02,
18375 /* P.GP.LH instruction pool */
18376 enum {
18377 NM_LHGP = 0x00,
18378 NM_LHUGP = 0x01,
18381 /* P.GP.SH instruction pool */
18382 enum {
18383 NM_SHGP = 0x00,
18386 /* P.GP.CP1 instruction pool */
18387 enum {
18388 NM_LWC1GP = 0x00,
18389 NM_SWC1GP = 0x01,
18390 NM_LDC1GP = 0x02,
18391 NM_SDC1GP = 0x03,
18394 /* P.LS.S0 instruction pool */
18395 enum {
18396 NM_LBS9 = 0x00,
18397 NM_LHS9 = 0x04,
18398 NM_LWS9 = 0x08,
18399 NM_LDS9 = 0x0c,
18401 NM_SBS9 = 0x01,
18402 NM_SHS9 = 0x05,
18403 NM_SWS9 = 0x09,
18404 NM_SDS9 = 0x0d,
18406 NM_LBUS9 = 0x02,
18407 NM_LHUS9 = 0x06,
18408 NM_LWC1S9 = 0x0a,
18409 NM_LDC1S9 = 0x0e,
18411 NM_P_PREFS9 = 0x03,
18412 NM_LWUS9 = 0x07,
18413 NM_SWC1S9 = 0x0b,
18414 NM_SDC1S9 = 0x0f,
18417 /* P.LS.S1 instruction pool */
18418 enum {
18419 NM_ASET_ACLR = 0x02,
18420 NM_UALH = 0x04,
18421 NM_UASH = 0x05,
18422 NM_CACHE = 0x07,
18423 NM_P_LL = 0x0a,
18424 NM_P_SC = 0x0b,
18427 /* P.LS.E0 instruction pool */
18428 enum {
18429 NM_LBE = 0x00,
18430 NM_SBE = 0x01,
18431 NM_LBUE = 0x02,
18432 NM_P_PREFE = 0x03,
18433 NM_LHE = 0x04,
18434 NM_SHE = 0x05,
18435 NM_LHUE = 0x06,
18436 NM_CACHEE = 0x07,
18437 NM_LWE = 0x08,
18438 NM_SWE = 0x09,
18439 NM_P_LLE = 0x0a,
18440 NM_P_SCE = 0x0b,
18443 /* P.PREFE instruction pool */
18444 enum {
18445 NM_SYNCIE = 0x00,
18446 NM_PREFE = 0x01,
18449 /* P.LLE instruction pool */
18450 enum {
18451 NM_LLE = 0x00,
18452 NM_LLWPE = 0x01,
18455 /* P.SCE instruction pool */
18456 enum {
18457 NM_SCE = 0x00,
18458 NM_SCWPE = 0x01,
18461 /* P.LS.WM instruction pool */
18462 enum {
18463 NM_LWM = 0x00,
18464 NM_SWM = 0x01,
18467 /* P.LS.UAWM instruction pool */
18468 enum {
18469 NM_UALWM = 0x00,
18470 NM_UASWM = 0x01,
18473 /* P.BR3A instruction pool */
18474 enum {
18475 NM_BC1EQZC = 0x00,
18476 NM_BC1NEZC = 0x01,
18477 NM_BC2EQZC = 0x02,
18478 NM_BC2NEZC = 0x03,
18479 NM_BPOSGE32C = 0x04,
18482 /* P16.RI instruction pool */
18483 enum {
18484 NM_P16_SYSCALL = 0x01,
18485 NM_BREAK16 = 0x02,
18486 NM_SDBBP16 = 0x03,
18489 /* POOL16C_0 instruction pool */
18490 enum {
18491 NM_POOL16C_00 = 0x00,
18494 /* P16.JRC instruction pool */
18495 enum {
18496 NM_JRC = 0x00,
18497 NM_JALRC16 = 0x01,
18500 /* P.SYSCALL instruction pool */
18501 enum {
18502 NM_SYSCALL = 0x00,
18503 NM_HYPCALL = 0x01,
18506 /* P.TRAP instruction pool */
18507 enum {
18508 NM_TEQ = 0x00,
18509 NM_TNE = 0x01,
18512 /* P.CMOVE instruction pool */
18513 enum {
18514 NM_MOVZ = 0x00,
18515 NM_MOVN = 0x01,
18518 /* POOL32Axf instruction pool */
18519 enum {
18520 NM_POOL32AXF_1 = 0x01,
18521 NM_POOL32AXF_2 = 0x02,
18522 NM_POOL32AXF_4 = 0x04,
18523 NM_POOL32AXF_5 = 0x05,
18524 NM_POOL32AXF_7 = 0x07,
18527 /* POOL32Axf_1 instruction pool */
18528 enum {
18529 NM_POOL32AXF_1_0 = 0x00,
18530 NM_POOL32AXF_1_1 = 0x01,
18531 NM_POOL32AXF_1_3 = 0x03,
18532 NM_POOL32AXF_1_4 = 0x04,
18533 NM_POOL32AXF_1_5 = 0x05,
18534 NM_POOL32AXF_1_7 = 0x07,
18537 /* POOL32Axf_2 instruction pool */
18538 enum {
18539 NM_POOL32AXF_2_0_7 = 0x00,
18540 NM_POOL32AXF_2_8_15 = 0x01,
18541 NM_POOL32AXF_2_16_23 = 0x02,
18542 NM_POOL32AXF_2_24_31 = 0x03,
18545 /* POOL32Axf_7 instruction pool */
18546 enum {
18547 NM_SHRA_R_QB = 0x0,
18548 NM_SHRL_PH = 0x1,
18549 NM_REPL_QB = 0x2,
18552 /* POOL32Axf_1_0 instruction pool */
18553 enum {
18554 NM_MFHI = 0x0,
18555 NM_MFLO = 0x1,
18556 NM_MTHI = 0x2,
18557 NM_MTLO = 0x3,
18560 /* POOL32Axf_1_1 instruction pool */
18561 enum {
18562 NM_MTHLIP = 0x0,
18563 NM_SHILOV = 0x1,
18566 /* POOL32Axf_1_3 instruction pool */
18567 enum {
18568 NM_RDDSP = 0x0,
18569 NM_WRDSP = 0x1,
18570 NM_EXTP = 0x2,
18571 NM_EXTPDP = 0x3,
18574 /* POOL32Axf_1_4 instruction pool */
18575 enum {
18576 NM_SHLL_QB = 0x0,
18577 NM_SHRL_QB = 0x1,
18580 /* POOL32Axf_1_5 instruction pool */
18581 enum {
18582 NM_MAQ_S_W_PHR = 0x0,
18583 NM_MAQ_S_W_PHL = 0x1,
18584 NM_MAQ_SA_W_PHR = 0x2,
18585 NM_MAQ_SA_W_PHL = 0x3,
18588 /* POOL32Axf_1_7 instruction pool */
18589 enum {
18590 NM_EXTR_W = 0x0,
18591 NM_EXTR_R_W = 0x1,
18592 NM_EXTR_RS_W = 0x2,
18593 NM_EXTR_S_H = 0x3,
18596 /* POOL32Axf_2_0_7 instruction pool */
18597 enum {
18598 NM_DPA_W_PH = 0x0,
18599 NM_DPAQ_S_W_PH = 0x1,
18600 NM_DPS_W_PH = 0x2,
18601 NM_DPSQ_S_W_PH = 0x3,
18602 NM_BALIGN = 0x4,
18603 NM_MADD = 0x5,
18604 NM_MULT = 0x6,
18605 NM_EXTRV_W = 0x7,
18608 /* POOL32Axf_2_8_15 instruction pool */
18609 enum {
18610 NM_DPAX_W_PH = 0x0,
18611 NM_DPAQ_SA_L_W = 0x1,
18612 NM_DPSX_W_PH = 0x2,
18613 NM_DPSQ_SA_L_W = 0x3,
18614 NM_MADDU = 0x5,
18615 NM_MULTU = 0x6,
18616 NM_EXTRV_R_W = 0x7,
18619 /* POOL32Axf_2_16_23 instruction pool */
18620 enum {
18621 NM_DPAU_H_QBL = 0x0,
18622 NM_DPAQX_S_W_PH = 0x1,
18623 NM_DPSU_H_QBL = 0x2,
18624 NM_DPSQX_S_W_PH = 0x3,
18625 NM_EXTPV = 0x4,
18626 NM_MSUB = 0x5,
18627 NM_MULSA_W_PH = 0x6,
18628 NM_EXTRV_RS_W = 0x7,
18631 /* POOL32Axf_2_24_31 instruction pool */
18632 enum {
18633 NM_DPAU_H_QBR = 0x0,
18634 NM_DPAQX_SA_W_PH = 0x1,
18635 NM_DPSU_H_QBR = 0x2,
18636 NM_DPSQX_SA_W_PH = 0x3,
18637 NM_EXTPDPV = 0x4,
18638 NM_MSUBU = 0x5,
18639 NM_MULSAQ_S_W_PH = 0x6,
18640 NM_EXTRV_S_H = 0x7,
18643 /* POOL32Axf_{4, 5} instruction pool */
18644 enum {
18645 NM_CLO = 0x25,
18646 NM_CLZ = 0x2d,
18648 NM_TLBP = 0x01,
18649 NM_TLBR = 0x09,
18650 NM_TLBWI = 0x11,
18651 NM_TLBWR = 0x19,
18652 NM_TLBINV = 0x03,
18653 NM_TLBINVF = 0x0b,
18654 NM_DI = 0x23,
18655 NM_EI = 0x2b,
18656 NM_RDPGPR = 0x70,
18657 NM_WRPGPR = 0x78,
18658 NM_WAIT = 0x61,
18659 NM_DERET = 0x71,
18660 NM_ERETX = 0x79,
18662 /* nanoMIPS DSP instructions */
18663 NM_ABSQ_S_QB = 0x00,
18664 NM_ABSQ_S_PH = 0x08,
18665 NM_ABSQ_S_W = 0x10,
18666 NM_PRECEQ_W_PHL = 0x28,
18667 NM_PRECEQ_W_PHR = 0x30,
18668 NM_PRECEQU_PH_QBL = 0x38,
18669 NM_PRECEQU_PH_QBR = 0x48,
18670 NM_PRECEU_PH_QBL = 0x58,
18671 NM_PRECEU_PH_QBR = 0x68,
18672 NM_PRECEQU_PH_QBLA = 0x39,
18673 NM_PRECEQU_PH_QBRA = 0x49,
18674 NM_PRECEU_PH_QBLA = 0x59,
18675 NM_PRECEU_PH_QBRA = 0x69,
18676 NM_REPLV_PH = 0x01,
18677 NM_REPLV_QB = 0x09,
18678 NM_BITREV = 0x18,
18679 NM_INSV = 0x20,
18680 NM_RADDU_W_QB = 0x78,
18682 NM_BITSWAP = 0x05,
18683 NM_WSBH = 0x3d,
18686 /* PP.SR instruction pool */
18687 enum {
18688 NM_SAVE = 0x00,
18689 NM_RESTORE = 0x02,
18690 NM_RESTORE_JRC = 0x03,
18693 /* P.SR.F instruction pool */
18694 enum {
18695 NM_SAVEF = 0x00,
18696 NM_RESTOREF = 0x01,
18699 /* P16.SYSCALL instruction pool */
18700 enum {
18701 NM_SYSCALL16 = 0x00,
18702 NM_HYPCALL16 = 0x01,
18705 /* POOL16C_00 instruction pool */
18706 enum {
18707 NM_NOT16 = 0x00,
18708 NM_XOR16 = 0x01,
18709 NM_AND16 = 0x02,
18710 NM_OR16 = 0x03,
18713 /* PP.LSX and PP.LSXS instruction pool */
18714 enum {
18715 NM_LBX = 0x00,
18716 NM_LHX = 0x04,
18717 NM_LWX = 0x08,
18718 NM_LDX = 0x0c,
18720 NM_SBX = 0x01,
18721 NM_SHX = 0x05,
18722 NM_SWX = 0x09,
18723 NM_SDX = 0x0d,
18725 NM_LBUX = 0x02,
18726 NM_LHUX = 0x06,
18727 NM_LWC1X = 0x0a,
18728 NM_LDC1X = 0x0e,
18730 NM_LWUX = 0x07,
18731 NM_SWC1X = 0x0b,
18732 NM_SDC1X = 0x0f,
18734 NM_LHXS = 0x04,
18735 NM_LWXS = 0x08,
18736 NM_LDXS = 0x0c,
18738 NM_SHXS = 0x05,
18739 NM_SWXS = 0x09,
18740 NM_SDXS = 0x0d,
18742 NM_LHUXS = 0x06,
18743 NM_LWC1XS = 0x0a,
18744 NM_LDC1XS = 0x0e,
18746 NM_LWUXS = 0x07,
18747 NM_SWC1XS = 0x0b,
18748 NM_SDC1XS = 0x0f,
18751 /* ERETx instruction pool */
18752 enum {
18753 NM_ERET = 0x00,
18754 NM_ERETNC = 0x01,
18757 /* POOL32FxF_{0, 1} insturction pool */
18758 enum {
18759 NM_CFC1 = 0x40,
18760 NM_CTC1 = 0x60,
18761 NM_MFC1 = 0x80,
18762 NM_MTC1 = 0xa0,
18763 NM_MFHC1 = 0xc0,
18764 NM_MTHC1 = 0xe0,
18766 NM_CVT_S_PL = 0x84,
18767 NM_CVT_S_PU = 0xa4,
18769 NM_CVT_L_S = 0x004,
18770 NM_CVT_L_D = 0x104,
18771 NM_CVT_W_S = 0x024,
18772 NM_CVT_W_D = 0x124,
18774 NM_RSQRT_S = 0x008,
18775 NM_RSQRT_D = 0x108,
18777 NM_SQRT_S = 0x028,
18778 NM_SQRT_D = 0x128,
18780 NM_RECIP_S = 0x048,
18781 NM_RECIP_D = 0x148,
18783 NM_FLOOR_L_S = 0x00c,
18784 NM_FLOOR_L_D = 0x10c,
18786 NM_FLOOR_W_S = 0x02c,
18787 NM_FLOOR_W_D = 0x12c,
18789 NM_CEIL_L_S = 0x04c,
18790 NM_CEIL_L_D = 0x14c,
18791 NM_CEIL_W_S = 0x06c,
18792 NM_CEIL_W_D = 0x16c,
18793 NM_TRUNC_L_S = 0x08c,
18794 NM_TRUNC_L_D = 0x18c,
18795 NM_TRUNC_W_S = 0x0ac,
18796 NM_TRUNC_W_D = 0x1ac,
18797 NM_ROUND_L_S = 0x0cc,
18798 NM_ROUND_L_D = 0x1cc,
18799 NM_ROUND_W_S = 0x0ec,
18800 NM_ROUND_W_D = 0x1ec,
18802 NM_MOV_S = 0x01,
18803 NM_MOV_D = 0x81,
18804 NM_ABS_S = 0x0d,
18805 NM_ABS_D = 0x8d,
18806 NM_NEG_S = 0x2d,
18807 NM_NEG_D = 0xad,
18808 NM_CVT_D_S = 0x04d,
18809 NM_CVT_D_W = 0x0cd,
18810 NM_CVT_D_L = 0x14d,
18811 NM_CVT_S_D = 0x06d,
18812 NM_CVT_S_W = 0x0ed,
18813 NM_CVT_S_L = 0x16d,
18816 /* P.LL instruction pool */
18817 enum {
18818 NM_LL = 0x00,
18819 NM_LLWP = 0x01,
18822 /* P.SC instruction pool */
18823 enum {
18824 NM_SC = 0x00,
18825 NM_SCWP = 0x01,
18828 /* P.DVP instruction pool */
18829 enum {
18830 NM_DVP = 0x00,
18831 NM_EVP = 0x01,
18837 * nanoMIPS decoding engine
18842 /* extraction utilities */
18844 #define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7)
18845 #define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7)
18846 #define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7)
18847 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18848 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18850 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
18851 static inline int decode_gpr_gpr3(int r)
18853 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
18855 return map[r & 0x7];
18858 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
18859 static inline int decode_gpr_gpr3_src_store(int r)
18861 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
18863 return map[r & 0x7];
18866 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
18867 static inline int decode_gpr_gpr4(int r)
18869 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
18870 16, 17, 18, 19, 20, 21, 22, 23 };
18872 return map[r & 0xf];
18875 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
18876 static inline int decode_gpr_gpr4_zero(int r)
18878 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
18879 16, 17, 18, 19, 20, 21, 22, 23 };
18881 return map[r & 0xf];
18885 static void gen_adjust_sp(DisasContext *ctx, int u)
18887 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
18890 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
18891 uint8_t gp, uint16_t u)
18893 int counter = 0;
18894 TCGv va = tcg_temp_new();
18895 TCGv t0 = tcg_temp_new();
18897 while (counter != count) {
18898 bool use_gp = gp && (counter == count - 1);
18899 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18900 int this_offset = -((counter + 1) << 2);
18901 gen_base_offset_addr(ctx, va, 29, this_offset);
18902 gen_load_gpr(t0, this_rt);
18903 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
18904 (MO_TEUL | ctx->default_tcg_memop_mask));
18905 counter++;
18908 /* adjust stack pointer */
18909 gen_adjust_sp(ctx, -u);
18911 tcg_temp_free(t0);
18912 tcg_temp_free(va);
18915 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
18916 uint8_t gp, uint16_t u)
18918 int counter = 0;
18919 TCGv va = tcg_temp_new();
18920 TCGv t0 = tcg_temp_new();
18922 while (counter != count) {
18923 bool use_gp = gp && (counter == count - 1);
18924 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18925 int this_offset = u - ((counter + 1) << 2);
18926 gen_base_offset_addr(ctx, va, 29, this_offset);
18927 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
18928 ctx->default_tcg_memop_mask);
18929 tcg_gen_ext32s_tl(t0, t0);
18930 gen_store_gpr(t0, this_rt);
18931 counter++;
18934 /* adjust stack pointer */
18935 gen_adjust_sp(ctx, u);
18937 tcg_temp_free(t0);
18938 tcg_temp_free(va);
18941 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
18943 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
18944 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
18946 switch (extract32(ctx->opcode, 2, 2)) {
18947 case NM_NOT16:
18948 gen_logic(ctx, OPC_NOR, rt, rs, 0);
18949 break;
18950 case NM_AND16:
18951 gen_logic(ctx, OPC_AND, rt, rt, rs);
18952 break;
18953 case NM_XOR16:
18954 gen_logic(ctx, OPC_XOR, rt, rt, rs);
18955 break;
18956 case NM_OR16:
18957 gen_logic(ctx, OPC_OR, rt, rt, rs);
18958 break;
18962 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18964 int rt = extract32(ctx->opcode, 21, 5);
18965 int rs = extract32(ctx->opcode, 16, 5);
18966 int rd = extract32(ctx->opcode, 11, 5);
18968 switch (extract32(ctx->opcode, 3, 7)) {
18969 case NM_P_TRAP:
18970 switch (extract32(ctx->opcode, 10, 1)) {
18971 case NM_TEQ:
18972 check_nms(ctx);
18973 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
18974 break;
18975 case NM_TNE:
18976 check_nms(ctx);
18977 gen_trap(ctx, OPC_TNE, rs, rt, -1);
18978 break;
18980 break;
18981 case NM_RDHWR:
18982 check_nms(ctx);
18983 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
18984 break;
18985 case NM_SEB:
18986 check_nms(ctx);
18987 gen_bshfl(ctx, OPC_SEB, rs, rt);
18988 break;
18989 case NM_SEH:
18990 gen_bshfl(ctx, OPC_SEH, rs, rt);
18991 break;
18992 case NM_SLLV:
18993 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
18994 break;
18995 case NM_SRLV:
18996 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
18997 break;
18998 case NM_SRAV:
18999 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
19000 break;
19001 case NM_ROTRV:
19002 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
19003 break;
19004 case NM_ADD:
19005 gen_arith(ctx, OPC_ADD, rd, rs, rt);
19006 break;
19007 case NM_ADDU:
19008 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
19009 break;
19010 case NM_SUB:
19011 check_nms(ctx);
19012 gen_arith(ctx, OPC_SUB, rd, rs, rt);
19013 break;
19014 case NM_SUBU:
19015 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
19016 break;
19017 case NM_P_CMOVE:
19018 switch (extract32(ctx->opcode, 10, 1)) {
19019 case NM_MOVZ:
19020 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
19021 break;
19022 case NM_MOVN:
19023 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
19024 break;
19026 break;
19027 case NM_AND:
19028 gen_logic(ctx, OPC_AND, rd, rs, rt);
19029 break;
19030 case NM_OR:
19031 gen_logic(ctx, OPC_OR, rd, rs, rt);
19032 break;
19033 case NM_NOR:
19034 gen_logic(ctx, OPC_NOR, rd, rs, rt);
19035 break;
19036 case NM_XOR:
19037 gen_logic(ctx, OPC_XOR, rd, rs, rt);
19038 break;
19039 case NM_SLT:
19040 gen_slt(ctx, OPC_SLT, rd, rs, rt);
19041 break;
19042 case NM_P_SLTU:
19043 if (rd == 0) {
19044 /* P_DVP */
19045 #ifndef CONFIG_USER_ONLY
19046 TCGv t0 = tcg_temp_new();
19047 switch (extract32(ctx->opcode, 10, 1)) {
19048 case NM_DVP:
19049 if (ctx->vp) {
19050 check_cp0_enabled(ctx);
19051 gen_helper_dvp(t0, cpu_env);
19052 gen_store_gpr(t0, rt);
19054 break;
19055 case NM_EVP:
19056 if (ctx->vp) {
19057 check_cp0_enabled(ctx);
19058 gen_helper_evp(t0, cpu_env);
19059 gen_store_gpr(t0, rt);
19061 break;
19063 tcg_temp_free(t0);
19064 #endif
19065 } else {
19066 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
19068 break;
19069 case NM_SOV:
19071 TCGv t0 = tcg_temp_new();
19072 TCGv t1 = tcg_temp_new();
19073 TCGv t2 = tcg_temp_new();
19075 gen_load_gpr(t1, rs);
19076 gen_load_gpr(t2, rt);
19077 tcg_gen_add_tl(t0, t1, t2);
19078 tcg_gen_ext32s_tl(t0, t0);
19079 tcg_gen_xor_tl(t1, t1, t2);
19080 tcg_gen_xor_tl(t2, t0, t2);
19081 tcg_gen_andc_tl(t1, t2, t1);
19083 /* operands of same sign, result different sign */
19084 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
19085 gen_store_gpr(t0, rd);
19087 tcg_temp_free(t0);
19088 tcg_temp_free(t1);
19089 tcg_temp_free(t2);
19091 break;
19092 case NM_MUL:
19093 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
19094 break;
19095 case NM_MUH:
19096 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
19097 break;
19098 case NM_MULU:
19099 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
19100 break;
19101 case NM_MUHU:
19102 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
19103 break;
19104 case NM_DIV:
19105 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
19106 break;
19107 case NM_MOD:
19108 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
19109 break;
19110 case NM_DIVU:
19111 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
19112 break;
19113 case NM_MODU:
19114 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
19115 break;
19116 #ifndef CONFIG_USER_ONLY
19117 case NM_MFC0:
19118 check_cp0_enabled(ctx);
19119 if (rt == 0) {
19120 /* Treat as NOP. */
19121 break;
19123 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
19124 break;
19125 case NM_MTC0:
19126 check_cp0_enabled(ctx);
19128 TCGv t0 = tcg_temp_new();
19130 gen_load_gpr(t0, rt);
19131 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
19132 tcg_temp_free(t0);
19134 break;
19135 case NM_D_E_MT_VPE:
19137 uint8_t sc = extract32(ctx->opcode, 10, 1);
19138 TCGv t0 = tcg_temp_new();
19140 switch (sc) {
19141 case 0:
19142 if (rs == 1) {
19143 /* DMT */
19144 check_cp0_mt(ctx);
19145 gen_helper_dmt(t0);
19146 gen_store_gpr(t0, rt);
19147 } else if (rs == 0) {
19148 /* DVPE */
19149 check_cp0_mt(ctx);
19150 gen_helper_dvpe(t0, cpu_env);
19151 gen_store_gpr(t0, rt);
19152 } else {
19153 gen_reserved_instruction(ctx);
19155 break;
19156 case 1:
19157 if (rs == 1) {
19158 /* EMT */
19159 check_cp0_mt(ctx);
19160 gen_helper_emt(t0);
19161 gen_store_gpr(t0, rt);
19162 } else if (rs == 0) {
19163 /* EVPE */
19164 check_cp0_mt(ctx);
19165 gen_helper_evpe(t0, cpu_env);
19166 gen_store_gpr(t0, rt);
19167 } else {
19168 gen_reserved_instruction(ctx);
19170 break;
19173 tcg_temp_free(t0);
19175 break;
19176 case NM_FORK:
19177 check_mt(ctx);
19179 TCGv t0 = tcg_temp_new();
19180 TCGv t1 = tcg_temp_new();
19182 gen_load_gpr(t0, rt);
19183 gen_load_gpr(t1, rs);
19184 gen_helper_fork(t0, t1);
19185 tcg_temp_free(t0);
19186 tcg_temp_free(t1);
19188 break;
19189 case NM_MFTR:
19190 case NM_MFHTR:
19191 check_cp0_enabled(ctx);
19192 if (rd == 0) {
19193 /* Treat as NOP. */
19194 return;
19196 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
19197 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
19198 break;
19199 case NM_MTTR:
19200 case NM_MTHTR:
19201 check_cp0_enabled(ctx);
19202 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
19203 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
19204 break;
19205 case NM_YIELD:
19206 check_mt(ctx);
19208 TCGv t0 = tcg_temp_new();
19210 gen_load_gpr(t0, rs);
19211 gen_helper_yield(t0, cpu_env, t0);
19212 gen_store_gpr(t0, rt);
19213 tcg_temp_free(t0);
19215 break;
19216 #endif
19217 default:
19218 gen_reserved_instruction(ctx);
19219 break;
19223 /* dsp */
19224 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
19225 int ret, int v1, int v2)
19227 TCGv_i32 t0;
19228 TCGv v0_t;
19229 TCGv v1_t;
19231 t0 = tcg_temp_new_i32();
19233 v0_t = tcg_temp_new();
19234 v1_t = tcg_temp_new();
19236 tcg_gen_movi_i32(t0, v2 >> 3);
19238 gen_load_gpr(v0_t, ret);
19239 gen_load_gpr(v1_t, v1);
19241 switch (opc) {
19242 case NM_MAQ_S_W_PHR:
19243 check_dsp(ctx);
19244 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
19245 break;
19246 case NM_MAQ_S_W_PHL:
19247 check_dsp(ctx);
19248 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
19249 break;
19250 case NM_MAQ_SA_W_PHR:
19251 check_dsp(ctx);
19252 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
19253 break;
19254 case NM_MAQ_SA_W_PHL:
19255 check_dsp(ctx);
19256 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
19257 break;
19258 default:
19259 gen_reserved_instruction(ctx);
19260 break;
19263 tcg_temp_free_i32(t0);
19265 tcg_temp_free(v0_t);
19266 tcg_temp_free(v1_t);
19270 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
19271 int ret, int v1, int v2)
19273 int16_t imm;
19274 TCGv t0 = tcg_temp_new();
19275 TCGv t1 = tcg_temp_new();
19276 TCGv v0_t = tcg_temp_new();
19278 gen_load_gpr(v0_t, v1);
19280 switch (opc) {
19281 case NM_POOL32AXF_1_0:
19282 check_dsp(ctx);
19283 switch (extract32(ctx->opcode, 12, 2)) {
19284 case NM_MFHI:
19285 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
19286 break;
19287 case NM_MFLO:
19288 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
19289 break;
19290 case NM_MTHI:
19291 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
19292 break;
19293 case NM_MTLO:
19294 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
19295 break;
19297 break;
19298 case NM_POOL32AXF_1_1:
19299 check_dsp(ctx);
19300 switch (extract32(ctx->opcode, 12, 2)) {
19301 case NM_MTHLIP:
19302 tcg_gen_movi_tl(t0, v2);
19303 gen_helper_mthlip(t0, v0_t, cpu_env);
19304 break;
19305 case NM_SHILOV:
19306 tcg_gen_movi_tl(t0, v2 >> 3);
19307 gen_helper_shilo(t0, v0_t, cpu_env);
19308 break;
19309 default:
19310 gen_reserved_instruction(ctx);
19311 break;
19313 break;
19314 case NM_POOL32AXF_1_3:
19315 check_dsp(ctx);
19316 imm = extract32(ctx->opcode, 14, 7);
19317 switch (extract32(ctx->opcode, 12, 2)) {
19318 case NM_RDDSP:
19319 tcg_gen_movi_tl(t0, imm);
19320 gen_helper_rddsp(t0, t0, cpu_env);
19321 gen_store_gpr(t0, ret);
19322 break;
19323 case NM_WRDSP:
19324 gen_load_gpr(t0, ret);
19325 tcg_gen_movi_tl(t1, imm);
19326 gen_helper_wrdsp(t0, t1, cpu_env);
19327 break;
19328 case NM_EXTP:
19329 tcg_gen_movi_tl(t0, v2 >> 3);
19330 tcg_gen_movi_tl(t1, v1);
19331 gen_helper_extp(t0, t0, t1, cpu_env);
19332 gen_store_gpr(t0, ret);
19333 break;
19334 case NM_EXTPDP:
19335 tcg_gen_movi_tl(t0, v2 >> 3);
19336 tcg_gen_movi_tl(t1, v1);
19337 gen_helper_extpdp(t0, t0, t1, cpu_env);
19338 gen_store_gpr(t0, ret);
19339 break;
19341 break;
19342 case NM_POOL32AXF_1_4:
19343 check_dsp(ctx);
19344 tcg_gen_movi_tl(t0, v2 >> 2);
19345 switch (extract32(ctx->opcode, 12, 1)) {
19346 case NM_SHLL_QB:
19347 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
19348 gen_store_gpr(t0, ret);
19349 break;
19350 case NM_SHRL_QB:
19351 gen_helper_shrl_qb(t0, t0, v0_t);
19352 gen_store_gpr(t0, ret);
19353 break;
19355 break;
19356 case NM_POOL32AXF_1_5:
19357 opc = extract32(ctx->opcode, 12, 2);
19358 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
19359 break;
19360 case NM_POOL32AXF_1_7:
19361 check_dsp(ctx);
19362 tcg_gen_movi_tl(t0, v2 >> 3);
19363 tcg_gen_movi_tl(t1, v1);
19364 switch (extract32(ctx->opcode, 12, 2)) {
19365 case NM_EXTR_W:
19366 gen_helper_extr_w(t0, t0, t1, cpu_env);
19367 gen_store_gpr(t0, ret);
19368 break;
19369 case NM_EXTR_R_W:
19370 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
19371 gen_store_gpr(t0, ret);
19372 break;
19373 case NM_EXTR_RS_W:
19374 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
19375 gen_store_gpr(t0, ret);
19376 break;
19377 case NM_EXTR_S_H:
19378 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
19379 gen_store_gpr(t0, ret);
19380 break;
19382 break;
19383 default:
19384 gen_reserved_instruction(ctx);
19385 break;
19388 tcg_temp_free(t0);
19389 tcg_temp_free(t1);
19390 tcg_temp_free(v0_t);
19393 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
19394 TCGv v0, TCGv v1, int rd)
19396 TCGv_i32 t0;
19398 t0 = tcg_temp_new_i32();
19400 tcg_gen_movi_i32(t0, rd >> 3);
19402 switch (opc) {
19403 case NM_POOL32AXF_2_0_7:
19404 switch (extract32(ctx->opcode, 9, 3)) {
19405 case NM_DPA_W_PH:
19406 check_dsp_r2(ctx);
19407 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
19408 break;
19409 case NM_DPAQ_S_W_PH:
19410 check_dsp(ctx);
19411 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
19412 break;
19413 case NM_DPS_W_PH:
19414 check_dsp_r2(ctx);
19415 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
19416 break;
19417 case NM_DPSQ_S_W_PH:
19418 check_dsp(ctx);
19419 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
19420 break;
19421 default:
19422 gen_reserved_instruction(ctx);
19423 break;
19425 break;
19426 case NM_POOL32AXF_2_8_15:
19427 switch (extract32(ctx->opcode, 9, 3)) {
19428 case NM_DPAX_W_PH:
19429 check_dsp_r2(ctx);
19430 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
19431 break;
19432 case NM_DPAQ_SA_L_W:
19433 check_dsp(ctx);
19434 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
19435 break;
19436 case NM_DPSX_W_PH:
19437 check_dsp_r2(ctx);
19438 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
19439 break;
19440 case NM_DPSQ_SA_L_W:
19441 check_dsp(ctx);
19442 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
19443 break;
19444 default:
19445 gen_reserved_instruction(ctx);
19446 break;
19448 break;
19449 case NM_POOL32AXF_2_16_23:
19450 switch (extract32(ctx->opcode, 9, 3)) {
19451 case NM_DPAU_H_QBL:
19452 check_dsp(ctx);
19453 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
19454 break;
19455 case NM_DPAQX_S_W_PH:
19456 check_dsp_r2(ctx);
19457 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
19458 break;
19459 case NM_DPSU_H_QBL:
19460 check_dsp(ctx);
19461 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
19462 break;
19463 case NM_DPSQX_S_W_PH:
19464 check_dsp_r2(ctx);
19465 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
19466 break;
19467 case NM_MULSA_W_PH:
19468 check_dsp_r2(ctx);
19469 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
19470 break;
19471 default:
19472 gen_reserved_instruction(ctx);
19473 break;
19475 break;
19476 case NM_POOL32AXF_2_24_31:
19477 switch (extract32(ctx->opcode, 9, 3)) {
19478 case NM_DPAU_H_QBR:
19479 check_dsp(ctx);
19480 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
19481 break;
19482 case NM_DPAQX_SA_W_PH:
19483 check_dsp_r2(ctx);
19484 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
19485 break;
19486 case NM_DPSU_H_QBR:
19487 check_dsp(ctx);
19488 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
19489 break;
19490 case NM_DPSQX_SA_W_PH:
19491 check_dsp_r2(ctx);
19492 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
19493 break;
19494 case NM_MULSAQ_S_W_PH:
19495 check_dsp(ctx);
19496 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
19497 break;
19498 default:
19499 gen_reserved_instruction(ctx);
19500 break;
19502 break;
19503 default:
19504 gen_reserved_instruction(ctx);
19505 break;
19508 tcg_temp_free_i32(t0);
19511 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
19512 int rt, int rs, int rd)
19514 int ret = rt;
19515 TCGv t0 = tcg_temp_new();
19516 TCGv t1 = tcg_temp_new();
19517 TCGv v0_t = tcg_temp_new();
19518 TCGv v1_t = tcg_temp_new();
19520 gen_load_gpr(v0_t, rt);
19521 gen_load_gpr(v1_t, rs);
19523 switch (opc) {
19524 case NM_POOL32AXF_2_0_7:
19525 switch (extract32(ctx->opcode, 9, 3)) {
19526 case NM_DPA_W_PH:
19527 case NM_DPAQ_S_W_PH:
19528 case NM_DPS_W_PH:
19529 case NM_DPSQ_S_W_PH:
19530 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19531 break;
19532 case NM_BALIGN:
19533 check_dsp_r2(ctx);
19534 if (rt != 0) {
19535 gen_load_gpr(t0, rs);
19536 rd &= 3;
19537 if (rd != 0 && rd != 2) {
19538 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
19539 tcg_gen_ext32u_tl(t0, t0);
19540 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
19541 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19543 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
19545 break;
19546 case NM_MADD:
19547 check_dsp(ctx);
19549 int acc = extract32(ctx->opcode, 14, 2);
19550 TCGv_i64 t2 = tcg_temp_new_i64();
19551 TCGv_i64 t3 = tcg_temp_new_i64();
19553 gen_load_gpr(t0, rt);
19554 gen_load_gpr(t1, rs);
19555 tcg_gen_ext_tl_i64(t2, t0);
19556 tcg_gen_ext_tl_i64(t3, t1);
19557 tcg_gen_mul_i64(t2, t2, t3);
19558 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19559 tcg_gen_add_i64(t2, t2, t3);
19560 tcg_temp_free_i64(t3);
19561 gen_move_low32(cpu_LO[acc], t2);
19562 gen_move_high32(cpu_HI[acc], t2);
19563 tcg_temp_free_i64(t2);
19565 break;
19566 case NM_MULT:
19567 check_dsp(ctx);
19569 int acc = extract32(ctx->opcode, 14, 2);
19570 TCGv_i32 t2 = tcg_temp_new_i32();
19571 TCGv_i32 t3 = tcg_temp_new_i32();
19573 gen_load_gpr(t0, rs);
19574 gen_load_gpr(t1, rt);
19575 tcg_gen_trunc_tl_i32(t2, t0);
19576 tcg_gen_trunc_tl_i32(t3, t1);
19577 tcg_gen_muls2_i32(t2, t3, t2, t3);
19578 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19579 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19580 tcg_temp_free_i32(t2);
19581 tcg_temp_free_i32(t3);
19583 break;
19584 case NM_EXTRV_W:
19585 check_dsp(ctx);
19586 gen_load_gpr(v1_t, rs);
19587 tcg_gen_movi_tl(t0, rd >> 3);
19588 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
19589 gen_store_gpr(t0, ret);
19590 break;
19592 break;
19593 case NM_POOL32AXF_2_8_15:
19594 switch (extract32(ctx->opcode, 9, 3)) {
19595 case NM_DPAX_W_PH:
19596 case NM_DPAQ_SA_L_W:
19597 case NM_DPSX_W_PH:
19598 case NM_DPSQ_SA_L_W:
19599 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19600 break;
19601 case NM_MADDU:
19602 check_dsp(ctx);
19604 int acc = extract32(ctx->opcode, 14, 2);
19605 TCGv_i64 t2 = tcg_temp_new_i64();
19606 TCGv_i64 t3 = tcg_temp_new_i64();
19608 gen_load_gpr(t0, rs);
19609 gen_load_gpr(t1, rt);
19610 tcg_gen_ext32u_tl(t0, t0);
19611 tcg_gen_ext32u_tl(t1, t1);
19612 tcg_gen_extu_tl_i64(t2, t0);
19613 tcg_gen_extu_tl_i64(t3, t1);
19614 tcg_gen_mul_i64(t2, t2, t3);
19615 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19616 tcg_gen_add_i64(t2, t2, t3);
19617 tcg_temp_free_i64(t3);
19618 gen_move_low32(cpu_LO[acc], t2);
19619 gen_move_high32(cpu_HI[acc], t2);
19620 tcg_temp_free_i64(t2);
19622 break;
19623 case NM_MULTU:
19624 check_dsp(ctx);
19626 int acc = extract32(ctx->opcode, 14, 2);
19627 TCGv_i32 t2 = tcg_temp_new_i32();
19628 TCGv_i32 t3 = tcg_temp_new_i32();
19630 gen_load_gpr(t0, rs);
19631 gen_load_gpr(t1, rt);
19632 tcg_gen_trunc_tl_i32(t2, t0);
19633 tcg_gen_trunc_tl_i32(t3, t1);
19634 tcg_gen_mulu2_i32(t2, t3, t2, t3);
19635 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19636 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19637 tcg_temp_free_i32(t2);
19638 tcg_temp_free_i32(t3);
19640 break;
19641 case NM_EXTRV_R_W:
19642 check_dsp(ctx);
19643 tcg_gen_movi_tl(t0, rd >> 3);
19644 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
19645 gen_store_gpr(t0, ret);
19646 break;
19647 default:
19648 gen_reserved_instruction(ctx);
19649 break;
19651 break;
19652 case NM_POOL32AXF_2_16_23:
19653 switch (extract32(ctx->opcode, 9, 3)) {
19654 case NM_DPAU_H_QBL:
19655 case NM_DPAQX_S_W_PH:
19656 case NM_DPSU_H_QBL:
19657 case NM_DPSQX_S_W_PH:
19658 case NM_MULSA_W_PH:
19659 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19660 break;
19661 case NM_EXTPV:
19662 check_dsp(ctx);
19663 tcg_gen_movi_tl(t0, rd >> 3);
19664 gen_helper_extp(t0, t0, v1_t, cpu_env);
19665 gen_store_gpr(t0, ret);
19666 break;
19667 case NM_MSUB:
19668 check_dsp(ctx);
19670 int acc = extract32(ctx->opcode, 14, 2);
19671 TCGv_i64 t2 = tcg_temp_new_i64();
19672 TCGv_i64 t3 = tcg_temp_new_i64();
19674 gen_load_gpr(t0, rs);
19675 gen_load_gpr(t1, rt);
19676 tcg_gen_ext_tl_i64(t2, t0);
19677 tcg_gen_ext_tl_i64(t3, t1);
19678 tcg_gen_mul_i64(t2, t2, t3);
19679 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19680 tcg_gen_sub_i64(t2, t3, t2);
19681 tcg_temp_free_i64(t3);
19682 gen_move_low32(cpu_LO[acc], t2);
19683 gen_move_high32(cpu_HI[acc], t2);
19684 tcg_temp_free_i64(t2);
19686 break;
19687 case NM_EXTRV_RS_W:
19688 check_dsp(ctx);
19689 tcg_gen_movi_tl(t0, rd >> 3);
19690 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
19691 gen_store_gpr(t0, ret);
19692 break;
19694 break;
19695 case NM_POOL32AXF_2_24_31:
19696 switch (extract32(ctx->opcode, 9, 3)) {
19697 case NM_DPAU_H_QBR:
19698 case NM_DPAQX_SA_W_PH:
19699 case NM_DPSU_H_QBR:
19700 case NM_DPSQX_SA_W_PH:
19701 case NM_MULSAQ_S_W_PH:
19702 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19703 break;
19704 case NM_EXTPDPV:
19705 check_dsp(ctx);
19706 tcg_gen_movi_tl(t0, rd >> 3);
19707 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
19708 gen_store_gpr(t0, ret);
19709 break;
19710 case NM_MSUBU:
19711 check_dsp(ctx);
19713 int acc = extract32(ctx->opcode, 14, 2);
19714 TCGv_i64 t2 = tcg_temp_new_i64();
19715 TCGv_i64 t3 = tcg_temp_new_i64();
19717 gen_load_gpr(t0, rs);
19718 gen_load_gpr(t1, rt);
19719 tcg_gen_ext32u_tl(t0, t0);
19720 tcg_gen_ext32u_tl(t1, t1);
19721 tcg_gen_extu_tl_i64(t2, t0);
19722 tcg_gen_extu_tl_i64(t3, t1);
19723 tcg_gen_mul_i64(t2, t2, t3);
19724 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19725 tcg_gen_sub_i64(t2, t3, t2);
19726 tcg_temp_free_i64(t3);
19727 gen_move_low32(cpu_LO[acc], t2);
19728 gen_move_high32(cpu_HI[acc], t2);
19729 tcg_temp_free_i64(t2);
19731 break;
19732 case NM_EXTRV_S_H:
19733 check_dsp(ctx);
19734 tcg_gen_movi_tl(t0, rd >> 3);
19735 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
19736 gen_store_gpr(t0, ret);
19737 break;
19739 break;
19740 default:
19741 gen_reserved_instruction(ctx);
19742 break;
19745 tcg_temp_free(t0);
19746 tcg_temp_free(t1);
19748 tcg_temp_free(v0_t);
19749 tcg_temp_free(v1_t);
19752 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
19753 int rt, int rs)
19755 int ret = rt;
19756 TCGv t0 = tcg_temp_new();
19757 TCGv v0_t = tcg_temp_new();
19759 gen_load_gpr(v0_t, rs);
19761 switch (opc) {
19762 case NM_ABSQ_S_QB:
19763 check_dsp_r2(ctx);
19764 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
19765 gen_store_gpr(v0_t, ret);
19766 break;
19767 case NM_ABSQ_S_PH:
19768 check_dsp(ctx);
19769 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
19770 gen_store_gpr(v0_t, ret);
19771 break;
19772 case NM_ABSQ_S_W:
19773 check_dsp(ctx);
19774 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
19775 gen_store_gpr(v0_t, ret);
19776 break;
19777 case NM_PRECEQ_W_PHL:
19778 check_dsp(ctx);
19779 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
19780 tcg_gen_ext32s_tl(v0_t, v0_t);
19781 gen_store_gpr(v0_t, ret);
19782 break;
19783 case NM_PRECEQ_W_PHR:
19784 check_dsp(ctx);
19785 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
19786 tcg_gen_shli_tl(v0_t, v0_t, 16);
19787 tcg_gen_ext32s_tl(v0_t, v0_t);
19788 gen_store_gpr(v0_t, ret);
19789 break;
19790 case NM_PRECEQU_PH_QBL:
19791 check_dsp(ctx);
19792 gen_helper_precequ_ph_qbl(v0_t, v0_t);
19793 gen_store_gpr(v0_t, ret);
19794 break;
19795 case NM_PRECEQU_PH_QBR:
19796 check_dsp(ctx);
19797 gen_helper_precequ_ph_qbr(v0_t, v0_t);
19798 gen_store_gpr(v0_t, ret);
19799 break;
19800 case NM_PRECEQU_PH_QBLA:
19801 check_dsp(ctx);
19802 gen_helper_precequ_ph_qbla(v0_t, v0_t);
19803 gen_store_gpr(v0_t, ret);
19804 break;
19805 case NM_PRECEQU_PH_QBRA:
19806 check_dsp(ctx);
19807 gen_helper_precequ_ph_qbra(v0_t, v0_t);
19808 gen_store_gpr(v0_t, ret);
19809 break;
19810 case NM_PRECEU_PH_QBL:
19811 check_dsp(ctx);
19812 gen_helper_preceu_ph_qbl(v0_t, v0_t);
19813 gen_store_gpr(v0_t, ret);
19814 break;
19815 case NM_PRECEU_PH_QBR:
19816 check_dsp(ctx);
19817 gen_helper_preceu_ph_qbr(v0_t, v0_t);
19818 gen_store_gpr(v0_t, ret);
19819 break;
19820 case NM_PRECEU_PH_QBLA:
19821 check_dsp(ctx);
19822 gen_helper_preceu_ph_qbla(v0_t, v0_t);
19823 gen_store_gpr(v0_t, ret);
19824 break;
19825 case NM_PRECEU_PH_QBRA:
19826 check_dsp(ctx);
19827 gen_helper_preceu_ph_qbra(v0_t, v0_t);
19828 gen_store_gpr(v0_t, ret);
19829 break;
19830 case NM_REPLV_PH:
19831 check_dsp(ctx);
19832 tcg_gen_ext16u_tl(v0_t, v0_t);
19833 tcg_gen_shli_tl(t0, v0_t, 16);
19834 tcg_gen_or_tl(v0_t, v0_t, t0);
19835 tcg_gen_ext32s_tl(v0_t, v0_t);
19836 gen_store_gpr(v0_t, ret);
19837 break;
19838 case NM_REPLV_QB:
19839 check_dsp(ctx);
19840 tcg_gen_ext8u_tl(v0_t, v0_t);
19841 tcg_gen_shli_tl(t0, v0_t, 8);
19842 tcg_gen_or_tl(v0_t, v0_t, t0);
19843 tcg_gen_shli_tl(t0, v0_t, 16);
19844 tcg_gen_or_tl(v0_t, v0_t, t0);
19845 tcg_gen_ext32s_tl(v0_t, v0_t);
19846 gen_store_gpr(v0_t, ret);
19847 break;
19848 case NM_BITREV:
19849 check_dsp(ctx);
19850 gen_helper_bitrev(v0_t, v0_t);
19851 gen_store_gpr(v0_t, ret);
19852 break;
19853 case NM_INSV:
19854 check_dsp(ctx);
19856 TCGv tv0 = tcg_temp_new();
19858 gen_load_gpr(tv0, rt);
19859 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
19860 gen_store_gpr(v0_t, ret);
19861 tcg_temp_free(tv0);
19863 break;
19864 case NM_RADDU_W_QB:
19865 check_dsp(ctx);
19866 gen_helper_raddu_w_qb(v0_t, v0_t);
19867 gen_store_gpr(v0_t, ret);
19868 break;
19869 case NM_BITSWAP:
19870 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
19871 break;
19872 case NM_CLO:
19873 check_nms(ctx);
19874 gen_cl(ctx, OPC_CLO, ret, rs);
19875 break;
19876 case NM_CLZ:
19877 check_nms(ctx);
19878 gen_cl(ctx, OPC_CLZ, ret, rs);
19879 break;
19880 case NM_WSBH:
19881 gen_bshfl(ctx, OPC_WSBH, ret, rs);
19882 break;
19883 default:
19884 gen_reserved_instruction(ctx);
19885 break;
19888 tcg_temp_free(v0_t);
19889 tcg_temp_free(t0);
19892 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
19893 int rt, int rs, int rd)
19895 TCGv t0 = tcg_temp_new();
19896 TCGv rs_t = tcg_temp_new();
19898 gen_load_gpr(rs_t, rs);
19900 switch (opc) {
19901 case NM_SHRA_R_QB:
19902 check_dsp_r2(ctx);
19903 tcg_gen_movi_tl(t0, rd >> 2);
19904 switch (extract32(ctx->opcode, 12, 1)) {
19905 case 0:
19906 /* NM_SHRA_QB */
19907 gen_helper_shra_qb(t0, t0, rs_t);
19908 gen_store_gpr(t0, rt);
19909 break;
19910 case 1:
19911 /* NM_SHRA_R_QB */
19912 gen_helper_shra_r_qb(t0, t0, rs_t);
19913 gen_store_gpr(t0, rt);
19914 break;
19916 break;
19917 case NM_SHRL_PH:
19918 check_dsp_r2(ctx);
19919 tcg_gen_movi_tl(t0, rd >> 1);
19920 gen_helper_shrl_ph(t0, t0, rs_t);
19921 gen_store_gpr(t0, rt);
19922 break;
19923 case NM_REPL_QB:
19924 check_dsp(ctx);
19926 int16_t imm;
19927 target_long result;
19928 imm = extract32(ctx->opcode, 13, 8);
19929 result = (uint32_t)imm << 24 |
19930 (uint32_t)imm << 16 |
19931 (uint32_t)imm << 8 |
19932 (uint32_t)imm;
19933 result = (int32_t)result;
19934 tcg_gen_movi_tl(t0, result);
19935 gen_store_gpr(t0, rt);
19937 break;
19938 default:
19939 gen_reserved_instruction(ctx);
19940 break;
19942 tcg_temp_free(t0);
19943 tcg_temp_free(rs_t);
19947 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19949 int rt = extract32(ctx->opcode, 21, 5);
19950 int rs = extract32(ctx->opcode, 16, 5);
19951 int rd = extract32(ctx->opcode, 11, 5);
19953 switch (extract32(ctx->opcode, 6, 3)) {
19954 case NM_POOL32AXF_1:
19956 int32_t op1 = extract32(ctx->opcode, 9, 3);
19957 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
19959 break;
19960 case NM_POOL32AXF_2:
19962 int32_t op1 = extract32(ctx->opcode, 12, 2);
19963 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
19965 break;
19966 case NM_POOL32AXF_4:
19968 int32_t op1 = extract32(ctx->opcode, 9, 7);
19969 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
19971 break;
19972 case NM_POOL32AXF_5:
19973 switch (extract32(ctx->opcode, 9, 7)) {
19974 #ifndef CONFIG_USER_ONLY
19975 case NM_TLBP:
19976 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
19977 break;
19978 case NM_TLBR:
19979 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
19980 break;
19981 case NM_TLBWI:
19982 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
19983 break;
19984 case NM_TLBWR:
19985 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
19986 break;
19987 case NM_TLBINV:
19988 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
19989 break;
19990 case NM_TLBINVF:
19991 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
19992 break;
19993 case NM_DI:
19994 check_cp0_enabled(ctx);
19996 TCGv t0 = tcg_temp_new();
19998 save_cpu_state(ctx, 1);
19999 gen_helper_di(t0, cpu_env);
20000 gen_store_gpr(t0, rt);
20001 /* Stop translation as we may have switched the execution mode */
20002 ctx->base.is_jmp = DISAS_STOP;
20003 tcg_temp_free(t0);
20005 break;
20006 case NM_EI:
20007 check_cp0_enabled(ctx);
20009 TCGv t0 = tcg_temp_new();
20011 save_cpu_state(ctx, 1);
20012 gen_helper_ei(t0, cpu_env);
20013 gen_store_gpr(t0, rt);
20014 /* Stop translation as we may have switched the execution mode */
20015 ctx->base.is_jmp = DISAS_STOP;
20016 tcg_temp_free(t0);
20018 break;
20019 case NM_RDPGPR:
20020 gen_load_srsgpr(rs, rt);
20021 break;
20022 case NM_WRPGPR:
20023 gen_store_srsgpr(rs, rt);
20024 break;
20025 case NM_WAIT:
20026 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
20027 break;
20028 case NM_DERET:
20029 gen_cp0(env, ctx, OPC_DERET, 0, 0);
20030 break;
20031 case NM_ERETX:
20032 gen_cp0(env, ctx, OPC_ERET, 0, 0);
20033 break;
20034 #endif
20035 default:
20036 gen_reserved_instruction(ctx);
20037 break;
20039 break;
20040 case NM_POOL32AXF_7:
20042 int32_t op1 = extract32(ctx->opcode, 9, 3);
20043 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
20045 break;
20046 default:
20047 gen_reserved_instruction(ctx);
20048 break;
20052 /* Immediate Value Compact Branches */
20053 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
20054 int rt, int32_t imm, int32_t offset)
20056 TCGCond cond = TCG_COND_ALWAYS;
20057 TCGv t0 = tcg_temp_new();
20058 TCGv t1 = tcg_temp_new();
20060 gen_load_gpr(t0, rt);
20061 tcg_gen_movi_tl(t1, imm);
20062 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20064 /* Load needed operands and calculate btarget */
20065 switch (opc) {
20066 case NM_BEQIC:
20067 if (rt == 0 && imm == 0) {
20068 /* Unconditional branch */
20069 } else if (rt == 0 && imm != 0) {
20070 /* Treat as NOP */
20071 goto out;
20072 } else {
20073 cond = TCG_COND_EQ;
20075 break;
20076 case NM_BBEQZC:
20077 case NM_BBNEZC:
20078 check_nms(ctx);
20079 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
20080 gen_reserved_instruction(ctx);
20081 goto out;
20082 } else if (rt == 0 && opc == NM_BBEQZC) {
20083 /* Unconditional branch */
20084 } else if (rt == 0 && opc == NM_BBNEZC) {
20085 /* Treat as NOP */
20086 goto out;
20087 } else {
20088 tcg_gen_shri_tl(t0, t0, imm);
20089 tcg_gen_andi_tl(t0, t0, 1);
20090 tcg_gen_movi_tl(t1, 0);
20091 if (opc == NM_BBEQZC) {
20092 cond = TCG_COND_EQ;
20093 } else {
20094 cond = TCG_COND_NE;
20097 break;
20098 case NM_BNEIC:
20099 if (rt == 0 && imm == 0) {
20100 /* Treat as NOP */
20101 goto out;
20102 } else if (rt == 0 && imm != 0) {
20103 /* Unconditional branch */
20104 } else {
20105 cond = TCG_COND_NE;
20107 break;
20108 case NM_BGEIC:
20109 if (rt == 0 && imm == 0) {
20110 /* Unconditional branch */
20111 } else {
20112 cond = TCG_COND_GE;
20114 break;
20115 case NM_BLTIC:
20116 cond = TCG_COND_LT;
20117 break;
20118 case NM_BGEIUC:
20119 if (rt == 0 && imm == 0) {
20120 /* Unconditional branch */
20121 } else {
20122 cond = TCG_COND_GEU;
20124 break;
20125 case NM_BLTIUC:
20126 cond = TCG_COND_LTU;
20127 break;
20128 default:
20129 MIPS_INVAL("Immediate Value Compact branch");
20130 gen_reserved_instruction(ctx);
20131 goto out;
20134 /* branch completion */
20135 clear_branch_hflags(ctx);
20136 ctx->base.is_jmp = DISAS_NORETURN;
20138 if (cond == TCG_COND_ALWAYS) {
20139 /* Uncoditional compact branch */
20140 gen_goto_tb(ctx, 0, ctx->btarget);
20141 } else {
20142 /* Conditional compact branch */
20143 TCGLabel *fs = gen_new_label();
20145 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
20147 gen_goto_tb(ctx, 1, ctx->btarget);
20148 gen_set_label(fs);
20150 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20153 out:
20154 tcg_temp_free(t0);
20155 tcg_temp_free(t1);
20158 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
20159 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
20160 int rt)
20162 TCGv t0 = tcg_temp_new();
20163 TCGv t1 = tcg_temp_new();
20165 /* load rs */
20166 gen_load_gpr(t0, rs);
20168 /* link */
20169 if (rt != 0) {
20170 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
20173 /* calculate btarget */
20174 tcg_gen_shli_tl(t0, t0, 1);
20175 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
20176 gen_op_addr_add(ctx, btarget, t1, t0);
20178 /* branch completion */
20179 clear_branch_hflags(ctx);
20180 ctx->base.is_jmp = DISAS_NORETURN;
20182 /* unconditional branch to register */
20183 tcg_gen_mov_tl(cpu_PC, btarget);
20184 tcg_gen_lookup_and_goto_ptr();
20186 tcg_temp_free(t0);
20187 tcg_temp_free(t1);
20190 /* nanoMIPS Branches */
20191 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
20192 int rs, int rt, int32_t offset)
20194 int bcond_compute = 0;
20195 TCGv t0 = tcg_temp_new();
20196 TCGv t1 = tcg_temp_new();
20198 /* Load needed operands and calculate btarget */
20199 switch (opc) {
20200 /* compact branch */
20201 case OPC_BGEC:
20202 case OPC_BLTC:
20203 gen_load_gpr(t0, rs);
20204 gen_load_gpr(t1, rt);
20205 bcond_compute = 1;
20206 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20207 break;
20208 case OPC_BGEUC:
20209 case OPC_BLTUC:
20210 if (rs == 0 || rs == rt) {
20211 /* OPC_BLEZALC, OPC_BGEZALC */
20212 /* OPC_BGTZALC, OPC_BLTZALC */
20213 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
20215 gen_load_gpr(t0, rs);
20216 gen_load_gpr(t1, rt);
20217 bcond_compute = 1;
20218 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20219 break;
20220 case OPC_BC:
20221 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20222 break;
20223 case OPC_BEQZC:
20224 if (rs != 0) {
20225 /* OPC_BEQZC, OPC_BNEZC */
20226 gen_load_gpr(t0, rs);
20227 bcond_compute = 1;
20228 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20229 } else {
20230 /* OPC_JIC, OPC_JIALC */
20231 TCGv tbase = tcg_temp_new();
20232 TCGv toffset = tcg_temp_new();
20234 gen_load_gpr(tbase, rt);
20235 tcg_gen_movi_tl(toffset, offset);
20236 gen_op_addr_add(ctx, btarget, tbase, toffset);
20237 tcg_temp_free(tbase);
20238 tcg_temp_free(toffset);
20240 break;
20241 default:
20242 MIPS_INVAL("Compact branch/jump");
20243 gen_reserved_instruction(ctx);
20244 goto out;
20247 if (bcond_compute == 0) {
20248 /* Uncoditional compact branch */
20249 switch (opc) {
20250 case OPC_BC:
20251 gen_goto_tb(ctx, 0, ctx->btarget);
20252 break;
20253 default:
20254 MIPS_INVAL("Compact branch/jump");
20255 gen_reserved_instruction(ctx);
20256 goto out;
20258 } else {
20259 /* Conditional compact branch */
20260 TCGLabel *fs = gen_new_label();
20262 switch (opc) {
20263 case OPC_BGEUC:
20264 if (rs == 0 && rt != 0) {
20265 /* OPC_BLEZALC */
20266 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20267 } else if (rs != 0 && rt != 0 && rs == rt) {
20268 /* OPC_BGEZALC */
20269 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20270 } else {
20271 /* OPC_BGEUC */
20272 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
20274 break;
20275 case OPC_BLTUC:
20276 if (rs == 0 && rt != 0) {
20277 /* OPC_BGTZALC */
20278 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20279 } else if (rs != 0 && rt != 0 && rs == rt) {
20280 /* OPC_BLTZALC */
20281 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20282 } else {
20283 /* OPC_BLTUC */
20284 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
20286 break;
20287 case OPC_BGEC:
20288 if (rs == 0 && rt != 0) {
20289 /* OPC_BLEZC */
20290 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20291 } else if (rs != 0 && rt != 0 && rs == rt) {
20292 /* OPC_BGEZC */
20293 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20294 } else {
20295 /* OPC_BGEC */
20296 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
20298 break;
20299 case OPC_BLTC:
20300 if (rs == 0 && rt != 0) {
20301 /* OPC_BGTZC */
20302 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20303 } else if (rs != 0 && rt != 0 && rs == rt) {
20304 /* OPC_BLTZC */
20305 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20306 } else {
20307 /* OPC_BLTC */
20308 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
20310 break;
20311 case OPC_BEQZC:
20312 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
20313 break;
20314 default:
20315 MIPS_INVAL("Compact conditional branch/jump");
20316 gen_reserved_instruction(ctx);
20317 goto out;
20320 /* branch completion */
20321 clear_branch_hflags(ctx);
20322 ctx->base.is_jmp = DISAS_NORETURN;
20324 /* Generating branch here as compact branches don't have delay slot */
20325 gen_goto_tb(ctx, 1, ctx->btarget);
20326 gen_set_label(fs);
20328 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20331 out:
20332 tcg_temp_free(t0);
20333 tcg_temp_free(t1);
20337 /* nanoMIPS CP1 Branches */
20338 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
20339 int32_t ft, int32_t offset)
20341 target_ulong btarget;
20342 TCGv_i64 t0 = tcg_temp_new_i64();
20344 gen_load_fpr64(ctx, t0, ft);
20345 tcg_gen_andi_i64(t0, t0, 1);
20347 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20349 switch (op) {
20350 case NM_BC1EQZC:
20351 tcg_gen_xori_i64(t0, t0, 1);
20352 ctx->hflags |= MIPS_HFLAG_BC;
20353 break;
20354 case NM_BC1NEZC:
20355 /* t0 already set */
20356 ctx->hflags |= MIPS_HFLAG_BC;
20357 break;
20358 default:
20359 MIPS_INVAL("cp1 cond branch");
20360 gen_reserved_instruction(ctx);
20361 goto out;
20364 tcg_gen_trunc_i64_tl(bcond, t0);
20366 ctx->btarget = btarget;
20368 out:
20369 tcg_temp_free_i64(t0);
20373 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
20375 TCGv t0, t1;
20376 t0 = tcg_temp_new();
20377 t1 = tcg_temp_new();
20379 gen_load_gpr(t0, rs);
20380 gen_load_gpr(t1, rt);
20382 if ((extract32(ctx->opcode, 6, 1)) == 1) {
20383 /* PP.LSXS instructions require shifting */
20384 switch (extract32(ctx->opcode, 7, 4)) {
20385 case NM_SHXS:
20386 check_nms(ctx);
20387 /* fall through */
20388 case NM_LHXS:
20389 case NM_LHUXS:
20390 tcg_gen_shli_tl(t0, t0, 1);
20391 break;
20392 case NM_SWXS:
20393 check_nms(ctx);
20394 /* fall through */
20395 case NM_LWXS:
20396 case NM_LWC1XS:
20397 case NM_SWC1XS:
20398 tcg_gen_shli_tl(t0, t0, 2);
20399 break;
20400 case NM_LDC1XS:
20401 case NM_SDC1XS:
20402 tcg_gen_shli_tl(t0, t0, 3);
20403 break;
20406 gen_op_addr_add(ctx, t0, t0, t1);
20408 switch (extract32(ctx->opcode, 7, 4)) {
20409 case NM_LBX:
20410 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20411 MO_SB);
20412 gen_store_gpr(t0, rd);
20413 break;
20414 case NM_LHX:
20415 /*case NM_LHXS:*/
20416 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20417 MO_TESW);
20418 gen_store_gpr(t0, rd);
20419 break;
20420 case NM_LWX:
20421 /*case NM_LWXS:*/
20422 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20423 MO_TESL);
20424 gen_store_gpr(t0, rd);
20425 break;
20426 case NM_LBUX:
20427 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20428 MO_UB);
20429 gen_store_gpr(t0, rd);
20430 break;
20431 case NM_LHUX:
20432 /*case NM_LHUXS:*/
20433 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20434 MO_TEUW);
20435 gen_store_gpr(t0, rd);
20436 break;
20437 case NM_SBX:
20438 check_nms(ctx);
20439 gen_load_gpr(t1, rd);
20440 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20441 MO_8);
20442 break;
20443 case NM_SHX:
20444 /*case NM_SHXS:*/
20445 check_nms(ctx);
20446 gen_load_gpr(t1, rd);
20447 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20448 MO_TEUW);
20449 break;
20450 case NM_SWX:
20451 /*case NM_SWXS:*/
20452 check_nms(ctx);
20453 gen_load_gpr(t1, rd);
20454 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20455 MO_TEUL);
20456 break;
20457 case NM_LWC1X:
20458 /*case NM_LWC1XS:*/
20459 case NM_LDC1X:
20460 /*case NM_LDC1XS:*/
20461 case NM_SWC1X:
20462 /*case NM_SWC1XS:*/
20463 case NM_SDC1X:
20464 /*case NM_SDC1XS:*/
20465 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
20466 check_cp1_enabled(ctx);
20467 switch (extract32(ctx->opcode, 7, 4)) {
20468 case NM_LWC1X:
20469 /*case NM_LWC1XS:*/
20470 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
20471 break;
20472 case NM_LDC1X:
20473 /*case NM_LDC1XS:*/
20474 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
20475 break;
20476 case NM_SWC1X:
20477 /*case NM_SWC1XS:*/
20478 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
20479 break;
20480 case NM_SDC1X:
20481 /*case NM_SDC1XS:*/
20482 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
20483 break;
20485 } else {
20486 generate_exception_err(ctx, EXCP_CpU, 1);
20488 break;
20489 default:
20490 gen_reserved_instruction(ctx);
20491 break;
20494 tcg_temp_free(t0);
20495 tcg_temp_free(t1);
20498 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
20500 int rt, rs, rd;
20502 rt = extract32(ctx->opcode, 21, 5);
20503 rs = extract32(ctx->opcode, 16, 5);
20504 rd = extract32(ctx->opcode, 11, 5);
20506 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
20507 gen_reserved_instruction(ctx);
20508 return;
20510 check_cp1_enabled(ctx);
20511 switch (extract32(ctx->opcode, 0, 3)) {
20512 case NM_POOL32F_0:
20513 switch (extract32(ctx->opcode, 3, 7)) {
20514 case NM_RINT_S:
20515 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
20516 break;
20517 case NM_RINT_D:
20518 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
20519 break;
20520 case NM_CLASS_S:
20521 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
20522 break;
20523 case NM_CLASS_D:
20524 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
20525 break;
20526 case NM_ADD_S:
20527 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
20528 break;
20529 case NM_ADD_D:
20530 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
20531 break;
20532 case NM_SUB_S:
20533 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
20534 break;
20535 case NM_SUB_D:
20536 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
20537 break;
20538 case NM_MUL_S:
20539 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
20540 break;
20541 case NM_MUL_D:
20542 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
20543 break;
20544 case NM_DIV_S:
20545 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
20546 break;
20547 case NM_DIV_D:
20548 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
20549 break;
20550 case NM_SELEQZ_S:
20551 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
20552 break;
20553 case NM_SELEQZ_D:
20554 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
20555 break;
20556 case NM_SELNEZ_S:
20557 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
20558 break;
20559 case NM_SELNEZ_D:
20560 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
20561 break;
20562 case NM_SEL_S:
20563 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
20564 break;
20565 case NM_SEL_D:
20566 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
20567 break;
20568 case NM_MADDF_S:
20569 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
20570 break;
20571 case NM_MADDF_D:
20572 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
20573 break;
20574 case NM_MSUBF_S:
20575 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
20576 break;
20577 case NM_MSUBF_D:
20578 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
20579 break;
20580 default:
20581 gen_reserved_instruction(ctx);
20582 break;
20584 break;
20585 case NM_POOL32F_3:
20586 switch (extract32(ctx->opcode, 3, 3)) {
20587 case NM_MIN_FMT:
20588 switch (extract32(ctx->opcode, 9, 1)) {
20589 case FMT_SDPS_S:
20590 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
20591 break;
20592 case FMT_SDPS_D:
20593 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
20594 break;
20596 break;
20597 case NM_MAX_FMT:
20598 switch (extract32(ctx->opcode, 9, 1)) {
20599 case FMT_SDPS_S:
20600 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
20601 break;
20602 case FMT_SDPS_D:
20603 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
20604 break;
20606 break;
20607 case NM_MINA_FMT:
20608 switch (extract32(ctx->opcode, 9, 1)) {
20609 case FMT_SDPS_S:
20610 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
20611 break;
20612 case FMT_SDPS_D:
20613 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
20614 break;
20616 break;
20617 case NM_MAXA_FMT:
20618 switch (extract32(ctx->opcode, 9, 1)) {
20619 case FMT_SDPS_S:
20620 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
20621 break;
20622 case FMT_SDPS_D:
20623 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
20624 break;
20626 break;
20627 case NM_POOL32FXF:
20628 switch (extract32(ctx->opcode, 6, 8)) {
20629 case NM_CFC1:
20630 gen_cp1(ctx, OPC_CFC1, rt, rs);
20631 break;
20632 case NM_CTC1:
20633 gen_cp1(ctx, OPC_CTC1, rt, rs);
20634 break;
20635 case NM_MFC1:
20636 gen_cp1(ctx, OPC_MFC1, rt, rs);
20637 break;
20638 case NM_MTC1:
20639 gen_cp1(ctx, OPC_MTC1, rt, rs);
20640 break;
20641 case NM_MFHC1:
20642 gen_cp1(ctx, OPC_MFHC1, rt, rs);
20643 break;
20644 case NM_MTHC1:
20645 gen_cp1(ctx, OPC_MTHC1, rt, rs);
20646 break;
20647 case NM_CVT_S_PL:
20648 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
20649 break;
20650 case NM_CVT_S_PU:
20651 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
20652 break;
20653 default:
20654 switch (extract32(ctx->opcode, 6, 9)) {
20655 case NM_CVT_L_S:
20656 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
20657 break;
20658 case NM_CVT_L_D:
20659 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
20660 break;
20661 case NM_CVT_W_S:
20662 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
20663 break;
20664 case NM_CVT_W_D:
20665 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
20666 break;
20667 case NM_RSQRT_S:
20668 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
20669 break;
20670 case NM_RSQRT_D:
20671 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
20672 break;
20673 case NM_SQRT_S:
20674 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
20675 break;
20676 case NM_SQRT_D:
20677 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
20678 break;
20679 case NM_RECIP_S:
20680 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
20681 break;
20682 case NM_RECIP_D:
20683 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
20684 break;
20685 case NM_FLOOR_L_S:
20686 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
20687 break;
20688 case NM_FLOOR_L_D:
20689 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
20690 break;
20691 case NM_FLOOR_W_S:
20692 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
20693 break;
20694 case NM_FLOOR_W_D:
20695 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
20696 break;
20697 case NM_CEIL_L_S:
20698 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
20699 break;
20700 case NM_CEIL_L_D:
20701 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
20702 break;
20703 case NM_CEIL_W_S:
20704 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
20705 break;
20706 case NM_CEIL_W_D:
20707 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
20708 break;
20709 case NM_TRUNC_L_S:
20710 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
20711 break;
20712 case NM_TRUNC_L_D:
20713 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
20714 break;
20715 case NM_TRUNC_W_S:
20716 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
20717 break;
20718 case NM_TRUNC_W_D:
20719 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
20720 break;
20721 case NM_ROUND_L_S:
20722 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
20723 break;
20724 case NM_ROUND_L_D:
20725 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
20726 break;
20727 case NM_ROUND_W_S:
20728 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
20729 break;
20730 case NM_ROUND_W_D:
20731 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
20732 break;
20733 case NM_MOV_S:
20734 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
20735 break;
20736 case NM_MOV_D:
20737 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
20738 break;
20739 case NM_ABS_S:
20740 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
20741 break;
20742 case NM_ABS_D:
20743 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
20744 break;
20745 case NM_NEG_S:
20746 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
20747 break;
20748 case NM_NEG_D:
20749 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
20750 break;
20751 case NM_CVT_D_S:
20752 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
20753 break;
20754 case NM_CVT_D_W:
20755 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
20756 break;
20757 case NM_CVT_D_L:
20758 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
20759 break;
20760 case NM_CVT_S_D:
20761 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
20762 break;
20763 case NM_CVT_S_W:
20764 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
20765 break;
20766 case NM_CVT_S_L:
20767 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
20768 break;
20769 default:
20770 gen_reserved_instruction(ctx);
20771 break;
20773 break;
20775 break;
20777 break;
20778 case NM_POOL32F_5:
20779 switch (extract32(ctx->opcode, 3, 3)) {
20780 case NM_CMP_CONDN_S:
20781 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20782 break;
20783 case NM_CMP_CONDN_D:
20784 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20785 break;
20786 default:
20787 gen_reserved_instruction(ctx);
20788 break;
20790 break;
20791 default:
20792 gen_reserved_instruction(ctx);
20793 break;
20797 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
20798 int rd, int rs, int rt)
20800 int ret = rd;
20801 TCGv t0 = tcg_temp_new();
20802 TCGv v1_t = tcg_temp_new();
20803 TCGv v2_t = tcg_temp_new();
20805 gen_load_gpr(v1_t, rs);
20806 gen_load_gpr(v2_t, rt);
20808 switch (opc) {
20809 case NM_CMP_EQ_PH:
20810 check_dsp(ctx);
20811 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
20812 break;
20813 case NM_CMP_LT_PH:
20814 check_dsp(ctx);
20815 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
20816 break;
20817 case NM_CMP_LE_PH:
20818 check_dsp(ctx);
20819 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
20820 break;
20821 case NM_CMPU_EQ_QB:
20822 check_dsp(ctx);
20823 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
20824 break;
20825 case NM_CMPU_LT_QB:
20826 check_dsp(ctx);
20827 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
20828 break;
20829 case NM_CMPU_LE_QB:
20830 check_dsp(ctx);
20831 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
20832 break;
20833 case NM_CMPGU_EQ_QB:
20834 check_dsp(ctx);
20835 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20836 gen_store_gpr(v1_t, ret);
20837 break;
20838 case NM_CMPGU_LT_QB:
20839 check_dsp(ctx);
20840 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20841 gen_store_gpr(v1_t, ret);
20842 break;
20843 case NM_CMPGU_LE_QB:
20844 check_dsp(ctx);
20845 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20846 gen_store_gpr(v1_t, ret);
20847 break;
20848 case NM_CMPGDU_EQ_QB:
20849 check_dsp_r2(ctx);
20850 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20851 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20852 gen_store_gpr(v1_t, ret);
20853 break;
20854 case NM_CMPGDU_LT_QB:
20855 check_dsp_r2(ctx);
20856 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20857 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20858 gen_store_gpr(v1_t, ret);
20859 break;
20860 case NM_CMPGDU_LE_QB:
20861 check_dsp_r2(ctx);
20862 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20863 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20864 gen_store_gpr(v1_t, ret);
20865 break;
20866 case NM_PACKRL_PH:
20867 check_dsp(ctx);
20868 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
20869 gen_store_gpr(v1_t, ret);
20870 break;
20871 case NM_PICK_QB:
20872 check_dsp(ctx);
20873 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
20874 gen_store_gpr(v1_t, ret);
20875 break;
20876 case NM_PICK_PH:
20877 check_dsp(ctx);
20878 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
20879 gen_store_gpr(v1_t, ret);
20880 break;
20881 case NM_ADDQ_S_W:
20882 check_dsp(ctx);
20883 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
20884 gen_store_gpr(v1_t, ret);
20885 break;
20886 case NM_SUBQ_S_W:
20887 check_dsp(ctx);
20888 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
20889 gen_store_gpr(v1_t, ret);
20890 break;
20891 case NM_ADDSC:
20892 check_dsp(ctx);
20893 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
20894 gen_store_gpr(v1_t, ret);
20895 break;
20896 case NM_ADDWC:
20897 check_dsp(ctx);
20898 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
20899 gen_store_gpr(v1_t, ret);
20900 break;
20901 case NM_ADDQ_S_PH:
20902 check_dsp(ctx);
20903 switch (extract32(ctx->opcode, 10, 1)) {
20904 case 0:
20905 /* ADDQ_PH */
20906 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
20907 gen_store_gpr(v1_t, ret);
20908 break;
20909 case 1:
20910 /* ADDQ_S_PH */
20911 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20912 gen_store_gpr(v1_t, ret);
20913 break;
20915 break;
20916 case NM_ADDQH_R_PH:
20917 check_dsp_r2(ctx);
20918 switch (extract32(ctx->opcode, 10, 1)) {
20919 case 0:
20920 /* ADDQH_PH */
20921 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
20922 gen_store_gpr(v1_t, ret);
20923 break;
20924 case 1:
20925 /* ADDQH_R_PH */
20926 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
20927 gen_store_gpr(v1_t, ret);
20928 break;
20930 break;
20931 case NM_ADDQH_R_W:
20932 check_dsp_r2(ctx);
20933 switch (extract32(ctx->opcode, 10, 1)) {
20934 case 0:
20935 /* ADDQH_W */
20936 gen_helper_addqh_w(v1_t, v1_t, v2_t);
20937 gen_store_gpr(v1_t, ret);
20938 break;
20939 case 1:
20940 /* ADDQH_R_W */
20941 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
20942 gen_store_gpr(v1_t, ret);
20943 break;
20945 break;
20946 case NM_ADDU_S_QB:
20947 check_dsp(ctx);
20948 switch (extract32(ctx->opcode, 10, 1)) {
20949 case 0:
20950 /* ADDU_QB */
20951 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
20952 gen_store_gpr(v1_t, ret);
20953 break;
20954 case 1:
20955 /* ADDU_S_QB */
20956 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20957 gen_store_gpr(v1_t, ret);
20958 break;
20960 break;
20961 case NM_ADDU_S_PH:
20962 check_dsp_r2(ctx);
20963 switch (extract32(ctx->opcode, 10, 1)) {
20964 case 0:
20965 /* ADDU_PH */
20966 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
20967 gen_store_gpr(v1_t, ret);
20968 break;
20969 case 1:
20970 /* ADDU_S_PH */
20971 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20972 gen_store_gpr(v1_t, ret);
20973 break;
20975 break;
20976 case NM_ADDUH_R_QB:
20977 check_dsp_r2(ctx);
20978 switch (extract32(ctx->opcode, 10, 1)) {
20979 case 0:
20980 /* ADDUH_QB */
20981 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
20982 gen_store_gpr(v1_t, ret);
20983 break;
20984 case 1:
20985 /* ADDUH_R_QB */
20986 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
20987 gen_store_gpr(v1_t, ret);
20988 break;
20990 break;
20991 case NM_SHRAV_R_PH:
20992 check_dsp(ctx);
20993 switch (extract32(ctx->opcode, 10, 1)) {
20994 case 0:
20995 /* SHRAV_PH */
20996 gen_helper_shra_ph(v1_t, v1_t, v2_t);
20997 gen_store_gpr(v1_t, ret);
20998 break;
20999 case 1:
21000 /* SHRAV_R_PH */
21001 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
21002 gen_store_gpr(v1_t, ret);
21003 break;
21005 break;
21006 case NM_SHRAV_R_QB:
21007 check_dsp_r2(ctx);
21008 switch (extract32(ctx->opcode, 10, 1)) {
21009 case 0:
21010 /* SHRAV_QB */
21011 gen_helper_shra_qb(v1_t, v1_t, v2_t);
21012 gen_store_gpr(v1_t, ret);
21013 break;
21014 case 1:
21015 /* SHRAV_R_QB */
21016 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
21017 gen_store_gpr(v1_t, ret);
21018 break;
21020 break;
21021 case NM_SUBQ_S_PH:
21022 check_dsp(ctx);
21023 switch (extract32(ctx->opcode, 10, 1)) {
21024 case 0:
21025 /* SUBQ_PH */
21026 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
21027 gen_store_gpr(v1_t, ret);
21028 break;
21029 case 1:
21030 /* SUBQ_S_PH */
21031 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
21032 gen_store_gpr(v1_t, ret);
21033 break;
21035 break;
21036 case NM_SUBQH_R_PH:
21037 check_dsp_r2(ctx);
21038 switch (extract32(ctx->opcode, 10, 1)) {
21039 case 0:
21040 /* SUBQH_PH */
21041 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
21042 gen_store_gpr(v1_t, ret);
21043 break;
21044 case 1:
21045 /* SUBQH_R_PH */
21046 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
21047 gen_store_gpr(v1_t, ret);
21048 break;
21050 break;
21051 case NM_SUBQH_R_W:
21052 check_dsp_r2(ctx);
21053 switch (extract32(ctx->opcode, 10, 1)) {
21054 case 0:
21055 /* SUBQH_W */
21056 gen_helper_subqh_w(v1_t, v1_t, v2_t);
21057 gen_store_gpr(v1_t, ret);
21058 break;
21059 case 1:
21060 /* SUBQH_R_W */
21061 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
21062 gen_store_gpr(v1_t, ret);
21063 break;
21065 break;
21066 case NM_SUBU_S_QB:
21067 check_dsp(ctx);
21068 switch (extract32(ctx->opcode, 10, 1)) {
21069 case 0:
21070 /* SUBU_QB */
21071 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
21072 gen_store_gpr(v1_t, ret);
21073 break;
21074 case 1:
21075 /* SUBU_S_QB */
21076 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
21077 gen_store_gpr(v1_t, ret);
21078 break;
21080 break;
21081 case NM_SUBU_S_PH:
21082 check_dsp_r2(ctx);
21083 switch (extract32(ctx->opcode, 10, 1)) {
21084 case 0:
21085 /* SUBU_PH */
21086 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
21087 gen_store_gpr(v1_t, ret);
21088 break;
21089 case 1:
21090 /* SUBU_S_PH */
21091 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
21092 gen_store_gpr(v1_t, ret);
21093 break;
21095 break;
21096 case NM_SUBUH_R_QB:
21097 check_dsp_r2(ctx);
21098 switch (extract32(ctx->opcode, 10, 1)) {
21099 case 0:
21100 /* SUBUH_QB */
21101 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
21102 gen_store_gpr(v1_t, ret);
21103 break;
21104 case 1:
21105 /* SUBUH_R_QB */
21106 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
21107 gen_store_gpr(v1_t, ret);
21108 break;
21110 break;
21111 case NM_SHLLV_S_PH:
21112 check_dsp(ctx);
21113 switch (extract32(ctx->opcode, 10, 1)) {
21114 case 0:
21115 /* SHLLV_PH */
21116 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
21117 gen_store_gpr(v1_t, ret);
21118 break;
21119 case 1:
21120 /* SHLLV_S_PH */
21121 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
21122 gen_store_gpr(v1_t, ret);
21123 break;
21125 break;
21126 case NM_PRECR_SRA_R_PH_W:
21127 check_dsp_r2(ctx);
21128 switch (extract32(ctx->opcode, 10, 1)) {
21129 case 0:
21130 /* PRECR_SRA_PH_W */
21132 TCGv_i32 sa_t = tcg_const_i32(rd);
21133 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
21134 cpu_gpr[rt]);
21135 gen_store_gpr(v1_t, rt);
21136 tcg_temp_free_i32(sa_t);
21138 break;
21139 case 1:
21140 /* PRECR_SRA_R_PH_W */
21142 TCGv_i32 sa_t = tcg_const_i32(rd);
21143 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
21144 cpu_gpr[rt]);
21145 gen_store_gpr(v1_t, rt);
21146 tcg_temp_free_i32(sa_t);
21148 break;
21150 break;
21151 case NM_MULEU_S_PH_QBL:
21152 check_dsp(ctx);
21153 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
21154 gen_store_gpr(v1_t, ret);
21155 break;
21156 case NM_MULEU_S_PH_QBR:
21157 check_dsp(ctx);
21158 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
21159 gen_store_gpr(v1_t, ret);
21160 break;
21161 case NM_MULQ_RS_PH:
21162 check_dsp(ctx);
21163 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
21164 gen_store_gpr(v1_t, ret);
21165 break;
21166 case NM_MULQ_S_PH:
21167 check_dsp_r2(ctx);
21168 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
21169 gen_store_gpr(v1_t, ret);
21170 break;
21171 case NM_MULQ_RS_W:
21172 check_dsp_r2(ctx);
21173 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
21174 gen_store_gpr(v1_t, ret);
21175 break;
21176 case NM_MULQ_S_W:
21177 check_dsp_r2(ctx);
21178 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
21179 gen_store_gpr(v1_t, ret);
21180 break;
21181 case NM_APPEND:
21182 check_dsp_r2(ctx);
21183 gen_load_gpr(t0, rs);
21184 if (rd != 0) {
21185 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
21187 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21188 break;
21189 case NM_MODSUB:
21190 check_dsp(ctx);
21191 gen_helper_modsub(v1_t, v1_t, v2_t);
21192 gen_store_gpr(v1_t, ret);
21193 break;
21194 case NM_SHRAV_R_W:
21195 check_dsp(ctx);
21196 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
21197 gen_store_gpr(v1_t, ret);
21198 break;
21199 case NM_SHRLV_PH:
21200 check_dsp_r2(ctx);
21201 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
21202 gen_store_gpr(v1_t, ret);
21203 break;
21204 case NM_SHRLV_QB:
21205 check_dsp(ctx);
21206 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
21207 gen_store_gpr(v1_t, ret);
21208 break;
21209 case NM_SHLLV_QB:
21210 check_dsp(ctx);
21211 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
21212 gen_store_gpr(v1_t, ret);
21213 break;
21214 case NM_SHLLV_S_W:
21215 check_dsp(ctx);
21216 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
21217 gen_store_gpr(v1_t, ret);
21218 break;
21219 case NM_SHILO:
21220 check_dsp(ctx);
21222 TCGv tv0 = tcg_temp_new();
21223 TCGv tv1 = tcg_temp_new();
21224 int16_t imm = extract32(ctx->opcode, 16, 7);
21226 tcg_gen_movi_tl(tv0, rd >> 3);
21227 tcg_gen_movi_tl(tv1, imm);
21228 gen_helper_shilo(tv0, tv1, cpu_env);
21230 break;
21231 case NM_MULEQ_S_W_PHL:
21232 check_dsp(ctx);
21233 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
21234 gen_store_gpr(v1_t, ret);
21235 break;
21236 case NM_MULEQ_S_W_PHR:
21237 check_dsp(ctx);
21238 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
21239 gen_store_gpr(v1_t, ret);
21240 break;
21241 case NM_MUL_S_PH:
21242 check_dsp_r2(ctx);
21243 switch (extract32(ctx->opcode, 10, 1)) {
21244 case 0:
21245 /* MUL_PH */
21246 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
21247 gen_store_gpr(v1_t, ret);
21248 break;
21249 case 1:
21250 /* MUL_S_PH */
21251 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
21252 gen_store_gpr(v1_t, ret);
21253 break;
21255 break;
21256 case NM_PRECR_QB_PH:
21257 check_dsp_r2(ctx);
21258 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
21259 gen_store_gpr(v1_t, ret);
21260 break;
21261 case NM_PRECRQ_QB_PH:
21262 check_dsp(ctx);
21263 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
21264 gen_store_gpr(v1_t, ret);
21265 break;
21266 case NM_PRECRQ_PH_W:
21267 check_dsp(ctx);
21268 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
21269 gen_store_gpr(v1_t, ret);
21270 break;
21271 case NM_PRECRQ_RS_PH_W:
21272 check_dsp(ctx);
21273 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
21274 gen_store_gpr(v1_t, ret);
21275 break;
21276 case NM_PRECRQU_S_QB_PH:
21277 check_dsp(ctx);
21278 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
21279 gen_store_gpr(v1_t, ret);
21280 break;
21281 case NM_SHRA_R_W:
21282 check_dsp(ctx);
21283 tcg_gen_movi_tl(t0, rd);
21284 gen_helper_shra_r_w(v1_t, t0, v1_t);
21285 gen_store_gpr(v1_t, rt);
21286 break;
21287 case NM_SHRA_R_PH:
21288 check_dsp(ctx);
21289 tcg_gen_movi_tl(t0, rd >> 1);
21290 switch (extract32(ctx->opcode, 10, 1)) {
21291 case 0:
21292 /* SHRA_PH */
21293 gen_helper_shra_ph(v1_t, t0, v1_t);
21294 gen_store_gpr(v1_t, rt);
21295 break;
21296 case 1:
21297 /* SHRA_R_PH */
21298 gen_helper_shra_r_ph(v1_t, t0, v1_t);
21299 gen_store_gpr(v1_t, rt);
21300 break;
21302 break;
21303 case NM_SHLL_S_PH:
21304 check_dsp(ctx);
21305 tcg_gen_movi_tl(t0, rd >> 1);
21306 switch (extract32(ctx->opcode, 10, 2)) {
21307 case 0:
21308 /* SHLL_PH */
21309 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
21310 gen_store_gpr(v1_t, rt);
21311 break;
21312 case 2:
21313 /* SHLL_S_PH */
21314 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
21315 gen_store_gpr(v1_t, rt);
21316 break;
21317 default:
21318 gen_reserved_instruction(ctx);
21319 break;
21321 break;
21322 case NM_SHLL_S_W:
21323 check_dsp(ctx);
21324 tcg_gen_movi_tl(t0, rd);
21325 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
21326 gen_store_gpr(v1_t, rt);
21327 break;
21328 case NM_REPL_PH:
21329 check_dsp(ctx);
21331 int16_t imm;
21332 imm = sextract32(ctx->opcode, 11, 11);
21333 imm = (int16_t)(imm << 6) >> 6;
21334 if (rt != 0) {
21335 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
21338 break;
21339 default:
21340 gen_reserved_instruction(ctx);
21341 break;
21345 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
21347 uint16_t insn;
21348 uint32_t op;
21349 int rt, rs, rd;
21350 int offset;
21351 int imm;
21353 insn = translator_lduw(env, ctx->base.pc_next + 2);
21354 ctx->opcode = (ctx->opcode << 16) | insn;
21356 rt = extract32(ctx->opcode, 21, 5);
21357 rs = extract32(ctx->opcode, 16, 5);
21358 rd = extract32(ctx->opcode, 11, 5);
21360 op = extract32(ctx->opcode, 26, 6);
21361 switch (op) {
21362 case NM_P_ADDIU:
21363 if (rt == 0) {
21364 /* P.RI */
21365 switch (extract32(ctx->opcode, 19, 2)) {
21366 case NM_SIGRIE:
21367 default:
21368 gen_reserved_instruction(ctx);
21369 break;
21370 case NM_P_SYSCALL:
21371 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
21372 generate_exception_end(ctx, EXCP_SYSCALL);
21373 } else {
21374 gen_reserved_instruction(ctx);
21376 break;
21377 case NM_BREAK:
21378 generate_exception_end(ctx, EXCP_BREAK);
21379 break;
21380 case NM_SDBBP:
21381 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
21382 gen_helper_do_semihosting(cpu_env);
21383 } else {
21384 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21385 gen_reserved_instruction(ctx);
21386 } else {
21387 generate_exception_end(ctx, EXCP_DBp);
21390 break;
21392 } else {
21393 /* NM_ADDIU */
21394 imm = extract32(ctx->opcode, 0, 16);
21395 if (rs != 0) {
21396 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
21397 } else {
21398 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21400 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21402 break;
21403 case NM_ADDIUPC:
21404 if (rt != 0) {
21405 offset = sextract32(ctx->opcode, 0, 1) << 21 |
21406 extract32(ctx->opcode, 1, 20) << 1;
21407 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
21408 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21410 break;
21411 case NM_POOL32A:
21412 switch (ctx->opcode & 0x07) {
21413 case NM_POOL32A0:
21414 gen_pool32a0_nanomips_insn(env, ctx);
21415 break;
21416 case NM_POOL32A5:
21418 int32_t op1 = extract32(ctx->opcode, 3, 7);
21419 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
21421 break;
21422 case NM_POOL32A7:
21423 switch (extract32(ctx->opcode, 3, 3)) {
21424 case NM_P_LSX:
21425 gen_p_lsx(ctx, rd, rs, rt);
21426 break;
21427 case NM_LSA:
21429 * In nanoMIPS, the shift field directly encodes the shift
21430 * amount, meaning that the supported shift values are in
21431 * the range 0 to 3 (instead of 1 to 4 in MIPSR6).
21433 gen_lsa(ctx, rd, rt, rs, extract32(ctx->opcode, 9, 2) - 1);
21434 break;
21435 case NM_EXTW:
21436 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
21437 break;
21438 case NM_POOL32AXF:
21439 gen_pool32axf_nanomips_insn(env, ctx);
21440 break;
21441 default:
21442 gen_reserved_instruction(ctx);
21443 break;
21445 break;
21446 default:
21447 gen_reserved_instruction(ctx);
21448 break;
21450 break;
21451 case NM_P_GP_W:
21452 switch (ctx->opcode & 0x03) {
21453 case NM_ADDIUGP_W:
21454 if (rt != 0) {
21455 offset = extract32(ctx->opcode, 0, 21);
21456 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
21458 break;
21459 case NM_LWGP:
21460 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21461 break;
21462 case NM_SWGP:
21463 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21464 break;
21465 default:
21466 gen_reserved_instruction(ctx);
21467 break;
21469 break;
21470 case NM_P48I:
21472 insn = translator_lduw(env, ctx->base.pc_next + 4);
21473 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
21474 switch (extract32(ctx->opcode, 16, 5)) {
21475 case NM_LI48:
21476 check_nms(ctx);
21477 if (rt != 0) {
21478 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
21480 break;
21481 case NM_ADDIU48:
21482 check_nms(ctx);
21483 if (rt != 0) {
21484 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
21485 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21487 break;
21488 case NM_ADDIUGP48:
21489 check_nms(ctx);
21490 if (rt != 0) {
21491 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
21493 break;
21494 case NM_ADDIUPC48:
21495 check_nms(ctx);
21496 if (rt != 0) {
21497 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21498 addr_off);
21500 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21502 break;
21503 case NM_LWPC48:
21504 check_nms(ctx);
21505 if (rt != 0) {
21506 TCGv t0;
21507 t0 = tcg_temp_new();
21509 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21510 addr_off);
21512 tcg_gen_movi_tl(t0, addr);
21513 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
21514 tcg_temp_free(t0);
21516 break;
21517 case NM_SWPC48:
21518 check_nms(ctx);
21520 TCGv t0, t1;
21521 t0 = tcg_temp_new();
21522 t1 = tcg_temp_new();
21524 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21525 addr_off);
21527 tcg_gen_movi_tl(t0, addr);
21528 gen_load_gpr(t1, rt);
21530 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
21532 tcg_temp_free(t0);
21533 tcg_temp_free(t1);
21535 break;
21536 default:
21537 gen_reserved_instruction(ctx);
21538 break;
21540 return 6;
21542 case NM_P_U12:
21543 switch (extract32(ctx->opcode, 12, 4)) {
21544 case NM_ORI:
21545 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
21546 break;
21547 case NM_XORI:
21548 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
21549 break;
21550 case NM_ANDI:
21551 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
21552 break;
21553 case NM_P_SR:
21554 switch (extract32(ctx->opcode, 20, 1)) {
21555 case NM_PP_SR:
21556 switch (ctx->opcode & 3) {
21557 case NM_SAVE:
21558 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
21559 extract32(ctx->opcode, 2, 1),
21560 extract32(ctx->opcode, 3, 9) << 3);
21561 break;
21562 case NM_RESTORE:
21563 case NM_RESTORE_JRC:
21564 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
21565 extract32(ctx->opcode, 2, 1),
21566 extract32(ctx->opcode, 3, 9) << 3);
21567 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
21568 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21570 break;
21571 default:
21572 gen_reserved_instruction(ctx);
21573 break;
21575 break;
21576 case NM_P_SR_F:
21577 gen_reserved_instruction(ctx);
21578 break;
21580 break;
21581 case NM_SLTI:
21582 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
21583 break;
21584 case NM_SLTIU:
21585 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
21586 break;
21587 case NM_SEQI:
21589 TCGv t0 = tcg_temp_new();
21591 imm = extract32(ctx->opcode, 0, 12);
21592 gen_load_gpr(t0, rs);
21593 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
21594 gen_store_gpr(t0, rt);
21596 tcg_temp_free(t0);
21598 break;
21599 case NM_ADDIUNEG:
21600 imm = (int16_t) extract32(ctx->opcode, 0, 12);
21601 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
21602 break;
21603 case NM_P_SHIFT:
21605 int shift = extract32(ctx->opcode, 0, 5);
21606 switch (extract32(ctx->opcode, 5, 4)) {
21607 case NM_P_SLL:
21608 if (rt == 0 && shift == 0) {
21609 /* NOP */
21610 } else if (rt == 0 && shift == 3) {
21611 /* EHB - treat as NOP */
21612 } else if (rt == 0 && shift == 5) {
21613 /* PAUSE - treat as NOP */
21614 } else if (rt == 0 && shift == 6) {
21615 /* SYNC */
21616 gen_sync(extract32(ctx->opcode, 16, 5));
21617 } else {
21618 /* SLL */
21619 gen_shift_imm(ctx, OPC_SLL, rt, rs,
21620 extract32(ctx->opcode, 0, 5));
21622 break;
21623 case NM_SRL:
21624 gen_shift_imm(ctx, OPC_SRL, rt, rs,
21625 extract32(ctx->opcode, 0, 5));
21626 break;
21627 case NM_SRA:
21628 gen_shift_imm(ctx, OPC_SRA, rt, rs,
21629 extract32(ctx->opcode, 0, 5));
21630 break;
21631 case NM_ROTR:
21632 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
21633 extract32(ctx->opcode, 0, 5));
21634 break;
21637 break;
21638 case NM_P_ROTX:
21639 check_nms(ctx);
21640 if (rt != 0) {
21641 TCGv t0 = tcg_temp_new();
21642 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
21643 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
21644 << 1);
21645 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
21647 gen_load_gpr(t0, rs);
21648 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
21649 tcg_temp_free(t0);
21651 tcg_temp_free_i32(shift);
21652 tcg_temp_free_i32(shiftx);
21653 tcg_temp_free_i32(stripe);
21655 break;
21656 case NM_P_INS:
21657 switch (((ctx->opcode >> 10) & 2) |
21658 (extract32(ctx->opcode, 5, 1))) {
21659 case NM_INS:
21660 check_nms(ctx);
21661 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
21662 extract32(ctx->opcode, 6, 5));
21663 break;
21664 default:
21665 gen_reserved_instruction(ctx);
21666 break;
21668 break;
21669 case NM_P_EXT:
21670 switch (((ctx->opcode >> 10) & 2) |
21671 (extract32(ctx->opcode, 5, 1))) {
21672 case NM_EXT:
21673 check_nms(ctx);
21674 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
21675 extract32(ctx->opcode, 6, 5));
21676 break;
21677 default:
21678 gen_reserved_instruction(ctx);
21679 break;
21681 break;
21682 default:
21683 gen_reserved_instruction(ctx);
21684 break;
21686 break;
21687 case NM_POOL32F:
21688 gen_pool32f_nanomips_insn(ctx);
21689 break;
21690 case NM_POOL32S:
21691 break;
21692 case NM_P_LUI:
21693 switch (extract32(ctx->opcode, 1, 1)) {
21694 case NM_LUI:
21695 if (rt != 0) {
21696 tcg_gen_movi_tl(cpu_gpr[rt],
21697 sextract32(ctx->opcode, 0, 1) << 31 |
21698 extract32(ctx->opcode, 2, 10) << 21 |
21699 extract32(ctx->opcode, 12, 9) << 12);
21701 break;
21702 case NM_ALUIPC:
21703 if (rt != 0) {
21704 offset = sextract32(ctx->opcode, 0, 1) << 31 |
21705 extract32(ctx->opcode, 2, 10) << 21 |
21706 extract32(ctx->opcode, 12, 9) << 12;
21707 target_long addr;
21708 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
21709 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21711 break;
21713 break;
21714 case NM_P_GP_BH:
21716 uint32_t u = extract32(ctx->opcode, 0, 18);
21718 switch (extract32(ctx->opcode, 18, 3)) {
21719 case NM_LBGP:
21720 gen_ld(ctx, OPC_LB, rt, 28, u);
21721 break;
21722 case NM_SBGP:
21723 gen_st(ctx, OPC_SB, rt, 28, u);
21724 break;
21725 case NM_LBUGP:
21726 gen_ld(ctx, OPC_LBU, rt, 28, u);
21727 break;
21728 case NM_ADDIUGP_B:
21729 if (rt != 0) {
21730 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
21732 break;
21733 case NM_P_GP_LH:
21734 u &= ~1;
21735 switch (ctx->opcode & 1) {
21736 case NM_LHGP:
21737 gen_ld(ctx, OPC_LH, rt, 28, u);
21738 break;
21739 case NM_LHUGP:
21740 gen_ld(ctx, OPC_LHU, rt, 28, u);
21741 break;
21743 break;
21744 case NM_P_GP_SH:
21745 u &= ~1;
21746 switch (ctx->opcode & 1) {
21747 case NM_SHGP:
21748 gen_st(ctx, OPC_SH, rt, 28, u);
21749 break;
21750 default:
21751 gen_reserved_instruction(ctx);
21752 break;
21754 break;
21755 case NM_P_GP_CP1:
21756 u &= ~0x3;
21757 switch (ctx->opcode & 0x3) {
21758 case NM_LWC1GP:
21759 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
21760 break;
21761 case NM_LDC1GP:
21762 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
21763 break;
21764 case NM_SWC1GP:
21765 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
21766 break;
21767 case NM_SDC1GP:
21768 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
21769 break;
21771 break;
21772 default:
21773 gen_reserved_instruction(ctx);
21774 break;
21777 break;
21778 case NM_P_LS_U12:
21780 uint32_t u = extract32(ctx->opcode, 0, 12);
21782 switch (extract32(ctx->opcode, 12, 4)) {
21783 case NM_P_PREFU12:
21784 if (rt == 31) {
21785 /* SYNCI */
21787 * Break the TB to be able to sync copied instructions
21788 * immediately.
21790 ctx->base.is_jmp = DISAS_STOP;
21791 } else {
21792 /* PREF */
21793 /* Treat as NOP. */
21795 break;
21796 case NM_LB:
21797 gen_ld(ctx, OPC_LB, rt, rs, u);
21798 break;
21799 case NM_LH:
21800 gen_ld(ctx, OPC_LH, rt, rs, u);
21801 break;
21802 case NM_LW:
21803 gen_ld(ctx, OPC_LW, rt, rs, u);
21804 break;
21805 case NM_LBU:
21806 gen_ld(ctx, OPC_LBU, rt, rs, u);
21807 break;
21808 case NM_LHU:
21809 gen_ld(ctx, OPC_LHU, rt, rs, u);
21810 break;
21811 case NM_SB:
21812 gen_st(ctx, OPC_SB, rt, rs, u);
21813 break;
21814 case NM_SH:
21815 gen_st(ctx, OPC_SH, rt, rs, u);
21816 break;
21817 case NM_SW:
21818 gen_st(ctx, OPC_SW, rt, rs, u);
21819 break;
21820 case NM_LWC1:
21821 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
21822 break;
21823 case NM_LDC1:
21824 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
21825 break;
21826 case NM_SWC1:
21827 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
21828 break;
21829 case NM_SDC1:
21830 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
21831 break;
21832 default:
21833 gen_reserved_instruction(ctx);
21834 break;
21837 break;
21838 case NM_P_LS_S9:
21840 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
21841 extract32(ctx->opcode, 0, 8);
21843 switch (extract32(ctx->opcode, 8, 3)) {
21844 case NM_P_LS_S0:
21845 switch (extract32(ctx->opcode, 11, 4)) {
21846 case NM_LBS9:
21847 gen_ld(ctx, OPC_LB, rt, rs, s);
21848 break;
21849 case NM_LHS9:
21850 gen_ld(ctx, OPC_LH, rt, rs, s);
21851 break;
21852 case NM_LWS9:
21853 gen_ld(ctx, OPC_LW, rt, rs, s);
21854 break;
21855 case NM_LBUS9:
21856 gen_ld(ctx, OPC_LBU, rt, rs, s);
21857 break;
21858 case NM_LHUS9:
21859 gen_ld(ctx, OPC_LHU, rt, rs, s);
21860 break;
21861 case NM_SBS9:
21862 gen_st(ctx, OPC_SB, rt, rs, s);
21863 break;
21864 case NM_SHS9:
21865 gen_st(ctx, OPC_SH, rt, rs, s);
21866 break;
21867 case NM_SWS9:
21868 gen_st(ctx, OPC_SW, rt, rs, s);
21869 break;
21870 case NM_LWC1S9:
21871 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
21872 break;
21873 case NM_LDC1S9:
21874 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
21875 break;
21876 case NM_SWC1S9:
21877 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
21878 break;
21879 case NM_SDC1S9:
21880 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
21881 break;
21882 case NM_P_PREFS9:
21883 if (rt == 31) {
21884 /* SYNCI */
21886 * Break the TB to be able to sync copied instructions
21887 * immediately.
21889 ctx->base.is_jmp = DISAS_STOP;
21890 } else {
21891 /* PREF */
21892 /* Treat as NOP. */
21894 break;
21895 default:
21896 gen_reserved_instruction(ctx);
21897 break;
21899 break;
21900 case NM_P_LS_S1:
21901 switch (extract32(ctx->opcode, 11, 4)) {
21902 case NM_UALH:
21903 case NM_UASH:
21904 check_nms(ctx);
21906 TCGv t0 = tcg_temp_new();
21907 TCGv t1 = tcg_temp_new();
21909 gen_base_offset_addr(ctx, t0, rs, s);
21911 switch (extract32(ctx->opcode, 11, 4)) {
21912 case NM_UALH:
21913 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
21914 MO_UNALN);
21915 gen_store_gpr(t0, rt);
21916 break;
21917 case NM_UASH:
21918 gen_load_gpr(t1, rt);
21919 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
21920 MO_UNALN);
21921 break;
21923 tcg_temp_free(t0);
21924 tcg_temp_free(t1);
21926 break;
21927 case NM_P_LL:
21928 switch (ctx->opcode & 0x03) {
21929 case NM_LL:
21930 gen_ld(ctx, OPC_LL, rt, rs, s);
21931 break;
21932 case NM_LLWP:
21933 check_xnp(ctx);
21934 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21935 break;
21937 break;
21938 case NM_P_SC:
21939 switch (ctx->opcode & 0x03) {
21940 case NM_SC:
21941 gen_st_cond(ctx, rt, rs, s, MO_TESL, false);
21942 break;
21943 case NM_SCWP:
21944 check_xnp(ctx);
21945 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21946 false);
21947 break;
21949 break;
21950 case NM_CACHE:
21951 check_cp0_enabled(ctx);
21952 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
21953 gen_cache_operation(ctx, rt, rs, s);
21955 break;
21957 break;
21958 case NM_P_LS_E0:
21959 switch (extract32(ctx->opcode, 11, 4)) {
21960 case NM_LBE:
21961 check_eva(ctx);
21962 check_cp0_enabled(ctx);
21963 gen_ld(ctx, OPC_LBE, rt, rs, s);
21964 break;
21965 case NM_SBE:
21966 check_eva(ctx);
21967 check_cp0_enabled(ctx);
21968 gen_st(ctx, OPC_SBE, rt, rs, s);
21969 break;
21970 case NM_LBUE:
21971 check_eva(ctx);
21972 check_cp0_enabled(ctx);
21973 gen_ld(ctx, OPC_LBUE, rt, rs, s);
21974 break;
21975 case NM_P_PREFE:
21976 if (rt == 31) {
21977 /* case NM_SYNCIE */
21978 check_eva(ctx);
21979 check_cp0_enabled(ctx);
21981 * Break the TB to be able to sync copied instructions
21982 * immediately.
21984 ctx->base.is_jmp = DISAS_STOP;
21985 } else {
21986 /* case NM_PREFE */
21987 check_eva(ctx);
21988 check_cp0_enabled(ctx);
21989 /* Treat as NOP. */
21991 break;
21992 case NM_LHE:
21993 check_eva(ctx);
21994 check_cp0_enabled(ctx);
21995 gen_ld(ctx, OPC_LHE, rt, rs, s);
21996 break;
21997 case NM_SHE:
21998 check_eva(ctx);
21999 check_cp0_enabled(ctx);
22000 gen_st(ctx, OPC_SHE, rt, rs, s);
22001 break;
22002 case NM_LHUE:
22003 check_eva(ctx);
22004 check_cp0_enabled(ctx);
22005 gen_ld(ctx, OPC_LHUE, rt, rs, s);
22006 break;
22007 case NM_CACHEE:
22008 check_nms_dl_il_sl_tl_l2c(ctx);
22009 gen_cache_operation(ctx, rt, rs, s);
22010 break;
22011 case NM_LWE:
22012 check_eva(ctx);
22013 check_cp0_enabled(ctx);
22014 gen_ld(ctx, OPC_LWE, rt, rs, s);
22015 break;
22016 case NM_SWE:
22017 check_eva(ctx);
22018 check_cp0_enabled(ctx);
22019 gen_st(ctx, OPC_SWE, rt, rs, s);
22020 break;
22021 case NM_P_LLE:
22022 switch (extract32(ctx->opcode, 2, 2)) {
22023 case NM_LLE:
22024 check_xnp(ctx);
22025 check_eva(ctx);
22026 check_cp0_enabled(ctx);
22027 gen_ld(ctx, OPC_LLE, rt, rs, s);
22028 break;
22029 case NM_LLWPE:
22030 check_xnp(ctx);
22031 check_eva(ctx);
22032 check_cp0_enabled(ctx);
22033 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
22034 break;
22035 default:
22036 gen_reserved_instruction(ctx);
22037 break;
22039 break;
22040 case NM_P_SCE:
22041 switch (extract32(ctx->opcode, 2, 2)) {
22042 case NM_SCE:
22043 check_xnp(ctx);
22044 check_eva(ctx);
22045 check_cp0_enabled(ctx);
22046 gen_st_cond(ctx, rt, rs, s, MO_TESL, true);
22047 break;
22048 case NM_SCWPE:
22049 check_xnp(ctx);
22050 check_eva(ctx);
22051 check_cp0_enabled(ctx);
22052 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
22053 true);
22054 break;
22055 default:
22056 gen_reserved_instruction(ctx);
22057 break;
22059 break;
22061 break;
22062 case NM_P_LS_WM:
22063 case NM_P_LS_UAWM:
22064 check_nms(ctx);
22066 int count = extract32(ctx->opcode, 12, 3);
22067 int counter = 0;
22069 offset = sextract32(ctx->opcode, 15, 1) << 8 |
22070 extract32(ctx->opcode, 0, 8);
22071 TCGv va = tcg_temp_new();
22072 TCGv t1 = tcg_temp_new();
22073 MemOp memop = (extract32(ctx->opcode, 8, 3)) ==
22074 NM_P_LS_UAWM ? MO_UNALN : 0;
22076 count = (count == 0) ? 8 : count;
22077 while (counter != count) {
22078 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
22079 int this_offset = offset + (counter << 2);
22081 gen_base_offset_addr(ctx, va, rs, this_offset);
22083 switch (extract32(ctx->opcode, 11, 1)) {
22084 case NM_LWM:
22085 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
22086 memop | MO_TESL);
22087 gen_store_gpr(t1, this_rt);
22088 if ((this_rt == rs) &&
22089 (counter != (count - 1))) {
22090 /* UNPREDICTABLE */
22092 break;
22093 case NM_SWM:
22094 this_rt = (rt == 0) ? 0 : this_rt;
22095 gen_load_gpr(t1, this_rt);
22096 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
22097 memop | MO_TEUL);
22098 break;
22100 counter++;
22102 tcg_temp_free(va);
22103 tcg_temp_free(t1);
22105 break;
22106 default:
22107 gen_reserved_instruction(ctx);
22108 break;
22111 break;
22112 case NM_MOVE_BALC:
22113 check_nms(ctx);
22115 TCGv t0 = tcg_temp_new();
22116 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
22117 extract32(ctx->opcode, 1, 20) << 1;
22118 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
22119 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
22120 extract32(ctx->opcode, 21, 3));
22121 gen_load_gpr(t0, rt);
22122 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22123 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
22124 tcg_temp_free(t0);
22126 break;
22127 case NM_P_BAL:
22129 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
22130 extract32(ctx->opcode, 1, 24) << 1;
22132 if ((extract32(ctx->opcode, 25, 1)) == 0) {
22133 /* BC */
22134 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
22135 } else {
22136 /* BALC */
22137 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
22140 break;
22141 case NM_P_J:
22142 switch (extract32(ctx->opcode, 12, 4)) {
22143 case NM_JALRC:
22144 case NM_JALRC_HB:
22145 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
22146 break;
22147 case NM_P_BALRSC:
22148 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
22149 break;
22150 default:
22151 gen_reserved_instruction(ctx);
22152 break;
22154 break;
22155 case NM_P_BR1:
22157 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
22158 extract32(ctx->opcode, 1, 13) << 1;
22159 switch (extract32(ctx->opcode, 14, 2)) {
22160 case NM_BEQC:
22161 check_nms(ctx);
22162 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
22163 break;
22164 case NM_P_BR3A:
22165 s = sextract32(ctx->opcode, 0, 1) << 14 |
22166 extract32(ctx->opcode, 1, 13) << 1;
22167 check_cp1_enabled(ctx);
22168 switch (extract32(ctx->opcode, 16, 5)) {
22169 case NM_BC1EQZC:
22170 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
22171 break;
22172 case NM_BC1NEZC:
22173 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
22174 break;
22175 case NM_BPOSGE32C:
22176 check_dsp_r3(ctx);
22178 int32_t imm = extract32(ctx->opcode, 1, 13) |
22179 extract32(ctx->opcode, 0, 1) << 13;
22181 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
22182 imm);
22184 break;
22185 default:
22186 gen_reserved_instruction(ctx);
22187 break;
22189 break;
22190 case NM_BGEC:
22191 if (rs == rt) {
22192 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
22193 } else {
22194 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
22196 break;
22197 case NM_BGEUC:
22198 if (rs == rt || rt == 0) {
22199 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
22200 } else if (rs == 0) {
22201 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
22202 } else {
22203 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
22205 break;
22208 break;
22209 case NM_P_BR2:
22211 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
22212 extract32(ctx->opcode, 1, 13) << 1;
22213 switch (extract32(ctx->opcode, 14, 2)) {
22214 case NM_BNEC:
22215 check_nms(ctx);
22216 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
22217 break;
22218 case NM_BLTC:
22219 if (rs != 0 && rt != 0 && rs == rt) {
22220 /* NOP */
22221 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22222 } else {
22223 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
22225 break;
22226 case NM_BLTUC:
22227 if (rs == 0 || rs == rt) {
22228 /* NOP */
22229 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22230 } else {
22231 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
22233 break;
22234 default:
22235 gen_reserved_instruction(ctx);
22236 break;
22239 break;
22240 case NM_P_BRI:
22242 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
22243 extract32(ctx->opcode, 1, 10) << 1;
22244 uint32_t u = extract32(ctx->opcode, 11, 7);
22246 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
22247 rt, u, s);
22249 break;
22250 default:
22251 gen_reserved_instruction(ctx);
22252 break;
22254 return 4;
22257 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
22259 uint32_t op;
22260 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
22261 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22262 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode));
22263 int offset;
22264 int imm;
22266 /* make sure instructions are on a halfword boundary */
22267 if (ctx->base.pc_next & 0x1) {
22268 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
22269 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
22270 tcg_temp_free(tmp);
22271 generate_exception_end(ctx, EXCP_AdEL);
22272 return 2;
22275 op = extract32(ctx->opcode, 10, 6);
22276 switch (op) {
22277 case NM_P16_MV:
22278 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22279 if (rt != 0) {
22280 /* MOVE */
22281 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
22282 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
22283 } else {
22284 /* P16.RI */
22285 switch (extract32(ctx->opcode, 3, 2)) {
22286 case NM_P16_SYSCALL:
22287 if (extract32(ctx->opcode, 2, 1) == 0) {
22288 generate_exception_end(ctx, EXCP_SYSCALL);
22289 } else {
22290 gen_reserved_instruction(ctx);
22292 break;
22293 case NM_BREAK16:
22294 generate_exception_end(ctx, EXCP_BREAK);
22295 break;
22296 case NM_SDBBP16:
22297 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
22298 gen_helper_do_semihosting(cpu_env);
22299 } else {
22300 if (ctx->hflags & MIPS_HFLAG_SBRI) {
22301 gen_reserved_instruction(ctx);
22302 } else {
22303 generate_exception_end(ctx, EXCP_DBp);
22306 break;
22307 default:
22308 gen_reserved_instruction(ctx);
22309 break;
22312 break;
22313 case NM_P16_SHIFT:
22315 int shift = extract32(ctx->opcode, 0, 3);
22316 uint32_t opc = 0;
22317 shift = (shift == 0) ? 8 : shift;
22319 switch (extract32(ctx->opcode, 3, 1)) {
22320 case NM_SLL16:
22321 opc = OPC_SLL;
22322 break;
22323 case NM_SRL16:
22324 opc = OPC_SRL;
22325 break;
22327 gen_shift_imm(ctx, opc, rt, rs, shift);
22329 break;
22330 case NM_P16C:
22331 switch (ctx->opcode & 1) {
22332 case NM_POOL16C_0:
22333 gen_pool16c_nanomips_insn(ctx);
22334 break;
22335 case NM_LWXS16:
22336 gen_ldxs(ctx, rt, rs, rd);
22337 break;
22339 break;
22340 case NM_P16_A1:
22341 switch (extract32(ctx->opcode, 6, 1)) {
22342 case NM_ADDIUR1SP:
22343 imm = extract32(ctx->opcode, 0, 6) << 2;
22344 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
22345 break;
22346 default:
22347 gen_reserved_instruction(ctx);
22348 break;
22350 break;
22351 case NM_P16_A2:
22352 switch (extract32(ctx->opcode, 3, 1)) {
22353 case NM_ADDIUR2:
22354 imm = extract32(ctx->opcode, 0, 3) << 2;
22355 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
22356 break;
22357 case NM_P_ADDIURS5:
22358 rt = extract32(ctx->opcode, 5, 5);
22359 if (rt != 0) {
22360 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
22361 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
22362 (extract32(ctx->opcode, 0, 3));
22363 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
22365 break;
22367 break;
22368 case NM_P16_ADDU:
22369 switch (ctx->opcode & 0x1) {
22370 case NM_ADDU16:
22371 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
22372 break;
22373 case NM_SUBU16:
22374 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
22375 break;
22377 break;
22378 case NM_P16_4X4:
22379 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22380 extract32(ctx->opcode, 5, 3);
22381 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22382 extract32(ctx->opcode, 0, 3);
22383 rt = decode_gpr_gpr4(rt);
22384 rs = decode_gpr_gpr4(rs);
22385 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
22386 (extract32(ctx->opcode, 3, 1))) {
22387 case NM_ADDU4X4:
22388 check_nms(ctx);
22389 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
22390 break;
22391 case NM_MUL4X4:
22392 check_nms(ctx);
22393 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
22394 break;
22395 default:
22396 gen_reserved_instruction(ctx);
22397 break;
22399 break;
22400 case NM_LI16:
22402 int imm = extract32(ctx->opcode, 0, 7);
22403 imm = (imm == 0x7f ? -1 : imm);
22404 if (rt != 0) {
22405 tcg_gen_movi_tl(cpu_gpr[rt], imm);
22408 break;
22409 case NM_ANDI16:
22411 uint32_t u = extract32(ctx->opcode, 0, 4);
22412 u = (u == 12) ? 0xff :
22413 (u == 13) ? 0xffff : u;
22414 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
22416 break;
22417 case NM_P16_LB:
22418 offset = extract32(ctx->opcode, 0, 2);
22419 switch (extract32(ctx->opcode, 2, 2)) {
22420 case NM_LB16:
22421 gen_ld(ctx, OPC_LB, rt, rs, offset);
22422 break;
22423 case NM_SB16:
22424 rt = decode_gpr_gpr3_src_store(
22425 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22426 gen_st(ctx, OPC_SB, rt, rs, offset);
22427 break;
22428 case NM_LBU16:
22429 gen_ld(ctx, OPC_LBU, rt, rs, offset);
22430 break;
22431 default:
22432 gen_reserved_instruction(ctx);
22433 break;
22435 break;
22436 case NM_P16_LH:
22437 offset = extract32(ctx->opcode, 1, 2) << 1;
22438 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
22439 case NM_LH16:
22440 gen_ld(ctx, OPC_LH, rt, rs, offset);
22441 break;
22442 case NM_SH16:
22443 rt = decode_gpr_gpr3_src_store(
22444 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22445 gen_st(ctx, OPC_SH, rt, rs, offset);
22446 break;
22447 case NM_LHU16:
22448 gen_ld(ctx, OPC_LHU, rt, rs, offset);
22449 break;
22450 default:
22451 gen_reserved_instruction(ctx);
22452 break;
22454 break;
22455 case NM_LW16:
22456 offset = extract32(ctx->opcode, 0, 4) << 2;
22457 gen_ld(ctx, OPC_LW, rt, rs, offset);
22458 break;
22459 case NM_LWSP16:
22460 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22461 offset = extract32(ctx->opcode, 0, 5) << 2;
22462 gen_ld(ctx, OPC_LW, rt, 29, offset);
22463 break;
22464 case NM_LW4X4:
22465 check_nms(ctx);
22466 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22467 extract32(ctx->opcode, 5, 3);
22468 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22469 extract32(ctx->opcode, 0, 3);
22470 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22471 (extract32(ctx->opcode, 8, 1) << 2);
22472 rt = decode_gpr_gpr4(rt);
22473 rs = decode_gpr_gpr4(rs);
22474 gen_ld(ctx, OPC_LW, rt, rs, offset);
22475 break;
22476 case NM_SW4X4:
22477 check_nms(ctx);
22478 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22479 extract32(ctx->opcode, 5, 3);
22480 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22481 extract32(ctx->opcode, 0, 3);
22482 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22483 (extract32(ctx->opcode, 8, 1) << 2);
22484 rt = decode_gpr_gpr4_zero(rt);
22485 rs = decode_gpr_gpr4(rs);
22486 gen_st(ctx, OPC_SW, rt, rs, offset);
22487 break;
22488 case NM_LWGP16:
22489 offset = extract32(ctx->opcode, 0, 7) << 2;
22490 gen_ld(ctx, OPC_LW, rt, 28, offset);
22491 break;
22492 case NM_SWSP16:
22493 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22494 offset = extract32(ctx->opcode, 0, 5) << 2;
22495 gen_st(ctx, OPC_SW, rt, 29, offset);
22496 break;
22497 case NM_SW16:
22498 rt = decode_gpr_gpr3_src_store(
22499 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22500 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22501 offset = extract32(ctx->opcode, 0, 4) << 2;
22502 gen_st(ctx, OPC_SW, rt, rs, offset);
22503 break;
22504 case NM_SWGP16:
22505 rt = decode_gpr_gpr3_src_store(
22506 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22507 offset = extract32(ctx->opcode, 0, 7) << 2;
22508 gen_st(ctx, OPC_SW, rt, 28, offset);
22509 break;
22510 case NM_BC16:
22511 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
22512 (sextract32(ctx->opcode, 0, 1) << 10) |
22513 (extract32(ctx->opcode, 1, 9) << 1));
22514 break;
22515 case NM_BALC16:
22516 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
22517 (sextract32(ctx->opcode, 0, 1) << 10) |
22518 (extract32(ctx->opcode, 1, 9) << 1));
22519 break;
22520 case NM_BEQZC16:
22521 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
22522 (sextract32(ctx->opcode, 0, 1) << 7) |
22523 (extract32(ctx->opcode, 1, 6) << 1));
22524 break;
22525 case NM_BNEZC16:
22526 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
22527 (sextract32(ctx->opcode, 0, 1) << 7) |
22528 (extract32(ctx->opcode, 1, 6) << 1));
22529 break;
22530 case NM_P16_BR:
22531 switch (ctx->opcode & 0xf) {
22532 case 0:
22533 /* P16.JRC */
22534 switch (extract32(ctx->opcode, 4, 1)) {
22535 case NM_JRC:
22536 gen_compute_branch_nm(ctx, OPC_JR, 2,
22537 extract32(ctx->opcode, 5, 5), 0, 0);
22538 break;
22539 case NM_JALRC16:
22540 gen_compute_branch_nm(ctx, OPC_JALR, 2,
22541 extract32(ctx->opcode, 5, 5), 31, 0);
22542 break;
22544 break;
22545 default:
22547 /* P16.BRI */
22548 uint32_t opc = extract32(ctx->opcode, 4, 3) <
22549 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
22550 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
22551 extract32(ctx->opcode, 0, 4) << 1);
22553 break;
22555 break;
22556 case NM_P16_SR:
22558 int count = extract32(ctx->opcode, 0, 4);
22559 int u = extract32(ctx->opcode, 4, 4) << 4;
22561 rt = 30 + extract32(ctx->opcode, 9, 1);
22562 switch (extract32(ctx->opcode, 8, 1)) {
22563 case NM_SAVE16:
22564 gen_save(ctx, rt, count, 0, u);
22565 break;
22566 case NM_RESTORE_JRC16:
22567 gen_restore(ctx, rt, count, 0, u);
22568 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
22569 break;
22572 break;
22573 case NM_MOVEP:
22574 case NM_MOVEPREV:
22575 check_nms(ctx);
22577 static const int gpr2reg1[] = {4, 5, 6, 7};
22578 static const int gpr2reg2[] = {5, 6, 7, 8};
22579 int re;
22580 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
22581 extract32(ctx->opcode, 8, 1);
22582 int r1 = gpr2reg1[rd2];
22583 int r2 = gpr2reg2[rd2];
22584 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
22585 extract32(ctx->opcode, 0, 3);
22586 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
22587 extract32(ctx->opcode, 5, 3);
22588 TCGv t0 = tcg_temp_new();
22589 TCGv t1 = tcg_temp_new();
22590 if (op == NM_MOVEP) {
22591 rd = r1;
22592 re = r2;
22593 rs = decode_gpr_gpr4_zero(r3);
22594 rt = decode_gpr_gpr4_zero(r4);
22595 } else {
22596 rd = decode_gpr_gpr4(r3);
22597 re = decode_gpr_gpr4(r4);
22598 rs = r1;
22599 rt = r2;
22601 gen_load_gpr(t0, rs);
22602 gen_load_gpr(t1, rt);
22603 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22604 tcg_gen_mov_tl(cpu_gpr[re], t1);
22605 tcg_temp_free(t0);
22606 tcg_temp_free(t1);
22608 break;
22609 default:
22610 return decode_nanomips_32_48_opc(env, ctx);
22613 return 2;
22617 /* SmartMIPS extension to MIPS32 */
22619 #if defined(TARGET_MIPS64)
22621 /* MDMX extension to MIPS64 */
22623 #endif
22625 /* MIPSDSP functions. */
22626 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
22627 int rd, int base, int offset)
22629 TCGv t0;
22631 check_dsp(ctx);
22632 t0 = tcg_temp_new();
22634 if (base == 0) {
22635 gen_load_gpr(t0, offset);
22636 } else if (offset == 0) {
22637 gen_load_gpr(t0, base);
22638 } else {
22639 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
22642 switch (opc) {
22643 case OPC_LBUX:
22644 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
22645 gen_store_gpr(t0, rd);
22646 break;
22647 case OPC_LHX:
22648 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
22649 gen_store_gpr(t0, rd);
22650 break;
22651 case OPC_LWX:
22652 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
22653 gen_store_gpr(t0, rd);
22654 break;
22655 #if defined(TARGET_MIPS64)
22656 case OPC_LDX:
22657 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
22658 gen_store_gpr(t0, rd);
22659 break;
22660 #endif
22662 tcg_temp_free(t0);
22665 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
22666 int ret, int v1, int v2)
22668 TCGv v1_t;
22669 TCGv v2_t;
22671 if (ret == 0) {
22672 /* Treat as NOP. */
22673 return;
22676 v1_t = tcg_temp_new();
22677 v2_t = tcg_temp_new();
22679 gen_load_gpr(v1_t, v1);
22680 gen_load_gpr(v2_t, v2);
22682 switch (op1) {
22683 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
22684 case OPC_MULT_G_2E:
22685 check_dsp_r2(ctx);
22686 switch (op2) {
22687 case OPC_ADDUH_QB:
22688 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
22689 break;
22690 case OPC_ADDUH_R_QB:
22691 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22692 break;
22693 case OPC_ADDQH_PH:
22694 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
22695 break;
22696 case OPC_ADDQH_R_PH:
22697 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22698 break;
22699 case OPC_ADDQH_W:
22700 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
22701 break;
22702 case OPC_ADDQH_R_W:
22703 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22704 break;
22705 case OPC_SUBUH_QB:
22706 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
22707 break;
22708 case OPC_SUBUH_R_QB:
22709 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22710 break;
22711 case OPC_SUBQH_PH:
22712 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
22713 break;
22714 case OPC_SUBQH_R_PH:
22715 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22716 break;
22717 case OPC_SUBQH_W:
22718 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
22719 break;
22720 case OPC_SUBQH_R_W:
22721 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22722 break;
22724 break;
22725 case OPC_ABSQ_S_PH_DSP:
22726 switch (op2) {
22727 case OPC_ABSQ_S_QB:
22728 check_dsp_r2(ctx);
22729 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
22730 break;
22731 case OPC_ABSQ_S_PH:
22732 check_dsp(ctx);
22733 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
22734 break;
22735 case OPC_ABSQ_S_W:
22736 check_dsp(ctx);
22737 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
22738 break;
22739 case OPC_PRECEQ_W_PHL:
22740 check_dsp(ctx);
22741 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
22742 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22743 break;
22744 case OPC_PRECEQ_W_PHR:
22745 check_dsp(ctx);
22746 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
22747 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
22748 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22749 break;
22750 case OPC_PRECEQU_PH_QBL:
22751 check_dsp(ctx);
22752 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
22753 break;
22754 case OPC_PRECEQU_PH_QBR:
22755 check_dsp(ctx);
22756 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
22757 break;
22758 case OPC_PRECEQU_PH_QBLA:
22759 check_dsp(ctx);
22760 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
22761 break;
22762 case OPC_PRECEQU_PH_QBRA:
22763 check_dsp(ctx);
22764 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
22765 break;
22766 case OPC_PRECEU_PH_QBL:
22767 check_dsp(ctx);
22768 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
22769 break;
22770 case OPC_PRECEU_PH_QBR:
22771 check_dsp(ctx);
22772 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
22773 break;
22774 case OPC_PRECEU_PH_QBLA:
22775 check_dsp(ctx);
22776 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
22777 break;
22778 case OPC_PRECEU_PH_QBRA:
22779 check_dsp(ctx);
22780 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
22781 break;
22783 break;
22784 case OPC_ADDU_QB_DSP:
22785 switch (op2) {
22786 case OPC_ADDQ_PH:
22787 check_dsp(ctx);
22788 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22789 break;
22790 case OPC_ADDQ_S_PH:
22791 check_dsp(ctx);
22792 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22793 break;
22794 case OPC_ADDQ_S_W:
22795 check_dsp(ctx);
22796 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22797 break;
22798 case OPC_ADDU_QB:
22799 check_dsp(ctx);
22800 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22801 break;
22802 case OPC_ADDU_S_QB:
22803 check_dsp(ctx);
22804 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22805 break;
22806 case OPC_ADDU_PH:
22807 check_dsp_r2(ctx);
22808 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22809 break;
22810 case OPC_ADDU_S_PH:
22811 check_dsp_r2(ctx);
22812 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22813 break;
22814 case OPC_SUBQ_PH:
22815 check_dsp(ctx);
22816 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22817 break;
22818 case OPC_SUBQ_S_PH:
22819 check_dsp(ctx);
22820 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22821 break;
22822 case OPC_SUBQ_S_W:
22823 check_dsp(ctx);
22824 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22825 break;
22826 case OPC_SUBU_QB:
22827 check_dsp(ctx);
22828 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22829 break;
22830 case OPC_SUBU_S_QB:
22831 check_dsp(ctx);
22832 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22833 break;
22834 case OPC_SUBU_PH:
22835 check_dsp_r2(ctx);
22836 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22837 break;
22838 case OPC_SUBU_S_PH:
22839 check_dsp_r2(ctx);
22840 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22841 break;
22842 case OPC_ADDSC:
22843 check_dsp(ctx);
22844 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22845 break;
22846 case OPC_ADDWC:
22847 check_dsp(ctx);
22848 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22849 break;
22850 case OPC_MODSUB:
22851 check_dsp(ctx);
22852 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
22853 break;
22854 case OPC_RADDU_W_QB:
22855 check_dsp(ctx);
22856 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
22857 break;
22859 break;
22860 case OPC_CMPU_EQ_QB_DSP:
22861 switch (op2) {
22862 case OPC_PRECR_QB_PH:
22863 check_dsp_r2(ctx);
22864 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22865 break;
22866 case OPC_PRECRQ_QB_PH:
22867 check_dsp(ctx);
22868 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22869 break;
22870 case OPC_PRECR_SRA_PH_W:
22871 check_dsp_r2(ctx);
22873 TCGv_i32 sa_t = tcg_const_i32(v2);
22874 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
22875 cpu_gpr[ret]);
22876 tcg_temp_free_i32(sa_t);
22877 break;
22879 case OPC_PRECR_SRA_R_PH_W:
22880 check_dsp_r2(ctx);
22882 TCGv_i32 sa_t = tcg_const_i32(v2);
22883 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
22884 cpu_gpr[ret]);
22885 tcg_temp_free_i32(sa_t);
22886 break;
22888 case OPC_PRECRQ_PH_W:
22889 check_dsp(ctx);
22890 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
22891 break;
22892 case OPC_PRECRQ_RS_PH_W:
22893 check_dsp(ctx);
22894 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22895 break;
22896 case OPC_PRECRQU_S_QB_PH:
22897 check_dsp(ctx);
22898 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22899 break;
22901 break;
22902 #ifdef TARGET_MIPS64
22903 case OPC_ABSQ_S_QH_DSP:
22904 switch (op2) {
22905 case OPC_PRECEQ_L_PWL:
22906 check_dsp(ctx);
22907 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
22908 break;
22909 case OPC_PRECEQ_L_PWR:
22910 check_dsp(ctx);
22911 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
22912 break;
22913 case OPC_PRECEQ_PW_QHL:
22914 check_dsp(ctx);
22915 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
22916 break;
22917 case OPC_PRECEQ_PW_QHR:
22918 check_dsp(ctx);
22919 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
22920 break;
22921 case OPC_PRECEQ_PW_QHLA:
22922 check_dsp(ctx);
22923 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
22924 break;
22925 case OPC_PRECEQ_PW_QHRA:
22926 check_dsp(ctx);
22927 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
22928 break;
22929 case OPC_PRECEQU_QH_OBL:
22930 check_dsp(ctx);
22931 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
22932 break;
22933 case OPC_PRECEQU_QH_OBR:
22934 check_dsp(ctx);
22935 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
22936 break;
22937 case OPC_PRECEQU_QH_OBLA:
22938 check_dsp(ctx);
22939 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
22940 break;
22941 case OPC_PRECEQU_QH_OBRA:
22942 check_dsp(ctx);
22943 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
22944 break;
22945 case OPC_PRECEU_QH_OBL:
22946 check_dsp(ctx);
22947 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
22948 break;
22949 case OPC_PRECEU_QH_OBR:
22950 check_dsp(ctx);
22951 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
22952 break;
22953 case OPC_PRECEU_QH_OBLA:
22954 check_dsp(ctx);
22955 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
22956 break;
22957 case OPC_PRECEU_QH_OBRA:
22958 check_dsp(ctx);
22959 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
22960 break;
22961 case OPC_ABSQ_S_OB:
22962 check_dsp_r2(ctx);
22963 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
22964 break;
22965 case OPC_ABSQ_S_PW:
22966 check_dsp(ctx);
22967 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
22968 break;
22969 case OPC_ABSQ_S_QH:
22970 check_dsp(ctx);
22971 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
22972 break;
22974 break;
22975 case OPC_ADDU_OB_DSP:
22976 switch (op2) {
22977 case OPC_RADDU_L_OB:
22978 check_dsp(ctx);
22979 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
22980 break;
22981 case OPC_SUBQ_PW:
22982 check_dsp(ctx);
22983 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22984 break;
22985 case OPC_SUBQ_S_PW:
22986 check_dsp(ctx);
22987 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22988 break;
22989 case OPC_SUBQ_QH:
22990 check_dsp(ctx);
22991 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22992 break;
22993 case OPC_SUBQ_S_QH:
22994 check_dsp(ctx);
22995 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22996 break;
22997 case OPC_SUBU_OB:
22998 check_dsp(ctx);
22999 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23000 break;
23001 case OPC_SUBU_S_OB:
23002 check_dsp(ctx);
23003 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23004 break;
23005 case OPC_SUBU_QH:
23006 check_dsp_r2(ctx);
23007 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23008 break;
23009 case OPC_SUBU_S_QH:
23010 check_dsp_r2(ctx);
23011 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23012 break;
23013 case OPC_SUBUH_OB:
23014 check_dsp_r2(ctx);
23015 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
23016 break;
23017 case OPC_SUBUH_R_OB:
23018 check_dsp_r2(ctx);
23019 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
23020 break;
23021 case OPC_ADDQ_PW:
23022 check_dsp(ctx);
23023 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23024 break;
23025 case OPC_ADDQ_S_PW:
23026 check_dsp(ctx);
23027 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23028 break;
23029 case OPC_ADDQ_QH:
23030 check_dsp(ctx);
23031 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23032 break;
23033 case OPC_ADDQ_S_QH:
23034 check_dsp(ctx);
23035 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23036 break;
23037 case OPC_ADDU_OB:
23038 check_dsp(ctx);
23039 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23040 break;
23041 case OPC_ADDU_S_OB:
23042 check_dsp(ctx);
23043 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23044 break;
23045 case OPC_ADDU_QH:
23046 check_dsp_r2(ctx);
23047 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23048 break;
23049 case OPC_ADDU_S_QH:
23050 check_dsp_r2(ctx);
23051 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23052 break;
23053 case OPC_ADDUH_OB:
23054 check_dsp_r2(ctx);
23055 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
23056 break;
23057 case OPC_ADDUH_R_OB:
23058 check_dsp_r2(ctx);
23059 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
23060 break;
23062 break;
23063 case OPC_CMPU_EQ_OB_DSP:
23064 switch (op2) {
23065 case OPC_PRECR_OB_QH:
23066 check_dsp_r2(ctx);
23067 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
23068 break;
23069 case OPC_PRECR_SRA_QH_PW:
23070 check_dsp_r2(ctx);
23072 TCGv_i32 ret_t = tcg_const_i32(ret);
23073 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
23074 tcg_temp_free_i32(ret_t);
23075 break;
23077 case OPC_PRECR_SRA_R_QH_PW:
23078 check_dsp_r2(ctx);
23080 TCGv_i32 sa_v = tcg_const_i32(ret);
23081 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
23082 tcg_temp_free_i32(sa_v);
23083 break;
23085 case OPC_PRECRQ_OB_QH:
23086 check_dsp(ctx);
23087 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
23088 break;
23089 case OPC_PRECRQ_PW_L:
23090 check_dsp(ctx);
23091 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
23092 break;
23093 case OPC_PRECRQ_QH_PW:
23094 check_dsp(ctx);
23095 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
23096 break;
23097 case OPC_PRECRQ_RS_QH_PW:
23098 check_dsp(ctx);
23099 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23100 break;
23101 case OPC_PRECRQU_S_OB_QH:
23102 check_dsp(ctx);
23103 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23104 break;
23106 break;
23107 #endif
23110 tcg_temp_free(v1_t);
23111 tcg_temp_free(v2_t);
23114 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
23115 int ret, int v1, int v2)
23117 uint32_t op2;
23118 TCGv t0;
23119 TCGv v1_t;
23120 TCGv v2_t;
23122 if (ret == 0) {
23123 /* Treat as NOP. */
23124 return;
23127 t0 = tcg_temp_new();
23128 v1_t = tcg_temp_new();
23129 v2_t = tcg_temp_new();
23131 tcg_gen_movi_tl(t0, v1);
23132 gen_load_gpr(v1_t, v1);
23133 gen_load_gpr(v2_t, v2);
23135 switch (opc) {
23136 case OPC_SHLL_QB_DSP:
23138 op2 = MASK_SHLL_QB(ctx->opcode);
23139 switch (op2) {
23140 case OPC_SHLL_QB:
23141 check_dsp(ctx);
23142 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
23143 break;
23144 case OPC_SHLLV_QB:
23145 check_dsp(ctx);
23146 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23147 break;
23148 case OPC_SHLL_PH:
23149 check_dsp(ctx);
23150 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
23151 break;
23152 case OPC_SHLLV_PH:
23153 check_dsp(ctx);
23154 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23155 break;
23156 case OPC_SHLL_S_PH:
23157 check_dsp(ctx);
23158 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
23159 break;
23160 case OPC_SHLLV_S_PH:
23161 check_dsp(ctx);
23162 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23163 break;
23164 case OPC_SHLL_S_W:
23165 check_dsp(ctx);
23166 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
23167 break;
23168 case OPC_SHLLV_S_W:
23169 check_dsp(ctx);
23170 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23171 break;
23172 case OPC_SHRL_QB:
23173 check_dsp(ctx);
23174 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
23175 break;
23176 case OPC_SHRLV_QB:
23177 check_dsp(ctx);
23178 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
23179 break;
23180 case OPC_SHRL_PH:
23181 check_dsp_r2(ctx);
23182 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
23183 break;
23184 case OPC_SHRLV_PH:
23185 check_dsp_r2(ctx);
23186 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
23187 break;
23188 case OPC_SHRA_QB:
23189 check_dsp_r2(ctx);
23190 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
23191 break;
23192 case OPC_SHRA_R_QB:
23193 check_dsp_r2(ctx);
23194 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
23195 break;
23196 case OPC_SHRAV_QB:
23197 check_dsp_r2(ctx);
23198 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
23199 break;
23200 case OPC_SHRAV_R_QB:
23201 check_dsp_r2(ctx);
23202 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
23203 break;
23204 case OPC_SHRA_PH:
23205 check_dsp(ctx);
23206 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
23207 break;
23208 case OPC_SHRA_R_PH:
23209 check_dsp(ctx);
23210 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
23211 break;
23212 case OPC_SHRAV_PH:
23213 check_dsp(ctx);
23214 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
23215 break;
23216 case OPC_SHRAV_R_PH:
23217 check_dsp(ctx);
23218 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
23219 break;
23220 case OPC_SHRA_R_W:
23221 check_dsp(ctx);
23222 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
23223 break;
23224 case OPC_SHRAV_R_W:
23225 check_dsp(ctx);
23226 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
23227 break;
23228 default: /* Invalid */
23229 MIPS_INVAL("MASK SHLL.QB");
23230 gen_reserved_instruction(ctx);
23231 break;
23233 break;
23235 #ifdef TARGET_MIPS64
23236 case OPC_SHLL_OB_DSP:
23237 op2 = MASK_SHLL_OB(ctx->opcode);
23238 switch (op2) {
23239 case OPC_SHLL_PW:
23240 check_dsp(ctx);
23241 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23242 break;
23243 case OPC_SHLLV_PW:
23244 check_dsp(ctx);
23245 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23246 break;
23247 case OPC_SHLL_S_PW:
23248 check_dsp(ctx);
23249 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23250 break;
23251 case OPC_SHLLV_S_PW:
23252 check_dsp(ctx);
23253 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23254 break;
23255 case OPC_SHLL_OB:
23256 check_dsp(ctx);
23257 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
23258 break;
23259 case OPC_SHLLV_OB:
23260 check_dsp(ctx);
23261 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23262 break;
23263 case OPC_SHLL_QH:
23264 check_dsp(ctx);
23265 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23266 break;
23267 case OPC_SHLLV_QH:
23268 check_dsp(ctx);
23269 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23270 break;
23271 case OPC_SHLL_S_QH:
23272 check_dsp(ctx);
23273 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23274 break;
23275 case OPC_SHLLV_S_QH:
23276 check_dsp(ctx);
23277 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23278 break;
23279 case OPC_SHRA_OB:
23280 check_dsp_r2(ctx);
23281 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
23282 break;
23283 case OPC_SHRAV_OB:
23284 check_dsp_r2(ctx);
23285 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
23286 break;
23287 case OPC_SHRA_R_OB:
23288 check_dsp_r2(ctx);
23289 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
23290 break;
23291 case OPC_SHRAV_R_OB:
23292 check_dsp_r2(ctx);
23293 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
23294 break;
23295 case OPC_SHRA_PW:
23296 check_dsp(ctx);
23297 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
23298 break;
23299 case OPC_SHRAV_PW:
23300 check_dsp(ctx);
23301 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
23302 break;
23303 case OPC_SHRA_R_PW:
23304 check_dsp(ctx);
23305 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
23306 break;
23307 case OPC_SHRAV_R_PW:
23308 check_dsp(ctx);
23309 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
23310 break;
23311 case OPC_SHRA_QH:
23312 check_dsp(ctx);
23313 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
23314 break;
23315 case OPC_SHRAV_QH:
23316 check_dsp(ctx);
23317 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
23318 break;
23319 case OPC_SHRA_R_QH:
23320 check_dsp(ctx);
23321 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
23322 break;
23323 case OPC_SHRAV_R_QH:
23324 check_dsp(ctx);
23325 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
23326 break;
23327 case OPC_SHRL_OB:
23328 check_dsp(ctx);
23329 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
23330 break;
23331 case OPC_SHRLV_OB:
23332 check_dsp(ctx);
23333 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
23334 break;
23335 case OPC_SHRL_QH:
23336 check_dsp_r2(ctx);
23337 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
23338 break;
23339 case OPC_SHRLV_QH:
23340 check_dsp_r2(ctx);
23341 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
23342 break;
23343 default: /* Invalid */
23344 MIPS_INVAL("MASK SHLL.OB");
23345 gen_reserved_instruction(ctx);
23346 break;
23348 break;
23349 #endif
23352 tcg_temp_free(t0);
23353 tcg_temp_free(v1_t);
23354 tcg_temp_free(v2_t);
23357 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
23358 int ret, int v1, int v2, int check_ret)
23360 TCGv_i32 t0;
23361 TCGv v1_t;
23362 TCGv v2_t;
23364 if ((ret == 0) && (check_ret == 1)) {
23365 /* Treat as NOP. */
23366 return;
23369 t0 = tcg_temp_new_i32();
23370 v1_t = tcg_temp_new();
23371 v2_t = tcg_temp_new();
23373 tcg_gen_movi_i32(t0, ret);
23374 gen_load_gpr(v1_t, v1);
23375 gen_load_gpr(v2_t, v2);
23377 switch (op1) {
23379 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
23380 * the same mask and op1.
23382 case OPC_MULT_G_2E:
23383 check_dsp_r2(ctx);
23384 switch (op2) {
23385 case OPC_MUL_PH:
23386 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23387 break;
23388 case OPC_MUL_S_PH:
23389 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23390 break;
23391 case OPC_MULQ_S_W:
23392 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23393 break;
23394 case OPC_MULQ_RS_W:
23395 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23396 break;
23398 break;
23399 case OPC_DPA_W_PH_DSP:
23400 switch (op2) {
23401 case OPC_DPAU_H_QBL:
23402 check_dsp(ctx);
23403 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
23404 break;
23405 case OPC_DPAU_H_QBR:
23406 check_dsp(ctx);
23407 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
23408 break;
23409 case OPC_DPSU_H_QBL:
23410 check_dsp(ctx);
23411 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
23412 break;
23413 case OPC_DPSU_H_QBR:
23414 check_dsp(ctx);
23415 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
23416 break;
23417 case OPC_DPA_W_PH:
23418 check_dsp_r2(ctx);
23419 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
23420 break;
23421 case OPC_DPAX_W_PH:
23422 check_dsp_r2(ctx);
23423 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
23424 break;
23425 case OPC_DPAQ_S_W_PH:
23426 check_dsp(ctx);
23427 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23428 break;
23429 case OPC_DPAQX_S_W_PH:
23430 check_dsp_r2(ctx);
23431 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23432 break;
23433 case OPC_DPAQX_SA_W_PH:
23434 check_dsp_r2(ctx);
23435 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23436 break;
23437 case OPC_DPS_W_PH:
23438 check_dsp_r2(ctx);
23439 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
23440 break;
23441 case OPC_DPSX_W_PH:
23442 check_dsp_r2(ctx);
23443 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
23444 break;
23445 case OPC_DPSQ_S_W_PH:
23446 check_dsp(ctx);
23447 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23448 break;
23449 case OPC_DPSQX_S_W_PH:
23450 check_dsp_r2(ctx);
23451 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23452 break;
23453 case OPC_DPSQX_SA_W_PH:
23454 check_dsp_r2(ctx);
23455 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23456 break;
23457 case OPC_MULSAQ_S_W_PH:
23458 check_dsp(ctx);
23459 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23460 break;
23461 case OPC_DPAQ_SA_L_W:
23462 check_dsp(ctx);
23463 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23464 break;
23465 case OPC_DPSQ_SA_L_W:
23466 check_dsp(ctx);
23467 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23468 break;
23469 case OPC_MAQ_S_W_PHL:
23470 check_dsp(ctx);
23471 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
23472 break;
23473 case OPC_MAQ_S_W_PHR:
23474 check_dsp(ctx);
23475 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
23476 break;
23477 case OPC_MAQ_SA_W_PHL:
23478 check_dsp(ctx);
23479 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
23480 break;
23481 case OPC_MAQ_SA_W_PHR:
23482 check_dsp(ctx);
23483 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
23484 break;
23485 case OPC_MULSA_W_PH:
23486 check_dsp_r2(ctx);
23487 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
23488 break;
23490 break;
23491 #ifdef TARGET_MIPS64
23492 case OPC_DPAQ_W_QH_DSP:
23494 int ac = ret & 0x03;
23495 tcg_gen_movi_i32(t0, ac);
23497 switch (op2) {
23498 case OPC_DMADD:
23499 check_dsp(ctx);
23500 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
23501 break;
23502 case OPC_DMADDU:
23503 check_dsp(ctx);
23504 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
23505 break;
23506 case OPC_DMSUB:
23507 check_dsp(ctx);
23508 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
23509 break;
23510 case OPC_DMSUBU:
23511 check_dsp(ctx);
23512 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
23513 break;
23514 case OPC_DPA_W_QH:
23515 check_dsp_r2(ctx);
23516 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
23517 break;
23518 case OPC_DPAQ_S_W_QH:
23519 check_dsp(ctx);
23520 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23521 break;
23522 case OPC_DPAQ_SA_L_PW:
23523 check_dsp(ctx);
23524 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23525 break;
23526 case OPC_DPAU_H_OBL:
23527 check_dsp(ctx);
23528 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
23529 break;
23530 case OPC_DPAU_H_OBR:
23531 check_dsp(ctx);
23532 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
23533 break;
23534 case OPC_DPS_W_QH:
23535 check_dsp_r2(ctx);
23536 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
23537 break;
23538 case OPC_DPSQ_S_W_QH:
23539 check_dsp(ctx);
23540 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23541 break;
23542 case OPC_DPSQ_SA_L_PW:
23543 check_dsp(ctx);
23544 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23545 break;
23546 case OPC_DPSU_H_OBL:
23547 check_dsp(ctx);
23548 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
23549 break;
23550 case OPC_DPSU_H_OBR:
23551 check_dsp(ctx);
23552 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
23553 break;
23554 case OPC_MAQ_S_L_PWL:
23555 check_dsp(ctx);
23556 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
23557 break;
23558 case OPC_MAQ_S_L_PWR:
23559 check_dsp(ctx);
23560 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
23561 break;
23562 case OPC_MAQ_S_W_QHLL:
23563 check_dsp(ctx);
23564 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
23565 break;
23566 case OPC_MAQ_SA_W_QHLL:
23567 check_dsp(ctx);
23568 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
23569 break;
23570 case OPC_MAQ_S_W_QHLR:
23571 check_dsp(ctx);
23572 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
23573 break;
23574 case OPC_MAQ_SA_W_QHLR:
23575 check_dsp(ctx);
23576 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
23577 break;
23578 case OPC_MAQ_S_W_QHRL:
23579 check_dsp(ctx);
23580 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
23581 break;
23582 case OPC_MAQ_SA_W_QHRL:
23583 check_dsp(ctx);
23584 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
23585 break;
23586 case OPC_MAQ_S_W_QHRR:
23587 check_dsp(ctx);
23588 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
23589 break;
23590 case OPC_MAQ_SA_W_QHRR:
23591 check_dsp(ctx);
23592 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
23593 break;
23594 case OPC_MULSAQ_S_L_PW:
23595 check_dsp(ctx);
23596 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
23597 break;
23598 case OPC_MULSAQ_S_W_QH:
23599 check_dsp(ctx);
23600 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23601 break;
23604 break;
23605 #endif
23606 case OPC_ADDU_QB_DSP:
23607 switch (op2) {
23608 case OPC_MULEU_S_PH_QBL:
23609 check_dsp(ctx);
23610 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23611 break;
23612 case OPC_MULEU_S_PH_QBR:
23613 check_dsp(ctx);
23614 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23615 break;
23616 case OPC_MULQ_RS_PH:
23617 check_dsp(ctx);
23618 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23619 break;
23620 case OPC_MULEQ_S_W_PHL:
23621 check_dsp(ctx);
23622 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23623 break;
23624 case OPC_MULEQ_S_W_PHR:
23625 check_dsp(ctx);
23626 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23627 break;
23628 case OPC_MULQ_S_PH:
23629 check_dsp_r2(ctx);
23630 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23631 break;
23633 break;
23634 #ifdef TARGET_MIPS64
23635 case OPC_ADDU_OB_DSP:
23636 switch (op2) {
23637 case OPC_MULEQ_S_PW_QHL:
23638 check_dsp(ctx);
23639 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23640 break;
23641 case OPC_MULEQ_S_PW_QHR:
23642 check_dsp(ctx);
23643 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23644 break;
23645 case OPC_MULEU_S_QH_OBL:
23646 check_dsp(ctx);
23647 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23648 break;
23649 case OPC_MULEU_S_QH_OBR:
23650 check_dsp(ctx);
23651 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23652 break;
23653 case OPC_MULQ_RS_QH:
23654 check_dsp(ctx);
23655 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23656 break;
23658 break;
23659 #endif
23662 tcg_temp_free_i32(t0);
23663 tcg_temp_free(v1_t);
23664 tcg_temp_free(v2_t);
23667 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23668 int ret, int val)
23670 int16_t imm;
23671 TCGv t0;
23672 TCGv val_t;
23674 if (ret == 0) {
23675 /* Treat as NOP. */
23676 return;
23679 t0 = tcg_temp_new();
23680 val_t = tcg_temp_new();
23681 gen_load_gpr(val_t, val);
23683 switch (op1) {
23684 case OPC_ABSQ_S_PH_DSP:
23685 switch (op2) {
23686 case OPC_BITREV:
23687 check_dsp(ctx);
23688 gen_helper_bitrev(cpu_gpr[ret], val_t);
23689 break;
23690 case OPC_REPL_QB:
23691 check_dsp(ctx);
23693 target_long result;
23694 imm = (ctx->opcode >> 16) & 0xFF;
23695 result = (uint32_t)imm << 24 |
23696 (uint32_t)imm << 16 |
23697 (uint32_t)imm << 8 |
23698 (uint32_t)imm;
23699 result = (int32_t)result;
23700 tcg_gen_movi_tl(cpu_gpr[ret], result);
23702 break;
23703 case OPC_REPLV_QB:
23704 check_dsp(ctx);
23705 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23706 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23707 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23708 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23709 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23710 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23711 break;
23712 case OPC_REPL_PH:
23713 check_dsp(ctx);
23715 imm = (ctx->opcode >> 16) & 0x03FF;
23716 imm = (int16_t)(imm << 6) >> 6;
23717 tcg_gen_movi_tl(cpu_gpr[ret], \
23718 (target_long)((int32_t)imm << 16 | \
23719 (uint16_t)imm));
23721 break;
23722 case OPC_REPLV_PH:
23723 check_dsp(ctx);
23724 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23725 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23726 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23727 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23728 break;
23730 break;
23731 #ifdef TARGET_MIPS64
23732 case OPC_ABSQ_S_QH_DSP:
23733 switch (op2) {
23734 case OPC_REPL_OB:
23735 check_dsp(ctx);
23737 target_long temp;
23739 imm = (ctx->opcode >> 16) & 0xFF;
23740 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
23741 temp = (temp << 16) | temp;
23742 temp = (temp << 32) | temp;
23743 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23744 break;
23746 case OPC_REPL_PW:
23747 check_dsp(ctx);
23749 target_long temp;
23751 imm = (ctx->opcode >> 16) & 0x03FF;
23752 imm = (int16_t)(imm << 6) >> 6;
23753 temp = ((target_long)imm << 32) \
23754 | ((target_long)imm & 0xFFFFFFFF);
23755 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23756 break;
23758 case OPC_REPL_QH:
23759 check_dsp(ctx);
23761 target_long temp;
23763 imm = (ctx->opcode >> 16) & 0x03FF;
23764 imm = (int16_t)(imm << 6) >> 6;
23766 temp = ((uint64_t)(uint16_t)imm << 48) |
23767 ((uint64_t)(uint16_t)imm << 32) |
23768 ((uint64_t)(uint16_t)imm << 16) |
23769 (uint64_t)(uint16_t)imm;
23770 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23771 break;
23773 case OPC_REPLV_OB:
23774 check_dsp(ctx);
23775 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23776 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23777 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23778 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23779 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23780 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23781 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23782 break;
23783 case OPC_REPLV_PW:
23784 check_dsp(ctx);
23785 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
23786 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23787 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23788 break;
23789 case OPC_REPLV_QH:
23790 check_dsp(ctx);
23791 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23792 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23793 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23794 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23795 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23796 break;
23798 break;
23799 #endif
23801 tcg_temp_free(t0);
23802 tcg_temp_free(val_t);
23805 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
23806 uint32_t op1, uint32_t op2,
23807 int ret, int v1, int v2, int check_ret)
23809 TCGv t1;
23810 TCGv v1_t;
23811 TCGv v2_t;
23813 if ((ret == 0) && (check_ret == 1)) {
23814 /* Treat as NOP. */
23815 return;
23818 t1 = tcg_temp_new();
23819 v1_t = tcg_temp_new();
23820 v2_t = tcg_temp_new();
23822 gen_load_gpr(v1_t, v1);
23823 gen_load_gpr(v2_t, v2);
23825 switch (op1) {
23826 case OPC_CMPU_EQ_QB_DSP:
23827 switch (op2) {
23828 case OPC_CMPU_EQ_QB:
23829 check_dsp(ctx);
23830 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
23831 break;
23832 case OPC_CMPU_LT_QB:
23833 check_dsp(ctx);
23834 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
23835 break;
23836 case OPC_CMPU_LE_QB:
23837 check_dsp(ctx);
23838 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
23839 break;
23840 case OPC_CMPGU_EQ_QB:
23841 check_dsp(ctx);
23842 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
23843 break;
23844 case OPC_CMPGU_LT_QB:
23845 check_dsp(ctx);
23846 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
23847 break;
23848 case OPC_CMPGU_LE_QB:
23849 check_dsp(ctx);
23850 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
23851 break;
23852 case OPC_CMPGDU_EQ_QB:
23853 check_dsp_r2(ctx);
23854 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
23855 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23856 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23857 tcg_gen_shli_tl(t1, t1, 24);
23858 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23859 break;
23860 case OPC_CMPGDU_LT_QB:
23861 check_dsp_r2(ctx);
23862 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
23863 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23864 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23865 tcg_gen_shli_tl(t1, t1, 24);
23866 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23867 break;
23868 case OPC_CMPGDU_LE_QB:
23869 check_dsp_r2(ctx);
23870 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
23871 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23872 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23873 tcg_gen_shli_tl(t1, t1, 24);
23874 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23875 break;
23876 case OPC_CMP_EQ_PH:
23877 check_dsp(ctx);
23878 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
23879 break;
23880 case OPC_CMP_LT_PH:
23881 check_dsp(ctx);
23882 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
23883 break;
23884 case OPC_CMP_LE_PH:
23885 check_dsp(ctx);
23886 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
23887 break;
23888 case OPC_PICK_QB:
23889 check_dsp(ctx);
23890 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23891 break;
23892 case OPC_PICK_PH:
23893 check_dsp(ctx);
23894 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23895 break;
23896 case OPC_PACKRL_PH:
23897 check_dsp(ctx);
23898 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
23899 break;
23901 break;
23902 #ifdef TARGET_MIPS64
23903 case OPC_CMPU_EQ_OB_DSP:
23904 switch (op2) {
23905 case OPC_CMP_EQ_PW:
23906 check_dsp(ctx);
23907 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
23908 break;
23909 case OPC_CMP_LT_PW:
23910 check_dsp(ctx);
23911 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
23912 break;
23913 case OPC_CMP_LE_PW:
23914 check_dsp(ctx);
23915 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
23916 break;
23917 case OPC_CMP_EQ_QH:
23918 check_dsp(ctx);
23919 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
23920 break;
23921 case OPC_CMP_LT_QH:
23922 check_dsp(ctx);
23923 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
23924 break;
23925 case OPC_CMP_LE_QH:
23926 check_dsp(ctx);
23927 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
23928 break;
23929 case OPC_CMPGDU_EQ_OB:
23930 check_dsp_r2(ctx);
23931 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23932 break;
23933 case OPC_CMPGDU_LT_OB:
23934 check_dsp_r2(ctx);
23935 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23936 break;
23937 case OPC_CMPGDU_LE_OB:
23938 check_dsp_r2(ctx);
23939 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23940 break;
23941 case OPC_CMPGU_EQ_OB:
23942 check_dsp(ctx);
23943 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
23944 break;
23945 case OPC_CMPGU_LT_OB:
23946 check_dsp(ctx);
23947 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
23948 break;
23949 case OPC_CMPGU_LE_OB:
23950 check_dsp(ctx);
23951 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
23952 break;
23953 case OPC_CMPU_EQ_OB:
23954 check_dsp(ctx);
23955 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
23956 break;
23957 case OPC_CMPU_LT_OB:
23958 check_dsp(ctx);
23959 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
23960 break;
23961 case OPC_CMPU_LE_OB:
23962 check_dsp(ctx);
23963 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
23964 break;
23965 case OPC_PACKRL_PW:
23966 check_dsp(ctx);
23967 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
23968 break;
23969 case OPC_PICK_OB:
23970 check_dsp(ctx);
23971 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23972 break;
23973 case OPC_PICK_PW:
23974 check_dsp(ctx);
23975 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23976 break;
23977 case OPC_PICK_QH:
23978 check_dsp(ctx);
23979 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23980 break;
23982 break;
23983 #endif
23986 tcg_temp_free(t1);
23987 tcg_temp_free(v1_t);
23988 tcg_temp_free(v2_t);
23991 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
23992 uint32_t op1, int rt, int rs, int sa)
23994 TCGv t0;
23996 check_dsp_r2(ctx);
23998 if (rt == 0) {
23999 /* Treat as NOP. */
24000 return;
24003 t0 = tcg_temp_new();
24004 gen_load_gpr(t0, rs);
24006 switch (op1) {
24007 case OPC_APPEND_DSP:
24008 switch (MASK_APPEND(ctx->opcode)) {
24009 case OPC_APPEND:
24010 if (sa != 0) {
24011 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
24013 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
24014 break;
24015 case OPC_PREPEND:
24016 if (sa != 0) {
24017 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
24018 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
24019 tcg_gen_shli_tl(t0, t0, 32 - sa);
24020 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24022 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
24023 break;
24024 case OPC_BALIGN:
24025 sa &= 3;
24026 if (sa != 0 && sa != 2) {
24027 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
24028 tcg_gen_ext32u_tl(t0, t0);
24029 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
24030 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24032 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
24033 break;
24034 default: /* Invalid */
24035 MIPS_INVAL("MASK APPEND");
24036 gen_reserved_instruction(ctx);
24037 break;
24039 break;
24040 #ifdef TARGET_MIPS64
24041 case OPC_DAPPEND_DSP:
24042 switch (MASK_DAPPEND(ctx->opcode)) {
24043 case OPC_DAPPEND:
24044 if (sa != 0) {
24045 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
24047 break;
24048 case OPC_PREPENDD:
24049 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
24050 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
24051 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
24052 break;
24053 case OPC_PREPENDW:
24054 if (sa != 0) {
24055 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
24056 tcg_gen_shli_tl(t0, t0, 64 - sa);
24057 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24059 break;
24060 case OPC_DBALIGN:
24061 sa &= 7;
24062 if (sa != 0 && sa != 2 && sa != 4) {
24063 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
24064 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
24065 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24067 break;
24068 default: /* Invalid */
24069 MIPS_INVAL("MASK DAPPEND");
24070 gen_reserved_instruction(ctx);
24071 break;
24073 break;
24074 #endif
24076 tcg_temp_free(t0);
24079 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
24080 int ret, int v1, int v2, int check_ret)
24083 TCGv t0;
24084 TCGv t1;
24085 TCGv v1_t;
24086 TCGv v2_t;
24087 int16_t imm;
24089 if ((ret == 0) && (check_ret == 1)) {
24090 /* Treat as NOP. */
24091 return;
24094 t0 = tcg_temp_new();
24095 t1 = tcg_temp_new();
24096 v1_t = tcg_temp_new();
24097 v2_t = tcg_temp_new();
24099 gen_load_gpr(v1_t, v1);
24100 gen_load_gpr(v2_t, v2);
24102 switch (op1) {
24103 case OPC_EXTR_W_DSP:
24104 check_dsp(ctx);
24105 switch (op2) {
24106 case OPC_EXTR_W:
24107 tcg_gen_movi_tl(t0, v2);
24108 tcg_gen_movi_tl(t1, v1);
24109 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
24110 break;
24111 case OPC_EXTR_R_W:
24112 tcg_gen_movi_tl(t0, v2);
24113 tcg_gen_movi_tl(t1, v1);
24114 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24115 break;
24116 case OPC_EXTR_RS_W:
24117 tcg_gen_movi_tl(t0, v2);
24118 tcg_gen_movi_tl(t1, v1);
24119 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24120 break;
24121 case OPC_EXTR_S_H:
24122 tcg_gen_movi_tl(t0, v2);
24123 tcg_gen_movi_tl(t1, v1);
24124 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24125 break;
24126 case OPC_EXTRV_S_H:
24127 tcg_gen_movi_tl(t0, v2);
24128 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
24129 break;
24130 case OPC_EXTRV_W:
24131 tcg_gen_movi_tl(t0, v2);
24132 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24133 break;
24134 case OPC_EXTRV_R_W:
24135 tcg_gen_movi_tl(t0, v2);
24136 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24137 break;
24138 case OPC_EXTRV_RS_W:
24139 tcg_gen_movi_tl(t0, v2);
24140 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24141 break;
24142 case OPC_EXTP:
24143 tcg_gen_movi_tl(t0, v2);
24144 tcg_gen_movi_tl(t1, v1);
24145 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
24146 break;
24147 case OPC_EXTPV:
24148 tcg_gen_movi_tl(t0, v2);
24149 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
24150 break;
24151 case OPC_EXTPDP:
24152 tcg_gen_movi_tl(t0, v2);
24153 tcg_gen_movi_tl(t1, v1);
24154 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
24155 break;
24156 case OPC_EXTPDPV:
24157 tcg_gen_movi_tl(t0, v2);
24158 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
24159 break;
24160 case OPC_SHILO:
24161 imm = (ctx->opcode >> 20) & 0x3F;
24162 tcg_gen_movi_tl(t0, ret);
24163 tcg_gen_movi_tl(t1, imm);
24164 gen_helper_shilo(t0, t1, cpu_env);
24165 break;
24166 case OPC_SHILOV:
24167 tcg_gen_movi_tl(t0, ret);
24168 gen_helper_shilo(t0, v1_t, cpu_env);
24169 break;
24170 case OPC_MTHLIP:
24171 tcg_gen_movi_tl(t0, ret);
24172 gen_helper_mthlip(t0, v1_t, cpu_env);
24173 break;
24174 case OPC_WRDSP:
24175 imm = (ctx->opcode >> 11) & 0x3FF;
24176 tcg_gen_movi_tl(t0, imm);
24177 gen_helper_wrdsp(v1_t, t0, cpu_env);
24178 break;
24179 case OPC_RDDSP:
24180 imm = (ctx->opcode >> 16) & 0x03FF;
24181 tcg_gen_movi_tl(t0, imm);
24182 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
24183 break;
24185 break;
24186 #ifdef TARGET_MIPS64
24187 case OPC_DEXTR_W_DSP:
24188 check_dsp(ctx);
24189 switch (op2) {
24190 case OPC_DMTHLIP:
24191 tcg_gen_movi_tl(t0, ret);
24192 gen_helper_dmthlip(v1_t, t0, cpu_env);
24193 break;
24194 case OPC_DSHILO:
24196 int shift = (ctx->opcode >> 19) & 0x7F;
24197 int ac = (ctx->opcode >> 11) & 0x03;
24198 tcg_gen_movi_tl(t0, shift);
24199 tcg_gen_movi_tl(t1, ac);
24200 gen_helper_dshilo(t0, t1, cpu_env);
24201 break;
24203 case OPC_DSHILOV:
24205 int ac = (ctx->opcode >> 11) & 0x03;
24206 tcg_gen_movi_tl(t0, ac);
24207 gen_helper_dshilo(v1_t, t0, cpu_env);
24208 break;
24210 case OPC_DEXTP:
24211 tcg_gen_movi_tl(t0, v2);
24212 tcg_gen_movi_tl(t1, v1);
24214 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
24215 break;
24216 case OPC_DEXTPV:
24217 tcg_gen_movi_tl(t0, v2);
24218 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
24219 break;
24220 case OPC_DEXTPDP:
24221 tcg_gen_movi_tl(t0, v2);
24222 tcg_gen_movi_tl(t1, v1);
24223 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
24224 break;
24225 case OPC_DEXTPDPV:
24226 tcg_gen_movi_tl(t0, v2);
24227 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
24228 break;
24229 case OPC_DEXTR_L:
24230 tcg_gen_movi_tl(t0, v2);
24231 tcg_gen_movi_tl(t1, v1);
24232 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
24233 break;
24234 case OPC_DEXTR_R_L:
24235 tcg_gen_movi_tl(t0, v2);
24236 tcg_gen_movi_tl(t1, v1);
24237 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
24238 break;
24239 case OPC_DEXTR_RS_L:
24240 tcg_gen_movi_tl(t0, v2);
24241 tcg_gen_movi_tl(t1, v1);
24242 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
24243 break;
24244 case OPC_DEXTR_W:
24245 tcg_gen_movi_tl(t0, v2);
24246 tcg_gen_movi_tl(t1, v1);
24247 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
24248 break;
24249 case OPC_DEXTR_R_W:
24250 tcg_gen_movi_tl(t0, v2);
24251 tcg_gen_movi_tl(t1, v1);
24252 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24253 break;
24254 case OPC_DEXTR_RS_W:
24255 tcg_gen_movi_tl(t0, v2);
24256 tcg_gen_movi_tl(t1, v1);
24257 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24258 break;
24259 case OPC_DEXTR_S_H:
24260 tcg_gen_movi_tl(t0, v2);
24261 tcg_gen_movi_tl(t1, v1);
24262 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24263 break;
24264 case OPC_DEXTRV_S_H:
24265 tcg_gen_movi_tl(t0, v2);
24266 tcg_gen_movi_tl(t1, v1);
24267 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24268 break;
24269 case OPC_DEXTRV_L:
24270 tcg_gen_movi_tl(t0, v2);
24271 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24272 break;
24273 case OPC_DEXTRV_R_L:
24274 tcg_gen_movi_tl(t0, v2);
24275 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24276 break;
24277 case OPC_DEXTRV_RS_L:
24278 tcg_gen_movi_tl(t0, v2);
24279 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24280 break;
24281 case OPC_DEXTRV_W:
24282 tcg_gen_movi_tl(t0, v2);
24283 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24284 break;
24285 case OPC_DEXTRV_R_W:
24286 tcg_gen_movi_tl(t0, v2);
24287 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24288 break;
24289 case OPC_DEXTRV_RS_W:
24290 tcg_gen_movi_tl(t0, v2);
24291 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24292 break;
24294 break;
24295 #endif
24298 tcg_temp_free(t0);
24299 tcg_temp_free(t1);
24300 tcg_temp_free(v1_t);
24301 tcg_temp_free(v2_t);
24304 /* End MIPSDSP functions. */
24306 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
24308 int rs, rt, rd, sa;
24309 uint32_t op1, op2;
24311 rs = (ctx->opcode >> 21) & 0x1f;
24312 rt = (ctx->opcode >> 16) & 0x1f;
24313 rd = (ctx->opcode >> 11) & 0x1f;
24314 sa = (ctx->opcode >> 6) & 0x1f;
24316 op1 = MASK_SPECIAL(ctx->opcode);
24317 switch (op1) {
24318 case OPC_MULT:
24319 case OPC_MULTU:
24320 case OPC_DIV:
24321 case OPC_DIVU:
24322 op2 = MASK_R6_MULDIV(ctx->opcode);
24323 switch (op2) {
24324 case R6_OPC_MUL:
24325 case R6_OPC_MUH:
24326 case R6_OPC_MULU:
24327 case R6_OPC_MUHU:
24328 case R6_OPC_DIV:
24329 case R6_OPC_MOD:
24330 case R6_OPC_DIVU:
24331 case R6_OPC_MODU:
24332 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24333 break;
24334 default:
24335 MIPS_INVAL("special_r6 muldiv");
24336 gen_reserved_instruction(ctx);
24337 break;
24339 break;
24340 case OPC_SELEQZ:
24341 case OPC_SELNEZ:
24342 gen_cond_move(ctx, op1, rd, rs, rt);
24343 break;
24344 case R6_OPC_CLO:
24345 case R6_OPC_CLZ:
24346 if (rt == 0 && sa == 1) {
24348 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24349 * We need additionally to check other fields.
24351 gen_cl(ctx, op1, rd, rs);
24352 } else {
24353 gen_reserved_instruction(ctx);
24355 break;
24356 case R6_OPC_SDBBP:
24357 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
24358 gen_helper_do_semihosting(cpu_env);
24359 } else {
24360 if (ctx->hflags & MIPS_HFLAG_SBRI) {
24361 gen_reserved_instruction(ctx);
24362 } else {
24363 generate_exception_end(ctx, EXCP_DBp);
24366 break;
24367 #if defined(TARGET_MIPS64)
24368 case R6_OPC_DCLO:
24369 case R6_OPC_DCLZ:
24370 if (rt == 0 && sa == 1) {
24372 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24373 * We need additionally to check other fields.
24375 check_mips_64(ctx);
24376 gen_cl(ctx, op1, rd, rs);
24377 } else {
24378 gen_reserved_instruction(ctx);
24380 break;
24381 case OPC_DMULT:
24382 case OPC_DMULTU:
24383 case OPC_DDIV:
24384 case OPC_DDIVU:
24386 op2 = MASK_R6_MULDIV(ctx->opcode);
24387 switch (op2) {
24388 case R6_OPC_DMUL:
24389 case R6_OPC_DMUH:
24390 case R6_OPC_DMULU:
24391 case R6_OPC_DMUHU:
24392 case R6_OPC_DDIV:
24393 case R6_OPC_DMOD:
24394 case R6_OPC_DDIVU:
24395 case R6_OPC_DMODU:
24396 check_mips_64(ctx);
24397 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24398 break;
24399 default:
24400 MIPS_INVAL("special_r6 muldiv");
24401 gen_reserved_instruction(ctx);
24402 break;
24404 break;
24405 #endif
24406 default: /* Invalid */
24407 MIPS_INVAL("special_r6");
24408 gen_reserved_instruction(ctx);
24409 break;
24413 static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
24415 int rs = extract32(ctx->opcode, 21, 5);
24416 int rt = extract32(ctx->opcode, 16, 5);
24417 int rd = extract32(ctx->opcode, 11, 5);
24418 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
24420 switch (op1) {
24421 case OPC_MOVN: /* Conditional move */
24422 case OPC_MOVZ:
24423 gen_cond_move(ctx, op1, rd, rs, rt);
24424 break;
24425 case OPC_MFHI: /* Move from HI/LO */
24426 case OPC_MFLO:
24427 gen_HILO(ctx, op1, 0, rd);
24428 break;
24429 case OPC_MTHI:
24430 case OPC_MTLO: /* Move to HI/LO */
24431 gen_HILO(ctx, op1, 0, rs);
24432 break;
24433 case OPC_MULT:
24434 case OPC_MULTU:
24435 gen_mul_txx9(ctx, op1, rd, rs, rt);
24436 break;
24437 case OPC_DIV:
24438 case OPC_DIVU:
24439 gen_muldiv(ctx, op1, 0, rs, rt);
24440 break;
24441 #if defined(TARGET_MIPS64)
24442 case OPC_DMULT:
24443 case OPC_DMULTU:
24444 case OPC_DDIV:
24445 case OPC_DDIVU:
24446 check_insn_opc_user_only(ctx, INSN_R5900);
24447 gen_muldiv(ctx, op1, 0, rs, rt);
24448 break;
24449 #endif
24450 case OPC_JR:
24451 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
24452 break;
24453 default: /* Invalid */
24454 MIPS_INVAL("special_tx79");
24455 gen_reserved_instruction(ctx);
24456 break;
24460 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
24462 int rs, rt, rd, sa;
24463 uint32_t op1;
24465 rs = (ctx->opcode >> 21) & 0x1f;
24466 rt = (ctx->opcode >> 16) & 0x1f;
24467 rd = (ctx->opcode >> 11) & 0x1f;
24468 sa = (ctx->opcode >> 6) & 0x1f;
24470 op1 = MASK_SPECIAL(ctx->opcode);
24471 switch (op1) {
24472 case OPC_MOVN: /* Conditional move */
24473 case OPC_MOVZ:
24474 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1 |
24475 INSN_LOONGSON2E | INSN_LOONGSON2F);
24476 gen_cond_move(ctx, op1, rd, rs, rt);
24477 break;
24478 case OPC_MFHI: /* Move from HI/LO */
24479 case OPC_MFLO:
24480 gen_HILO(ctx, op1, rs & 3, rd);
24481 break;
24482 case OPC_MTHI:
24483 case OPC_MTLO: /* Move to HI/LO */
24484 gen_HILO(ctx, op1, rd & 3, rs);
24485 break;
24486 case OPC_MOVCI:
24487 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
24488 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
24489 check_cp1_enabled(ctx);
24490 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
24491 (ctx->opcode >> 16) & 1);
24492 } else {
24493 generate_exception_err(ctx, EXCP_CpU, 1);
24495 break;
24496 case OPC_MULT:
24497 case OPC_MULTU:
24498 if (sa) {
24499 check_insn(ctx, INSN_VR54XX);
24500 op1 = MASK_MUL_VR54XX(ctx->opcode);
24501 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
24502 } else {
24503 gen_muldiv(ctx, op1, rd & 3, rs, rt);
24505 break;
24506 case OPC_DIV:
24507 case OPC_DIVU:
24508 gen_muldiv(ctx, op1, 0, rs, rt);
24509 break;
24510 #if defined(TARGET_MIPS64)
24511 case OPC_DMULT:
24512 case OPC_DMULTU:
24513 case OPC_DDIV:
24514 case OPC_DDIVU:
24515 check_insn(ctx, ISA_MIPS3);
24516 check_mips_64(ctx);
24517 gen_muldiv(ctx, op1, 0, rs, rt);
24518 break;
24519 #endif
24520 case OPC_JR:
24521 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24522 break;
24523 case OPC_SPIM:
24524 #ifdef MIPS_STRICT_STANDARD
24525 MIPS_INVAL("SPIM");
24526 gen_reserved_instruction(ctx);
24527 #else
24528 /* Implemented as RI exception for now. */
24529 MIPS_INVAL("spim (unofficial)");
24530 gen_reserved_instruction(ctx);
24531 #endif
24532 break;
24533 default: /* Invalid */
24534 MIPS_INVAL("special_legacy");
24535 gen_reserved_instruction(ctx);
24536 break;
24540 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
24542 int rs, rt, rd, sa;
24543 uint32_t op1;
24545 rs = (ctx->opcode >> 21) & 0x1f;
24546 rt = (ctx->opcode >> 16) & 0x1f;
24547 rd = (ctx->opcode >> 11) & 0x1f;
24548 sa = (ctx->opcode >> 6) & 0x1f;
24550 op1 = MASK_SPECIAL(ctx->opcode);
24551 switch (op1) {
24552 case OPC_SLL: /* Shift with immediate */
24553 if (sa == 5 && rd == 0 &&
24554 rs == 0 && rt == 0) { /* PAUSE */
24555 if ((ctx->insn_flags & ISA_MIPS_R6) &&
24556 (ctx->hflags & MIPS_HFLAG_BMASK)) {
24557 gen_reserved_instruction(ctx);
24558 break;
24561 /* Fallthrough */
24562 case OPC_SRA:
24563 gen_shift_imm(ctx, op1, rd, rt, sa);
24564 break;
24565 case OPC_SRL:
24566 switch ((ctx->opcode >> 21) & 0x1f) {
24567 case 1:
24568 /* rotr is decoded as srl on non-R2 CPUs */
24569 if (ctx->insn_flags & ISA_MIPS_R2) {
24570 op1 = OPC_ROTR;
24572 /* Fallthrough */
24573 case 0:
24574 gen_shift_imm(ctx, op1, rd, rt, sa);
24575 break;
24576 default:
24577 gen_reserved_instruction(ctx);
24578 break;
24580 break;
24581 case OPC_ADD:
24582 case OPC_ADDU:
24583 case OPC_SUB:
24584 case OPC_SUBU:
24585 gen_arith(ctx, op1, rd, rs, rt);
24586 break;
24587 case OPC_SLLV: /* Shifts */
24588 case OPC_SRAV:
24589 gen_shift(ctx, op1, rd, rs, rt);
24590 break;
24591 case OPC_SRLV:
24592 switch ((ctx->opcode >> 6) & 0x1f) {
24593 case 1:
24594 /* rotrv is decoded as srlv on non-R2 CPUs */
24595 if (ctx->insn_flags & ISA_MIPS_R2) {
24596 op1 = OPC_ROTRV;
24598 /* Fallthrough */
24599 case 0:
24600 gen_shift(ctx, op1, rd, rs, rt);
24601 break;
24602 default:
24603 gen_reserved_instruction(ctx);
24604 break;
24606 break;
24607 case OPC_SLT: /* Set on less than */
24608 case OPC_SLTU:
24609 gen_slt(ctx, op1, rd, rs, rt);
24610 break;
24611 case OPC_AND: /* Logic*/
24612 case OPC_OR:
24613 case OPC_NOR:
24614 case OPC_XOR:
24615 gen_logic(ctx, op1, rd, rs, rt);
24616 break;
24617 case OPC_JALR:
24618 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24619 break;
24620 case OPC_TGE: /* Traps */
24621 case OPC_TGEU:
24622 case OPC_TLT:
24623 case OPC_TLTU:
24624 case OPC_TEQ:
24625 case OPC_TNE:
24626 check_insn(ctx, ISA_MIPS2);
24627 gen_trap(ctx, op1, rs, rt, -1);
24628 break;
24629 case OPC_PMON:
24630 /* Pmon entry point, also R4010 selsl */
24631 #ifdef MIPS_STRICT_STANDARD
24632 MIPS_INVAL("PMON / selsl");
24633 gen_reserved_instruction(ctx);
24634 #else
24635 gen_helper_0e0i(pmon, sa);
24636 #endif
24637 break;
24638 case OPC_SYSCALL:
24639 generate_exception_end(ctx, EXCP_SYSCALL);
24640 break;
24641 case OPC_BREAK:
24642 generate_exception_end(ctx, EXCP_BREAK);
24643 break;
24644 case OPC_SYNC:
24645 check_insn(ctx, ISA_MIPS2);
24646 gen_sync(extract32(ctx->opcode, 6, 5));
24647 break;
24649 #if defined(TARGET_MIPS64)
24650 /* MIPS64 specific opcodes */
24651 case OPC_DSLL:
24652 case OPC_DSRA:
24653 case OPC_DSLL32:
24654 case OPC_DSRA32:
24655 check_insn(ctx, ISA_MIPS3);
24656 check_mips_64(ctx);
24657 gen_shift_imm(ctx, op1, rd, rt, sa);
24658 break;
24659 case OPC_DSRL:
24660 switch ((ctx->opcode >> 21) & 0x1f) {
24661 case 1:
24662 /* drotr is decoded as dsrl on non-R2 CPUs */
24663 if (ctx->insn_flags & ISA_MIPS_R2) {
24664 op1 = OPC_DROTR;
24666 /* Fallthrough */
24667 case 0:
24668 check_insn(ctx, ISA_MIPS3);
24669 check_mips_64(ctx);
24670 gen_shift_imm(ctx, op1, rd, rt, sa);
24671 break;
24672 default:
24673 gen_reserved_instruction(ctx);
24674 break;
24676 break;
24677 case OPC_DSRL32:
24678 switch ((ctx->opcode >> 21) & 0x1f) {
24679 case 1:
24680 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
24681 if (ctx->insn_flags & ISA_MIPS_R2) {
24682 op1 = OPC_DROTR32;
24684 /* Fallthrough */
24685 case 0:
24686 check_insn(ctx, ISA_MIPS3);
24687 check_mips_64(ctx);
24688 gen_shift_imm(ctx, op1, rd, rt, sa);
24689 break;
24690 default:
24691 gen_reserved_instruction(ctx);
24692 break;
24694 break;
24695 case OPC_DADD:
24696 case OPC_DADDU:
24697 case OPC_DSUB:
24698 case OPC_DSUBU:
24699 check_insn(ctx, ISA_MIPS3);
24700 check_mips_64(ctx);
24701 gen_arith(ctx, op1, rd, rs, rt);
24702 break;
24703 case OPC_DSLLV:
24704 case OPC_DSRAV:
24705 check_insn(ctx, ISA_MIPS3);
24706 check_mips_64(ctx);
24707 gen_shift(ctx, op1, rd, rs, rt);
24708 break;
24709 case OPC_DSRLV:
24710 switch ((ctx->opcode >> 6) & 0x1f) {
24711 case 1:
24712 /* drotrv is decoded as dsrlv on non-R2 CPUs */
24713 if (ctx->insn_flags & ISA_MIPS_R2) {
24714 op1 = OPC_DROTRV;
24716 /* Fallthrough */
24717 case 0:
24718 check_insn(ctx, ISA_MIPS3);
24719 check_mips_64(ctx);
24720 gen_shift(ctx, op1, rd, rs, rt);
24721 break;
24722 default:
24723 gen_reserved_instruction(ctx);
24724 break;
24726 break;
24727 #endif
24728 default:
24729 if (ctx->insn_flags & ISA_MIPS_R6) {
24730 decode_opc_special_r6(env, ctx);
24731 } else if (ctx->insn_flags & INSN_R5900) {
24732 decode_opc_special_tx79(env, ctx);
24733 } else {
24734 decode_opc_special_legacy(env, ctx);
24740 #if defined(TARGET_MIPS64)
24744 * MMI (MultiMedia Interface) ASE instructions
24745 * ===========================================
24749 * MMI instructions category: data communication
24750 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24752 * PCPYH PEXCH PEXTLB PINTH PPACB PEXT5 PREVH
24753 * PCPYLD PEXCW PEXTLH PINTEH PPACH PPAC5 PROT3W
24754 * PCPYUD PEXEH PEXTLW PPACW
24755 * PEXEW PEXTUB
24756 * PEXTUH
24757 * PEXTUW
24761 * PCPYH rd, rt
24763 * Parallel Copy Halfword
24765 * 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
24766 * +-----------+---------+---------+---------+---------+-----------+
24767 * | MMI |0 0 0 0 0| rt | rd | PCPYH | MMI3 |
24768 * +-----------+---------+---------+---------+---------+-----------+
24770 static void gen_mmi_pcpyh(DisasContext *ctx)
24772 uint32_t pd, rt, rd;
24773 uint32_t opcode;
24775 opcode = ctx->opcode;
24777 pd = extract32(opcode, 21, 5);
24778 rt = extract32(opcode, 16, 5);
24779 rd = extract32(opcode, 11, 5);
24781 if (unlikely(pd != 0)) {
24782 gen_reserved_instruction(ctx);
24783 } else if (rd == 0) {
24784 /* nop */
24785 } else if (rt == 0) {
24786 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24787 tcg_gen_movi_i64(cpu_gpr_hi[rd], 0);
24788 } else {
24789 TCGv_i64 t0 = tcg_temp_new();
24790 TCGv_i64 t1 = tcg_temp_new();
24791 uint64_t mask = (1ULL << 16) - 1;
24793 tcg_gen_andi_i64(t0, cpu_gpr[rt], mask);
24794 tcg_gen_movi_i64(t1, 0);
24795 tcg_gen_or_i64(t1, t0, t1);
24796 tcg_gen_shli_i64(t0, t0, 16);
24797 tcg_gen_or_i64(t1, t0, t1);
24798 tcg_gen_shli_i64(t0, t0, 16);
24799 tcg_gen_or_i64(t1, t0, t1);
24800 tcg_gen_shli_i64(t0, t0, 16);
24801 tcg_gen_or_i64(t1, t0, t1);
24803 tcg_gen_mov_i64(cpu_gpr[rd], t1);
24805 tcg_gen_andi_i64(t0, cpu_gpr_hi[rt], mask);
24806 tcg_gen_movi_i64(t1, 0);
24807 tcg_gen_or_i64(t1, t0, t1);
24808 tcg_gen_shli_i64(t0, t0, 16);
24809 tcg_gen_or_i64(t1, t0, t1);
24810 tcg_gen_shli_i64(t0, t0, 16);
24811 tcg_gen_or_i64(t1, t0, t1);
24812 tcg_gen_shli_i64(t0, t0, 16);
24813 tcg_gen_or_i64(t1, t0, t1);
24815 tcg_gen_mov_i64(cpu_gpr_hi[rd], t1);
24817 tcg_temp_free(t0);
24818 tcg_temp_free(t1);
24823 * PCPYLD rd, rs, rt
24825 * Parallel Copy Lower Doubleword
24827 * 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
24828 * +-----------+---------+---------+---------+---------+-----------+
24829 * | MMI | rs | rt | rd | PCPYLD | MMI2 |
24830 * +-----------+---------+---------+---------+---------+-----------+
24832 static void gen_mmi_pcpyld(DisasContext *ctx)
24834 uint32_t rs, rt, rd;
24835 uint32_t opcode;
24837 opcode = ctx->opcode;
24839 rs = extract32(opcode, 21, 5);
24840 rt = extract32(opcode, 16, 5);
24841 rd = extract32(opcode, 11, 5);
24843 if (rd == 0) {
24844 /* nop */
24845 } else {
24846 if (rs == 0) {
24847 tcg_gen_movi_i64(cpu_gpr_hi[rd], 0);
24848 } else {
24849 tcg_gen_mov_i64(cpu_gpr_hi[rd], cpu_gpr[rs]);
24851 if (rt == 0) {
24852 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24853 } else {
24854 if (rd != rt) {
24855 tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr[rt]);
24862 * PCPYUD rd, rs, rt
24864 * Parallel Copy Upper Doubleword
24866 * 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
24867 * +-----------+---------+---------+---------+---------+-----------+
24868 * | MMI | rs | rt | rd | PCPYUD | MMI3 |
24869 * +-----------+---------+---------+---------+---------+-----------+
24871 static void gen_mmi_pcpyud(DisasContext *ctx)
24873 uint32_t rs, rt, rd;
24874 uint32_t opcode;
24876 opcode = ctx->opcode;
24878 rs = extract32(opcode, 21, 5);
24879 rt = extract32(opcode, 16, 5);
24880 rd = extract32(opcode, 11, 5);
24882 if (rd == 0) {
24883 /* nop */
24884 } else {
24885 if (rs == 0) {
24886 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24887 } else {
24888 tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr_hi[rs]);
24890 if (rt == 0) {
24891 tcg_gen_movi_i64(cpu_gpr_hi[rd], 0);
24892 } else {
24893 if (rd != rt) {
24894 tcg_gen_mov_i64(cpu_gpr_hi[rd], cpu_gpr_hi[rt]);
24900 #endif
24903 #if !defined(TARGET_MIPS64)
24905 /* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
24906 #define MXU_APTN1_A 0
24907 #define MXU_APTN1_S 1
24909 /* MXU accumulate add/subtract 2-bit pattern 'aptn2' */
24910 #define MXU_APTN2_AA 0
24911 #define MXU_APTN2_AS 1
24912 #define MXU_APTN2_SA 2
24913 #define MXU_APTN2_SS 3
24915 /* MXU execute add/subtract 2-bit pattern 'eptn2' */
24916 #define MXU_EPTN2_AA 0
24917 #define MXU_EPTN2_AS 1
24918 #define MXU_EPTN2_SA 2
24919 #define MXU_EPTN2_SS 3
24921 /* MXU operand getting pattern 'optn2' */
24922 #define MXU_OPTN2_PTN0 0
24923 #define MXU_OPTN2_PTN1 1
24924 #define MXU_OPTN2_PTN2 2
24925 #define MXU_OPTN2_PTN3 3
24926 /* alternative naming scheme for 'optn2' */
24927 #define MXU_OPTN2_WW 0
24928 #define MXU_OPTN2_LW 1
24929 #define MXU_OPTN2_HW 2
24930 #define MXU_OPTN2_XW 3
24932 /* MXU operand getting pattern 'optn3' */
24933 #define MXU_OPTN3_PTN0 0
24934 #define MXU_OPTN3_PTN1 1
24935 #define MXU_OPTN3_PTN2 2
24936 #define MXU_OPTN3_PTN3 3
24937 #define MXU_OPTN3_PTN4 4
24938 #define MXU_OPTN3_PTN5 5
24939 #define MXU_OPTN3_PTN6 6
24940 #define MXU_OPTN3_PTN7 7
24944 * S32I2M XRa, rb - Register move from GRF to XRF
24946 static void gen_mxu_s32i2m(DisasContext *ctx)
24948 TCGv t0;
24949 uint32_t XRa, Rb;
24951 t0 = tcg_temp_new();
24953 XRa = extract32(ctx->opcode, 6, 5);
24954 Rb = extract32(ctx->opcode, 16, 5);
24956 gen_load_gpr(t0, Rb);
24957 if (XRa <= 15) {
24958 gen_store_mxu_gpr(t0, XRa);
24959 } else if (XRa == 16) {
24960 gen_store_mxu_cr(t0);
24963 tcg_temp_free(t0);
24967 * S32M2I XRa, rb - Register move from XRF to GRF
24969 static void gen_mxu_s32m2i(DisasContext *ctx)
24971 TCGv t0;
24972 uint32_t XRa, Rb;
24974 t0 = tcg_temp_new();
24976 XRa = extract32(ctx->opcode, 6, 5);
24977 Rb = extract32(ctx->opcode, 16, 5);
24979 if (XRa <= 15) {
24980 gen_load_mxu_gpr(t0, XRa);
24981 } else if (XRa == 16) {
24982 gen_load_mxu_cr(t0);
24985 gen_store_gpr(t0, Rb);
24987 tcg_temp_free(t0);
24991 * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF
24993 static void gen_mxu_s8ldd(DisasContext *ctx)
24995 TCGv t0, t1;
24996 uint32_t XRa, Rb, s8, optn3;
24998 t0 = tcg_temp_new();
24999 t1 = tcg_temp_new();
25001 XRa = extract32(ctx->opcode, 6, 4);
25002 s8 = extract32(ctx->opcode, 10, 8);
25003 optn3 = extract32(ctx->opcode, 18, 3);
25004 Rb = extract32(ctx->opcode, 21, 5);
25006 gen_load_gpr(t0, Rb);
25007 tcg_gen_addi_tl(t0, t0, (int8_t)s8);
25009 switch (optn3) {
25010 /* XRa[7:0] = tmp8 */
25011 case MXU_OPTN3_PTN0:
25012 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25013 gen_load_mxu_gpr(t0, XRa);
25014 tcg_gen_deposit_tl(t0, t0, t1, 0, 8);
25015 break;
25016 /* XRa[15:8] = tmp8 */
25017 case MXU_OPTN3_PTN1:
25018 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25019 gen_load_mxu_gpr(t0, XRa);
25020 tcg_gen_deposit_tl(t0, t0, t1, 8, 8);
25021 break;
25022 /* XRa[23:16] = tmp8 */
25023 case MXU_OPTN3_PTN2:
25024 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25025 gen_load_mxu_gpr(t0, XRa);
25026 tcg_gen_deposit_tl(t0, t0, t1, 16, 8);
25027 break;
25028 /* XRa[31:24] = tmp8 */
25029 case MXU_OPTN3_PTN3:
25030 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25031 gen_load_mxu_gpr(t0, XRa);
25032 tcg_gen_deposit_tl(t0, t0, t1, 24, 8);
25033 break;
25034 /* XRa = {8'b0, tmp8, 8'b0, tmp8} */
25035 case MXU_OPTN3_PTN4:
25036 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25037 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25038 break;
25039 /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */
25040 case MXU_OPTN3_PTN5:
25041 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25042 tcg_gen_shli_tl(t1, t1, 8);
25043 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25044 break;
25045 /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */
25046 case MXU_OPTN3_PTN6:
25047 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB);
25048 tcg_gen_mov_tl(t0, t1);
25049 tcg_gen_andi_tl(t0, t0, 0xFF00FFFF);
25050 tcg_gen_shli_tl(t1, t1, 16);
25051 tcg_gen_or_tl(t0, t0, t1);
25052 break;
25053 /* XRa = {tmp8, tmp8, tmp8, tmp8} */
25054 case MXU_OPTN3_PTN7:
25055 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25056 tcg_gen_deposit_tl(t1, t1, t1, 8, 8);
25057 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25058 break;
25061 gen_store_mxu_gpr(t0, XRa);
25063 tcg_temp_free(t0);
25064 tcg_temp_free(t1);
25068 * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication
25070 static void gen_mxu_d16mul(DisasContext *ctx)
25072 TCGv t0, t1, t2, t3;
25073 uint32_t XRa, XRb, XRc, XRd, optn2;
25075 t0 = tcg_temp_new();
25076 t1 = tcg_temp_new();
25077 t2 = tcg_temp_new();
25078 t3 = tcg_temp_new();
25080 XRa = extract32(ctx->opcode, 6, 4);
25081 XRb = extract32(ctx->opcode, 10, 4);
25082 XRc = extract32(ctx->opcode, 14, 4);
25083 XRd = extract32(ctx->opcode, 18, 4);
25084 optn2 = extract32(ctx->opcode, 22, 2);
25086 gen_load_mxu_gpr(t1, XRb);
25087 tcg_gen_sextract_tl(t0, t1, 0, 16);
25088 tcg_gen_sextract_tl(t1, t1, 16, 16);
25089 gen_load_mxu_gpr(t3, XRc);
25090 tcg_gen_sextract_tl(t2, t3, 0, 16);
25091 tcg_gen_sextract_tl(t3, t3, 16, 16);
25093 switch (optn2) {
25094 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
25095 tcg_gen_mul_tl(t3, t1, t3);
25096 tcg_gen_mul_tl(t2, t0, t2);
25097 break;
25098 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
25099 tcg_gen_mul_tl(t3, t0, t3);
25100 tcg_gen_mul_tl(t2, t0, t2);
25101 break;
25102 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
25103 tcg_gen_mul_tl(t3, t1, t3);
25104 tcg_gen_mul_tl(t2, t1, t2);
25105 break;
25106 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
25107 tcg_gen_mul_tl(t3, t0, t3);
25108 tcg_gen_mul_tl(t2, t1, t2);
25109 break;
25111 gen_store_mxu_gpr(t3, XRa);
25112 gen_store_mxu_gpr(t2, XRd);
25114 tcg_temp_free(t0);
25115 tcg_temp_free(t1);
25116 tcg_temp_free(t2);
25117 tcg_temp_free(t3);
25121 * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply
25122 * and accumulate
25124 static void gen_mxu_d16mac(DisasContext *ctx)
25126 TCGv t0, t1, t2, t3;
25127 uint32_t XRa, XRb, XRc, XRd, optn2, aptn2;
25129 t0 = tcg_temp_new();
25130 t1 = tcg_temp_new();
25131 t2 = tcg_temp_new();
25132 t3 = tcg_temp_new();
25134 XRa = extract32(ctx->opcode, 6, 4);
25135 XRb = extract32(ctx->opcode, 10, 4);
25136 XRc = extract32(ctx->opcode, 14, 4);
25137 XRd = extract32(ctx->opcode, 18, 4);
25138 optn2 = extract32(ctx->opcode, 22, 2);
25139 aptn2 = extract32(ctx->opcode, 24, 2);
25141 gen_load_mxu_gpr(t1, XRb);
25142 tcg_gen_sextract_tl(t0, t1, 0, 16);
25143 tcg_gen_sextract_tl(t1, t1, 16, 16);
25145 gen_load_mxu_gpr(t3, XRc);
25146 tcg_gen_sextract_tl(t2, t3, 0, 16);
25147 tcg_gen_sextract_tl(t3, t3, 16, 16);
25149 switch (optn2) {
25150 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
25151 tcg_gen_mul_tl(t3, t1, t3);
25152 tcg_gen_mul_tl(t2, t0, t2);
25153 break;
25154 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
25155 tcg_gen_mul_tl(t3, t0, t3);
25156 tcg_gen_mul_tl(t2, t0, t2);
25157 break;
25158 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
25159 tcg_gen_mul_tl(t3, t1, t3);
25160 tcg_gen_mul_tl(t2, t1, t2);
25161 break;
25162 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
25163 tcg_gen_mul_tl(t3, t0, t3);
25164 tcg_gen_mul_tl(t2, t1, t2);
25165 break;
25167 gen_load_mxu_gpr(t0, XRa);
25168 gen_load_mxu_gpr(t1, XRd);
25170 switch (aptn2) {
25171 case MXU_APTN2_AA:
25172 tcg_gen_add_tl(t3, t0, t3);
25173 tcg_gen_add_tl(t2, t1, t2);
25174 break;
25175 case MXU_APTN2_AS:
25176 tcg_gen_add_tl(t3, t0, t3);
25177 tcg_gen_sub_tl(t2, t1, t2);
25178 break;
25179 case MXU_APTN2_SA:
25180 tcg_gen_sub_tl(t3, t0, t3);
25181 tcg_gen_add_tl(t2, t1, t2);
25182 break;
25183 case MXU_APTN2_SS:
25184 tcg_gen_sub_tl(t3, t0, t3);
25185 tcg_gen_sub_tl(t2, t1, t2);
25186 break;
25188 gen_store_mxu_gpr(t3, XRa);
25189 gen_store_mxu_gpr(t2, XRd);
25191 tcg_temp_free(t0);
25192 tcg_temp_free(t1);
25193 tcg_temp_free(t2);
25194 tcg_temp_free(t3);
25198 * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply
25199 * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply
25201 static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx)
25203 TCGv t0, t1, t2, t3, t4, t5, t6, t7;
25204 uint32_t XRa, XRb, XRc, XRd, sel;
25206 t0 = tcg_temp_new();
25207 t1 = tcg_temp_new();
25208 t2 = tcg_temp_new();
25209 t3 = tcg_temp_new();
25210 t4 = tcg_temp_new();
25211 t5 = tcg_temp_new();
25212 t6 = tcg_temp_new();
25213 t7 = tcg_temp_new();
25215 XRa = extract32(ctx->opcode, 6, 4);
25216 XRb = extract32(ctx->opcode, 10, 4);
25217 XRc = extract32(ctx->opcode, 14, 4);
25218 XRd = extract32(ctx->opcode, 18, 4);
25219 sel = extract32(ctx->opcode, 22, 2);
25221 gen_load_mxu_gpr(t3, XRb);
25222 gen_load_mxu_gpr(t7, XRc);
25224 if (sel == 0x2) {
25225 /* Q8MULSU */
25226 tcg_gen_ext8s_tl(t0, t3);
25227 tcg_gen_shri_tl(t3, t3, 8);
25228 tcg_gen_ext8s_tl(t1, t3);
25229 tcg_gen_shri_tl(t3, t3, 8);
25230 tcg_gen_ext8s_tl(t2, t3);
25231 tcg_gen_shri_tl(t3, t3, 8);
25232 tcg_gen_ext8s_tl(t3, t3);
25233 } else {
25234 /* Q8MUL */
25235 tcg_gen_ext8u_tl(t0, t3);
25236 tcg_gen_shri_tl(t3, t3, 8);
25237 tcg_gen_ext8u_tl(t1, t3);
25238 tcg_gen_shri_tl(t3, t3, 8);
25239 tcg_gen_ext8u_tl(t2, t3);
25240 tcg_gen_shri_tl(t3, t3, 8);
25241 tcg_gen_ext8u_tl(t3, t3);
25244 tcg_gen_ext8u_tl(t4, t7);
25245 tcg_gen_shri_tl(t7, t7, 8);
25246 tcg_gen_ext8u_tl(t5, t7);
25247 tcg_gen_shri_tl(t7, t7, 8);
25248 tcg_gen_ext8u_tl(t6, t7);
25249 tcg_gen_shri_tl(t7, t7, 8);
25250 tcg_gen_ext8u_tl(t7, t7);
25252 tcg_gen_mul_tl(t0, t0, t4);
25253 tcg_gen_mul_tl(t1, t1, t5);
25254 tcg_gen_mul_tl(t2, t2, t6);
25255 tcg_gen_mul_tl(t3, t3, t7);
25257 tcg_gen_andi_tl(t0, t0, 0xFFFF);
25258 tcg_gen_andi_tl(t1, t1, 0xFFFF);
25259 tcg_gen_andi_tl(t2, t2, 0xFFFF);
25260 tcg_gen_andi_tl(t3, t3, 0xFFFF);
25262 tcg_gen_shli_tl(t1, t1, 16);
25263 tcg_gen_shli_tl(t3, t3, 16);
25265 tcg_gen_or_tl(t0, t0, t1);
25266 tcg_gen_or_tl(t1, t2, t3);
25268 gen_store_mxu_gpr(t0, XRd);
25269 gen_store_mxu_gpr(t1, XRa);
25271 tcg_temp_free(t0);
25272 tcg_temp_free(t1);
25273 tcg_temp_free(t2);
25274 tcg_temp_free(t3);
25275 tcg_temp_free(t4);
25276 tcg_temp_free(t5);
25277 tcg_temp_free(t6);
25278 tcg_temp_free(t7);
25282 * S32LDD XRa, Rb, S12 - Load a word from memory to XRF
25283 * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte seq.
25285 static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx)
25287 TCGv t0, t1;
25288 uint32_t XRa, Rb, s12, sel;
25290 t0 = tcg_temp_new();
25291 t1 = tcg_temp_new();
25293 XRa = extract32(ctx->opcode, 6, 4);
25294 s12 = extract32(ctx->opcode, 10, 10);
25295 sel = extract32(ctx->opcode, 20, 1);
25296 Rb = extract32(ctx->opcode, 21, 5);
25298 gen_load_gpr(t0, Rb);
25300 tcg_gen_movi_tl(t1, s12);
25301 tcg_gen_shli_tl(t1, t1, 2);
25302 if (s12 & 0x200) {
25303 tcg_gen_ori_tl(t1, t1, 0xFFFFF000);
25305 tcg_gen_add_tl(t1, t0, t1);
25306 tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL);
25308 if (sel == 1) {
25309 /* S32LDDR */
25310 tcg_gen_bswap32_tl(t1, t1);
25312 gen_store_mxu_gpr(t1, XRa);
25314 tcg_temp_free(t0);
25315 tcg_temp_free(t1);
25320 * MXU instruction category: logic
25321 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25323 * S32NOR S32AND S32OR S32XOR
25327 * S32NOR XRa, XRb, XRc
25328 * Update XRa with the result of logical bitwise 'nor' operation
25329 * applied to the content of XRb and XRc.
25331 * 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
25332 * +-----------+---------+-----+-------+-------+-------+-----------+
25333 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25334 * +-----------+---------+-----+-------+-------+-------+-----------+
25336 static void gen_mxu_S32NOR(DisasContext *ctx)
25338 uint32_t pad, XRc, XRb, XRa;
25340 pad = extract32(ctx->opcode, 21, 5);
25341 XRc = extract32(ctx->opcode, 14, 4);
25342 XRb = extract32(ctx->opcode, 10, 4);
25343 XRa = extract32(ctx->opcode, 6, 4);
25345 if (unlikely(pad != 0)) {
25346 /* opcode padding incorrect -> do nothing */
25347 } else if (unlikely(XRa == 0)) {
25348 /* destination is zero register -> do nothing */
25349 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25350 /* both operands zero registers -> just set destination to all 1s */
25351 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF);
25352 } else if (unlikely(XRb == 0)) {
25353 /* XRb zero register -> just set destination to the negation of XRc */
25354 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25355 } else if (unlikely(XRc == 0)) {
25356 /* XRa zero register -> just set destination to the negation of XRb */
25357 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25358 } else if (unlikely(XRb == XRc)) {
25359 /* both operands same -> just set destination to the negation of XRb */
25360 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25361 } else {
25362 /* the most general case */
25363 tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25368 * S32AND XRa, XRb, XRc
25369 * Update XRa with the result of logical bitwise 'and' operation
25370 * applied to the content of XRb and XRc.
25372 * 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
25373 * +-----------+---------+-----+-------+-------+-------+-----------+
25374 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25375 * +-----------+---------+-----+-------+-------+-------+-----------+
25377 static void gen_mxu_S32AND(DisasContext *ctx)
25379 uint32_t pad, XRc, XRb, XRa;
25381 pad = extract32(ctx->opcode, 21, 5);
25382 XRc = extract32(ctx->opcode, 14, 4);
25383 XRb = extract32(ctx->opcode, 10, 4);
25384 XRa = extract32(ctx->opcode, 6, 4);
25386 if (unlikely(pad != 0)) {
25387 /* opcode padding incorrect -> do nothing */
25388 } else if (unlikely(XRa == 0)) {
25389 /* destination is zero register -> do nothing */
25390 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25391 /* one of operands zero register -> just set destination to all 0s */
25392 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25393 } else if (unlikely(XRb == XRc)) {
25394 /* both operands same -> just set destination to one of them */
25395 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25396 } else {
25397 /* the most general case */
25398 tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25403 * S32OR XRa, XRb, XRc
25404 * Update XRa with the result of logical bitwise 'or' operation
25405 * applied to the content of XRb and XRc.
25407 * 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
25408 * +-----------+---------+-----+-------+-------+-------+-----------+
25409 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25410 * +-----------+---------+-----+-------+-------+-------+-----------+
25412 static void gen_mxu_S32OR(DisasContext *ctx)
25414 uint32_t pad, XRc, XRb, XRa;
25416 pad = extract32(ctx->opcode, 21, 5);
25417 XRc = extract32(ctx->opcode, 14, 4);
25418 XRb = extract32(ctx->opcode, 10, 4);
25419 XRa = extract32(ctx->opcode, 6, 4);
25421 if (unlikely(pad != 0)) {
25422 /* opcode padding incorrect -> do nothing */
25423 } else if (unlikely(XRa == 0)) {
25424 /* destination is zero register -> do nothing */
25425 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25426 /* both operands zero registers -> just set destination to all 0s */
25427 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25428 } else if (unlikely(XRb == 0)) {
25429 /* XRb zero register -> just set destination to the content of XRc */
25430 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25431 } else if (unlikely(XRc == 0)) {
25432 /* XRc zero register -> just set destination to the content of XRb */
25433 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25434 } else if (unlikely(XRb == XRc)) {
25435 /* both operands same -> just set destination to one of them */
25436 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25437 } else {
25438 /* the most general case */
25439 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25444 * S32XOR XRa, XRb, XRc
25445 * Update XRa with the result of logical bitwise 'xor' operation
25446 * applied to the content of XRb and XRc.
25448 * 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
25449 * +-----------+---------+-----+-------+-------+-------+-----------+
25450 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25451 * +-----------+---------+-----+-------+-------+-------+-----------+
25453 static void gen_mxu_S32XOR(DisasContext *ctx)
25455 uint32_t pad, XRc, XRb, XRa;
25457 pad = extract32(ctx->opcode, 21, 5);
25458 XRc = extract32(ctx->opcode, 14, 4);
25459 XRb = extract32(ctx->opcode, 10, 4);
25460 XRa = extract32(ctx->opcode, 6, 4);
25462 if (unlikely(pad != 0)) {
25463 /* opcode padding incorrect -> do nothing */
25464 } else if (unlikely(XRa == 0)) {
25465 /* destination is zero register -> do nothing */
25466 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25467 /* both operands zero registers -> just set destination to all 0s */
25468 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25469 } else if (unlikely(XRb == 0)) {
25470 /* XRb zero register -> just set destination to the content of XRc */
25471 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25472 } else if (unlikely(XRc == 0)) {
25473 /* XRc zero register -> just set destination to the content of XRb */
25474 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25475 } else if (unlikely(XRb == XRc)) {
25476 /* both operands same -> just set destination to all 0s */
25477 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25478 } else {
25479 /* the most general case */
25480 tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25486 * MXU instruction category max/min
25487 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25489 * S32MAX D16MAX Q8MAX
25490 * S32MIN D16MIN Q8MIN
25494 * S32MAX XRa, XRb, XRc
25495 * Update XRa with the maximum of signed 32-bit integers contained
25496 * in XRb and XRc.
25498 * S32MIN XRa, XRb, XRc
25499 * Update XRa with the minimum of signed 32-bit integers contained
25500 * in XRb and XRc.
25502 * 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
25503 * +-----------+---------+-----+-------+-------+-------+-----------+
25504 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25505 * +-----------+---------+-----+-------+-------+-------+-----------+
25507 static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx)
25509 uint32_t pad, opc, XRc, XRb, XRa;
25511 pad = extract32(ctx->opcode, 21, 5);
25512 opc = extract32(ctx->opcode, 18, 3);
25513 XRc = extract32(ctx->opcode, 14, 4);
25514 XRb = extract32(ctx->opcode, 10, 4);
25515 XRa = extract32(ctx->opcode, 6, 4);
25517 if (unlikely(pad != 0)) {
25518 /* opcode padding incorrect -> do nothing */
25519 } else if (unlikely(XRa == 0)) {
25520 /* destination is zero register -> do nothing */
25521 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25522 /* both operands zero registers -> just set destination to zero */
25523 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25524 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25525 /* exactly one operand is zero register - find which one is not...*/
25526 uint32_t XRx = XRb ? XRb : XRc;
25527 /* ...and do max/min operation with one operand 0 */
25528 if (opc == OPC_MXU_S32MAX) {
25529 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25530 } else {
25531 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25533 } else if (unlikely(XRb == XRc)) {
25534 /* both operands same -> just set destination to one of them */
25535 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25536 } else {
25537 /* the most general case */
25538 if (opc == OPC_MXU_S32MAX) {
25539 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25540 mxu_gpr[XRc - 1]);
25541 } else {
25542 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25543 mxu_gpr[XRc - 1]);
25549 * D16MAX
25550 * Update XRa with the 16-bit-wise maximums of signed integers
25551 * contained in XRb and XRc.
25553 * D16MIN
25554 * Update XRa with the 16-bit-wise minimums of signed integers
25555 * contained in XRb and XRc.
25557 * 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
25558 * +-----------+---------+-----+-------+-------+-------+-----------+
25559 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25560 * +-----------+---------+-----+-------+-------+-------+-----------+
25562 static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx)
25564 uint32_t pad, opc, XRc, XRb, XRa;
25566 pad = extract32(ctx->opcode, 21, 5);
25567 opc = extract32(ctx->opcode, 18, 3);
25568 XRc = extract32(ctx->opcode, 14, 4);
25569 XRb = extract32(ctx->opcode, 10, 4);
25570 XRa = extract32(ctx->opcode, 6, 4);
25572 if (unlikely(pad != 0)) {
25573 /* opcode padding incorrect -> do nothing */
25574 } else if (unlikely(XRc == 0)) {
25575 /* destination is zero register -> do nothing */
25576 } else if (unlikely((XRb == 0) && (XRa == 0))) {
25577 /* both operands zero registers -> just set destination to zero */
25578 tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0);
25579 } else if (unlikely((XRb == 0) || (XRa == 0))) {
25580 /* exactly one operand is zero register - find which one is not...*/
25581 uint32_t XRx = XRb ? XRb : XRc;
25582 /* ...and do half-word-wise max/min with one operand 0 */
25583 TCGv_i32 t0 = tcg_temp_new();
25584 TCGv_i32 t1 = tcg_const_i32(0);
25586 /* the left half-word first */
25587 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000);
25588 if (opc == OPC_MXU_D16MAX) {
25589 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25590 } else {
25591 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25594 /* the right half-word */
25595 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF);
25596 /* move half-words to the leftmost position */
25597 tcg_gen_shli_i32(t0, t0, 16);
25598 /* t0 will be max/min of t0 and t1 */
25599 if (opc == OPC_MXU_D16MAX) {
25600 tcg_gen_smax_i32(t0, t0, t1);
25601 } else {
25602 tcg_gen_smin_i32(t0, t0, t1);
25604 /* return resulting half-words to its original position */
25605 tcg_gen_shri_i32(t0, t0, 16);
25606 /* finally update the destination */
25607 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25609 tcg_temp_free(t1);
25610 tcg_temp_free(t0);
25611 } else if (unlikely(XRb == XRc)) {
25612 /* both operands same -> just set destination to one of them */
25613 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25614 } else {
25615 /* the most general case */
25616 TCGv_i32 t0 = tcg_temp_new();
25617 TCGv_i32 t1 = tcg_temp_new();
25619 /* the left half-word first */
25620 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000);
25621 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25622 if (opc == OPC_MXU_D16MAX) {
25623 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25624 } else {
25625 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25628 /* the right half-word */
25629 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25630 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF);
25631 /* move half-words to the leftmost position */
25632 tcg_gen_shli_i32(t0, t0, 16);
25633 tcg_gen_shli_i32(t1, t1, 16);
25634 /* t0 will be max/min of t0 and t1 */
25635 if (opc == OPC_MXU_D16MAX) {
25636 tcg_gen_smax_i32(t0, t0, t1);
25637 } else {
25638 tcg_gen_smin_i32(t0, t0, t1);
25640 /* return resulting half-words to its original position */
25641 tcg_gen_shri_i32(t0, t0, 16);
25642 /* finally update the destination */
25643 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25645 tcg_temp_free(t1);
25646 tcg_temp_free(t0);
25651 * Q8MAX
25652 * Update XRa with the 8-bit-wise maximums of signed integers
25653 * contained in XRb and XRc.
25655 * Q8MIN
25656 * Update XRa with the 8-bit-wise minimums of signed integers
25657 * contained in XRb and XRc.
25659 * 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
25660 * +-----------+---------+-----+-------+-------+-------+-----------+
25661 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25662 * +-----------+---------+-----+-------+-------+-------+-----------+
25664 static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx)
25666 uint32_t pad, opc, XRc, XRb, XRa;
25668 pad = extract32(ctx->opcode, 21, 5);
25669 opc = extract32(ctx->opcode, 18, 3);
25670 XRc = extract32(ctx->opcode, 14, 4);
25671 XRb = extract32(ctx->opcode, 10, 4);
25672 XRa = extract32(ctx->opcode, 6, 4);
25674 if (unlikely(pad != 0)) {
25675 /* opcode padding incorrect -> do nothing */
25676 } else if (unlikely(XRa == 0)) {
25677 /* destination is zero register -> do nothing */
25678 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25679 /* both operands zero registers -> just set destination to zero */
25680 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25681 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25682 /* exactly one operand is zero register - make it be the first...*/
25683 uint32_t XRx = XRb ? XRb : XRc;
25684 /* ...and do byte-wise max/min with one operand 0 */
25685 TCGv_i32 t0 = tcg_temp_new();
25686 TCGv_i32 t1 = tcg_const_i32(0);
25687 int32_t i;
25689 /* the leftmost byte (byte 3) first */
25690 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000);
25691 if (opc == OPC_MXU_Q8MAX) {
25692 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25693 } else {
25694 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25697 /* bytes 2, 1, 0 */
25698 for (i = 2; i >= 0; i--) {
25699 /* extract the byte */
25700 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i));
25701 /* move the byte to the leftmost position */
25702 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25703 /* t0 will be max/min of t0 and t1 */
25704 if (opc == OPC_MXU_Q8MAX) {
25705 tcg_gen_smax_i32(t0, t0, t1);
25706 } else {
25707 tcg_gen_smin_i32(t0, t0, t1);
25709 /* return resulting byte to its original position */
25710 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25711 /* finally update the destination */
25712 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25715 tcg_temp_free(t1);
25716 tcg_temp_free(t0);
25717 } else if (unlikely(XRb == XRc)) {
25718 /* both operands same -> just set destination to one of them */
25719 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25720 } else {
25721 /* the most general case */
25722 TCGv_i32 t0 = tcg_temp_new();
25723 TCGv_i32 t1 = tcg_temp_new();
25724 int32_t i;
25726 /* the leftmost bytes (bytes 3) first */
25727 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000);
25728 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25729 if (opc == OPC_MXU_Q8MAX) {
25730 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25731 } else {
25732 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25735 /* bytes 2, 1, 0 */
25736 for (i = 2; i >= 0; i--) {
25737 /* extract corresponding bytes */
25738 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i));
25739 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i));
25740 /* move the bytes to the leftmost position */
25741 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25742 tcg_gen_shli_i32(t1, t1, 8 * (3 - i));
25743 /* t0 will be max/min of t0 and t1 */
25744 if (opc == OPC_MXU_Q8MAX) {
25745 tcg_gen_smax_i32(t0, t0, t1);
25746 } else {
25747 tcg_gen_smin_i32(t0, t0, t1);
25749 /* return resulting byte to its original position */
25750 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25751 /* finally update the destination */
25752 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25755 tcg_temp_free(t1);
25756 tcg_temp_free(t0);
25762 * MXU instruction category: align
25763 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25765 * S32ALN S32ALNI
25769 * S32ALNI XRc, XRb, XRa, optn3
25770 * Arrange bytes from XRb and XRc according to one of five sets of
25771 * rules determined by optn3, and place the result in XRa.
25773 * 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
25774 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25775 * | SPECIAL2 |optn3|0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
25776 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25779 static void gen_mxu_S32ALNI(DisasContext *ctx)
25781 uint32_t optn3, pad, XRc, XRb, XRa;
25783 optn3 = extract32(ctx->opcode, 23, 3);
25784 pad = extract32(ctx->opcode, 21, 2);
25785 XRc = extract32(ctx->opcode, 14, 4);
25786 XRb = extract32(ctx->opcode, 10, 4);
25787 XRa = extract32(ctx->opcode, 6, 4);
25789 if (unlikely(pad != 0)) {
25790 /* opcode padding incorrect -> do nothing */
25791 } else if (unlikely(XRa == 0)) {
25792 /* destination is zero register -> do nothing */
25793 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25794 /* both operands zero registers -> just set destination to all 0s */
25795 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25796 } else if (unlikely(XRb == 0)) {
25797 /* XRb zero register -> just appropriatelly shift XRc into XRa */
25798 switch (optn3) {
25799 case MXU_OPTN3_PTN0:
25800 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25801 break;
25802 case MXU_OPTN3_PTN1:
25803 case MXU_OPTN3_PTN2:
25804 case MXU_OPTN3_PTN3:
25805 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1],
25806 8 * (4 - optn3));
25807 break;
25808 case MXU_OPTN3_PTN4:
25809 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25810 break;
25812 } else if (unlikely(XRc == 0)) {
25813 /* XRc zero register -> just appropriatelly shift XRb into XRa */
25814 switch (optn3) {
25815 case MXU_OPTN3_PTN0:
25816 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25817 break;
25818 case MXU_OPTN3_PTN1:
25819 case MXU_OPTN3_PTN2:
25820 case MXU_OPTN3_PTN3:
25821 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25822 break;
25823 case MXU_OPTN3_PTN4:
25824 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25825 break;
25827 } else if (unlikely(XRb == XRc)) {
25828 /* both operands same -> just rotation or moving from any of them */
25829 switch (optn3) {
25830 case MXU_OPTN3_PTN0:
25831 case MXU_OPTN3_PTN4:
25832 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25833 break;
25834 case MXU_OPTN3_PTN1:
25835 case MXU_OPTN3_PTN2:
25836 case MXU_OPTN3_PTN3:
25837 tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25838 break;
25840 } else {
25841 /* the most general case */
25842 switch (optn3) {
25843 case MXU_OPTN3_PTN0:
25845 /* */
25846 /* XRb XRc */
25847 /* +---------------+ */
25848 /* | A B C D | E F G H */
25849 /* +-------+-------+ */
25850 /* | */
25851 /* XRa */
25852 /* */
25854 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25856 break;
25857 case MXU_OPTN3_PTN1:
25859 /* */
25860 /* XRb XRc */
25861 /* +-------------------+ */
25862 /* A | B C D E | F G H */
25863 /* +---------+---------+ */
25864 /* | */
25865 /* XRa */
25866 /* */
25868 TCGv_i32 t0 = tcg_temp_new();
25869 TCGv_i32 t1 = tcg_temp_new();
25871 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF);
25872 tcg_gen_shli_i32(t0, t0, 8);
25874 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25875 tcg_gen_shri_i32(t1, t1, 24);
25877 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25879 tcg_temp_free(t1);
25880 tcg_temp_free(t0);
25882 break;
25883 case MXU_OPTN3_PTN2:
25885 /* */
25886 /* XRb XRc */
25887 /* +-------------------+ */
25888 /* A B | C D E F | G H */
25889 /* +---------+---------+ */
25890 /* | */
25891 /* XRa */
25892 /* */
25894 TCGv_i32 t0 = tcg_temp_new();
25895 TCGv_i32 t1 = tcg_temp_new();
25897 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25898 tcg_gen_shli_i32(t0, t0, 16);
25900 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25901 tcg_gen_shri_i32(t1, t1, 16);
25903 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25905 tcg_temp_free(t1);
25906 tcg_temp_free(t0);
25908 break;
25909 case MXU_OPTN3_PTN3:
25911 /* */
25912 /* XRb XRc */
25913 /* +-------------------+ */
25914 /* A B C | D E F G | H */
25915 /* +---------+---------+ */
25916 /* | */
25917 /* XRa */
25918 /* */
25920 TCGv_i32 t0 = tcg_temp_new();
25921 TCGv_i32 t1 = tcg_temp_new();
25923 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF);
25924 tcg_gen_shli_i32(t0, t0, 24);
25926 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00);
25927 tcg_gen_shri_i32(t1, t1, 8);
25929 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25931 tcg_temp_free(t1);
25932 tcg_temp_free(t0);
25934 break;
25935 case MXU_OPTN3_PTN4:
25937 /* */
25938 /* XRb XRc */
25939 /* +---------------+ */
25940 /* A B C D | E F G H | */
25941 /* +-------+-------+ */
25942 /* | */
25943 /* XRa */
25944 /* */
25946 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25948 break;
25955 * Decoding engine for MXU
25956 * =======================
25961 * Decode MXU pool00
25963 * 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
25964 * +-----------+---------+-----+-------+-------+-------+-----------+
25965 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL00|
25966 * +-----------+---------+-----+-------+-------+-------+-----------+
25969 static void decode_opc_mxu__pool00(CPUMIPSState *env, DisasContext *ctx)
25971 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25973 switch (opcode) {
25974 case OPC_MXU_S32MAX:
25975 case OPC_MXU_S32MIN:
25976 gen_mxu_S32MAX_S32MIN(ctx);
25977 break;
25978 case OPC_MXU_D16MAX:
25979 case OPC_MXU_D16MIN:
25980 gen_mxu_D16MAX_D16MIN(ctx);
25981 break;
25982 case OPC_MXU_Q8MAX:
25983 case OPC_MXU_Q8MIN:
25984 gen_mxu_Q8MAX_Q8MIN(ctx);
25985 break;
25986 case OPC_MXU_Q8SLT:
25987 /* TODO: Implement emulation of Q8SLT instruction. */
25988 MIPS_INVAL("OPC_MXU_Q8SLT");
25989 gen_reserved_instruction(ctx);
25990 break;
25991 case OPC_MXU_Q8SLTU:
25992 /* TODO: Implement emulation of Q8SLTU instruction. */
25993 MIPS_INVAL("OPC_MXU_Q8SLTU");
25994 gen_reserved_instruction(ctx);
25995 break;
25996 default:
25997 MIPS_INVAL("decode_opc_mxu");
25998 gen_reserved_instruction(ctx);
25999 break;
26005 * Decode MXU pool01
26007 * S32SLT, D16SLT, D16AVG, D16AVGR, Q8AVG, Q8AVGR:
26008 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26009 * +-----------+---------+-----+-------+-------+-------+-----------+
26010 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
26011 * +-----------+---------+-----+-------+-------+-------+-----------+
26013 * Q8ADD:
26014 * 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
26015 * +-----------+---+-----+-----+-------+-------+-------+-----------+
26016 * | SPECIAL2 |en2|0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
26017 * +-----------+---+-----+-----+-------+-------+-------+-----------+
26020 static void decode_opc_mxu__pool01(CPUMIPSState *env, DisasContext *ctx)
26022 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26024 switch (opcode) {
26025 case OPC_MXU_S32SLT:
26026 /* TODO: Implement emulation of S32SLT instruction. */
26027 MIPS_INVAL("OPC_MXU_S32SLT");
26028 gen_reserved_instruction(ctx);
26029 break;
26030 case OPC_MXU_D16SLT:
26031 /* TODO: Implement emulation of D16SLT instruction. */
26032 MIPS_INVAL("OPC_MXU_D16SLT");
26033 gen_reserved_instruction(ctx);
26034 break;
26035 case OPC_MXU_D16AVG:
26036 /* TODO: Implement emulation of D16AVG instruction. */
26037 MIPS_INVAL("OPC_MXU_D16AVG");
26038 gen_reserved_instruction(ctx);
26039 break;
26040 case OPC_MXU_D16AVGR:
26041 /* TODO: Implement emulation of D16AVGR instruction. */
26042 MIPS_INVAL("OPC_MXU_D16AVGR");
26043 gen_reserved_instruction(ctx);
26044 break;
26045 case OPC_MXU_Q8AVG:
26046 /* TODO: Implement emulation of Q8AVG instruction. */
26047 MIPS_INVAL("OPC_MXU_Q8AVG");
26048 gen_reserved_instruction(ctx);
26049 break;
26050 case OPC_MXU_Q8AVGR:
26051 /* TODO: Implement emulation of Q8AVGR instruction. */
26052 MIPS_INVAL("OPC_MXU_Q8AVGR");
26053 gen_reserved_instruction(ctx);
26054 break;
26055 case OPC_MXU_Q8ADD:
26056 /* TODO: Implement emulation of Q8ADD instruction. */
26057 MIPS_INVAL("OPC_MXU_Q8ADD");
26058 gen_reserved_instruction(ctx);
26059 break;
26060 default:
26061 MIPS_INVAL("decode_opc_mxu");
26062 gen_reserved_instruction(ctx);
26063 break;
26069 * Decode MXU pool02
26071 * 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
26072 * +-----------+---------+-----+-------+-------+-------+-----------+
26073 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL02|
26074 * +-----------+---------+-----+-------+-------+-------+-----------+
26077 static void decode_opc_mxu__pool02(CPUMIPSState *env, DisasContext *ctx)
26079 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26081 switch (opcode) {
26082 case OPC_MXU_S32CPS:
26083 /* TODO: Implement emulation of S32CPS instruction. */
26084 MIPS_INVAL("OPC_MXU_S32CPS");
26085 gen_reserved_instruction(ctx);
26086 break;
26087 case OPC_MXU_D16CPS:
26088 /* TODO: Implement emulation of D16CPS instruction. */
26089 MIPS_INVAL("OPC_MXU_D16CPS");
26090 gen_reserved_instruction(ctx);
26091 break;
26092 case OPC_MXU_Q8ABD:
26093 /* TODO: Implement emulation of Q8ABD instruction. */
26094 MIPS_INVAL("OPC_MXU_Q8ABD");
26095 gen_reserved_instruction(ctx);
26096 break;
26097 case OPC_MXU_Q16SAT:
26098 /* TODO: Implement emulation of Q16SAT instruction. */
26099 MIPS_INVAL("OPC_MXU_Q16SAT");
26100 gen_reserved_instruction(ctx);
26101 break;
26102 default:
26103 MIPS_INVAL("decode_opc_mxu");
26104 gen_reserved_instruction(ctx);
26105 break;
26111 * Decode MXU pool03
26113 * D16MULF:
26114 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26115 * +-----------+---+---+-------+-------+-------+-------+-----------+
26116 * | SPECIAL2 |x x|on2|0 0 0 0| XRc | XRb | XRa |MXU__POOL03|
26117 * +-----------+---+---+-------+-------+-------+-------+-----------+
26119 * D16MULE:
26120 * 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
26121 * +-----------+---+---+-------+-------+-------+-------+-----------+
26122 * | SPECIAL2 |x x|on2| Xd | XRc | XRb | XRa |MXU__POOL03|
26123 * +-----------+---+---+-------+-------+-------+-------+-----------+
26126 static void decode_opc_mxu__pool03(CPUMIPSState *env, DisasContext *ctx)
26128 uint32_t opcode = extract32(ctx->opcode, 24, 2);
26130 switch (opcode) {
26131 case OPC_MXU_D16MULF:
26132 /* TODO: Implement emulation of D16MULF instruction. */
26133 MIPS_INVAL("OPC_MXU_D16MULF");
26134 gen_reserved_instruction(ctx);
26135 break;
26136 case OPC_MXU_D16MULE:
26137 /* TODO: Implement emulation of D16MULE instruction. */
26138 MIPS_INVAL("OPC_MXU_D16MULE");
26139 gen_reserved_instruction(ctx);
26140 break;
26141 default:
26142 MIPS_INVAL("decode_opc_mxu");
26143 gen_reserved_instruction(ctx);
26144 break;
26150 * Decode MXU pool04
26152 * 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
26153 * +-----------+---------+-+-------------------+-------+-----------+
26154 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL04|
26155 * +-----------+---------+-+-------------------+-------+-----------+
26158 static void decode_opc_mxu__pool04(CPUMIPSState *env, DisasContext *ctx)
26160 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26162 switch (opcode) {
26163 case OPC_MXU_S32LDD:
26164 case OPC_MXU_S32LDDR:
26165 gen_mxu_s32ldd_s32lddr(ctx);
26166 break;
26167 default:
26168 MIPS_INVAL("decode_opc_mxu");
26169 gen_reserved_instruction(ctx);
26170 break;
26176 * Decode MXU pool05
26178 * 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
26179 * +-----------+---------+-+-------------------+-------+-----------+
26180 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL05|
26181 * +-----------+---------+-+-------------------+-------+-----------+
26184 static void decode_opc_mxu__pool05(CPUMIPSState *env, DisasContext *ctx)
26186 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26188 switch (opcode) {
26189 case OPC_MXU_S32STD:
26190 /* TODO: Implement emulation of S32STD instruction. */
26191 MIPS_INVAL("OPC_MXU_S32STD");
26192 gen_reserved_instruction(ctx);
26193 break;
26194 case OPC_MXU_S32STDR:
26195 /* TODO: Implement emulation of S32STDR instruction. */
26196 MIPS_INVAL("OPC_MXU_S32STDR");
26197 gen_reserved_instruction(ctx);
26198 break;
26199 default:
26200 MIPS_INVAL("decode_opc_mxu");
26201 gen_reserved_instruction(ctx);
26202 break;
26208 * Decode MXU pool06
26210 * 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
26211 * +-----------+---------+---------+---+-------+-------+-----------+
26212 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL06|
26213 * +-----------+---------+---------+---+-------+-------+-----------+
26216 static void decode_opc_mxu__pool06(CPUMIPSState *env, DisasContext *ctx)
26218 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26220 switch (opcode) {
26221 case OPC_MXU_S32LDDV:
26222 /* TODO: Implement emulation of S32LDDV instruction. */
26223 MIPS_INVAL("OPC_MXU_S32LDDV");
26224 gen_reserved_instruction(ctx);
26225 break;
26226 case OPC_MXU_S32LDDVR:
26227 /* TODO: Implement emulation of S32LDDVR instruction. */
26228 MIPS_INVAL("OPC_MXU_S32LDDVR");
26229 gen_reserved_instruction(ctx);
26230 break;
26231 default:
26232 MIPS_INVAL("decode_opc_mxu");
26233 gen_reserved_instruction(ctx);
26234 break;
26240 * Decode MXU pool07
26242 * 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
26243 * +-----------+---------+---------+---+-------+-------+-----------+
26244 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL07|
26245 * +-----------+---------+---------+---+-------+-------+-----------+
26248 static void decode_opc_mxu__pool07(CPUMIPSState *env, DisasContext *ctx)
26250 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26252 switch (opcode) {
26253 case OPC_MXU_S32STDV:
26254 /* TODO: Implement emulation of S32TDV instruction. */
26255 MIPS_INVAL("OPC_MXU_S32TDV");
26256 gen_reserved_instruction(ctx);
26257 break;
26258 case OPC_MXU_S32STDVR:
26259 /* TODO: Implement emulation of S32TDVR instruction. */
26260 MIPS_INVAL("OPC_MXU_S32TDVR");
26261 gen_reserved_instruction(ctx);
26262 break;
26263 default:
26264 MIPS_INVAL("decode_opc_mxu");
26265 gen_reserved_instruction(ctx);
26266 break;
26272 * Decode MXU pool08
26274 * 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
26275 * +-----------+---------+-+-------------------+-------+-----------+
26276 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL08|
26277 * +-----------+---------+-+-------------------+-------+-----------+
26280 static void decode_opc_mxu__pool08(CPUMIPSState *env, DisasContext *ctx)
26282 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26284 switch (opcode) {
26285 case OPC_MXU_S32LDI:
26286 /* TODO: Implement emulation of S32LDI instruction. */
26287 MIPS_INVAL("OPC_MXU_S32LDI");
26288 gen_reserved_instruction(ctx);
26289 break;
26290 case OPC_MXU_S32LDIR:
26291 /* TODO: Implement emulation of S32LDIR instruction. */
26292 MIPS_INVAL("OPC_MXU_S32LDIR");
26293 gen_reserved_instruction(ctx);
26294 break;
26295 default:
26296 MIPS_INVAL("decode_opc_mxu");
26297 gen_reserved_instruction(ctx);
26298 break;
26304 * Decode MXU pool09
26306 * 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
26307 * +-----------+---------+-+-------------------+-------+-----------+
26308 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL09|
26309 * +-----------+---------+-+-------------------+-------+-----------+
26312 static void decode_opc_mxu__pool09(CPUMIPSState *env, DisasContext *ctx)
26314 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26316 switch (opcode) {
26317 case OPC_MXU_S32SDI:
26318 /* TODO: Implement emulation of S32SDI instruction. */
26319 MIPS_INVAL("OPC_MXU_S32SDI");
26320 gen_reserved_instruction(ctx);
26321 break;
26322 case OPC_MXU_S32SDIR:
26323 /* TODO: Implement emulation of S32SDIR instruction. */
26324 MIPS_INVAL("OPC_MXU_S32SDIR");
26325 gen_reserved_instruction(ctx);
26326 break;
26327 default:
26328 MIPS_INVAL("decode_opc_mxu");
26329 gen_reserved_instruction(ctx);
26330 break;
26336 * Decode MXU pool10
26338 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26339 * +-----------+---------+---------+---+-------+-------+-----------+
26340 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL10|
26341 * +-----------+---------+---------+---+-------+-------+-----------+
26344 static void decode_opc_mxu__pool10(CPUMIPSState *env, DisasContext *ctx)
26346 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26348 switch (opcode) {
26349 case OPC_MXU_S32LDIV:
26350 /* TODO: Implement emulation of S32LDIV instruction. */
26351 MIPS_INVAL("OPC_MXU_S32LDIV");
26352 gen_reserved_instruction(ctx);
26353 break;
26354 case OPC_MXU_S32LDIVR:
26355 /* TODO: Implement emulation of S32LDIVR instruction. */
26356 MIPS_INVAL("OPC_MXU_S32LDIVR");
26357 gen_reserved_instruction(ctx);
26358 break;
26359 default:
26360 MIPS_INVAL("decode_opc_mxu");
26361 gen_reserved_instruction(ctx);
26362 break;
26368 * Decode MXU pool11
26370 * 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
26371 * +-----------+---------+---------+---+-------+-------+-----------+
26372 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL11|
26373 * +-----------+---------+---------+---+-------+-------+-----------+
26376 static void decode_opc_mxu__pool11(CPUMIPSState *env, DisasContext *ctx)
26378 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26380 switch (opcode) {
26381 case OPC_MXU_S32SDIV:
26382 /* TODO: Implement emulation of S32SDIV instruction. */
26383 MIPS_INVAL("OPC_MXU_S32SDIV");
26384 gen_reserved_instruction(ctx);
26385 break;
26386 case OPC_MXU_S32SDIVR:
26387 /* TODO: Implement emulation of S32SDIVR instruction. */
26388 MIPS_INVAL("OPC_MXU_S32SDIVR");
26389 gen_reserved_instruction(ctx);
26390 break;
26391 default:
26392 MIPS_INVAL("decode_opc_mxu");
26393 gen_reserved_instruction(ctx);
26394 break;
26400 * Decode MXU pool12
26402 * 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
26403 * +-----------+---+---+-------+-------+-------+-------+-----------+
26404 * | SPECIAL2 |an2|x x| Xd | XRc | XRb | XRa |MXU__POOL12|
26405 * +-----------+---+---+-------+-------+-------+-------+-----------+
26408 static void decode_opc_mxu__pool12(CPUMIPSState *env, DisasContext *ctx)
26410 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26412 switch (opcode) {
26413 case OPC_MXU_D32ACC:
26414 /* TODO: Implement emulation of D32ACC instruction. */
26415 MIPS_INVAL("OPC_MXU_D32ACC");
26416 gen_reserved_instruction(ctx);
26417 break;
26418 case OPC_MXU_D32ACCM:
26419 /* TODO: Implement emulation of D32ACCM instruction. */
26420 MIPS_INVAL("OPC_MXU_D32ACCM");
26421 gen_reserved_instruction(ctx);
26422 break;
26423 case OPC_MXU_D32ASUM:
26424 /* TODO: Implement emulation of D32ASUM instruction. */
26425 MIPS_INVAL("OPC_MXU_D32ASUM");
26426 gen_reserved_instruction(ctx);
26427 break;
26428 default:
26429 MIPS_INVAL("decode_opc_mxu");
26430 gen_reserved_instruction(ctx);
26431 break;
26437 * Decode MXU pool13
26439 * 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
26440 * +-----------+---+---+-------+-------+-------+-------+-----------+
26441 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL13|
26442 * +-----------+---+---+-------+-------+-------+-------+-----------+
26445 static void decode_opc_mxu__pool13(CPUMIPSState *env, DisasContext *ctx)
26447 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26449 switch (opcode) {
26450 case OPC_MXU_Q16ACC:
26451 /* TODO: Implement emulation of Q16ACC instruction. */
26452 MIPS_INVAL("OPC_MXU_Q16ACC");
26453 gen_reserved_instruction(ctx);
26454 break;
26455 case OPC_MXU_Q16ACCM:
26456 /* TODO: Implement emulation of Q16ACCM instruction. */
26457 MIPS_INVAL("OPC_MXU_Q16ACCM");
26458 gen_reserved_instruction(ctx);
26459 break;
26460 case OPC_MXU_Q16ASUM:
26461 /* TODO: Implement emulation of Q16ASUM instruction. */
26462 MIPS_INVAL("OPC_MXU_Q16ASUM");
26463 gen_reserved_instruction(ctx);
26464 break;
26465 default:
26466 MIPS_INVAL("decode_opc_mxu");
26467 gen_reserved_instruction(ctx);
26468 break;
26474 * Decode MXU pool14
26476 * Q8ADDE, Q8ACCE:
26477 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26478 * +-----------+---+---+-------+-------+-------+-------+-----------+
26479 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL14|
26480 * +-----------+---+---+-------+-------+-------+-------+-----------+
26482 * D8SUM, D8SUMC:
26483 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26484 * +-----------+---+---+-------+-------+-------+-------+-----------+
26485 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL14|
26486 * +-----------+---+---+-------+-------+-------+-------+-----------+
26489 static void decode_opc_mxu__pool14(CPUMIPSState *env, DisasContext *ctx)
26491 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26493 switch (opcode) {
26494 case OPC_MXU_Q8ADDE:
26495 /* TODO: Implement emulation of Q8ADDE instruction. */
26496 MIPS_INVAL("OPC_MXU_Q8ADDE");
26497 gen_reserved_instruction(ctx);
26498 break;
26499 case OPC_MXU_D8SUM:
26500 /* TODO: Implement emulation of D8SUM instruction. */
26501 MIPS_INVAL("OPC_MXU_D8SUM");
26502 gen_reserved_instruction(ctx);
26503 break;
26504 case OPC_MXU_D8SUMC:
26505 /* TODO: Implement emulation of D8SUMC instruction. */
26506 MIPS_INVAL("OPC_MXU_D8SUMC");
26507 gen_reserved_instruction(ctx);
26508 break;
26509 default:
26510 MIPS_INVAL("decode_opc_mxu");
26511 gen_reserved_instruction(ctx);
26512 break;
26518 * Decode MXU pool15
26520 * S32MUL, S32MULU, S32EXTRV:
26521 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26522 * +-----------+---------+---------+---+-------+-------+-----------+
26523 * | SPECIAL2 | rs | rt |x x| XRd | XRa |MXU__POOL15|
26524 * +-----------+---------+---------+---+-------+-------+-----------+
26526 * S32EXTR:
26527 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26528 * +-----------+---------+---------+---+-------+-------+-----------+
26529 * | SPECIAL2 | rb | sft5 |x x| XRd | XRa |MXU__POOL15|
26530 * +-----------+---------+---------+---+-------+-------+-----------+
26533 static void decode_opc_mxu__pool15(CPUMIPSState *env, DisasContext *ctx)
26535 uint32_t opcode = extract32(ctx->opcode, 14, 2);
26537 switch (opcode) {
26538 case OPC_MXU_S32MUL:
26539 /* TODO: Implement emulation of S32MUL instruction. */
26540 MIPS_INVAL("OPC_MXU_S32MUL");
26541 gen_reserved_instruction(ctx);
26542 break;
26543 case OPC_MXU_S32MULU:
26544 /* TODO: Implement emulation of S32MULU instruction. */
26545 MIPS_INVAL("OPC_MXU_S32MULU");
26546 gen_reserved_instruction(ctx);
26547 break;
26548 case OPC_MXU_S32EXTR:
26549 /* TODO: Implement emulation of S32EXTR instruction. */
26550 MIPS_INVAL("OPC_MXU_S32EXTR");
26551 gen_reserved_instruction(ctx);
26552 break;
26553 case OPC_MXU_S32EXTRV:
26554 /* TODO: Implement emulation of S32EXTRV instruction. */
26555 MIPS_INVAL("OPC_MXU_S32EXTRV");
26556 gen_reserved_instruction(ctx);
26557 break;
26558 default:
26559 MIPS_INVAL("decode_opc_mxu");
26560 gen_reserved_instruction(ctx);
26561 break;
26567 * Decode MXU pool16
26569 * D32SARW:
26570 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26571 * +-----------+---------+-----+-------+-------+-------+-----------+
26572 * | SPECIAL2 | rb |x x x| XRc | XRb | XRa |MXU__POOL16|
26573 * +-----------+---------+-----+-------+-------+-------+-----------+
26575 * S32ALN:
26576 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26577 * +-----------+---------+-----+-------+-------+-------+-----------+
26578 * | SPECIAL2 | rs |x x x| XRc | XRb | XRa |MXU__POOL16|
26579 * +-----------+---------+-----+-------+-------+-------+-----------+
26581 * S32ALNI:
26582 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26583 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26584 * | SPECIAL2 | s3 |0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26585 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26587 * S32LUI:
26588 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26589 * +-----------+-----+---+-----+-------+---------------+-----------+
26590 * | SPECIAL2 |optn3|0 0|x x x| XRc | s8 |MXU__POOL16|
26591 * +-----------+-----+---+-----+-------+---------------+-----------+
26593 * S32NOR, S32AND, S32OR, S32XOR:
26594 * 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
26595 * +-----------+---------+-----+-------+-------+-------+-----------+
26596 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26597 * +-----------+---------+-----+-------+-------+-------+-----------+
26600 static void decode_opc_mxu__pool16(CPUMIPSState *env, DisasContext *ctx)
26602 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26604 switch (opcode) {
26605 case OPC_MXU_D32SARW:
26606 /* TODO: Implement emulation of D32SARW instruction. */
26607 MIPS_INVAL("OPC_MXU_D32SARW");
26608 gen_reserved_instruction(ctx);
26609 break;
26610 case OPC_MXU_S32ALN:
26611 /* TODO: Implement emulation of S32ALN instruction. */
26612 MIPS_INVAL("OPC_MXU_S32ALN");
26613 gen_reserved_instruction(ctx);
26614 break;
26615 case OPC_MXU_S32ALNI:
26616 gen_mxu_S32ALNI(ctx);
26617 break;
26618 case OPC_MXU_S32LUI:
26619 /* TODO: Implement emulation of S32LUI instruction. */
26620 MIPS_INVAL("OPC_MXU_S32LUI");
26621 gen_reserved_instruction(ctx);
26622 break;
26623 case OPC_MXU_S32NOR:
26624 gen_mxu_S32NOR(ctx);
26625 break;
26626 case OPC_MXU_S32AND:
26627 gen_mxu_S32AND(ctx);
26628 break;
26629 case OPC_MXU_S32OR:
26630 gen_mxu_S32OR(ctx);
26631 break;
26632 case OPC_MXU_S32XOR:
26633 gen_mxu_S32XOR(ctx);
26634 break;
26635 default:
26636 MIPS_INVAL("decode_opc_mxu");
26637 gen_reserved_instruction(ctx);
26638 break;
26644 * Decode MXU pool17
26646 * 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
26647 * +-----------+---------+---------+---+---------+-----+-----------+
26648 * | SPECIAL2 | rs | rt |0 0| rd |x x x|MXU__POOL15|
26649 * +-----------+---------+---------+---+---------+-----+-----------+
26652 static void decode_opc_mxu__pool17(CPUMIPSState *env, DisasContext *ctx)
26654 uint32_t opcode = extract32(ctx->opcode, 6, 2);
26656 switch (opcode) {
26657 case OPC_MXU_LXW:
26658 /* TODO: Implement emulation of LXW instruction. */
26659 MIPS_INVAL("OPC_MXU_LXW");
26660 gen_reserved_instruction(ctx);
26661 break;
26662 case OPC_MXU_LXH:
26663 /* TODO: Implement emulation of LXH instruction. */
26664 MIPS_INVAL("OPC_MXU_LXH");
26665 gen_reserved_instruction(ctx);
26666 break;
26667 case OPC_MXU_LXHU:
26668 /* TODO: Implement emulation of LXHU instruction. */
26669 MIPS_INVAL("OPC_MXU_LXHU");
26670 gen_reserved_instruction(ctx);
26671 break;
26672 case OPC_MXU_LXB:
26673 /* TODO: Implement emulation of LXB instruction. */
26674 MIPS_INVAL("OPC_MXU_LXB");
26675 gen_reserved_instruction(ctx);
26676 break;
26677 case OPC_MXU_LXBU:
26678 /* TODO: Implement emulation of LXBU instruction. */
26679 MIPS_INVAL("OPC_MXU_LXBU");
26680 gen_reserved_instruction(ctx);
26681 break;
26682 default:
26683 MIPS_INVAL("decode_opc_mxu");
26684 gen_reserved_instruction(ctx);
26685 break;
26690 * Decode MXU pool18
26692 * 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
26693 * +-----------+---------+-----+-------+-------+-------+-----------+
26694 * | SPECIAL2 | rb |x x x| XRd | XRa |0 0 0 0|MXU__POOL18|
26695 * +-----------+---------+-----+-------+-------+-------+-----------+
26698 static void decode_opc_mxu__pool18(CPUMIPSState *env, DisasContext *ctx)
26700 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26702 switch (opcode) {
26703 case OPC_MXU_D32SLLV:
26704 /* TODO: Implement emulation of D32SLLV instruction. */
26705 MIPS_INVAL("OPC_MXU_D32SLLV");
26706 gen_reserved_instruction(ctx);
26707 break;
26708 case OPC_MXU_D32SLRV:
26709 /* TODO: Implement emulation of D32SLRV instruction. */
26710 MIPS_INVAL("OPC_MXU_D32SLRV");
26711 gen_reserved_instruction(ctx);
26712 break;
26713 case OPC_MXU_D32SARV:
26714 /* TODO: Implement emulation of D32SARV instruction. */
26715 MIPS_INVAL("OPC_MXU_D32SARV");
26716 gen_reserved_instruction(ctx);
26717 break;
26718 case OPC_MXU_Q16SLLV:
26719 /* TODO: Implement emulation of Q16SLLV instruction. */
26720 MIPS_INVAL("OPC_MXU_Q16SLLV");
26721 gen_reserved_instruction(ctx);
26722 break;
26723 case OPC_MXU_Q16SLRV:
26724 /* TODO: Implement emulation of Q16SLRV instruction. */
26725 MIPS_INVAL("OPC_MXU_Q16SLRV");
26726 gen_reserved_instruction(ctx);
26727 break;
26728 case OPC_MXU_Q16SARV:
26729 /* TODO: Implement emulation of Q16SARV instruction. */
26730 MIPS_INVAL("OPC_MXU_Q16SARV");
26731 gen_reserved_instruction(ctx);
26732 break;
26733 default:
26734 MIPS_INVAL("decode_opc_mxu");
26735 gen_reserved_instruction(ctx);
26736 break;
26742 * Decode MXU pool19
26744 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26745 * +-----------+---+---+-------+-------+-------+-------+-----------+
26746 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL19|
26747 * +-----------+---+---+-------+-------+-------+-------+-----------+
26750 static void decode_opc_mxu__pool19(CPUMIPSState *env, DisasContext *ctx)
26752 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26754 switch (opcode) {
26755 case OPC_MXU_Q8MUL:
26756 case OPC_MXU_Q8MULSU:
26757 gen_mxu_q8mul_q8mulsu(ctx);
26758 break;
26759 default:
26760 MIPS_INVAL("decode_opc_mxu");
26761 gen_reserved_instruction(ctx);
26762 break;
26768 * Decode MXU pool20
26770 * 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
26771 * +-----------+---------+-----+-------+-------+-------+-----------+
26772 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL20|
26773 * +-----------+---------+-----+-------+-------+-------+-----------+
26776 static void decode_opc_mxu__pool20(CPUMIPSState *env, DisasContext *ctx)
26778 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26780 switch (opcode) {
26781 case OPC_MXU_Q8MOVZ:
26782 /* TODO: Implement emulation of Q8MOVZ instruction. */
26783 MIPS_INVAL("OPC_MXU_Q8MOVZ");
26784 gen_reserved_instruction(ctx);
26785 break;
26786 case OPC_MXU_Q8MOVN:
26787 /* TODO: Implement emulation of Q8MOVN instruction. */
26788 MIPS_INVAL("OPC_MXU_Q8MOVN");
26789 gen_reserved_instruction(ctx);
26790 break;
26791 case OPC_MXU_D16MOVZ:
26792 /* TODO: Implement emulation of D16MOVZ instruction. */
26793 MIPS_INVAL("OPC_MXU_D16MOVZ");
26794 gen_reserved_instruction(ctx);
26795 break;
26796 case OPC_MXU_D16MOVN:
26797 /* TODO: Implement emulation of D16MOVN instruction. */
26798 MIPS_INVAL("OPC_MXU_D16MOVN");
26799 gen_reserved_instruction(ctx);
26800 break;
26801 case OPC_MXU_S32MOVZ:
26802 /* TODO: Implement emulation of S32MOVZ instruction. */
26803 MIPS_INVAL("OPC_MXU_S32MOVZ");
26804 gen_reserved_instruction(ctx);
26805 break;
26806 case OPC_MXU_S32MOVN:
26807 /* TODO: Implement emulation of S32MOVN instruction. */
26808 MIPS_INVAL("OPC_MXU_S32MOVN");
26809 gen_reserved_instruction(ctx);
26810 break;
26811 default:
26812 MIPS_INVAL("decode_opc_mxu");
26813 gen_reserved_instruction(ctx);
26814 break;
26820 * Decode MXU pool21
26822 * 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
26823 * +-----------+---+---+-------+-------+-------+-------+-----------+
26824 * | SPECIAL2 |an2|x x| XRd | XRc | XRb | XRa |MXU__POOL21|
26825 * +-----------+---+---+-------+-------+-------+-------+-----------+
26828 static void decode_opc_mxu__pool21(CPUMIPSState *env, DisasContext *ctx)
26830 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26832 switch (opcode) {
26833 case OPC_MXU_Q8MAC:
26834 /* TODO: Implement emulation of Q8MAC instruction. */
26835 MIPS_INVAL("OPC_MXU_Q8MAC");
26836 gen_reserved_instruction(ctx);
26837 break;
26838 case OPC_MXU_Q8MACSU:
26839 /* TODO: Implement emulation of Q8MACSU instruction. */
26840 MIPS_INVAL("OPC_MXU_Q8MACSU");
26841 gen_reserved_instruction(ctx);
26842 break;
26843 default:
26844 MIPS_INVAL("decode_opc_mxu");
26845 gen_reserved_instruction(ctx);
26846 break;
26852 * Main MXU decoding function
26854 * 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
26855 * +-----------+---------------------------------------+-----------+
26856 * | SPECIAL2 | |x x x x x x|
26857 * +-----------+---------------------------------------+-----------+
26860 static void decode_opc_mxu(CPUMIPSState *env, DisasContext *ctx)
26863 * TODO: Investigate necessity of including handling of
26864 * CLZ, CLO, SDBB in this function, as they belong to
26865 * SPECIAL2 opcode space for regular pre-R6 MIPS ISAs.
26867 uint32_t opcode = extract32(ctx->opcode, 0, 6);
26869 if (opcode == OPC__MXU_MUL) {
26870 uint32_t rs, rt, rd, op1;
26872 rs = extract32(ctx->opcode, 21, 5);
26873 rt = extract32(ctx->opcode, 16, 5);
26874 rd = extract32(ctx->opcode, 11, 5);
26875 op1 = MASK_SPECIAL2(ctx->opcode);
26877 gen_arith(ctx, op1, rd, rs, rt);
26879 return;
26882 if (opcode == OPC_MXU_S32M2I) {
26883 gen_mxu_s32m2i(ctx);
26884 return;
26887 if (opcode == OPC_MXU_S32I2M) {
26888 gen_mxu_s32i2m(ctx);
26889 return;
26893 TCGv t_mxu_cr = tcg_temp_new();
26894 TCGLabel *l_exit = gen_new_label();
26896 gen_load_mxu_cr(t_mxu_cr);
26897 tcg_gen_andi_tl(t_mxu_cr, t_mxu_cr, MXU_CR_MXU_EN);
26898 tcg_gen_brcondi_tl(TCG_COND_NE, t_mxu_cr, MXU_CR_MXU_EN, l_exit);
26900 switch (opcode) {
26901 case OPC_MXU_S32MADD:
26902 /* TODO: Implement emulation of S32MADD instruction. */
26903 MIPS_INVAL("OPC_MXU_S32MADD");
26904 gen_reserved_instruction(ctx);
26905 break;
26906 case OPC_MXU_S32MADDU:
26907 /* TODO: Implement emulation of S32MADDU instruction. */
26908 MIPS_INVAL("OPC_MXU_S32MADDU");
26909 gen_reserved_instruction(ctx);
26910 break;
26911 case OPC_MXU__POOL00:
26912 decode_opc_mxu__pool00(env, ctx);
26913 break;
26914 case OPC_MXU_S32MSUB:
26915 /* TODO: Implement emulation of S32MSUB instruction. */
26916 MIPS_INVAL("OPC_MXU_S32MSUB");
26917 gen_reserved_instruction(ctx);
26918 break;
26919 case OPC_MXU_S32MSUBU:
26920 /* TODO: Implement emulation of S32MSUBU instruction. */
26921 MIPS_INVAL("OPC_MXU_S32MSUBU");
26922 gen_reserved_instruction(ctx);
26923 break;
26924 case OPC_MXU__POOL01:
26925 decode_opc_mxu__pool01(env, ctx);
26926 break;
26927 case OPC_MXU__POOL02:
26928 decode_opc_mxu__pool02(env, ctx);
26929 break;
26930 case OPC_MXU_D16MUL:
26931 gen_mxu_d16mul(ctx);
26932 break;
26933 case OPC_MXU__POOL03:
26934 decode_opc_mxu__pool03(env, ctx);
26935 break;
26936 case OPC_MXU_D16MAC:
26937 gen_mxu_d16mac(ctx);
26938 break;
26939 case OPC_MXU_D16MACF:
26940 /* TODO: Implement emulation of D16MACF instruction. */
26941 MIPS_INVAL("OPC_MXU_D16MACF");
26942 gen_reserved_instruction(ctx);
26943 break;
26944 case OPC_MXU_D16MADL:
26945 /* TODO: Implement emulation of D16MADL instruction. */
26946 MIPS_INVAL("OPC_MXU_D16MADL");
26947 gen_reserved_instruction(ctx);
26948 break;
26949 case OPC_MXU_S16MAD:
26950 /* TODO: Implement emulation of S16MAD instruction. */
26951 MIPS_INVAL("OPC_MXU_S16MAD");
26952 gen_reserved_instruction(ctx);
26953 break;
26954 case OPC_MXU_Q16ADD:
26955 /* TODO: Implement emulation of Q16ADD instruction. */
26956 MIPS_INVAL("OPC_MXU_Q16ADD");
26957 gen_reserved_instruction(ctx);
26958 break;
26959 case OPC_MXU_D16MACE:
26960 /* TODO: Implement emulation of D16MACE instruction. */
26961 MIPS_INVAL("OPC_MXU_D16MACE");
26962 gen_reserved_instruction(ctx);
26963 break;
26964 case OPC_MXU__POOL04:
26965 decode_opc_mxu__pool04(env, ctx);
26966 break;
26967 case OPC_MXU__POOL05:
26968 decode_opc_mxu__pool05(env, ctx);
26969 break;
26970 case OPC_MXU__POOL06:
26971 decode_opc_mxu__pool06(env, ctx);
26972 break;
26973 case OPC_MXU__POOL07:
26974 decode_opc_mxu__pool07(env, ctx);
26975 break;
26976 case OPC_MXU__POOL08:
26977 decode_opc_mxu__pool08(env, ctx);
26978 break;
26979 case OPC_MXU__POOL09:
26980 decode_opc_mxu__pool09(env, ctx);
26981 break;
26982 case OPC_MXU__POOL10:
26983 decode_opc_mxu__pool10(env, ctx);
26984 break;
26985 case OPC_MXU__POOL11:
26986 decode_opc_mxu__pool11(env, ctx);
26987 break;
26988 case OPC_MXU_D32ADD:
26989 /* TODO: Implement emulation of D32ADD instruction. */
26990 MIPS_INVAL("OPC_MXU_D32ADD");
26991 gen_reserved_instruction(ctx);
26992 break;
26993 case OPC_MXU__POOL12:
26994 decode_opc_mxu__pool12(env, ctx);
26995 break;
26996 case OPC_MXU__POOL13:
26997 decode_opc_mxu__pool13(env, ctx);
26998 break;
26999 case OPC_MXU__POOL14:
27000 decode_opc_mxu__pool14(env, ctx);
27001 break;
27002 case OPC_MXU_Q8ACCE:
27003 /* TODO: Implement emulation of Q8ACCE instruction. */
27004 MIPS_INVAL("OPC_MXU_Q8ACCE");
27005 gen_reserved_instruction(ctx);
27006 break;
27007 case OPC_MXU_S8LDD:
27008 gen_mxu_s8ldd(ctx);
27009 break;
27010 case OPC_MXU_S8STD:
27011 /* TODO: Implement emulation of S8STD instruction. */
27012 MIPS_INVAL("OPC_MXU_S8STD");
27013 gen_reserved_instruction(ctx);
27014 break;
27015 case OPC_MXU_S8LDI:
27016 /* TODO: Implement emulation of S8LDI instruction. */
27017 MIPS_INVAL("OPC_MXU_S8LDI");
27018 gen_reserved_instruction(ctx);
27019 break;
27020 case OPC_MXU_S8SDI:
27021 /* TODO: Implement emulation of S8SDI instruction. */
27022 MIPS_INVAL("OPC_MXU_S8SDI");
27023 gen_reserved_instruction(ctx);
27024 break;
27025 case OPC_MXU__POOL15:
27026 decode_opc_mxu__pool15(env, ctx);
27027 break;
27028 case OPC_MXU__POOL16:
27029 decode_opc_mxu__pool16(env, ctx);
27030 break;
27031 case OPC_MXU__POOL17:
27032 decode_opc_mxu__pool17(env, ctx);
27033 break;
27034 case OPC_MXU_S16LDD:
27035 /* TODO: Implement emulation of S16LDD instruction. */
27036 MIPS_INVAL("OPC_MXU_S16LDD");
27037 gen_reserved_instruction(ctx);
27038 break;
27039 case OPC_MXU_S16STD:
27040 /* TODO: Implement emulation of S16STD instruction. */
27041 MIPS_INVAL("OPC_MXU_S16STD");
27042 gen_reserved_instruction(ctx);
27043 break;
27044 case OPC_MXU_S16LDI:
27045 /* TODO: Implement emulation of S16LDI instruction. */
27046 MIPS_INVAL("OPC_MXU_S16LDI");
27047 gen_reserved_instruction(ctx);
27048 break;
27049 case OPC_MXU_S16SDI:
27050 /* TODO: Implement emulation of S16SDI instruction. */
27051 MIPS_INVAL("OPC_MXU_S16SDI");
27052 gen_reserved_instruction(ctx);
27053 break;
27054 case OPC_MXU_D32SLL:
27055 /* TODO: Implement emulation of D32SLL instruction. */
27056 MIPS_INVAL("OPC_MXU_D32SLL");
27057 gen_reserved_instruction(ctx);
27058 break;
27059 case OPC_MXU_D32SLR:
27060 /* TODO: Implement emulation of D32SLR instruction. */
27061 MIPS_INVAL("OPC_MXU_D32SLR");
27062 gen_reserved_instruction(ctx);
27063 break;
27064 case OPC_MXU_D32SARL:
27065 /* TODO: Implement emulation of D32SARL instruction. */
27066 MIPS_INVAL("OPC_MXU_D32SARL");
27067 gen_reserved_instruction(ctx);
27068 break;
27069 case OPC_MXU_D32SAR:
27070 /* TODO: Implement emulation of D32SAR instruction. */
27071 MIPS_INVAL("OPC_MXU_D32SAR");
27072 gen_reserved_instruction(ctx);
27073 break;
27074 case OPC_MXU_Q16SLL:
27075 /* TODO: Implement emulation of Q16SLL instruction. */
27076 MIPS_INVAL("OPC_MXU_Q16SLL");
27077 gen_reserved_instruction(ctx);
27078 break;
27079 case OPC_MXU_Q16SLR:
27080 /* TODO: Implement emulation of Q16SLR instruction. */
27081 MIPS_INVAL("OPC_MXU_Q16SLR");
27082 gen_reserved_instruction(ctx);
27083 break;
27084 case OPC_MXU__POOL18:
27085 decode_opc_mxu__pool18(env, ctx);
27086 break;
27087 case OPC_MXU_Q16SAR:
27088 /* TODO: Implement emulation of Q16SAR instruction. */
27089 MIPS_INVAL("OPC_MXU_Q16SAR");
27090 gen_reserved_instruction(ctx);
27091 break;
27092 case OPC_MXU__POOL19:
27093 decode_opc_mxu__pool19(env, ctx);
27094 break;
27095 case OPC_MXU__POOL20:
27096 decode_opc_mxu__pool20(env, ctx);
27097 break;
27098 case OPC_MXU__POOL21:
27099 decode_opc_mxu__pool21(env, ctx);
27100 break;
27101 case OPC_MXU_Q16SCOP:
27102 /* TODO: Implement emulation of Q16SCOP instruction. */
27103 MIPS_INVAL("OPC_MXU_Q16SCOP");
27104 gen_reserved_instruction(ctx);
27105 break;
27106 case OPC_MXU_Q8MADL:
27107 /* TODO: Implement emulation of Q8MADL instruction. */
27108 MIPS_INVAL("OPC_MXU_Q8MADL");
27109 gen_reserved_instruction(ctx);
27110 break;
27111 case OPC_MXU_S32SFL:
27112 /* TODO: Implement emulation of S32SFL instruction. */
27113 MIPS_INVAL("OPC_MXU_S32SFL");
27114 gen_reserved_instruction(ctx);
27115 break;
27116 case OPC_MXU_Q8SAD:
27117 /* TODO: Implement emulation of Q8SAD instruction. */
27118 MIPS_INVAL("OPC_MXU_Q8SAD");
27119 gen_reserved_instruction(ctx);
27120 break;
27121 default:
27122 MIPS_INVAL("decode_opc_mxu");
27123 gen_reserved_instruction(ctx);
27126 gen_set_label(l_exit);
27127 tcg_temp_free(t_mxu_cr);
27131 #endif /* !defined(TARGET_MIPS64) */
27134 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
27136 int rs, rt, rd;
27137 uint32_t op1;
27139 rs = (ctx->opcode >> 21) & 0x1f;
27140 rt = (ctx->opcode >> 16) & 0x1f;
27141 rd = (ctx->opcode >> 11) & 0x1f;
27143 op1 = MASK_SPECIAL2(ctx->opcode);
27144 switch (op1) {
27145 case OPC_MADD: /* Multiply and add/sub */
27146 case OPC_MADDU:
27147 case OPC_MSUB:
27148 case OPC_MSUBU:
27149 check_insn(ctx, ISA_MIPS_R1);
27150 gen_muldiv(ctx, op1, rd & 3, rs, rt);
27151 break;
27152 case OPC_MUL:
27153 gen_arith(ctx, op1, rd, rs, rt);
27154 break;
27155 case OPC_DIV_G_2F:
27156 case OPC_DIVU_G_2F:
27157 case OPC_MULT_G_2F:
27158 case OPC_MULTU_G_2F:
27159 case OPC_MOD_G_2F:
27160 case OPC_MODU_G_2F:
27161 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
27162 gen_loongson_integer(ctx, op1, rd, rs, rt);
27163 break;
27164 case OPC_CLO:
27165 case OPC_CLZ:
27166 check_insn(ctx, ISA_MIPS_R1);
27167 gen_cl(ctx, op1, rd, rs);
27168 break;
27169 case OPC_SDBBP:
27170 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
27171 gen_helper_do_semihosting(cpu_env);
27172 } else {
27174 * XXX: not clear which exception should be raised
27175 * when in debug mode...
27177 check_insn(ctx, ISA_MIPS_R1);
27178 generate_exception_end(ctx, EXCP_DBp);
27180 break;
27181 #if defined(TARGET_MIPS64)
27182 case OPC_DCLO:
27183 case OPC_DCLZ:
27184 check_insn(ctx, ISA_MIPS_R1);
27185 check_mips_64(ctx);
27186 gen_cl(ctx, op1, rd, rs);
27187 break;
27188 case OPC_DMULT_G_2F:
27189 case OPC_DMULTU_G_2F:
27190 case OPC_DDIV_G_2F:
27191 case OPC_DDIVU_G_2F:
27192 case OPC_DMOD_G_2F:
27193 case OPC_DMODU_G_2F:
27194 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
27195 gen_loongson_integer(ctx, op1, rd, rs, rt);
27196 break;
27197 #endif
27198 default: /* Invalid */
27199 MIPS_INVAL("special2_legacy");
27200 gen_reserved_instruction(ctx);
27201 break;
27205 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
27207 int rs, rt, rd, sa;
27208 uint32_t op1, op2;
27209 int16_t imm;
27211 rs = (ctx->opcode >> 21) & 0x1f;
27212 rt = (ctx->opcode >> 16) & 0x1f;
27213 rd = (ctx->opcode >> 11) & 0x1f;
27214 sa = (ctx->opcode >> 6) & 0x1f;
27215 imm = (int16_t)ctx->opcode >> 7;
27217 op1 = MASK_SPECIAL3(ctx->opcode);
27218 switch (op1) {
27219 case R6_OPC_PREF:
27220 if (rt >= 24) {
27221 /* hint codes 24-31 are reserved and signal RI */
27222 gen_reserved_instruction(ctx);
27224 /* Treat as NOP. */
27225 break;
27226 case R6_OPC_CACHE:
27227 check_cp0_enabled(ctx);
27228 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
27229 gen_cache_operation(ctx, rt, rs, imm);
27231 break;
27232 case R6_OPC_SC:
27233 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
27234 break;
27235 case R6_OPC_LL:
27236 gen_ld(ctx, op1, rt, rs, imm);
27237 break;
27238 case OPC_BSHFL:
27240 if (rd == 0) {
27241 /* Treat as NOP. */
27242 break;
27244 op2 = MASK_BSHFL(ctx->opcode);
27245 switch (op2) {
27246 case OPC_ALIGN:
27247 case OPC_ALIGN_1:
27248 case OPC_ALIGN_2:
27249 case OPC_ALIGN_3:
27250 gen_align(ctx, 32, rd, rs, rt, sa & 3);
27251 break;
27252 case OPC_BITSWAP:
27253 gen_bitswap(ctx, op2, rd, rt);
27254 break;
27257 break;
27258 #ifndef CONFIG_USER_ONLY
27259 case OPC_GINV:
27260 if (unlikely(ctx->gi <= 1)) {
27261 gen_reserved_instruction(ctx);
27263 check_cp0_enabled(ctx);
27264 switch ((ctx->opcode >> 6) & 3) {
27265 case 0: /* GINVI */
27266 /* Treat as NOP. */
27267 break;
27268 case 2: /* GINVT */
27269 gen_helper_0e1i(ginvt, cpu_gpr[rs], extract32(ctx->opcode, 8, 2));
27270 break;
27271 default:
27272 gen_reserved_instruction(ctx);
27273 break;
27275 break;
27276 #endif
27277 #if defined(TARGET_MIPS64)
27278 case R6_OPC_SCD:
27279 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
27280 break;
27281 case R6_OPC_LLD:
27282 gen_ld(ctx, op1, rt, rs, imm);
27283 break;
27284 case OPC_DBSHFL:
27285 check_mips_64(ctx);
27287 if (rd == 0) {
27288 /* Treat as NOP. */
27289 break;
27291 op2 = MASK_DBSHFL(ctx->opcode);
27292 switch (op2) {
27293 case OPC_DALIGN:
27294 case OPC_DALIGN_1:
27295 case OPC_DALIGN_2:
27296 case OPC_DALIGN_3:
27297 case OPC_DALIGN_4:
27298 case OPC_DALIGN_5:
27299 case OPC_DALIGN_6:
27300 case OPC_DALIGN_7:
27301 gen_align(ctx, 64, rd, rs, rt, sa & 7);
27302 break;
27303 case OPC_DBITSWAP:
27304 gen_bitswap(ctx, op2, rd, rt);
27305 break;
27309 break;
27310 #endif
27311 default: /* Invalid */
27312 MIPS_INVAL("special3_r6");
27313 gen_reserved_instruction(ctx);
27314 break;
27318 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
27320 int rs, rt, rd;
27321 uint32_t op1, op2;
27323 rs = (ctx->opcode >> 21) & 0x1f;
27324 rt = (ctx->opcode >> 16) & 0x1f;
27325 rd = (ctx->opcode >> 11) & 0x1f;
27327 op1 = MASK_SPECIAL3(ctx->opcode);
27328 switch (op1) {
27329 case OPC_DIV_G_2E:
27330 case OPC_DIVU_G_2E:
27331 case OPC_MOD_G_2E:
27332 case OPC_MODU_G_2E:
27333 case OPC_MULT_G_2E:
27334 case OPC_MULTU_G_2E:
27336 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
27337 * the same mask and op1.
27339 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
27340 op2 = MASK_ADDUH_QB(ctx->opcode);
27341 switch (op2) {
27342 case OPC_ADDUH_QB:
27343 case OPC_ADDUH_R_QB:
27344 case OPC_ADDQH_PH:
27345 case OPC_ADDQH_R_PH:
27346 case OPC_ADDQH_W:
27347 case OPC_ADDQH_R_W:
27348 case OPC_SUBUH_QB:
27349 case OPC_SUBUH_R_QB:
27350 case OPC_SUBQH_PH:
27351 case OPC_SUBQH_R_PH:
27352 case OPC_SUBQH_W:
27353 case OPC_SUBQH_R_W:
27354 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27355 break;
27356 case OPC_MUL_PH:
27357 case OPC_MUL_S_PH:
27358 case OPC_MULQ_S_W:
27359 case OPC_MULQ_RS_W:
27360 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27361 break;
27362 default:
27363 MIPS_INVAL("MASK ADDUH.QB");
27364 gen_reserved_instruction(ctx);
27365 break;
27367 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
27368 gen_loongson_integer(ctx, op1, rd, rs, rt);
27369 } else {
27370 gen_reserved_instruction(ctx);
27372 break;
27373 case OPC_LX_DSP:
27374 op2 = MASK_LX(ctx->opcode);
27375 switch (op2) {
27376 #if defined(TARGET_MIPS64)
27377 case OPC_LDX:
27378 #endif
27379 case OPC_LBUX:
27380 case OPC_LHX:
27381 case OPC_LWX:
27382 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
27383 break;
27384 default: /* Invalid */
27385 MIPS_INVAL("MASK LX");
27386 gen_reserved_instruction(ctx);
27387 break;
27389 break;
27390 case OPC_ABSQ_S_PH_DSP:
27391 op2 = MASK_ABSQ_S_PH(ctx->opcode);
27392 switch (op2) {
27393 case OPC_ABSQ_S_QB:
27394 case OPC_ABSQ_S_PH:
27395 case OPC_ABSQ_S_W:
27396 case OPC_PRECEQ_W_PHL:
27397 case OPC_PRECEQ_W_PHR:
27398 case OPC_PRECEQU_PH_QBL:
27399 case OPC_PRECEQU_PH_QBR:
27400 case OPC_PRECEQU_PH_QBLA:
27401 case OPC_PRECEQU_PH_QBRA:
27402 case OPC_PRECEU_PH_QBL:
27403 case OPC_PRECEU_PH_QBR:
27404 case OPC_PRECEU_PH_QBLA:
27405 case OPC_PRECEU_PH_QBRA:
27406 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27407 break;
27408 case OPC_BITREV:
27409 case OPC_REPL_QB:
27410 case OPC_REPLV_QB:
27411 case OPC_REPL_PH:
27412 case OPC_REPLV_PH:
27413 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27414 break;
27415 default:
27416 MIPS_INVAL("MASK ABSQ_S.PH");
27417 gen_reserved_instruction(ctx);
27418 break;
27420 break;
27421 case OPC_ADDU_QB_DSP:
27422 op2 = MASK_ADDU_QB(ctx->opcode);
27423 switch (op2) {
27424 case OPC_ADDQ_PH:
27425 case OPC_ADDQ_S_PH:
27426 case OPC_ADDQ_S_W:
27427 case OPC_ADDU_QB:
27428 case OPC_ADDU_S_QB:
27429 case OPC_ADDU_PH:
27430 case OPC_ADDU_S_PH:
27431 case OPC_SUBQ_PH:
27432 case OPC_SUBQ_S_PH:
27433 case OPC_SUBQ_S_W:
27434 case OPC_SUBU_QB:
27435 case OPC_SUBU_S_QB:
27436 case OPC_SUBU_PH:
27437 case OPC_SUBU_S_PH:
27438 case OPC_ADDSC:
27439 case OPC_ADDWC:
27440 case OPC_MODSUB:
27441 case OPC_RADDU_W_QB:
27442 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27443 break;
27444 case OPC_MULEU_S_PH_QBL:
27445 case OPC_MULEU_S_PH_QBR:
27446 case OPC_MULQ_RS_PH:
27447 case OPC_MULEQ_S_W_PHL:
27448 case OPC_MULEQ_S_W_PHR:
27449 case OPC_MULQ_S_PH:
27450 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27451 break;
27452 default: /* Invalid */
27453 MIPS_INVAL("MASK ADDU.QB");
27454 gen_reserved_instruction(ctx);
27455 break;
27458 break;
27459 case OPC_CMPU_EQ_QB_DSP:
27460 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
27461 switch (op2) {
27462 case OPC_PRECR_SRA_PH_W:
27463 case OPC_PRECR_SRA_R_PH_W:
27464 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
27465 break;
27466 case OPC_PRECR_QB_PH:
27467 case OPC_PRECRQ_QB_PH:
27468 case OPC_PRECRQ_PH_W:
27469 case OPC_PRECRQ_RS_PH_W:
27470 case OPC_PRECRQU_S_QB_PH:
27471 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27472 break;
27473 case OPC_CMPU_EQ_QB:
27474 case OPC_CMPU_LT_QB:
27475 case OPC_CMPU_LE_QB:
27476 case OPC_CMP_EQ_PH:
27477 case OPC_CMP_LT_PH:
27478 case OPC_CMP_LE_PH:
27479 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
27480 break;
27481 case OPC_CMPGU_EQ_QB:
27482 case OPC_CMPGU_LT_QB:
27483 case OPC_CMPGU_LE_QB:
27484 case OPC_CMPGDU_EQ_QB:
27485 case OPC_CMPGDU_LT_QB:
27486 case OPC_CMPGDU_LE_QB:
27487 case OPC_PICK_QB:
27488 case OPC_PICK_PH:
27489 case OPC_PACKRL_PH:
27490 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27491 break;
27492 default: /* Invalid */
27493 MIPS_INVAL("MASK CMPU.EQ.QB");
27494 gen_reserved_instruction(ctx);
27495 break;
27497 break;
27498 case OPC_SHLL_QB_DSP:
27499 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27500 break;
27501 case OPC_DPA_W_PH_DSP:
27502 op2 = MASK_DPA_W_PH(ctx->opcode);
27503 switch (op2) {
27504 case OPC_DPAU_H_QBL:
27505 case OPC_DPAU_H_QBR:
27506 case OPC_DPSU_H_QBL:
27507 case OPC_DPSU_H_QBR:
27508 case OPC_DPA_W_PH:
27509 case OPC_DPAX_W_PH:
27510 case OPC_DPAQ_S_W_PH:
27511 case OPC_DPAQX_S_W_PH:
27512 case OPC_DPAQX_SA_W_PH:
27513 case OPC_DPS_W_PH:
27514 case OPC_DPSX_W_PH:
27515 case OPC_DPSQ_S_W_PH:
27516 case OPC_DPSQX_S_W_PH:
27517 case OPC_DPSQX_SA_W_PH:
27518 case OPC_MULSAQ_S_W_PH:
27519 case OPC_DPAQ_SA_L_W:
27520 case OPC_DPSQ_SA_L_W:
27521 case OPC_MAQ_S_W_PHL:
27522 case OPC_MAQ_S_W_PHR:
27523 case OPC_MAQ_SA_W_PHL:
27524 case OPC_MAQ_SA_W_PHR:
27525 case OPC_MULSA_W_PH:
27526 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27527 break;
27528 default: /* Invalid */
27529 MIPS_INVAL("MASK DPAW.PH");
27530 gen_reserved_instruction(ctx);
27531 break;
27533 break;
27534 case OPC_INSV_DSP:
27535 op2 = MASK_INSV(ctx->opcode);
27536 switch (op2) {
27537 case OPC_INSV:
27538 check_dsp(ctx);
27540 TCGv t0, t1;
27542 if (rt == 0) {
27543 break;
27546 t0 = tcg_temp_new();
27547 t1 = tcg_temp_new();
27549 gen_load_gpr(t0, rt);
27550 gen_load_gpr(t1, rs);
27552 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
27554 tcg_temp_free(t0);
27555 tcg_temp_free(t1);
27556 break;
27558 default: /* Invalid */
27559 MIPS_INVAL("MASK INSV");
27560 gen_reserved_instruction(ctx);
27561 break;
27563 break;
27564 case OPC_APPEND_DSP:
27565 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27566 break;
27567 case OPC_EXTR_W_DSP:
27568 op2 = MASK_EXTR_W(ctx->opcode);
27569 switch (op2) {
27570 case OPC_EXTR_W:
27571 case OPC_EXTR_R_W:
27572 case OPC_EXTR_RS_W:
27573 case OPC_EXTR_S_H:
27574 case OPC_EXTRV_S_H:
27575 case OPC_EXTRV_W:
27576 case OPC_EXTRV_R_W:
27577 case OPC_EXTRV_RS_W:
27578 case OPC_EXTP:
27579 case OPC_EXTPV:
27580 case OPC_EXTPDP:
27581 case OPC_EXTPDPV:
27582 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27583 break;
27584 case OPC_RDDSP:
27585 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
27586 break;
27587 case OPC_SHILO:
27588 case OPC_SHILOV:
27589 case OPC_MTHLIP:
27590 case OPC_WRDSP:
27591 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27592 break;
27593 default: /* Invalid */
27594 MIPS_INVAL("MASK EXTR.W");
27595 gen_reserved_instruction(ctx);
27596 break;
27598 break;
27599 #if defined(TARGET_MIPS64)
27600 case OPC_DDIV_G_2E:
27601 case OPC_DDIVU_G_2E:
27602 case OPC_DMULT_G_2E:
27603 case OPC_DMULTU_G_2E:
27604 case OPC_DMOD_G_2E:
27605 case OPC_DMODU_G_2E:
27606 check_insn(ctx, INSN_LOONGSON2E);
27607 gen_loongson_integer(ctx, op1, rd, rs, rt);
27608 break;
27609 case OPC_ABSQ_S_QH_DSP:
27610 op2 = MASK_ABSQ_S_QH(ctx->opcode);
27611 switch (op2) {
27612 case OPC_PRECEQ_L_PWL:
27613 case OPC_PRECEQ_L_PWR:
27614 case OPC_PRECEQ_PW_QHL:
27615 case OPC_PRECEQ_PW_QHR:
27616 case OPC_PRECEQ_PW_QHLA:
27617 case OPC_PRECEQ_PW_QHRA:
27618 case OPC_PRECEQU_QH_OBL:
27619 case OPC_PRECEQU_QH_OBR:
27620 case OPC_PRECEQU_QH_OBLA:
27621 case OPC_PRECEQU_QH_OBRA:
27622 case OPC_PRECEU_QH_OBL:
27623 case OPC_PRECEU_QH_OBR:
27624 case OPC_PRECEU_QH_OBLA:
27625 case OPC_PRECEU_QH_OBRA:
27626 case OPC_ABSQ_S_OB:
27627 case OPC_ABSQ_S_PW:
27628 case OPC_ABSQ_S_QH:
27629 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27630 break;
27631 case OPC_REPL_OB:
27632 case OPC_REPL_PW:
27633 case OPC_REPL_QH:
27634 case OPC_REPLV_OB:
27635 case OPC_REPLV_PW:
27636 case OPC_REPLV_QH:
27637 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27638 break;
27639 default: /* Invalid */
27640 MIPS_INVAL("MASK ABSQ_S.QH");
27641 gen_reserved_instruction(ctx);
27642 break;
27644 break;
27645 case OPC_ADDU_OB_DSP:
27646 op2 = MASK_ADDU_OB(ctx->opcode);
27647 switch (op2) {
27648 case OPC_RADDU_L_OB:
27649 case OPC_SUBQ_PW:
27650 case OPC_SUBQ_S_PW:
27651 case OPC_SUBQ_QH:
27652 case OPC_SUBQ_S_QH:
27653 case OPC_SUBU_OB:
27654 case OPC_SUBU_S_OB:
27655 case OPC_SUBU_QH:
27656 case OPC_SUBU_S_QH:
27657 case OPC_SUBUH_OB:
27658 case OPC_SUBUH_R_OB:
27659 case OPC_ADDQ_PW:
27660 case OPC_ADDQ_S_PW:
27661 case OPC_ADDQ_QH:
27662 case OPC_ADDQ_S_QH:
27663 case OPC_ADDU_OB:
27664 case OPC_ADDU_S_OB:
27665 case OPC_ADDU_QH:
27666 case OPC_ADDU_S_QH:
27667 case OPC_ADDUH_OB:
27668 case OPC_ADDUH_R_OB:
27669 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27670 break;
27671 case OPC_MULEQ_S_PW_QHL:
27672 case OPC_MULEQ_S_PW_QHR:
27673 case OPC_MULEU_S_QH_OBL:
27674 case OPC_MULEU_S_QH_OBR:
27675 case OPC_MULQ_RS_QH:
27676 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27677 break;
27678 default: /* Invalid */
27679 MIPS_INVAL("MASK ADDU.OB");
27680 gen_reserved_instruction(ctx);
27681 break;
27683 break;
27684 case OPC_CMPU_EQ_OB_DSP:
27685 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
27686 switch (op2) {
27687 case OPC_PRECR_SRA_QH_PW:
27688 case OPC_PRECR_SRA_R_QH_PW:
27689 /* Return value is rt. */
27690 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
27691 break;
27692 case OPC_PRECR_OB_QH:
27693 case OPC_PRECRQ_OB_QH:
27694 case OPC_PRECRQ_PW_L:
27695 case OPC_PRECRQ_QH_PW:
27696 case OPC_PRECRQ_RS_QH_PW:
27697 case OPC_PRECRQU_S_OB_QH:
27698 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27699 break;
27700 case OPC_CMPU_EQ_OB:
27701 case OPC_CMPU_LT_OB:
27702 case OPC_CMPU_LE_OB:
27703 case OPC_CMP_EQ_QH:
27704 case OPC_CMP_LT_QH:
27705 case OPC_CMP_LE_QH:
27706 case OPC_CMP_EQ_PW:
27707 case OPC_CMP_LT_PW:
27708 case OPC_CMP_LE_PW:
27709 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
27710 break;
27711 case OPC_CMPGDU_EQ_OB:
27712 case OPC_CMPGDU_LT_OB:
27713 case OPC_CMPGDU_LE_OB:
27714 case OPC_CMPGU_EQ_OB:
27715 case OPC_CMPGU_LT_OB:
27716 case OPC_CMPGU_LE_OB:
27717 case OPC_PACKRL_PW:
27718 case OPC_PICK_OB:
27719 case OPC_PICK_PW:
27720 case OPC_PICK_QH:
27721 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27722 break;
27723 default: /* Invalid */
27724 MIPS_INVAL("MASK CMPU_EQ.OB");
27725 gen_reserved_instruction(ctx);
27726 break;
27728 break;
27729 case OPC_DAPPEND_DSP:
27730 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27731 break;
27732 case OPC_DEXTR_W_DSP:
27733 op2 = MASK_DEXTR_W(ctx->opcode);
27734 switch (op2) {
27735 case OPC_DEXTP:
27736 case OPC_DEXTPDP:
27737 case OPC_DEXTPDPV:
27738 case OPC_DEXTPV:
27739 case OPC_DEXTR_L:
27740 case OPC_DEXTR_R_L:
27741 case OPC_DEXTR_RS_L:
27742 case OPC_DEXTR_W:
27743 case OPC_DEXTR_R_W:
27744 case OPC_DEXTR_RS_W:
27745 case OPC_DEXTR_S_H:
27746 case OPC_DEXTRV_L:
27747 case OPC_DEXTRV_R_L:
27748 case OPC_DEXTRV_RS_L:
27749 case OPC_DEXTRV_S_H:
27750 case OPC_DEXTRV_W:
27751 case OPC_DEXTRV_R_W:
27752 case OPC_DEXTRV_RS_W:
27753 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27754 break;
27755 case OPC_DMTHLIP:
27756 case OPC_DSHILO:
27757 case OPC_DSHILOV:
27758 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27759 break;
27760 default: /* Invalid */
27761 MIPS_INVAL("MASK EXTR.W");
27762 gen_reserved_instruction(ctx);
27763 break;
27765 break;
27766 case OPC_DPAQ_W_QH_DSP:
27767 op2 = MASK_DPAQ_W_QH(ctx->opcode);
27768 switch (op2) {
27769 case OPC_DPAU_H_OBL:
27770 case OPC_DPAU_H_OBR:
27771 case OPC_DPSU_H_OBL:
27772 case OPC_DPSU_H_OBR:
27773 case OPC_DPA_W_QH:
27774 case OPC_DPAQ_S_W_QH:
27775 case OPC_DPS_W_QH:
27776 case OPC_DPSQ_S_W_QH:
27777 case OPC_MULSAQ_S_W_QH:
27778 case OPC_DPAQ_SA_L_PW:
27779 case OPC_DPSQ_SA_L_PW:
27780 case OPC_MULSAQ_S_L_PW:
27781 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27782 break;
27783 case OPC_MAQ_S_W_QHLL:
27784 case OPC_MAQ_S_W_QHLR:
27785 case OPC_MAQ_S_W_QHRL:
27786 case OPC_MAQ_S_W_QHRR:
27787 case OPC_MAQ_SA_W_QHLL:
27788 case OPC_MAQ_SA_W_QHLR:
27789 case OPC_MAQ_SA_W_QHRL:
27790 case OPC_MAQ_SA_W_QHRR:
27791 case OPC_MAQ_S_L_PWL:
27792 case OPC_MAQ_S_L_PWR:
27793 case OPC_DMADD:
27794 case OPC_DMADDU:
27795 case OPC_DMSUB:
27796 case OPC_DMSUBU:
27797 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27798 break;
27799 default: /* Invalid */
27800 MIPS_INVAL("MASK DPAQ.W.QH");
27801 gen_reserved_instruction(ctx);
27802 break;
27804 break;
27805 case OPC_DINSV_DSP:
27806 op2 = MASK_INSV(ctx->opcode);
27807 switch (op2) {
27808 case OPC_DINSV:
27810 TCGv t0, t1;
27812 if (rt == 0) {
27813 break;
27815 check_dsp(ctx);
27817 t0 = tcg_temp_new();
27818 t1 = tcg_temp_new();
27820 gen_load_gpr(t0, rt);
27821 gen_load_gpr(t1, rs);
27823 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
27825 tcg_temp_free(t0);
27826 tcg_temp_free(t1);
27827 break;
27829 default: /* Invalid */
27830 MIPS_INVAL("MASK DINSV");
27831 gen_reserved_instruction(ctx);
27832 break;
27834 break;
27835 case OPC_SHLL_OB_DSP:
27836 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27837 break;
27838 #endif
27839 default: /* Invalid */
27840 MIPS_INVAL("special3_legacy");
27841 gen_reserved_instruction(ctx);
27842 break;
27847 #if defined(TARGET_MIPS64)
27849 static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx)
27851 uint32_t opc = MASK_MMI0(ctx->opcode);
27853 switch (opc) {
27854 case MMI_OPC_0_PADDW: /* TODO: MMI_OPC_0_PADDW */
27855 case MMI_OPC_0_PSUBW: /* TODO: MMI_OPC_0_PSUBW */
27856 case MMI_OPC_0_PCGTW: /* TODO: MMI_OPC_0_PCGTW */
27857 case MMI_OPC_0_PMAXW: /* TODO: MMI_OPC_0_PMAXW */
27858 case MMI_OPC_0_PADDH: /* TODO: MMI_OPC_0_PADDH */
27859 case MMI_OPC_0_PSUBH: /* TODO: MMI_OPC_0_PSUBH */
27860 case MMI_OPC_0_PCGTH: /* TODO: MMI_OPC_0_PCGTH */
27861 case MMI_OPC_0_PMAXH: /* TODO: MMI_OPC_0_PMAXH */
27862 case MMI_OPC_0_PADDB: /* TODO: MMI_OPC_0_PADDB */
27863 case MMI_OPC_0_PSUBB: /* TODO: MMI_OPC_0_PSUBB */
27864 case MMI_OPC_0_PCGTB: /* TODO: MMI_OPC_0_PCGTB */
27865 case MMI_OPC_0_PADDSW: /* TODO: MMI_OPC_0_PADDSW */
27866 case MMI_OPC_0_PSUBSW: /* TODO: MMI_OPC_0_PSUBSW */
27867 case MMI_OPC_0_PEXTLW: /* TODO: MMI_OPC_0_PEXTLW */
27868 case MMI_OPC_0_PPACW: /* TODO: MMI_OPC_0_PPACW */
27869 case MMI_OPC_0_PADDSH: /* TODO: MMI_OPC_0_PADDSH */
27870 case MMI_OPC_0_PSUBSH: /* TODO: MMI_OPC_0_PSUBSH */
27871 case MMI_OPC_0_PEXTLH: /* TODO: MMI_OPC_0_PEXTLH */
27872 case MMI_OPC_0_PPACH: /* TODO: MMI_OPC_0_PPACH */
27873 case MMI_OPC_0_PADDSB: /* TODO: MMI_OPC_0_PADDSB */
27874 case MMI_OPC_0_PSUBSB: /* TODO: MMI_OPC_0_PSUBSB */
27875 case MMI_OPC_0_PEXTLB: /* TODO: MMI_OPC_0_PEXTLB */
27876 case MMI_OPC_0_PPACB: /* TODO: MMI_OPC_0_PPACB */
27877 case MMI_OPC_0_PEXT5: /* TODO: MMI_OPC_0_PEXT5 */
27878 case MMI_OPC_0_PPAC5: /* TODO: MMI_OPC_0_PPAC5 */
27879 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI0 */
27880 break;
27881 default:
27882 MIPS_INVAL("TX79 MMI class MMI0");
27883 gen_reserved_instruction(ctx);
27884 break;
27888 static void decode_mmi1(CPUMIPSState *env, DisasContext *ctx)
27890 uint32_t opc = MASK_MMI1(ctx->opcode);
27892 switch (opc) {
27893 case MMI_OPC_1_PABSW: /* TODO: MMI_OPC_1_PABSW */
27894 case MMI_OPC_1_PCEQW: /* TODO: MMI_OPC_1_PCEQW */
27895 case MMI_OPC_1_PMINW: /* TODO: MMI_OPC_1_PMINW */
27896 case MMI_OPC_1_PADSBH: /* TODO: MMI_OPC_1_PADSBH */
27897 case MMI_OPC_1_PABSH: /* TODO: MMI_OPC_1_PABSH */
27898 case MMI_OPC_1_PCEQH: /* TODO: MMI_OPC_1_PCEQH */
27899 case MMI_OPC_1_PMINH: /* TODO: MMI_OPC_1_PMINH */
27900 case MMI_OPC_1_PCEQB: /* TODO: MMI_OPC_1_PCEQB */
27901 case MMI_OPC_1_PADDUW: /* TODO: MMI_OPC_1_PADDUW */
27902 case MMI_OPC_1_PSUBUW: /* TODO: MMI_OPC_1_PSUBUW */
27903 case MMI_OPC_1_PEXTUW: /* TODO: MMI_OPC_1_PEXTUW */
27904 case MMI_OPC_1_PADDUH: /* TODO: MMI_OPC_1_PADDUH */
27905 case MMI_OPC_1_PSUBUH: /* TODO: MMI_OPC_1_PSUBUH */
27906 case MMI_OPC_1_PEXTUH: /* TODO: MMI_OPC_1_PEXTUH */
27907 case MMI_OPC_1_PADDUB: /* TODO: MMI_OPC_1_PADDUB */
27908 case MMI_OPC_1_PSUBUB: /* TODO: MMI_OPC_1_PSUBUB */
27909 case MMI_OPC_1_PEXTUB: /* TODO: MMI_OPC_1_PEXTUB */
27910 case MMI_OPC_1_QFSRV: /* TODO: MMI_OPC_1_QFSRV */
27911 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI1 */
27912 break;
27913 default:
27914 MIPS_INVAL("TX79 MMI class MMI1");
27915 gen_reserved_instruction(ctx);
27916 break;
27920 static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx)
27922 uint32_t opc = MASK_MMI2(ctx->opcode);
27924 switch (opc) {
27925 case MMI_OPC_2_PMADDW: /* TODO: MMI_OPC_2_PMADDW */
27926 case MMI_OPC_2_PSLLVW: /* TODO: MMI_OPC_2_PSLLVW */
27927 case MMI_OPC_2_PSRLVW: /* TODO: MMI_OPC_2_PSRLVW */
27928 case MMI_OPC_2_PMSUBW: /* TODO: MMI_OPC_2_PMSUBW */
27929 case MMI_OPC_2_PMFHI: /* TODO: MMI_OPC_2_PMFHI */
27930 case MMI_OPC_2_PMFLO: /* TODO: MMI_OPC_2_PMFLO */
27931 case MMI_OPC_2_PINTH: /* TODO: MMI_OPC_2_PINTH */
27932 case MMI_OPC_2_PMULTW: /* TODO: MMI_OPC_2_PMULTW */
27933 case MMI_OPC_2_PDIVW: /* TODO: MMI_OPC_2_PDIVW */
27934 case MMI_OPC_2_PMADDH: /* TODO: MMI_OPC_2_PMADDH */
27935 case MMI_OPC_2_PHMADH: /* TODO: MMI_OPC_2_PHMADH */
27936 case MMI_OPC_2_PAND: /* TODO: MMI_OPC_2_PAND */
27937 case MMI_OPC_2_PXOR: /* TODO: MMI_OPC_2_PXOR */
27938 case MMI_OPC_2_PMSUBH: /* TODO: MMI_OPC_2_PMSUBH */
27939 case MMI_OPC_2_PHMSBH: /* TODO: MMI_OPC_2_PHMSBH */
27940 case MMI_OPC_2_PEXEH: /* TODO: MMI_OPC_2_PEXEH */
27941 case MMI_OPC_2_PREVH: /* TODO: MMI_OPC_2_PREVH */
27942 case MMI_OPC_2_PMULTH: /* TODO: MMI_OPC_2_PMULTH */
27943 case MMI_OPC_2_PDIVBW: /* TODO: MMI_OPC_2_PDIVBW */
27944 case MMI_OPC_2_PEXEW: /* TODO: MMI_OPC_2_PEXEW */
27945 case MMI_OPC_2_PROT3W: /* TODO: MMI_OPC_2_PROT3W */
27946 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI2 */
27947 break;
27948 case MMI_OPC_2_PCPYLD:
27949 gen_mmi_pcpyld(ctx);
27950 break;
27951 default:
27952 MIPS_INVAL("TX79 MMI class MMI2");
27953 gen_reserved_instruction(ctx);
27954 break;
27958 static void decode_mmi3(CPUMIPSState *env, DisasContext *ctx)
27960 uint32_t opc = MASK_MMI3(ctx->opcode);
27962 switch (opc) {
27963 case MMI_OPC_3_PMADDUW: /* TODO: MMI_OPC_3_PMADDUW */
27964 case MMI_OPC_3_PSRAVW: /* TODO: MMI_OPC_3_PSRAVW */
27965 case MMI_OPC_3_PMTHI: /* TODO: MMI_OPC_3_PMTHI */
27966 case MMI_OPC_3_PMTLO: /* TODO: MMI_OPC_3_PMTLO */
27967 case MMI_OPC_3_PINTEH: /* TODO: MMI_OPC_3_PINTEH */
27968 case MMI_OPC_3_PMULTUW: /* TODO: MMI_OPC_3_PMULTUW */
27969 case MMI_OPC_3_PDIVUW: /* TODO: MMI_OPC_3_PDIVUW */
27970 case MMI_OPC_3_POR: /* TODO: MMI_OPC_3_POR */
27971 case MMI_OPC_3_PNOR: /* TODO: MMI_OPC_3_PNOR */
27972 case MMI_OPC_3_PEXCH: /* TODO: MMI_OPC_3_PEXCH */
27973 case MMI_OPC_3_PEXCW: /* TODO: MMI_OPC_3_PEXCW */
27974 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI3 */
27975 break;
27976 case MMI_OPC_3_PCPYH:
27977 gen_mmi_pcpyh(ctx);
27978 break;
27979 case MMI_OPC_3_PCPYUD:
27980 gen_mmi_pcpyud(ctx);
27981 break;
27982 default:
27983 MIPS_INVAL("TX79 MMI class MMI3");
27984 gen_reserved_instruction(ctx);
27985 break;
27989 static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
27991 uint32_t opc = MASK_MMI(ctx->opcode);
27992 int rs = extract32(ctx->opcode, 21, 5);
27993 int rt = extract32(ctx->opcode, 16, 5);
27994 int rd = extract32(ctx->opcode, 11, 5);
27996 switch (opc) {
27997 case MMI_OPC_CLASS_MMI0:
27998 decode_mmi0(env, ctx);
27999 break;
28000 case MMI_OPC_CLASS_MMI1:
28001 decode_mmi1(env, ctx);
28002 break;
28003 case MMI_OPC_CLASS_MMI2:
28004 decode_mmi2(env, ctx);
28005 break;
28006 case MMI_OPC_CLASS_MMI3:
28007 decode_mmi3(env, ctx);
28008 break;
28009 case MMI_OPC_MULT1:
28010 case MMI_OPC_MULTU1:
28011 case MMI_OPC_MADD:
28012 case MMI_OPC_MADDU:
28013 case MMI_OPC_MADD1:
28014 case MMI_OPC_MADDU1:
28015 gen_mul_txx9(ctx, opc, rd, rs, rt);
28016 break;
28017 case MMI_OPC_DIV1:
28018 case MMI_OPC_DIVU1:
28019 gen_div1_tx79(ctx, opc, rs, rt);
28020 break;
28021 case MMI_OPC_MTLO1:
28022 case MMI_OPC_MTHI1:
28023 gen_HILO1_tx79(ctx, opc, rs);
28024 break;
28025 case MMI_OPC_MFLO1:
28026 case MMI_OPC_MFHI1:
28027 gen_HILO1_tx79(ctx, opc, rd);
28028 break;
28029 case MMI_OPC_PLZCW: /* TODO: MMI_OPC_PLZCW */
28030 case MMI_OPC_PMFHL: /* TODO: MMI_OPC_PMFHL */
28031 case MMI_OPC_PMTHL: /* TODO: MMI_OPC_PMTHL */
28032 case MMI_OPC_PSLLH: /* TODO: MMI_OPC_PSLLH */
28033 case MMI_OPC_PSRLH: /* TODO: MMI_OPC_PSRLH */
28034 case MMI_OPC_PSRAH: /* TODO: MMI_OPC_PSRAH */
28035 case MMI_OPC_PSLLW: /* TODO: MMI_OPC_PSLLW */
28036 case MMI_OPC_PSRLW: /* TODO: MMI_OPC_PSRLW */
28037 case MMI_OPC_PSRAW: /* TODO: MMI_OPC_PSRAW */
28038 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI */
28039 break;
28040 default:
28041 MIPS_INVAL("TX79 MMI class");
28042 gen_reserved_instruction(ctx);
28043 break;
28047 static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
28049 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_LQ */
28052 static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
28054 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_SQ */
28058 * The TX79-specific instruction Store Quadword
28060 * +--------+-------+-------+------------------------+
28061 * | 011111 | base | rt | offset | SQ
28062 * +--------+-------+-------+------------------------+
28063 * 6 5 5 16
28065 * has the same opcode as the Read Hardware Register instruction
28067 * +--------+-------+-------+-------+-------+--------+
28068 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
28069 * +--------+-------+-------+-------+-------+--------+
28070 * 6 5 5 5 5 6
28072 * that is required, trapped and emulated by the Linux kernel. However, all
28073 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
28074 * offset is odd. Therefore all valid SQ instructions can execute normally.
28075 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
28076 * between SQ and RDHWR, as the Linux kernel does.
28078 static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
28080 int base = extract32(ctx->opcode, 21, 5);
28081 int rt = extract32(ctx->opcode, 16, 5);
28082 int offset = extract32(ctx->opcode, 0, 16);
28084 #ifdef CONFIG_USER_ONLY
28085 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
28086 uint32_t op2 = extract32(ctx->opcode, 6, 5);
28088 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
28089 int rd = extract32(ctx->opcode, 11, 5);
28091 gen_rdhwr(ctx, rt, rd, 0);
28092 return;
28094 #endif
28096 gen_mmi_sq(ctx, base, rt, offset);
28099 #endif
28101 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
28103 int rs, rt, rd, sa;
28104 uint32_t op1, op2;
28105 int16_t imm;
28107 rs = (ctx->opcode >> 21) & 0x1f;
28108 rt = (ctx->opcode >> 16) & 0x1f;
28109 rd = (ctx->opcode >> 11) & 0x1f;
28110 sa = (ctx->opcode >> 6) & 0x1f;
28111 imm = sextract32(ctx->opcode, 7, 9);
28113 op1 = MASK_SPECIAL3(ctx->opcode);
28116 * EVA loads and stores overlap Loongson 2E instructions decoded by
28117 * decode_opc_special3_legacy(), so be careful to allow their decoding when
28118 * EVA is absent.
28120 if (ctx->eva) {
28121 switch (op1) {
28122 case OPC_LWLE:
28123 case OPC_LWRE:
28124 case OPC_LBUE:
28125 case OPC_LHUE:
28126 case OPC_LBE:
28127 case OPC_LHE:
28128 case OPC_LLE:
28129 case OPC_LWE:
28130 check_cp0_enabled(ctx);
28131 gen_ld(ctx, op1, rt, rs, imm);
28132 return;
28133 case OPC_SWLE:
28134 case OPC_SWRE:
28135 case OPC_SBE:
28136 case OPC_SHE:
28137 case OPC_SWE:
28138 check_cp0_enabled(ctx);
28139 gen_st(ctx, op1, rt, rs, imm);
28140 return;
28141 case OPC_SCE:
28142 check_cp0_enabled(ctx);
28143 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
28144 return;
28145 case OPC_CACHEE:
28146 check_cp0_enabled(ctx);
28147 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
28148 gen_cache_operation(ctx, rt, rs, imm);
28150 /* Treat as NOP. */
28151 return;
28152 case OPC_PREFE:
28153 check_cp0_enabled(ctx);
28154 /* Treat as NOP. */
28155 return;
28159 switch (op1) {
28160 case OPC_EXT:
28161 case OPC_INS:
28162 check_insn(ctx, ISA_MIPS_R2);
28163 gen_bitops(ctx, op1, rt, rs, sa, rd);
28164 break;
28165 case OPC_BSHFL:
28166 op2 = MASK_BSHFL(ctx->opcode);
28167 switch (op2) {
28168 case OPC_ALIGN:
28169 case OPC_ALIGN_1:
28170 case OPC_ALIGN_2:
28171 case OPC_ALIGN_3:
28172 case OPC_BITSWAP:
28173 check_insn(ctx, ISA_MIPS_R6);
28174 decode_opc_special3_r6(env, ctx);
28175 break;
28176 default:
28177 check_insn(ctx, ISA_MIPS_R2);
28178 gen_bshfl(ctx, op2, rt, rd);
28179 break;
28181 break;
28182 #if defined(TARGET_MIPS64)
28183 case OPC_DEXTM:
28184 case OPC_DEXTU:
28185 case OPC_DEXT:
28186 case OPC_DINSM:
28187 case OPC_DINSU:
28188 case OPC_DINS:
28189 check_insn(ctx, ISA_MIPS_R2);
28190 check_mips_64(ctx);
28191 gen_bitops(ctx, op1, rt, rs, sa, rd);
28192 break;
28193 case OPC_DBSHFL:
28194 op2 = MASK_DBSHFL(ctx->opcode);
28195 switch (op2) {
28196 case OPC_DALIGN:
28197 case OPC_DALIGN_1:
28198 case OPC_DALIGN_2:
28199 case OPC_DALIGN_3:
28200 case OPC_DALIGN_4:
28201 case OPC_DALIGN_5:
28202 case OPC_DALIGN_6:
28203 case OPC_DALIGN_7:
28204 case OPC_DBITSWAP:
28205 check_insn(ctx, ISA_MIPS_R6);
28206 decode_opc_special3_r6(env, ctx);
28207 break;
28208 default:
28209 check_insn(ctx, ISA_MIPS_R2);
28210 check_mips_64(ctx);
28211 op2 = MASK_DBSHFL(ctx->opcode);
28212 gen_bshfl(ctx, op2, rt, rd);
28213 break;
28215 break;
28216 #endif
28217 case OPC_RDHWR:
28218 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
28219 break;
28220 case OPC_FORK:
28221 check_mt(ctx);
28223 TCGv t0 = tcg_temp_new();
28224 TCGv t1 = tcg_temp_new();
28226 gen_load_gpr(t0, rt);
28227 gen_load_gpr(t1, rs);
28228 gen_helper_fork(t0, t1);
28229 tcg_temp_free(t0);
28230 tcg_temp_free(t1);
28232 break;
28233 case OPC_YIELD:
28234 check_mt(ctx);
28236 TCGv t0 = tcg_temp_new();
28238 gen_load_gpr(t0, rs);
28239 gen_helper_yield(t0, cpu_env, t0);
28240 gen_store_gpr(t0, rd);
28241 tcg_temp_free(t0);
28243 break;
28244 default:
28245 if (ctx->insn_flags & ISA_MIPS_R6) {
28246 decode_opc_special3_r6(env, ctx);
28247 } else {
28248 decode_opc_special3_legacy(env, ctx);
28253 static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx)
28255 int32_t offset;
28256 int rs, rt, rd, sa;
28257 uint32_t op, op1;
28258 int16_t imm;
28260 op = MASK_OP_MAJOR(ctx->opcode);
28261 rs = (ctx->opcode >> 21) & 0x1f;
28262 rt = (ctx->opcode >> 16) & 0x1f;
28263 rd = (ctx->opcode >> 11) & 0x1f;
28264 sa = (ctx->opcode >> 6) & 0x1f;
28265 imm = (int16_t)ctx->opcode;
28266 switch (op) {
28267 case OPC_SPECIAL:
28268 decode_opc_special(env, ctx);
28269 break;
28270 case OPC_SPECIAL2:
28271 #if defined(TARGET_MIPS64)
28272 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
28273 decode_mmi(env, ctx);
28274 #else
28275 if (ctx->insn_flags & ASE_MXU) {
28276 decode_opc_mxu(env, ctx);
28277 #endif
28278 } else {
28279 decode_opc_special2_legacy(env, ctx);
28281 break;
28282 case OPC_SPECIAL3:
28283 #if defined(TARGET_MIPS64)
28284 if (ctx->insn_flags & INSN_R5900) {
28285 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
28286 } else {
28287 decode_opc_special3(env, ctx);
28289 #else
28290 decode_opc_special3(env, ctx);
28291 #endif
28292 break;
28293 case OPC_REGIMM:
28294 op1 = MASK_REGIMM(ctx->opcode);
28295 switch (op1) {
28296 case OPC_BLTZL: /* REGIMM branches */
28297 case OPC_BGEZL:
28298 case OPC_BLTZALL:
28299 case OPC_BGEZALL:
28300 check_insn(ctx, ISA_MIPS2);
28301 check_insn_opc_removed(ctx, ISA_MIPS_R6);
28302 /* Fallthrough */
28303 case OPC_BLTZ:
28304 case OPC_BGEZ:
28305 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
28306 break;
28307 case OPC_BLTZAL:
28308 case OPC_BGEZAL:
28309 if (ctx->insn_flags & ISA_MIPS_R6) {
28310 if (rs == 0) {
28311 /* OPC_NAL, OPC_BAL */
28312 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
28313 } else {
28314 gen_reserved_instruction(ctx);
28316 } else {
28317 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
28319 break;
28320 case OPC_TGEI: /* REGIMM traps */
28321 case OPC_TGEIU:
28322 case OPC_TLTI:
28323 case OPC_TLTIU:
28324 case OPC_TEQI:
28326 case OPC_TNEI:
28327 check_insn(ctx, ISA_MIPS2);
28328 check_insn_opc_removed(ctx, ISA_MIPS_R6);
28329 gen_trap(ctx, op1, rs, -1, imm);
28330 break;
28331 case OPC_SIGRIE:
28332 check_insn(ctx, ISA_MIPS_R6);
28333 gen_reserved_instruction(ctx);
28334 break;
28335 case OPC_SYNCI:
28336 check_insn(ctx, ISA_MIPS_R2);
28338 * Break the TB to be able to sync copied instructions
28339 * immediately.
28341 ctx->base.is_jmp = DISAS_STOP;
28342 break;
28343 case OPC_BPOSGE32: /* MIPS DSP branch */
28344 #if defined(TARGET_MIPS64)
28345 case OPC_BPOSGE64:
28346 #endif
28347 check_dsp(ctx);
28348 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
28349 break;
28350 #if defined(TARGET_MIPS64)
28351 case OPC_DAHI:
28352 check_insn(ctx, ISA_MIPS_R6);
28353 check_mips_64(ctx);
28354 if (rs != 0) {
28355 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
28357 break;
28358 case OPC_DATI:
28359 check_insn(ctx, ISA_MIPS_R6);
28360 check_mips_64(ctx);
28361 if (rs != 0) {
28362 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
28364 break;
28365 #endif
28366 default: /* Invalid */
28367 MIPS_INVAL("regimm");
28368 gen_reserved_instruction(ctx);
28369 break;
28371 break;
28372 case OPC_CP0:
28373 check_cp0_enabled(ctx);
28374 op1 = MASK_CP0(ctx->opcode);
28375 switch (op1) {
28376 case OPC_MFC0:
28377 case OPC_MTC0:
28378 case OPC_MFTR:
28379 case OPC_MTTR:
28380 case OPC_MFHC0:
28381 case OPC_MTHC0:
28382 #if defined(TARGET_MIPS64)
28383 case OPC_DMFC0:
28384 case OPC_DMTC0:
28385 #endif
28386 #ifndef CONFIG_USER_ONLY
28387 gen_cp0(env, ctx, op1, rt, rd);
28388 #endif /* !CONFIG_USER_ONLY */
28389 break;
28390 case OPC_C0:
28391 case OPC_C0_1:
28392 case OPC_C0_2:
28393 case OPC_C0_3:
28394 case OPC_C0_4:
28395 case OPC_C0_5:
28396 case OPC_C0_6:
28397 case OPC_C0_7:
28398 case OPC_C0_8:
28399 case OPC_C0_9:
28400 case OPC_C0_A:
28401 case OPC_C0_B:
28402 case OPC_C0_C:
28403 case OPC_C0_D:
28404 case OPC_C0_E:
28405 case OPC_C0_F:
28406 #ifndef CONFIG_USER_ONLY
28407 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
28408 #endif /* !CONFIG_USER_ONLY */
28409 break;
28410 case OPC_MFMC0:
28411 #ifndef CONFIG_USER_ONLY
28413 uint32_t op2;
28414 TCGv t0 = tcg_temp_new();
28416 op2 = MASK_MFMC0(ctx->opcode);
28417 switch (op2) {
28418 case OPC_DMT:
28419 check_cp0_mt(ctx);
28420 gen_helper_dmt(t0);
28421 gen_store_gpr(t0, rt);
28422 break;
28423 case OPC_EMT:
28424 check_cp0_mt(ctx);
28425 gen_helper_emt(t0);
28426 gen_store_gpr(t0, rt);
28427 break;
28428 case OPC_DVPE:
28429 check_cp0_mt(ctx);
28430 gen_helper_dvpe(t0, cpu_env);
28431 gen_store_gpr(t0, rt);
28432 break;
28433 case OPC_EVPE:
28434 check_cp0_mt(ctx);
28435 gen_helper_evpe(t0, cpu_env);
28436 gen_store_gpr(t0, rt);
28437 break;
28438 case OPC_DVP:
28439 check_insn(ctx, ISA_MIPS_R6);
28440 if (ctx->vp) {
28441 gen_helper_dvp(t0, cpu_env);
28442 gen_store_gpr(t0, rt);
28444 break;
28445 case OPC_EVP:
28446 check_insn(ctx, ISA_MIPS_R6);
28447 if (ctx->vp) {
28448 gen_helper_evp(t0, cpu_env);
28449 gen_store_gpr(t0, rt);
28451 break;
28452 case OPC_DI:
28453 check_insn(ctx, ISA_MIPS_R2);
28454 save_cpu_state(ctx, 1);
28455 gen_helper_di(t0, cpu_env);
28456 gen_store_gpr(t0, rt);
28458 * Stop translation as we may have switched
28459 * the execution mode.
28461 ctx->base.is_jmp = DISAS_STOP;
28462 break;
28463 case OPC_EI:
28464 check_insn(ctx, ISA_MIPS_R2);
28465 save_cpu_state(ctx, 1);
28466 gen_helper_ei(t0, cpu_env);
28467 gen_store_gpr(t0, rt);
28469 * DISAS_STOP isn't sufficient, we need to ensure we break
28470 * out of translated code to check for pending interrupts.
28472 gen_save_pc(ctx->base.pc_next + 4);
28473 ctx->base.is_jmp = DISAS_EXIT;
28474 break;
28475 default: /* Invalid */
28476 MIPS_INVAL("mfmc0");
28477 gen_reserved_instruction(ctx);
28478 break;
28480 tcg_temp_free(t0);
28482 #endif /* !CONFIG_USER_ONLY */
28483 break;
28484 case OPC_RDPGPR:
28485 check_insn(ctx, ISA_MIPS_R2);
28486 gen_load_srsgpr(rt, rd);
28487 break;
28488 case OPC_WRPGPR:
28489 check_insn(ctx, ISA_MIPS_R2);
28490 gen_store_srsgpr(rt, rd);
28491 break;
28492 default:
28493 MIPS_INVAL("cp0");
28494 gen_reserved_instruction(ctx);
28495 break;
28497 break;
28498 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
28499 if (ctx->insn_flags & ISA_MIPS_R6) {
28500 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
28501 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
28502 } else {
28503 /* OPC_ADDI */
28504 /* Arithmetic with immediate opcode */
28505 gen_arith_imm(ctx, op, rt, rs, imm);
28507 break;
28508 case OPC_ADDIU:
28509 gen_arith_imm(ctx, op, rt, rs, imm);
28510 break;
28511 case OPC_SLTI: /* Set on less than with immediate opcode */
28512 case OPC_SLTIU:
28513 gen_slt_imm(ctx, op, rt, rs, imm);
28514 break;
28515 case OPC_ANDI: /* Arithmetic with immediate opcode */
28516 case OPC_LUI: /* OPC_AUI */
28517 case OPC_ORI:
28518 case OPC_XORI:
28519 gen_logic_imm(ctx, op, rt, rs, imm);
28520 break;
28521 case OPC_J: /* Jump */
28522 case OPC_JAL:
28523 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
28524 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
28525 break;
28526 /* Branch */
28527 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
28528 if (ctx->insn_flags & ISA_MIPS_R6) {
28529 if (rt == 0) {
28530 gen_reserved_instruction(ctx);
28531 break;
28533 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
28534 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
28535 } else {
28536 /* OPC_BLEZL */
28537 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
28539 break;
28540 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
28541 if (ctx->insn_flags & ISA_MIPS_R6) {
28542 if (rt == 0) {
28543 gen_reserved_instruction(ctx);
28544 break;
28546 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
28547 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
28548 } else {
28549 /* OPC_BGTZL */
28550 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
28552 break;
28553 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
28554 if (rt == 0) {
28555 /* OPC_BLEZ */
28556 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
28557 } else {
28558 check_insn(ctx, ISA_MIPS_R6);
28559 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
28560 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
28562 break;
28563 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
28564 if (rt == 0) {
28565 /* OPC_BGTZ */
28566 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
28567 } else {
28568 check_insn(ctx, ISA_MIPS_R6);
28569 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
28570 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
28572 break;
28573 case OPC_BEQL:
28574 case OPC_BNEL:
28575 check_insn(ctx, ISA_MIPS2);
28576 check_insn_opc_removed(ctx, ISA_MIPS_R6);
28577 /* Fallthrough */
28578 case OPC_BEQ:
28579 case OPC_BNE:
28580 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
28581 break;
28582 case OPC_LL: /* Load and stores */
28583 check_insn(ctx, ISA_MIPS2);
28584 if (ctx->insn_flags & INSN_R5900) {
28585 check_insn_opc_user_only(ctx, INSN_R5900);
28587 /* Fallthrough */
28588 case OPC_LWL:
28589 case OPC_LWR:
28590 case OPC_LB:
28591 case OPC_LH:
28592 case OPC_LW:
28593 case OPC_LWPC:
28594 case OPC_LBU:
28595 case OPC_LHU:
28596 gen_ld(ctx, op, rt, rs, imm);
28597 break;
28598 case OPC_SWL:
28599 case OPC_SWR:
28600 case OPC_SB:
28601 case OPC_SH:
28602 case OPC_SW:
28603 gen_st(ctx, op, rt, rs, imm);
28604 break;
28605 case OPC_SC:
28606 check_insn(ctx, ISA_MIPS2);
28607 if (ctx->insn_flags & INSN_R5900) {
28608 check_insn_opc_user_only(ctx, INSN_R5900);
28610 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
28611 break;
28612 case OPC_CACHE:
28613 check_cp0_enabled(ctx);
28614 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
28615 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
28616 gen_cache_operation(ctx, rt, rs, imm);
28618 /* Treat as NOP. */
28619 break;
28620 case OPC_PREF:
28621 if (ctx->insn_flags & INSN_R5900) {
28622 /* Treat as NOP. */
28623 } else {
28624 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
28625 /* Treat as NOP. */
28627 break;
28629 /* Floating point (COP1). */
28630 case OPC_LWC1:
28631 case OPC_LDC1:
28632 case OPC_SWC1:
28633 case OPC_SDC1:
28634 gen_cop1_ldst(ctx, op, rt, rs, imm);
28635 break;
28637 case OPC_CP1:
28638 op1 = MASK_CP1(ctx->opcode);
28640 switch (op1) {
28641 case OPC_MFHC1:
28642 case OPC_MTHC1:
28643 check_cp1_enabled(ctx);
28644 check_insn(ctx, ISA_MIPS_R2);
28645 /* fall through */
28646 case OPC_MFC1:
28647 case OPC_CFC1:
28648 case OPC_MTC1:
28649 case OPC_CTC1:
28650 check_cp1_enabled(ctx);
28651 gen_cp1(ctx, op1, rt, rd);
28652 break;
28653 #if defined(TARGET_MIPS64)
28654 case OPC_DMFC1:
28655 case OPC_DMTC1:
28656 check_cp1_enabled(ctx);
28657 check_insn(ctx, ISA_MIPS3);
28658 check_mips_64(ctx);
28659 gen_cp1(ctx, op1, rt, rd);
28660 break;
28661 #endif
28662 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
28663 check_cp1_enabled(ctx);
28664 if (ctx->insn_flags & ISA_MIPS_R6) {
28665 /* OPC_BC1EQZ */
28666 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
28667 rt, imm << 2, 4);
28668 } else {
28669 /* OPC_BC1ANY2 */
28670 check_cop1x(ctx);
28671 check_insn(ctx, ASE_MIPS3D);
28672 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
28673 (rt >> 2) & 0x7, imm << 2);
28675 break;
28676 case OPC_BC1NEZ:
28677 check_cp1_enabled(ctx);
28678 check_insn(ctx, ISA_MIPS_R6);
28679 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
28680 rt, imm << 2, 4);
28681 break;
28682 case OPC_BC1ANY4:
28683 check_cp1_enabled(ctx);
28684 check_insn_opc_removed(ctx, ISA_MIPS_R6);
28685 check_cop1x(ctx);
28686 check_insn(ctx, ASE_MIPS3D);
28687 /* fall through */
28688 case OPC_BC1:
28689 check_cp1_enabled(ctx);
28690 check_insn_opc_removed(ctx, ISA_MIPS_R6);
28691 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
28692 (rt >> 2) & 0x7, imm << 2);
28693 break;
28694 case OPC_PS_FMT:
28695 check_ps(ctx);
28696 /* fall through */
28697 case OPC_S_FMT:
28698 case OPC_D_FMT:
28699 check_cp1_enabled(ctx);
28700 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
28701 (imm >> 8) & 0x7);
28702 break;
28703 case OPC_W_FMT:
28704 case OPC_L_FMT:
28706 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
28707 check_cp1_enabled(ctx);
28708 if (ctx->insn_flags & ISA_MIPS_R6) {
28709 switch (r6_op) {
28710 case R6_OPC_CMP_AF_S:
28711 case R6_OPC_CMP_UN_S:
28712 case R6_OPC_CMP_EQ_S:
28713 case R6_OPC_CMP_UEQ_S:
28714 case R6_OPC_CMP_LT_S:
28715 case R6_OPC_CMP_ULT_S:
28716 case R6_OPC_CMP_LE_S:
28717 case R6_OPC_CMP_ULE_S:
28718 case R6_OPC_CMP_SAF_S:
28719 case R6_OPC_CMP_SUN_S:
28720 case R6_OPC_CMP_SEQ_S:
28721 case R6_OPC_CMP_SEUQ_S:
28722 case R6_OPC_CMP_SLT_S:
28723 case R6_OPC_CMP_SULT_S:
28724 case R6_OPC_CMP_SLE_S:
28725 case R6_OPC_CMP_SULE_S:
28726 case R6_OPC_CMP_OR_S:
28727 case R6_OPC_CMP_UNE_S:
28728 case R6_OPC_CMP_NE_S:
28729 case R6_OPC_CMP_SOR_S:
28730 case R6_OPC_CMP_SUNE_S:
28731 case R6_OPC_CMP_SNE_S:
28732 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
28733 break;
28734 case R6_OPC_CMP_AF_D:
28735 case R6_OPC_CMP_UN_D:
28736 case R6_OPC_CMP_EQ_D:
28737 case R6_OPC_CMP_UEQ_D:
28738 case R6_OPC_CMP_LT_D:
28739 case R6_OPC_CMP_ULT_D:
28740 case R6_OPC_CMP_LE_D:
28741 case R6_OPC_CMP_ULE_D:
28742 case R6_OPC_CMP_SAF_D:
28743 case R6_OPC_CMP_SUN_D:
28744 case R6_OPC_CMP_SEQ_D:
28745 case R6_OPC_CMP_SEUQ_D:
28746 case R6_OPC_CMP_SLT_D:
28747 case R6_OPC_CMP_SULT_D:
28748 case R6_OPC_CMP_SLE_D:
28749 case R6_OPC_CMP_SULE_D:
28750 case R6_OPC_CMP_OR_D:
28751 case R6_OPC_CMP_UNE_D:
28752 case R6_OPC_CMP_NE_D:
28753 case R6_OPC_CMP_SOR_D:
28754 case R6_OPC_CMP_SUNE_D:
28755 case R6_OPC_CMP_SNE_D:
28756 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
28757 break;
28758 default:
28759 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
28760 rt, rd, sa, (imm >> 8) & 0x7);
28762 break;
28764 } else {
28765 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
28766 (imm >> 8) & 0x7);
28768 break;
28770 default:
28771 MIPS_INVAL("cp1");
28772 gen_reserved_instruction(ctx);
28773 break;
28775 break;
28777 /* Compact branches [R6] and COP2 [non-R6] */
28778 case OPC_BC: /* OPC_LWC2 */
28779 case OPC_BALC: /* OPC_SWC2 */
28780 if (ctx->insn_flags & ISA_MIPS_R6) {
28781 /* OPC_BC, OPC_BALC */
28782 gen_compute_compact_branch(ctx, op, 0, 0,
28783 sextract32(ctx->opcode << 2, 0, 28));
28784 } else if (ctx->insn_flags & ASE_LEXT) {
28785 gen_loongson_lswc2(ctx, rt, rs, rd);
28786 } else {
28787 /* OPC_LWC2, OPC_SWC2 */
28788 /* COP2: Not implemented. */
28789 generate_exception_err(ctx, EXCP_CpU, 2);
28791 break;
28792 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
28793 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
28794 if (ctx->insn_flags & ISA_MIPS_R6) {
28795 if (rs != 0) {
28796 /* OPC_BEQZC, OPC_BNEZC */
28797 gen_compute_compact_branch(ctx, op, rs, 0,
28798 sextract32(ctx->opcode << 2, 0, 23));
28799 } else {
28800 /* OPC_JIC, OPC_JIALC */
28801 gen_compute_compact_branch(ctx, op, 0, rt, imm);
28803 } else if (ctx->insn_flags & ASE_LEXT) {
28804 gen_loongson_lsdc2(ctx, rt, rs, rd);
28805 } else {
28806 /* OPC_LWC2, OPC_SWC2 */
28807 /* COP2: Not implemented. */
28808 generate_exception_err(ctx, EXCP_CpU, 2);
28810 break;
28811 case OPC_CP2:
28812 check_insn(ctx, ASE_LMMI);
28813 /* Note that these instructions use different fields. */
28814 gen_loongson_multimedia(ctx, sa, rd, rt);
28815 break;
28817 case OPC_CP3:
28818 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
28819 check_cp1_enabled(ctx);
28820 op1 = MASK_CP3(ctx->opcode);
28821 switch (op1) {
28822 case OPC_LUXC1:
28823 case OPC_SUXC1:
28824 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
28825 /* Fallthrough */
28826 case OPC_LWXC1:
28827 case OPC_LDXC1:
28828 case OPC_SWXC1:
28829 case OPC_SDXC1:
28830 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
28831 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
28832 break;
28833 case OPC_PREFX:
28834 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
28835 /* Treat as NOP. */
28836 break;
28837 case OPC_ALNV_PS:
28838 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
28839 /* Fallthrough */
28840 case OPC_MADD_S:
28841 case OPC_MADD_D:
28842 case OPC_MADD_PS:
28843 case OPC_MSUB_S:
28844 case OPC_MSUB_D:
28845 case OPC_MSUB_PS:
28846 case OPC_NMADD_S:
28847 case OPC_NMADD_D:
28848 case OPC_NMADD_PS:
28849 case OPC_NMSUB_S:
28850 case OPC_NMSUB_D:
28851 case OPC_NMSUB_PS:
28852 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
28853 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
28854 break;
28855 default:
28856 MIPS_INVAL("cp3");
28857 gen_reserved_instruction(ctx);
28858 break;
28860 } else {
28861 generate_exception_err(ctx, EXCP_CpU, 1);
28863 break;
28865 #if defined(TARGET_MIPS64)
28866 /* MIPS64 opcodes */
28867 case OPC_LLD:
28868 if (ctx->insn_flags & INSN_R5900) {
28869 check_insn_opc_user_only(ctx, INSN_R5900);
28871 /* fall through */
28872 case OPC_LDL:
28873 case OPC_LDR:
28874 case OPC_LWU:
28875 case OPC_LD:
28876 check_insn(ctx, ISA_MIPS3);
28877 check_mips_64(ctx);
28878 gen_ld(ctx, op, rt, rs, imm);
28879 break;
28880 case OPC_SDL:
28881 case OPC_SDR:
28882 case OPC_SD:
28883 check_insn(ctx, ISA_MIPS3);
28884 check_mips_64(ctx);
28885 gen_st(ctx, op, rt, rs, imm);
28886 break;
28887 case OPC_SCD:
28888 check_insn(ctx, ISA_MIPS3);
28889 if (ctx->insn_flags & INSN_R5900) {
28890 check_insn_opc_user_only(ctx, INSN_R5900);
28892 check_mips_64(ctx);
28893 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
28894 break;
28895 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
28896 if (ctx->insn_flags & ISA_MIPS_R6) {
28897 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
28898 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
28899 } else {
28900 /* OPC_DADDI */
28901 check_insn(ctx, ISA_MIPS3);
28902 check_mips_64(ctx);
28903 gen_arith_imm(ctx, op, rt, rs, imm);
28905 break;
28906 case OPC_DADDIU:
28907 check_insn(ctx, ISA_MIPS3);
28908 check_mips_64(ctx);
28909 gen_arith_imm(ctx, op, rt, rs, imm);
28910 break;
28911 #else
28912 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
28913 if (ctx->insn_flags & ISA_MIPS_R6) {
28914 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
28915 } else {
28916 MIPS_INVAL("major opcode");
28917 gen_reserved_instruction(ctx);
28919 break;
28920 #endif
28921 case OPC_DAUI: /* OPC_JALX */
28922 if (ctx->insn_flags & ISA_MIPS_R6) {
28923 #if defined(TARGET_MIPS64)
28924 /* OPC_DAUI */
28925 check_mips_64(ctx);
28926 if (rs == 0) {
28927 generate_exception(ctx, EXCP_RI);
28928 } else if (rt != 0) {
28929 TCGv t0 = tcg_temp_new();
28930 gen_load_gpr(t0, rs);
28931 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
28932 tcg_temp_free(t0);
28934 #else
28935 gen_reserved_instruction(ctx);
28936 MIPS_INVAL("major opcode");
28937 #endif
28938 } else {
28939 /* OPC_JALX */
28940 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
28941 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
28942 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
28944 break;
28945 case OPC_MDMX: /* MMI_OPC_LQ */
28946 if (ctx->insn_flags & INSN_R5900) {
28947 #if defined(TARGET_MIPS64)
28948 gen_mmi_lq(env, ctx);
28949 #endif
28950 } else {
28951 /* MDMX: Not implemented. */
28953 break;
28954 case OPC_PCREL:
28955 check_insn(ctx, ISA_MIPS_R6);
28956 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
28957 break;
28958 default: /* Invalid */
28959 MIPS_INVAL("major opcode");
28960 return false;
28962 return true;
28965 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
28967 /* make sure instructions are on a word boundary */
28968 if (ctx->base.pc_next & 0x3) {
28969 env->CP0_BadVAddr = ctx->base.pc_next;
28970 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
28971 return;
28974 /* Handle blikely not taken case */
28975 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
28976 TCGLabel *l1 = gen_new_label();
28978 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
28979 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
28980 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
28981 gen_set_label(l1);
28984 /* Transition to the auto-generated decoder. */
28986 /* ISA extensions */
28987 if (ase_msa_available(env) && decode_ase_msa(ctx, ctx->opcode)) {
28988 return;
28991 /* ISA (from latest to oldest) */
28992 if (cpu_supports_isa(env, ISA_MIPS_R6) && decode_isa_rel6(ctx, ctx->opcode)) {
28993 return;
28996 if (decode_opc_legacy(env, ctx)) {
28997 return;
29000 gen_reserved_instruction(ctx);
29003 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
29005 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29006 CPUMIPSState *env = cs->env_ptr;
29008 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
29009 ctx->saved_pc = -1;
29010 ctx->insn_flags = env->insn_flags;
29011 ctx->CP0_Config1 = env->CP0_Config1;
29012 ctx->CP0_Config2 = env->CP0_Config2;
29013 ctx->CP0_Config3 = env->CP0_Config3;
29014 ctx->CP0_Config5 = env->CP0_Config5;
29015 ctx->btarget = 0;
29016 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
29017 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
29018 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
29019 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
29020 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
29021 ctx->PAMask = env->PAMask;
29022 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
29023 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
29024 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
29025 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
29026 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
29027 /* Restore delay slot state from the tb context. */
29028 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
29029 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
29030 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
29031 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
29032 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
29033 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
29034 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
29035 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
29036 ctx->mi = (env->CP0_Config5 >> CP0C5_MI) & 1;
29037 ctx->gi = (env->CP0_Config5 >> CP0C5_GI) & 3;
29038 restore_cpu_state(env, ctx);
29039 #ifdef CONFIG_USER_ONLY
29040 ctx->mem_idx = MIPS_HFLAG_UM;
29041 #else
29042 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
29043 #endif
29044 ctx->default_tcg_memop_mask = (ctx->insn_flags & (ISA_MIPS_R6 |
29045 INSN_LOONGSON3A)) ? MO_UNALN : MO_ALIGN;
29047 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
29048 ctx->hflags);
29051 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
29055 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
29057 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29059 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
29060 ctx->btarget);
29063 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
29064 const CPUBreakpoint *bp)
29066 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29068 save_cpu_state(ctx, 1);
29069 ctx->base.is_jmp = DISAS_NORETURN;
29070 gen_helper_raise_exception_debug(cpu_env);
29072 * The address covered by the breakpoint must be included in
29073 * [tb->pc, tb->pc + tb->size) in order to for it to be
29074 * properly cleared -- thus we increment the PC here so that
29075 * the logic setting tb->size below does the right thing.
29077 ctx->base.pc_next += 4;
29078 return true;
29081 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
29083 CPUMIPSState *env = cs->env_ptr;
29084 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29085 int insn_bytes;
29086 int is_slot;
29088 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
29089 if (ctx->insn_flags & ISA_NANOMIPS32) {
29090 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
29091 insn_bytes = decode_nanomips_opc(env, ctx);
29092 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
29093 ctx->opcode = translator_ldl(env, ctx->base.pc_next);
29094 insn_bytes = 4;
29095 decode_opc(env, ctx);
29096 } else if (ctx->insn_flags & ASE_MICROMIPS) {
29097 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
29098 insn_bytes = decode_micromips_opc(env, ctx);
29099 } else if (ctx->insn_flags & ASE_MIPS16) {
29100 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
29101 insn_bytes = decode_mips16_opc(env, ctx);
29102 } else {
29103 gen_reserved_instruction(ctx);
29104 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
29105 return;
29108 if (ctx->hflags & MIPS_HFLAG_BMASK) {
29109 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
29110 MIPS_HFLAG_FBNSLOT))) {
29112 * Force to generate branch as there is neither delay nor
29113 * forbidden slot.
29115 is_slot = 1;
29117 if ((ctx->hflags & MIPS_HFLAG_M16) &&
29118 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
29120 * Force to generate branch as microMIPS R6 doesn't restrict
29121 * branches in the forbidden slot.
29123 is_slot = 1;
29126 if (is_slot) {
29127 gen_branch(ctx, insn_bytes);
29129 ctx->base.pc_next += insn_bytes;
29131 if (ctx->base.is_jmp != DISAS_NEXT) {
29132 return;
29135 * Execute a branch and its delay slot as a single instruction.
29136 * This is what GDB expects and is consistent with what the
29137 * hardware does (e.g. if a delay slot instruction faults, the
29138 * reported PC is the PC of the branch).
29140 if (ctx->base.singlestep_enabled &&
29141 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
29142 ctx->base.is_jmp = DISAS_TOO_MANY;
29144 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
29145 ctx->base.is_jmp = DISAS_TOO_MANY;
29149 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
29151 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29153 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
29154 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
29155 gen_helper_raise_exception_debug(cpu_env);
29156 } else {
29157 switch (ctx->base.is_jmp) {
29158 case DISAS_STOP:
29159 gen_save_pc(ctx->base.pc_next);
29160 tcg_gen_lookup_and_goto_ptr();
29161 break;
29162 case DISAS_NEXT:
29163 case DISAS_TOO_MANY:
29164 save_cpu_state(ctx, 0);
29165 gen_goto_tb(ctx, 0, ctx->base.pc_next);
29166 break;
29167 case DISAS_EXIT:
29168 tcg_gen_exit_tb(NULL, 0);
29169 break;
29170 case DISAS_NORETURN:
29171 break;
29172 default:
29173 g_assert_not_reached();
29178 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
29180 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
29181 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
29184 static const TranslatorOps mips_tr_ops = {
29185 .init_disas_context = mips_tr_init_disas_context,
29186 .tb_start = mips_tr_tb_start,
29187 .insn_start = mips_tr_insn_start,
29188 .breakpoint_check = mips_tr_breakpoint_check,
29189 .translate_insn = mips_tr_translate_insn,
29190 .tb_stop = mips_tr_tb_stop,
29191 .disas_log = mips_tr_disas_log,
29194 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
29196 DisasContext ctx;
29198 translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
29201 static void fpu_dump_state(CPUMIPSState *env, FILE * f, int flags)
29203 int i;
29204 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
29206 #define printfpr(fp) \
29207 do { \
29208 if (is_fpu64) \
29209 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
29210 " fd:%13g fs:%13g psu: %13g\n", \
29211 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
29212 (double)(fp)->fd, \
29213 (double)(fp)->fs[FP_ENDIAN_IDX], \
29214 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
29215 else { \
29216 fpr_t tmp; \
29217 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
29218 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
29219 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
29220 " fd:%13g fs:%13g psu:%13g\n", \
29221 tmp.w[FP_ENDIAN_IDX], tmp.d, \
29222 (double)tmp.fd, \
29223 (double)tmp.fs[FP_ENDIAN_IDX], \
29224 (double)tmp.fs[!FP_ENDIAN_IDX]); \
29226 } while (0)
29229 qemu_fprintf(f,
29230 "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
29231 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
29232 get_float_exception_flags(&env->active_fpu.fp_status));
29233 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
29234 qemu_fprintf(f, "%3s: ", fregnames[i]);
29235 printfpr(&env->active_fpu.fpr[i]);
29238 #undef printfpr
29241 void mips_cpu_dump_state(CPUState *cs, FILE *f, int flags)
29243 MIPSCPU *cpu = MIPS_CPU(cs);
29244 CPUMIPSState *env = &cpu->env;
29245 int i;
29247 qemu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
29248 " LO=0x" TARGET_FMT_lx " ds %04x "
29249 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
29250 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
29251 env->hflags, env->btarget, env->bcond);
29252 for (i = 0; i < 32; i++) {
29253 if ((i & 3) == 0) {
29254 qemu_fprintf(f, "GPR%02d:", i);
29256 qemu_fprintf(f, " %s " TARGET_FMT_lx,
29257 regnames[i], env->active_tc.gpr[i]);
29258 if ((i & 3) == 3) {
29259 qemu_fprintf(f, "\n");
29263 qemu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x"
29264 TARGET_FMT_lx "\n",
29265 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
29266 qemu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
29267 PRIx64 "\n",
29268 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
29269 qemu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
29270 env->CP0_Config2, env->CP0_Config3);
29271 qemu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
29272 env->CP0_Config4, env->CP0_Config5);
29273 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
29274 fpu_dump_state(env, f, flags);
29278 void mips_tcg_init(void)
29280 int i;
29282 cpu_gpr[0] = NULL;
29283 for (i = 1; i < 32; i++)
29284 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
29285 offsetof(CPUMIPSState,
29286 active_tc.gpr[i]),
29287 regnames[i]);
29288 #if defined(TARGET_MIPS64)
29289 cpu_gpr_hi[0] = NULL;
29291 for (unsigned i = 1; i < 32; i++) {
29292 cpu_gpr_hi[i] = tcg_global_mem_new_i64(cpu_env,
29293 offsetof(CPUMIPSState,
29294 active_tc.gpr_hi[i]),
29295 regnames[i]);
29297 #endif /* !TARGET_MIPS64 */
29298 for (i = 0; i < 32; i++) {
29299 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
29301 fpu_f64[i] = tcg_global_mem_new_i64(cpu_env, off, fregnames[i]);
29303 msa_translate_init();
29304 cpu_PC = tcg_global_mem_new(cpu_env,
29305 offsetof(CPUMIPSState, active_tc.PC), "PC");
29306 for (i = 0; i < MIPS_DSP_ACC; i++) {
29307 cpu_HI[i] = tcg_global_mem_new(cpu_env,
29308 offsetof(CPUMIPSState, active_tc.HI[i]),
29309 regnames_HI[i]);
29310 cpu_LO[i] = tcg_global_mem_new(cpu_env,
29311 offsetof(CPUMIPSState, active_tc.LO[i]),
29312 regnames_LO[i]);
29314 cpu_dspctrl = tcg_global_mem_new(cpu_env,
29315 offsetof(CPUMIPSState,
29316 active_tc.DSPControl),
29317 "DSPControl");
29318 bcond = tcg_global_mem_new(cpu_env,
29319 offsetof(CPUMIPSState, bcond), "bcond");
29320 btarget = tcg_global_mem_new(cpu_env,
29321 offsetof(CPUMIPSState, btarget), "btarget");
29322 hflags = tcg_global_mem_new_i32(cpu_env,
29323 offsetof(CPUMIPSState, hflags), "hflags");
29325 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
29326 offsetof(CPUMIPSState, active_fpu.fcr0),
29327 "fcr0");
29328 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
29329 offsetof(CPUMIPSState, active_fpu.fcr31),
29330 "fcr31");
29331 cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
29332 "lladdr");
29333 cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
29334 "llval");
29336 #if !defined(TARGET_MIPS64)
29337 for (i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
29338 mxu_gpr[i] = tcg_global_mem_new(cpu_env,
29339 offsetof(CPUMIPSState,
29340 active_tc.mxu_gpr[i]),
29341 mxuregnames[i]);
29344 mxu_CR = tcg_global_mem_new(cpu_env,
29345 offsetof(CPUMIPSState, active_tc.mxu_cr),
29346 mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
29347 #endif /* !TARGET_MIPS64 */
29350 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
29351 target_ulong *data)
29353 env->active_tc.PC = data[0];
29354 env->hflags &= ~MIPS_HFLAG_BMASK;
29355 env->hflags |= data[1];
29356 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
29357 case MIPS_HFLAG_BR:
29358 break;
29359 case MIPS_HFLAG_BC:
29360 case MIPS_HFLAG_BL:
29361 case MIPS_HFLAG_B:
29362 env->btarget = data[2];
29363 break;