semihosting: Move include/hw/semihosting/ -> include/semihosting/
[qemu/ar7.git] / target / mips / translate.c
blob0b6d82d228ecb6aec1d1e38abf979744151460b2
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 "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 #if defined(TARGET_MIPS64)
2295 void gen_load_gpr_hi(TCGv_i64 t, int reg)
2297 if (reg == 0) {
2298 tcg_gen_movi_i64(t, 0);
2299 } else {
2300 tcg_gen_mov_i64(t, cpu_gpr_hi[reg]);
2304 void gen_store_gpr_hi(TCGv_i64 t, int reg)
2306 if (reg != 0) {
2307 tcg_gen_mov_i64(cpu_gpr_hi[reg], t);
2310 #endif /* TARGET_MIPS64 */
2312 /* Moves to/from shadow registers. */
2313 static inline void gen_load_srsgpr(int from, int to)
2315 TCGv t0 = tcg_temp_new();
2317 if (from == 0) {
2318 tcg_gen_movi_tl(t0, 0);
2319 } else {
2320 TCGv_i32 t2 = tcg_temp_new_i32();
2321 TCGv_ptr addr = tcg_temp_new_ptr();
2323 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2324 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2325 tcg_gen_andi_i32(t2, t2, 0xf);
2326 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2327 tcg_gen_ext_i32_ptr(addr, t2);
2328 tcg_gen_add_ptr(addr, cpu_env, addr);
2330 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
2331 tcg_temp_free_ptr(addr);
2332 tcg_temp_free_i32(t2);
2334 gen_store_gpr(t0, to);
2335 tcg_temp_free(t0);
2338 static inline void gen_store_srsgpr(int from, int to)
2340 if (to != 0) {
2341 TCGv t0 = tcg_temp_new();
2342 TCGv_i32 t2 = tcg_temp_new_i32();
2343 TCGv_ptr addr = tcg_temp_new_ptr();
2345 gen_load_gpr(t0, from);
2346 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2347 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2348 tcg_gen_andi_i32(t2, t2, 0xf);
2349 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2350 tcg_gen_ext_i32_ptr(addr, t2);
2351 tcg_gen_add_ptr(addr, cpu_env, addr);
2353 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
2354 tcg_temp_free_ptr(addr);
2355 tcg_temp_free_i32(t2);
2356 tcg_temp_free(t0);
2360 #if !defined(TARGET_MIPS64)
2361 /* MXU General purpose registers moves. */
2362 static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg)
2364 if (reg == 0) {
2365 tcg_gen_movi_tl(t, 0);
2366 } else if (reg <= 15) {
2367 tcg_gen_mov_tl(t, mxu_gpr[reg - 1]);
2371 static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg)
2373 if (reg > 0 && reg <= 15) {
2374 tcg_gen_mov_tl(mxu_gpr[reg - 1], t);
2378 /* MXU control register moves. */
2379 static inline void gen_load_mxu_cr(TCGv t)
2381 tcg_gen_mov_tl(t, mxu_CR);
2384 static inline void gen_store_mxu_cr(TCGv t)
2386 /* TODO: Add handling of RW rules for MXU_CR. */
2387 tcg_gen_mov_tl(mxu_CR, t);
2389 #endif
2392 /* Tests */
2393 static inline void gen_save_pc(target_ulong pc)
2395 tcg_gen_movi_tl(cpu_PC, pc);
2398 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2400 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
2401 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2402 gen_save_pc(ctx->base.pc_next);
2403 ctx->saved_pc = ctx->base.pc_next;
2405 if (ctx->hflags != ctx->saved_hflags) {
2406 tcg_gen_movi_i32(hflags, ctx->hflags);
2407 ctx->saved_hflags = ctx->hflags;
2408 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2409 case MIPS_HFLAG_BR:
2410 break;
2411 case MIPS_HFLAG_BC:
2412 case MIPS_HFLAG_BL:
2413 case MIPS_HFLAG_B:
2414 tcg_gen_movi_tl(btarget, ctx->btarget);
2415 break;
2420 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2422 ctx->saved_hflags = ctx->hflags;
2423 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2424 case MIPS_HFLAG_BR:
2425 break;
2426 case MIPS_HFLAG_BC:
2427 case MIPS_HFLAG_BL:
2428 case MIPS_HFLAG_B:
2429 ctx->btarget = env->btarget;
2430 break;
2434 void generate_exception_err(DisasContext *ctx, int excp, int err)
2436 TCGv_i32 texcp = tcg_const_i32(excp);
2437 TCGv_i32 terr = tcg_const_i32(err);
2438 save_cpu_state(ctx, 1);
2439 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2440 tcg_temp_free_i32(terr);
2441 tcg_temp_free_i32(texcp);
2442 ctx->base.is_jmp = DISAS_NORETURN;
2445 void generate_exception(DisasContext *ctx, int excp)
2447 gen_helper_0e0i(raise_exception, excp);
2450 void generate_exception_end(DisasContext *ctx, int excp)
2452 generate_exception_err(ctx, excp, 0);
2455 void gen_reserved_instruction(DisasContext *ctx)
2457 generate_exception_end(ctx, EXCP_RI);
2460 /* Floating point register moves. */
2461 void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2463 if (ctx->hflags & MIPS_HFLAG_FRE) {
2464 generate_exception(ctx, EXCP_RI);
2466 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
2469 void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2471 TCGv_i64 t64;
2472 if (ctx->hflags & MIPS_HFLAG_FRE) {
2473 generate_exception(ctx, EXCP_RI);
2475 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, 0, 32);
2478 tcg_temp_free_i64(t64);
2481 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2483 if (ctx->hflags & MIPS_HFLAG_F64) {
2484 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
2485 } else {
2486 gen_load_fpr32(ctx, t, reg | 1);
2490 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2492 if (ctx->hflags & MIPS_HFLAG_F64) {
2493 TCGv_i64 t64 = tcg_temp_new_i64();
2494 tcg_gen_extu_i32_i64(t64, t);
2495 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2496 tcg_temp_free_i64(t64);
2497 } else {
2498 gen_store_fpr32(ctx, t, reg | 1);
2502 void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2504 if (ctx->hflags & MIPS_HFLAG_F64) {
2505 tcg_gen_mov_i64(t, fpu_f64[reg]);
2506 } else {
2507 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
2511 void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2513 if (ctx->hflags & MIPS_HFLAG_F64) {
2514 tcg_gen_mov_i64(fpu_f64[reg], t);
2515 } else {
2516 TCGv_i64 t0;
2517 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2518 t0 = tcg_temp_new_i64();
2519 tcg_gen_shri_i64(t0, t, 32);
2520 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
2521 tcg_temp_free_i64(t0);
2525 int get_fp_bit(int cc)
2527 if (cc) {
2528 return 24 + cc;
2529 } else {
2530 return 23;
2534 /* Addresses computation */
2535 void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
2537 tcg_gen_add_tl(ret, arg0, arg1);
2539 #if defined(TARGET_MIPS64)
2540 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2541 tcg_gen_ext32s_i64(ret, ret);
2543 #endif
2546 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2547 target_long ofs)
2549 tcg_gen_addi_tl(ret, base, ofs);
2551 #if defined(TARGET_MIPS64)
2552 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2553 tcg_gen_ext32s_i64(ret, ret);
2555 #endif
2558 /* Addresses computation (translation time) */
2559 static target_long addr_add(DisasContext *ctx, target_long base,
2560 target_long offset)
2562 target_long sum = base + offset;
2564 #if defined(TARGET_MIPS64)
2565 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2566 sum = (int32_t)sum;
2568 #endif
2569 return sum;
2572 /* Sign-extract the low 32-bits to a target_long. */
2573 void gen_move_low32(TCGv ret, TCGv_i64 arg)
2575 #if defined(TARGET_MIPS64)
2576 tcg_gen_ext32s_i64(ret, arg);
2577 #else
2578 tcg_gen_extrl_i64_i32(ret, arg);
2579 #endif
2582 /* Sign-extract the high 32-bits to a target_long. */
2583 void gen_move_high32(TCGv ret, TCGv_i64 arg)
2585 #if defined(TARGET_MIPS64)
2586 tcg_gen_sari_i64(ret, arg, 32);
2587 #else
2588 tcg_gen_extrh_i64_i32(ret, arg);
2589 #endif
2592 void check_cp0_enabled(DisasContext *ctx)
2594 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
2595 generate_exception_end(ctx, EXCP_CpU);
2599 void check_cp1_enabled(DisasContext *ctx)
2601 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) {
2602 generate_exception_err(ctx, EXCP_CpU, 1);
2607 * Verify that the processor is running with COP1X instructions enabled.
2608 * This is associated with the nabla symbol in the MIPS32 and MIPS64
2609 * opcode tables.
2611 void check_cop1x(DisasContext *ctx)
2613 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) {
2614 gen_reserved_instruction(ctx);
2619 * Verify that the processor is running with 64-bit floating-point
2620 * operations enabled.
2622 void check_cp1_64bitmode(DisasContext *ctx)
2624 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) {
2625 gen_reserved_instruction(ctx);
2630 * Verify if floating point register is valid; an operation is not defined
2631 * if bit 0 of any register specification is set and the FR bit in the
2632 * Status register equals zero, since the register numbers specify an
2633 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2634 * in the Status register equals one, both even and odd register numbers
2635 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2637 * Multiple 64 bit wide registers can be checked by calling
2638 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2640 void check_cp1_registers(DisasContext *ctx, int regs)
2642 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) {
2643 gen_reserved_instruction(ctx);
2648 * Verify that the processor is running with DSP instructions enabled.
2649 * This is enabled by CP0 Status register MX(24) bit.
2651 static inline void check_dsp(DisasContext *ctx)
2653 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
2654 if (ctx->insn_flags & ASE_DSP) {
2655 generate_exception_end(ctx, EXCP_DSPDIS);
2656 } else {
2657 gen_reserved_instruction(ctx);
2662 static inline void check_dsp_r2(DisasContext *ctx)
2664 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
2665 if (ctx->insn_flags & ASE_DSP) {
2666 generate_exception_end(ctx, EXCP_DSPDIS);
2667 } else {
2668 gen_reserved_instruction(ctx);
2673 static inline void check_dsp_r3(DisasContext *ctx)
2675 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
2676 if (ctx->insn_flags & ASE_DSP) {
2677 generate_exception_end(ctx, EXCP_DSPDIS);
2678 } else {
2679 gen_reserved_instruction(ctx);
2685 * This code generates a "reserved instruction" exception if the
2686 * CPU does not support the instruction set corresponding to flags.
2688 void check_insn(DisasContext *ctx, uint64_t flags)
2690 if (unlikely(!(ctx->insn_flags & flags))) {
2691 gen_reserved_instruction(ctx);
2696 * This code generates a "reserved instruction" exception if the
2697 * CPU has corresponding flag set which indicates that the instruction
2698 * has been removed.
2700 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
2702 if (unlikely(ctx->insn_flags & flags)) {
2703 gen_reserved_instruction(ctx);
2708 * The Linux kernel traps certain reserved instruction exceptions to
2709 * emulate the corresponding instructions. QEMU is the kernel in user
2710 * mode, so those traps are emulated by accepting the instructions.
2712 * A reserved instruction exception is generated for flagged CPUs if
2713 * QEMU runs in system mode.
2715 static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
2717 #ifndef CONFIG_USER_ONLY
2718 check_insn_opc_removed(ctx, flags);
2719 #endif
2723 * This code generates a "reserved instruction" exception if the
2724 * CPU does not support 64-bit paired-single (PS) floating point data type.
2726 static inline void check_ps(DisasContext *ctx)
2728 if (unlikely(!ctx->ps)) {
2729 generate_exception(ctx, EXCP_RI);
2731 check_cp1_64bitmode(ctx);
2735 * This code generates a "reserved instruction" exception if cpu is not
2736 * 64-bit or 64-bit instructions are not enabled.
2738 void check_mips_64(DisasContext *ctx)
2740 if (unlikely((TARGET_LONG_BITS != 64) || !(ctx->hflags & MIPS_HFLAG_64))) {
2741 gen_reserved_instruction(ctx);
2745 #ifndef CONFIG_USER_ONLY
2746 static inline void check_mvh(DisasContext *ctx)
2748 if (unlikely(!ctx->mvh)) {
2749 generate_exception(ctx, EXCP_RI);
2752 #endif
2755 * This code generates a "reserved instruction" exception if the
2756 * Config5 XNP bit is set.
2758 static inline void check_xnp(DisasContext *ctx)
2760 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
2761 gen_reserved_instruction(ctx);
2765 #ifndef CONFIG_USER_ONLY
2767 * This code generates a "reserved instruction" exception if the
2768 * Config3 PW bit is NOT set.
2770 static inline void check_pw(DisasContext *ctx)
2772 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
2773 gen_reserved_instruction(ctx);
2776 #endif
2779 * This code generates a "reserved instruction" exception if the
2780 * Config3 MT bit is NOT set.
2782 static inline void check_mt(DisasContext *ctx)
2784 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
2785 gen_reserved_instruction(ctx);
2789 #ifndef CONFIG_USER_ONLY
2791 * This code generates a "coprocessor unusable" exception if CP0 is not
2792 * available, and, if that is not the case, generates a "reserved instruction"
2793 * exception if the Config5 MT bit is NOT set. This is needed for availability
2794 * control of some of MT ASE instructions.
2796 static inline void check_cp0_mt(DisasContext *ctx)
2798 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
2799 generate_exception_end(ctx, EXCP_CpU);
2800 } else {
2801 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
2802 gen_reserved_instruction(ctx);
2806 #endif
2809 * This code generates a "reserved instruction" exception if the
2810 * Config5 NMS bit is set.
2812 static inline void check_nms(DisasContext *ctx)
2814 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
2815 gen_reserved_instruction(ctx);
2820 * This code generates a "reserved instruction" exception if the
2821 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
2822 * Config2 TL, and Config5 L2C are unset.
2824 static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
2826 if (unlikely((ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
2827 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
2828 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
2829 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
2830 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
2831 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))) {
2832 gen_reserved_instruction(ctx);
2837 * This code generates a "reserved instruction" exception if the
2838 * Config5 EVA bit is NOT set.
2840 static inline void check_eva(DisasContext *ctx)
2842 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
2843 gen_reserved_instruction(ctx);
2849 * Define small wrappers for gen_load_fpr* so that we have a uniform
2850 * calling interface for 32 and 64-bit FPRs. No sense in changing
2851 * all callers for gen_load_fpr32 when we need the CTX parameter for
2852 * this one use.
2854 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
2855 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
2856 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
2857 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
2858 int ft, int fs, int cc) \
2860 TCGv_i##bits fp0 = tcg_temp_new_i##bits(); \
2861 TCGv_i##bits fp1 = tcg_temp_new_i##bits(); \
2862 switch (ifmt) { \
2863 case FMT_PS: \
2864 check_ps(ctx); \
2865 break; \
2866 case FMT_D: \
2867 if (abs) { \
2868 check_cop1x(ctx); \
2870 check_cp1_registers(ctx, fs | ft); \
2871 break; \
2872 case FMT_S: \
2873 if (abs) { \
2874 check_cop1x(ctx); \
2876 break; \
2878 gen_ldcmp_fpr##bits(ctx, fp0, fs); \
2879 gen_ldcmp_fpr##bits(ctx, fp1, ft); \
2880 switch (n) { \
2881 case 0: \
2882 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); \
2883 break; \
2884 case 1: \
2885 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); \
2886 break; \
2887 case 2: \
2888 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); \
2889 break; \
2890 case 3: \
2891 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); \
2892 break; \
2893 case 4: \
2894 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); \
2895 break; \
2896 case 5: \
2897 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); \
2898 break; \
2899 case 6: \
2900 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); \
2901 break; \
2902 case 7: \
2903 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); \
2904 break; \
2905 case 8: \
2906 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); \
2907 break; \
2908 case 9: \
2909 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); \
2910 break; \
2911 case 10: \
2912 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); \
2913 break; \
2914 case 11: \
2915 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); \
2916 break; \
2917 case 12: \
2918 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); \
2919 break; \
2920 case 13: \
2921 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); \
2922 break; \
2923 case 14: \
2924 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); \
2925 break; \
2926 case 15: \
2927 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); \
2928 break; \
2929 default: \
2930 abort(); \
2932 tcg_temp_free_i##bits(fp0); \
2933 tcg_temp_free_i##bits(fp1); \
2936 FOP_CONDS(, 0, d, FMT_D, 64)
2937 FOP_CONDS(abs, 1, d, FMT_D, 64)
2938 FOP_CONDS(, 0, s, FMT_S, 32)
2939 FOP_CONDS(abs, 1, s, FMT_S, 32)
2940 FOP_CONDS(, 0, ps, FMT_PS, 64)
2941 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
2942 #undef FOP_CONDS
2944 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
2945 static inline void gen_r6_cmp_ ## fmt(DisasContext *ctx, int n, \
2946 int ft, int fs, int fd) \
2948 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
2949 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
2950 if (ifmt == FMT_D) { \
2951 check_cp1_registers(ctx, fs | ft | fd); \
2953 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
2954 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
2955 switch (n) { \
2956 case 0: \
2957 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
2958 break; \
2959 case 1: \
2960 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
2961 break; \
2962 case 2: \
2963 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
2964 break; \
2965 case 3: \
2966 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
2967 break; \
2968 case 4: \
2969 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
2970 break; \
2971 case 5: \
2972 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
2973 break; \
2974 case 6: \
2975 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
2976 break; \
2977 case 7: \
2978 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
2979 break; \
2980 case 8: \
2981 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
2982 break; \
2983 case 9: \
2984 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
2985 break; \
2986 case 10: \
2987 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
2988 break; \
2989 case 11: \
2990 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
2991 break; \
2992 case 12: \
2993 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
2994 break; \
2995 case 13: \
2996 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
2997 break; \
2998 case 14: \
2999 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
3000 break; \
3001 case 15: \
3002 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
3003 break; \
3004 case 17: \
3005 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
3006 break; \
3007 case 18: \
3008 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
3009 break; \
3010 case 19: \
3011 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
3012 break; \
3013 case 25: \
3014 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
3015 break; \
3016 case 26: \
3017 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
3018 break; \
3019 case 27: \
3020 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
3021 break; \
3022 default: \
3023 abort(); \
3025 STORE; \
3026 tcg_temp_free_i ## bits(fp0); \
3027 tcg_temp_free_i ## bits(fp1); \
3030 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
3031 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3032 #undef FOP_CONDNS
3033 #undef gen_ldcmp_fpr32
3034 #undef gen_ldcmp_fpr64
3036 /* load/store instructions. */
3037 #ifdef CONFIG_USER_ONLY
3038 #define OP_LD_ATOMIC(insn, fname) \
3039 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3040 DisasContext *ctx) \
3042 TCGv t0 = tcg_temp_new(); \
3043 tcg_gen_mov_tl(t0, arg1); \
3044 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
3045 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3046 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
3047 tcg_temp_free(t0); \
3049 #else
3050 #define OP_LD_ATOMIC(insn, fname) \
3051 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3052 DisasContext *ctx) \
3054 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
3056 #endif
3057 OP_LD_ATOMIC(ll, ld32s);
3058 #if defined(TARGET_MIPS64)
3059 OP_LD_ATOMIC(lld, ld64);
3060 #endif
3061 #undef OP_LD_ATOMIC
3063 void gen_base_offset_addr(DisasContext *ctx, TCGv addr, int base, int offset)
3065 if (base == 0) {
3066 tcg_gen_movi_tl(addr, offset);
3067 } else if (offset == 0) {
3068 gen_load_gpr(addr, base);
3069 } else {
3070 tcg_gen_movi_tl(addr, offset);
3071 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
3075 static target_ulong pc_relative_pc(DisasContext *ctx)
3077 target_ulong pc = ctx->base.pc_next;
3079 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3080 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
3082 pc -= branch_bytes;
3085 pc &= ~(target_ulong)3;
3086 return pc;
3089 /* Load */
3090 static void gen_ld(DisasContext *ctx, uint32_t opc,
3091 int rt, int base, int offset)
3093 TCGv t0, t1, t2;
3094 int mem_idx = ctx->mem_idx;
3096 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F |
3097 INSN_LOONGSON3A)) {
3099 * Loongson CPU uses a load to zero register for prefetch.
3100 * We emulate it as a NOP. On other CPU we must perform the
3101 * actual memory access.
3103 return;
3106 t0 = tcg_temp_new();
3107 gen_base_offset_addr(ctx, t0, base, offset);
3109 switch (opc) {
3110 #if defined(TARGET_MIPS64)
3111 case OPC_LWU:
3112 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
3113 ctx->default_tcg_memop_mask);
3114 gen_store_gpr(t0, rt);
3115 break;
3116 case OPC_LD:
3117 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
3118 ctx->default_tcg_memop_mask);
3119 gen_store_gpr(t0, rt);
3120 break;
3121 case OPC_LLD:
3122 case R6_OPC_LLD:
3123 op_ld_lld(t0, t0, mem_idx, ctx);
3124 gen_store_gpr(t0, rt);
3125 break;
3126 case OPC_LDL:
3127 t1 = tcg_temp_new();
3129 * Do a byte access to possibly trigger a page
3130 * fault with the unaligned address.
3132 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3133 tcg_gen_andi_tl(t1, t0, 7);
3134 #ifndef TARGET_WORDS_BIGENDIAN
3135 tcg_gen_xori_tl(t1, t1, 7);
3136 #endif
3137 tcg_gen_shli_tl(t1, t1, 3);
3138 tcg_gen_andi_tl(t0, t0, ~7);
3139 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3140 tcg_gen_shl_tl(t0, t0, t1);
3141 t2 = tcg_const_tl(-1);
3142 tcg_gen_shl_tl(t2, t2, t1);
3143 gen_load_gpr(t1, rt);
3144 tcg_gen_andc_tl(t1, t1, t2);
3145 tcg_temp_free(t2);
3146 tcg_gen_or_tl(t0, t0, t1);
3147 tcg_temp_free(t1);
3148 gen_store_gpr(t0, rt);
3149 break;
3150 case OPC_LDR:
3151 t1 = tcg_temp_new();
3153 * Do a byte access to possibly trigger a page
3154 * fault with the unaligned address.
3156 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3157 tcg_gen_andi_tl(t1, t0, 7);
3158 #ifdef TARGET_WORDS_BIGENDIAN
3159 tcg_gen_xori_tl(t1, t1, 7);
3160 #endif
3161 tcg_gen_shli_tl(t1, t1, 3);
3162 tcg_gen_andi_tl(t0, t0, ~7);
3163 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3164 tcg_gen_shr_tl(t0, t0, t1);
3165 tcg_gen_xori_tl(t1, t1, 63);
3166 t2 = tcg_const_tl(0xfffffffffffffffeull);
3167 tcg_gen_shl_tl(t2, t2, t1);
3168 gen_load_gpr(t1, rt);
3169 tcg_gen_and_tl(t1, t1, t2);
3170 tcg_temp_free(t2);
3171 tcg_gen_or_tl(t0, t0, t1);
3172 tcg_temp_free(t1);
3173 gen_store_gpr(t0, rt);
3174 break;
3175 case OPC_LDPC:
3176 t1 = tcg_const_tl(pc_relative_pc(ctx));
3177 gen_op_addr_add(ctx, t0, t0, t1);
3178 tcg_temp_free(t1);
3179 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3180 gen_store_gpr(t0, rt);
3181 break;
3182 #endif
3183 case OPC_LWPC:
3184 t1 = tcg_const_tl(pc_relative_pc(ctx));
3185 gen_op_addr_add(ctx, t0, t0, t1);
3186 tcg_temp_free(t1);
3187 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
3188 gen_store_gpr(t0, rt);
3189 break;
3190 case OPC_LWE:
3191 mem_idx = MIPS_HFLAG_UM;
3192 /* fall through */
3193 case OPC_LW:
3194 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
3195 ctx->default_tcg_memop_mask);
3196 gen_store_gpr(t0, rt);
3197 break;
3198 case OPC_LHE:
3199 mem_idx = MIPS_HFLAG_UM;
3200 /* fall through */
3201 case OPC_LH:
3202 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
3203 ctx->default_tcg_memop_mask);
3204 gen_store_gpr(t0, rt);
3205 break;
3206 case OPC_LHUE:
3207 mem_idx = MIPS_HFLAG_UM;
3208 /* fall through */
3209 case OPC_LHU:
3210 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
3211 ctx->default_tcg_memop_mask);
3212 gen_store_gpr(t0, rt);
3213 break;
3214 case OPC_LBE:
3215 mem_idx = MIPS_HFLAG_UM;
3216 /* fall through */
3217 case OPC_LB:
3218 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
3219 gen_store_gpr(t0, rt);
3220 break;
3221 case OPC_LBUE:
3222 mem_idx = MIPS_HFLAG_UM;
3223 /* fall through */
3224 case OPC_LBU:
3225 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
3226 gen_store_gpr(t0, rt);
3227 break;
3228 case OPC_LWLE:
3229 mem_idx = MIPS_HFLAG_UM;
3230 /* fall through */
3231 case OPC_LWL:
3232 t1 = tcg_temp_new();
3234 * Do a byte access to possibly trigger a page
3235 * fault with the unaligned address.
3237 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3238 tcg_gen_andi_tl(t1, t0, 3);
3239 #ifndef TARGET_WORDS_BIGENDIAN
3240 tcg_gen_xori_tl(t1, t1, 3);
3241 #endif
3242 tcg_gen_shli_tl(t1, t1, 3);
3243 tcg_gen_andi_tl(t0, t0, ~3);
3244 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3245 tcg_gen_shl_tl(t0, t0, t1);
3246 t2 = tcg_const_tl(-1);
3247 tcg_gen_shl_tl(t2, t2, t1);
3248 gen_load_gpr(t1, rt);
3249 tcg_gen_andc_tl(t1, t1, t2);
3250 tcg_temp_free(t2);
3251 tcg_gen_or_tl(t0, t0, t1);
3252 tcg_temp_free(t1);
3253 tcg_gen_ext32s_tl(t0, t0);
3254 gen_store_gpr(t0, rt);
3255 break;
3256 case OPC_LWRE:
3257 mem_idx = MIPS_HFLAG_UM;
3258 /* fall through */
3259 case OPC_LWR:
3260 t1 = tcg_temp_new();
3262 * Do a byte access to possibly trigger a page
3263 * fault with the unaligned address.
3265 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3266 tcg_gen_andi_tl(t1, t0, 3);
3267 #ifdef TARGET_WORDS_BIGENDIAN
3268 tcg_gen_xori_tl(t1, t1, 3);
3269 #endif
3270 tcg_gen_shli_tl(t1, t1, 3);
3271 tcg_gen_andi_tl(t0, t0, ~3);
3272 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3273 tcg_gen_shr_tl(t0, t0, t1);
3274 tcg_gen_xori_tl(t1, t1, 31);
3275 t2 = tcg_const_tl(0xfffffffeull);
3276 tcg_gen_shl_tl(t2, t2, t1);
3277 gen_load_gpr(t1, rt);
3278 tcg_gen_and_tl(t1, t1, t2);
3279 tcg_temp_free(t2);
3280 tcg_gen_or_tl(t0, t0, t1);
3281 tcg_temp_free(t1);
3282 tcg_gen_ext32s_tl(t0, t0);
3283 gen_store_gpr(t0, rt);
3284 break;
3285 case OPC_LLE:
3286 mem_idx = MIPS_HFLAG_UM;
3287 /* fall through */
3288 case OPC_LL:
3289 case R6_OPC_LL:
3290 op_ld_ll(t0, t0, mem_idx, ctx);
3291 gen_store_gpr(t0, rt);
3292 break;
3294 tcg_temp_free(t0);
3297 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3298 uint32_t reg1, uint32_t reg2)
3300 TCGv taddr = tcg_temp_new();
3301 TCGv_i64 tval = tcg_temp_new_i64();
3302 TCGv tmp1 = tcg_temp_new();
3303 TCGv tmp2 = tcg_temp_new();
3305 gen_base_offset_addr(ctx, taddr, base, offset);
3306 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3307 #ifdef TARGET_WORDS_BIGENDIAN
3308 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3309 #else
3310 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3311 #endif
3312 gen_store_gpr(tmp1, reg1);
3313 tcg_temp_free(tmp1);
3314 gen_store_gpr(tmp2, reg2);
3315 tcg_temp_free(tmp2);
3316 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3317 tcg_temp_free_i64(tval);
3318 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3319 tcg_temp_free(taddr);
3322 /* Store */
3323 static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
3324 int base, int offset)
3326 TCGv t0 = tcg_temp_new();
3327 TCGv t1 = tcg_temp_new();
3328 int mem_idx = ctx->mem_idx;
3330 gen_base_offset_addr(ctx, t0, base, offset);
3331 gen_load_gpr(t1, rt);
3332 switch (opc) {
3333 #if defined(TARGET_MIPS64)
3334 case OPC_SD:
3335 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
3336 ctx->default_tcg_memop_mask);
3337 break;
3338 case OPC_SDL:
3339 gen_helper_0e2i(sdl, t1, t0, mem_idx);
3340 break;
3341 case OPC_SDR:
3342 gen_helper_0e2i(sdr, t1, t0, mem_idx);
3343 break;
3344 #endif
3345 case OPC_SWE:
3346 mem_idx = MIPS_HFLAG_UM;
3347 /* fall through */
3348 case OPC_SW:
3349 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
3350 ctx->default_tcg_memop_mask);
3351 break;
3352 case OPC_SHE:
3353 mem_idx = MIPS_HFLAG_UM;
3354 /* fall through */
3355 case OPC_SH:
3356 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
3357 ctx->default_tcg_memop_mask);
3358 break;
3359 case OPC_SBE:
3360 mem_idx = MIPS_HFLAG_UM;
3361 /* fall through */
3362 case OPC_SB:
3363 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
3364 break;
3365 case OPC_SWLE:
3366 mem_idx = MIPS_HFLAG_UM;
3367 /* fall through */
3368 case OPC_SWL:
3369 gen_helper_0e2i(swl, t1, t0, mem_idx);
3370 break;
3371 case OPC_SWRE:
3372 mem_idx = MIPS_HFLAG_UM;
3373 /* fall through */
3374 case OPC_SWR:
3375 gen_helper_0e2i(swr, t1, t0, mem_idx);
3376 break;
3378 tcg_temp_free(t0);
3379 tcg_temp_free(t1);
3383 /* Store conditional */
3384 static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
3385 MemOp tcg_mo, bool eva)
3387 TCGv addr, t0, val;
3388 TCGLabel *l1 = gen_new_label();
3389 TCGLabel *done = gen_new_label();
3391 t0 = tcg_temp_new();
3392 addr = tcg_temp_new();
3393 /* compare the address against that of the preceding LL */
3394 gen_base_offset_addr(ctx, addr, base, offset);
3395 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
3396 tcg_temp_free(addr);
3397 tcg_gen_movi_tl(t0, 0);
3398 gen_store_gpr(t0, rt);
3399 tcg_gen_br(done);
3401 gen_set_label(l1);
3402 /* generate cmpxchg */
3403 val = tcg_temp_new();
3404 gen_load_gpr(val, rt);
3405 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
3406 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
3407 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
3408 gen_store_gpr(t0, rt);
3409 tcg_temp_free(val);
3411 gen_set_label(done);
3412 tcg_temp_free(t0);
3416 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
3417 uint32_t reg1, uint32_t reg2, bool eva)
3419 TCGv taddr = tcg_temp_local_new();
3420 TCGv lladdr = tcg_temp_local_new();
3421 TCGv_i64 tval = tcg_temp_new_i64();
3422 TCGv_i64 llval = tcg_temp_new_i64();
3423 TCGv_i64 val = tcg_temp_new_i64();
3424 TCGv tmp1 = tcg_temp_new();
3425 TCGv tmp2 = tcg_temp_new();
3426 TCGLabel *lab_fail = gen_new_label();
3427 TCGLabel *lab_done = gen_new_label();
3429 gen_base_offset_addr(ctx, taddr, base, offset);
3431 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3432 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3434 gen_load_gpr(tmp1, reg1);
3435 gen_load_gpr(tmp2, reg2);
3437 #ifdef TARGET_WORDS_BIGENDIAN
3438 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3439 #else
3440 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3441 #endif
3443 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3444 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
3445 eva ? MIPS_HFLAG_UM : ctx->mem_idx, MO_64);
3446 if (reg1 != 0) {
3447 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3449 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3451 gen_set_label(lab_fail);
3453 if (reg1 != 0) {
3454 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3456 gen_set_label(lab_done);
3457 tcg_gen_movi_tl(lladdr, -1);
3458 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3461 /* Load and store */
3462 static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
3463 TCGv t0)
3466 * Don't do NOP if destination is zero: we must perform the actual
3467 * memory access.
3469 switch (opc) {
3470 case OPC_LWC1:
3472 TCGv_i32 fp0 = tcg_temp_new_i32();
3473 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3474 ctx->default_tcg_memop_mask);
3475 gen_store_fpr32(ctx, fp0, ft);
3476 tcg_temp_free_i32(fp0);
3478 break;
3479 case OPC_SWC1:
3481 TCGv_i32 fp0 = tcg_temp_new_i32();
3482 gen_load_fpr32(ctx, fp0, ft);
3483 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3484 ctx->default_tcg_memop_mask);
3485 tcg_temp_free_i32(fp0);
3487 break;
3488 case OPC_LDC1:
3490 TCGv_i64 fp0 = tcg_temp_new_i64();
3491 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3492 ctx->default_tcg_memop_mask);
3493 gen_store_fpr64(ctx, fp0, ft);
3494 tcg_temp_free_i64(fp0);
3496 break;
3497 case OPC_SDC1:
3499 TCGv_i64 fp0 = tcg_temp_new_i64();
3500 gen_load_fpr64(ctx, fp0, ft);
3501 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3502 ctx->default_tcg_memop_mask);
3503 tcg_temp_free_i64(fp0);
3505 break;
3506 default:
3507 MIPS_INVAL("flt_ldst");
3508 gen_reserved_instruction(ctx);
3509 break;
3513 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3514 int rs, int16_t imm)
3516 TCGv t0 = tcg_temp_new();
3518 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3519 check_cp1_enabled(ctx);
3520 switch (op) {
3521 case OPC_LDC1:
3522 case OPC_SDC1:
3523 check_insn(ctx, ISA_MIPS2);
3524 /* Fallthrough */
3525 default:
3526 gen_base_offset_addr(ctx, t0, rs, imm);
3527 gen_flt_ldst(ctx, op, rt, t0);
3529 } else {
3530 generate_exception_err(ctx, EXCP_CpU, 1);
3532 tcg_temp_free(t0);
3535 /* Arithmetic with immediate operand */
3536 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
3537 int rt, int rs, int imm)
3539 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3541 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
3543 * If no destination, treat it as a NOP.
3544 * For addi, we must generate the overflow exception when needed.
3546 return;
3548 switch (opc) {
3549 case OPC_ADDI:
3551 TCGv t0 = tcg_temp_local_new();
3552 TCGv t1 = tcg_temp_new();
3553 TCGv t2 = tcg_temp_new();
3554 TCGLabel *l1 = gen_new_label();
3556 gen_load_gpr(t1, rs);
3557 tcg_gen_addi_tl(t0, t1, uimm);
3558 tcg_gen_ext32s_tl(t0, t0);
3560 tcg_gen_xori_tl(t1, t1, ~uimm);
3561 tcg_gen_xori_tl(t2, t0, uimm);
3562 tcg_gen_and_tl(t1, t1, t2);
3563 tcg_temp_free(t2);
3564 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3565 tcg_temp_free(t1);
3566 /* operands of same sign, result different sign */
3567 generate_exception(ctx, EXCP_OVERFLOW);
3568 gen_set_label(l1);
3569 tcg_gen_ext32s_tl(t0, t0);
3570 gen_store_gpr(t0, rt);
3571 tcg_temp_free(t0);
3573 break;
3574 case OPC_ADDIU:
3575 if (rs != 0) {
3576 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3577 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3578 } else {
3579 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3581 break;
3582 #if defined(TARGET_MIPS64)
3583 case OPC_DADDI:
3585 TCGv t0 = tcg_temp_local_new();
3586 TCGv t1 = tcg_temp_new();
3587 TCGv t2 = tcg_temp_new();
3588 TCGLabel *l1 = gen_new_label();
3590 gen_load_gpr(t1, rs);
3591 tcg_gen_addi_tl(t0, t1, uimm);
3593 tcg_gen_xori_tl(t1, t1, ~uimm);
3594 tcg_gen_xori_tl(t2, t0, uimm);
3595 tcg_gen_and_tl(t1, t1, t2);
3596 tcg_temp_free(t2);
3597 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3598 tcg_temp_free(t1);
3599 /* operands of same sign, result different sign */
3600 generate_exception(ctx, EXCP_OVERFLOW);
3601 gen_set_label(l1);
3602 gen_store_gpr(t0, rt);
3603 tcg_temp_free(t0);
3605 break;
3606 case OPC_DADDIU:
3607 if (rs != 0) {
3608 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3609 } else {
3610 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3612 break;
3613 #endif
3617 /* Logic with immediate operand */
3618 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
3619 int rt, int rs, int16_t imm)
3621 target_ulong uimm;
3623 if (rt == 0) {
3624 /* If no destination, treat it as a NOP. */
3625 return;
3627 uimm = (uint16_t)imm;
3628 switch (opc) {
3629 case OPC_ANDI:
3630 if (likely(rs != 0)) {
3631 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3632 } else {
3633 tcg_gen_movi_tl(cpu_gpr[rt], 0);
3635 break;
3636 case OPC_ORI:
3637 if (rs != 0) {
3638 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3639 } else {
3640 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3642 break;
3643 case OPC_XORI:
3644 if (likely(rs != 0)) {
3645 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3646 } else {
3647 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3649 break;
3650 case OPC_LUI:
3651 if (rs != 0 && (ctx->insn_flags & ISA_MIPS_R6)) {
3652 /* OPC_AUI */
3653 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3654 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3655 } else {
3656 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
3658 break;
3660 default:
3661 break;
3665 /* Set on less than with immediate operand */
3666 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
3667 int rt, int rs, int16_t imm)
3669 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3670 TCGv t0;
3672 if (rt == 0) {
3673 /* If no destination, treat it as a NOP. */
3674 return;
3676 t0 = tcg_temp_new();
3677 gen_load_gpr(t0, rs);
3678 switch (opc) {
3679 case OPC_SLTI:
3680 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
3681 break;
3682 case OPC_SLTIU:
3683 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
3684 break;
3686 tcg_temp_free(t0);
3689 /* Shifts with immediate operand */
3690 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
3691 int rt, int rs, int16_t imm)
3693 target_ulong uimm = ((uint16_t)imm) & 0x1f;
3694 TCGv t0;
3696 if (rt == 0) {
3697 /* If no destination, treat it as a NOP. */
3698 return;
3701 t0 = tcg_temp_new();
3702 gen_load_gpr(t0, rs);
3703 switch (opc) {
3704 case OPC_SLL:
3705 tcg_gen_shli_tl(t0, t0, uimm);
3706 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3707 break;
3708 case OPC_SRA:
3709 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3710 break;
3711 case OPC_SRL:
3712 if (uimm != 0) {
3713 tcg_gen_ext32u_tl(t0, t0);
3714 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3715 } else {
3716 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3718 break;
3719 case OPC_ROTR:
3720 if (uimm != 0) {
3721 TCGv_i32 t1 = tcg_temp_new_i32();
3723 tcg_gen_trunc_tl_i32(t1, t0);
3724 tcg_gen_rotri_i32(t1, t1, uimm);
3725 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
3726 tcg_temp_free_i32(t1);
3727 } else {
3728 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3730 break;
3731 #if defined(TARGET_MIPS64)
3732 case OPC_DSLL:
3733 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
3734 break;
3735 case OPC_DSRA:
3736 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3737 break;
3738 case OPC_DSRL:
3739 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3740 break;
3741 case OPC_DROTR:
3742 if (uimm != 0) {
3743 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3744 } else {
3745 tcg_gen_mov_tl(cpu_gpr[rt], t0);
3747 break;
3748 case OPC_DSLL32:
3749 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
3750 break;
3751 case OPC_DSRA32:
3752 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
3753 break;
3754 case OPC_DSRL32:
3755 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
3756 break;
3757 case OPC_DROTR32:
3758 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
3759 break;
3760 #endif
3762 tcg_temp_free(t0);
3765 /* Arithmetic */
3766 static void gen_arith(DisasContext *ctx, uint32_t opc,
3767 int rd, int rs, int rt)
3769 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
3770 && opc != OPC_DADD && opc != OPC_DSUB) {
3772 * If no destination, treat it as a NOP.
3773 * For add & sub, we must generate the overflow exception when needed.
3775 return;
3778 switch (opc) {
3779 case OPC_ADD:
3781 TCGv t0 = tcg_temp_local_new();
3782 TCGv t1 = tcg_temp_new();
3783 TCGv t2 = tcg_temp_new();
3784 TCGLabel *l1 = gen_new_label();
3786 gen_load_gpr(t1, rs);
3787 gen_load_gpr(t2, rt);
3788 tcg_gen_add_tl(t0, t1, t2);
3789 tcg_gen_ext32s_tl(t0, t0);
3790 tcg_gen_xor_tl(t1, t1, t2);
3791 tcg_gen_xor_tl(t2, t0, t2);
3792 tcg_gen_andc_tl(t1, t2, t1);
3793 tcg_temp_free(t2);
3794 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3795 tcg_temp_free(t1);
3796 /* operands of same sign, result different sign */
3797 generate_exception(ctx, EXCP_OVERFLOW);
3798 gen_set_label(l1);
3799 gen_store_gpr(t0, rd);
3800 tcg_temp_free(t0);
3802 break;
3803 case OPC_ADDU:
3804 if (rs != 0 && rt != 0) {
3805 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3806 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3807 } else if (rs == 0 && rt != 0) {
3808 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3809 } else if (rs != 0 && rt == 0) {
3810 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3811 } else {
3812 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3814 break;
3815 case OPC_SUB:
3817 TCGv t0 = tcg_temp_local_new();
3818 TCGv t1 = tcg_temp_new();
3819 TCGv t2 = tcg_temp_new();
3820 TCGLabel *l1 = gen_new_label();
3822 gen_load_gpr(t1, rs);
3823 gen_load_gpr(t2, rt);
3824 tcg_gen_sub_tl(t0, t1, t2);
3825 tcg_gen_ext32s_tl(t0, t0);
3826 tcg_gen_xor_tl(t2, t1, t2);
3827 tcg_gen_xor_tl(t1, t0, t1);
3828 tcg_gen_and_tl(t1, t1, t2);
3829 tcg_temp_free(t2);
3830 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3831 tcg_temp_free(t1);
3833 * operands of different sign, first operand and the result
3834 * of different sign
3836 generate_exception(ctx, EXCP_OVERFLOW);
3837 gen_set_label(l1);
3838 gen_store_gpr(t0, rd);
3839 tcg_temp_free(t0);
3841 break;
3842 case OPC_SUBU:
3843 if (rs != 0 && rt != 0) {
3844 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3845 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3846 } else if (rs == 0 && rt != 0) {
3847 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
3848 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3849 } else if (rs != 0 && rt == 0) {
3850 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3851 } else {
3852 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3854 break;
3855 #if defined(TARGET_MIPS64)
3856 case OPC_DADD:
3858 TCGv t0 = tcg_temp_local_new();
3859 TCGv t1 = tcg_temp_new();
3860 TCGv t2 = tcg_temp_new();
3861 TCGLabel *l1 = gen_new_label();
3863 gen_load_gpr(t1, rs);
3864 gen_load_gpr(t2, rt);
3865 tcg_gen_add_tl(t0, t1, t2);
3866 tcg_gen_xor_tl(t1, t1, t2);
3867 tcg_gen_xor_tl(t2, t0, t2);
3868 tcg_gen_andc_tl(t1, t2, t1);
3869 tcg_temp_free(t2);
3870 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3871 tcg_temp_free(t1);
3872 /* operands of same sign, result different sign */
3873 generate_exception(ctx, EXCP_OVERFLOW);
3874 gen_set_label(l1);
3875 gen_store_gpr(t0, rd);
3876 tcg_temp_free(t0);
3878 break;
3879 case OPC_DADDU:
3880 if (rs != 0 && rt != 0) {
3881 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3882 } else if (rs == 0 && rt != 0) {
3883 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3884 } else if (rs != 0 && rt == 0) {
3885 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3886 } else {
3887 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3889 break;
3890 case OPC_DSUB:
3892 TCGv t0 = tcg_temp_local_new();
3893 TCGv t1 = tcg_temp_new();
3894 TCGv t2 = tcg_temp_new();
3895 TCGLabel *l1 = gen_new_label();
3897 gen_load_gpr(t1, rs);
3898 gen_load_gpr(t2, rt);
3899 tcg_gen_sub_tl(t0, t1, t2);
3900 tcg_gen_xor_tl(t2, t1, t2);
3901 tcg_gen_xor_tl(t1, t0, t1);
3902 tcg_gen_and_tl(t1, t1, t2);
3903 tcg_temp_free(t2);
3904 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3905 tcg_temp_free(t1);
3907 * Operands of different sign, first operand and result different
3908 * sign.
3910 generate_exception(ctx, EXCP_OVERFLOW);
3911 gen_set_label(l1);
3912 gen_store_gpr(t0, rd);
3913 tcg_temp_free(t0);
3915 break;
3916 case OPC_DSUBU:
3917 if (rs != 0 && rt != 0) {
3918 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3919 } else if (rs == 0 && rt != 0) {
3920 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
3921 } else if (rs != 0 && rt == 0) {
3922 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3923 } else {
3924 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3926 break;
3927 #endif
3928 case OPC_MUL:
3929 if (likely(rs != 0 && rt != 0)) {
3930 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3931 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3932 } else {
3933 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3935 break;
3939 /* Conditional move */
3940 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
3941 int rd, int rs, int rt)
3943 TCGv t0, t1, t2;
3945 if (rd == 0) {
3946 /* If no destination, treat it as a NOP. */
3947 return;
3950 t0 = tcg_temp_new();
3951 gen_load_gpr(t0, rt);
3952 t1 = tcg_const_tl(0);
3953 t2 = tcg_temp_new();
3954 gen_load_gpr(t2, rs);
3955 switch (opc) {
3956 case OPC_MOVN:
3957 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
3958 break;
3959 case OPC_MOVZ:
3960 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
3961 break;
3962 case OPC_SELNEZ:
3963 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
3964 break;
3965 case OPC_SELEQZ:
3966 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
3967 break;
3969 tcg_temp_free(t2);
3970 tcg_temp_free(t1);
3971 tcg_temp_free(t0);
3974 /* Logic */
3975 static void gen_logic(DisasContext *ctx, uint32_t opc,
3976 int rd, int rs, int rt)
3978 if (rd == 0) {
3979 /* If no destination, treat it as a NOP. */
3980 return;
3983 switch (opc) {
3984 case OPC_AND:
3985 if (likely(rs != 0 && rt != 0)) {
3986 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3987 } else {
3988 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3990 break;
3991 case OPC_NOR:
3992 if (rs != 0 && rt != 0) {
3993 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3994 } else if (rs == 0 && rt != 0) {
3995 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
3996 } else if (rs != 0 && rt == 0) {
3997 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
3998 } else {
3999 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
4001 break;
4002 case OPC_OR:
4003 if (likely(rs != 0 && rt != 0)) {
4004 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4005 } else if (rs == 0 && rt != 0) {
4006 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4007 } else if (rs != 0 && rt == 0) {
4008 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4009 } else {
4010 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4012 break;
4013 case OPC_XOR:
4014 if (likely(rs != 0 && rt != 0)) {
4015 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4016 } else if (rs == 0 && rt != 0) {
4017 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4018 } else if (rs != 0 && rt == 0) {
4019 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4020 } else {
4021 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4023 break;
4027 /* Set on lower than */
4028 static void gen_slt(DisasContext *ctx, uint32_t opc,
4029 int rd, int rs, int rt)
4031 TCGv t0, t1;
4033 if (rd == 0) {
4034 /* If no destination, treat it as a NOP. */
4035 return;
4038 t0 = tcg_temp_new();
4039 t1 = tcg_temp_new();
4040 gen_load_gpr(t0, rs);
4041 gen_load_gpr(t1, rt);
4042 switch (opc) {
4043 case OPC_SLT:
4044 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
4045 break;
4046 case OPC_SLTU:
4047 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
4048 break;
4050 tcg_temp_free(t0);
4051 tcg_temp_free(t1);
4054 /* Shifts */
4055 static void gen_shift(DisasContext *ctx, uint32_t opc,
4056 int rd, int rs, int rt)
4058 TCGv t0, t1;
4060 if (rd == 0) {
4062 * If no destination, treat it as a NOP.
4063 * For add & sub, we must generate the overflow exception when needed.
4065 return;
4068 t0 = tcg_temp_new();
4069 t1 = tcg_temp_new();
4070 gen_load_gpr(t0, rs);
4071 gen_load_gpr(t1, rt);
4072 switch (opc) {
4073 case OPC_SLLV:
4074 tcg_gen_andi_tl(t0, t0, 0x1f);
4075 tcg_gen_shl_tl(t0, t1, t0);
4076 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4077 break;
4078 case OPC_SRAV:
4079 tcg_gen_andi_tl(t0, t0, 0x1f);
4080 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4081 break;
4082 case OPC_SRLV:
4083 tcg_gen_ext32u_tl(t1, t1);
4084 tcg_gen_andi_tl(t0, t0, 0x1f);
4085 tcg_gen_shr_tl(t0, t1, t0);
4086 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4087 break;
4088 case OPC_ROTRV:
4090 TCGv_i32 t2 = tcg_temp_new_i32();
4091 TCGv_i32 t3 = tcg_temp_new_i32();
4093 tcg_gen_trunc_tl_i32(t2, t0);
4094 tcg_gen_trunc_tl_i32(t3, t1);
4095 tcg_gen_andi_i32(t2, t2, 0x1f);
4096 tcg_gen_rotr_i32(t2, t3, t2);
4097 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4098 tcg_temp_free_i32(t2);
4099 tcg_temp_free_i32(t3);
4101 break;
4102 #if defined(TARGET_MIPS64)
4103 case OPC_DSLLV:
4104 tcg_gen_andi_tl(t0, t0, 0x3f);
4105 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
4106 break;
4107 case OPC_DSRAV:
4108 tcg_gen_andi_tl(t0, t0, 0x3f);
4109 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4110 break;
4111 case OPC_DSRLV:
4112 tcg_gen_andi_tl(t0, t0, 0x3f);
4113 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
4114 break;
4115 case OPC_DROTRV:
4116 tcg_gen_andi_tl(t0, t0, 0x3f);
4117 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
4118 break;
4119 #endif
4121 tcg_temp_free(t0);
4122 tcg_temp_free(t1);
4125 #if defined(TARGET_MIPS64)
4126 /* Copy GPR to and from TX79 HI1/LO1 register. */
4127 static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg)
4129 switch (opc) {
4130 case MMI_OPC_MFHI1:
4131 gen_store_gpr(cpu_HI[1], reg);
4132 break;
4133 case MMI_OPC_MFLO1:
4134 gen_store_gpr(cpu_LO[1], reg);
4135 break;
4136 case MMI_OPC_MTHI1:
4137 gen_load_gpr(cpu_HI[1], reg);
4138 break;
4139 case MMI_OPC_MTLO1:
4140 gen_load_gpr(cpu_LO[1], reg);
4141 break;
4142 default:
4143 MIPS_INVAL("mfthilo1 TX79");
4144 gen_reserved_instruction(ctx);
4145 break;
4148 #endif
4150 /* Arithmetic on HI/LO registers */
4151 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
4153 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
4154 /* Treat as NOP. */
4155 return;
4158 if (acc != 0) {
4159 check_dsp(ctx);
4162 switch (opc) {
4163 case OPC_MFHI:
4164 #if defined(TARGET_MIPS64)
4165 if (acc != 0) {
4166 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
4167 } else
4168 #endif
4170 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
4172 break;
4173 case OPC_MFLO:
4174 #if defined(TARGET_MIPS64)
4175 if (acc != 0) {
4176 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
4177 } else
4178 #endif
4180 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
4182 break;
4183 case OPC_MTHI:
4184 if (reg != 0) {
4185 #if defined(TARGET_MIPS64)
4186 if (acc != 0) {
4187 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
4188 } else
4189 #endif
4191 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
4193 } else {
4194 tcg_gen_movi_tl(cpu_HI[acc], 0);
4196 break;
4197 case OPC_MTLO:
4198 if (reg != 0) {
4199 #if defined(TARGET_MIPS64)
4200 if (acc != 0) {
4201 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
4202 } else
4203 #endif
4205 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
4207 } else {
4208 tcg_gen_movi_tl(cpu_LO[acc], 0);
4210 break;
4214 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
4215 MemOp memop)
4217 TCGv t0 = tcg_const_tl(addr);
4218 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
4219 gen_store_gpr(t0, reg);
4220 tcg_temp_free(t0);
4223 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
4224 int rs)
4226 target_long offset;
4227 target_long addr;
4229 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
4230 case OPC_ADDIUPC:
4231 if (rs != 0) {
4232 offset = sextract32(ctx->opcode << 2, 0, 21);
4233 addr = addr_add(ctx, pc, offset);
4234 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4236 break;
4237 case R6_OPC_LWPC:
4238 offset = sextract32(ctx->opcode << 2, 0, 21);
4239 addr = addr_add(ctx, pc, offset);
4240 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4241 break;
4242 #if defined(TARGET_MIPS64)
4243 case OPC_LWUPC:
4244 check_mips_64(ctx);
4245 offset = sextract32(ctx->opcode << 2, 0, 21);
4246 addr = addr_add(ctx, pc, offset);
4247 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4248 break;
4249 #endif
4250 default:
4251 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
4252 case OPC_AUIPC:
4253 if (rs != 0) {
4254 offset = sextract32(ctx->opcode, 0, 16) << 16;
4255 addr = addr_add(ctx, pc, offset);
4256 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4258 break;
4259 case OPC_ALUIPC:
4260 if (rs != 0) {
4261 offset = sextract32(ctx->opcode, 0, 16) << 16;
4262 addr = ~0xFFFF & addr_add(ctx, pc, offset);
4263 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4265 break;
4266 #if defined(TARGET_MIPS64)
4267 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4268 case R6_OPC_LDPC + (1 << 16):
4269 case R6_OPC_LDPC + (2 << 16):
4270 case R6_OPC_LDPC + (3 << 16):
4271 check_mips_64(ctx);
4272 offset = sextract32(ctx->opcode << 3, 0, 21);
4273 addr = addr_add(ctx, (pc & ~0x7), offset);
4274 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4275 break;
4276 #endif
4277 default:
4278 MIPS_INVAL("OPC_PCREL");
4279 gen_reserved_instruction(ctx);
4280 break;
4282 break;
4286 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4288 TCGv t0, t1;
4290 if (rd == 0) {
4291 /* Treat as NOP. */
4292 return;
4295 t0 = tcg_temp_new();
4296 t1 = tcg_temp_new();
4298 gen_load_gpr(t0, rs);
4299 gen_load_gpr(t1, rt);
4301 switch (opc) {
4302 case R6_OPC_DIV:
4304 TCGv t2 = tcg_temp_new();
4305 TCGv t3 = tcg_temp_new();
4306 tcg_gen_ext32s_tl(t0, t0);
4307 tcg_gen_ext32s_tl(t1, t1);
4308 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4309 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4310 tcg_gen_and_tl(t2, t2, t3);
4311 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4312 tcg_gen_or_tl(t2, t2, t3);
4313 tcg_gen_movi_tl(t3, 0);
4314 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4315 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4316 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4317 tcg_temp_free(t3);
4318 tcg_temp_free(t2);
4320 break;
4321 case R6_OPC_MOD:
4323 TCGv t2 = tcg_temp_new();
4324 TCGv t3 = tcg_temp_new();
4325 tcg_gen_ext32s_tl(t0, t0);
4326 tcg_gen_ext32s_tl(t1, t1);
4327 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4328 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4329 tcg_gen_and_tl(t2, t2, t3);
4330 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4331 tcg_gen_or_tl(t2, t2, t3);
4332 tcg_gen_movi_tl(t3, 0);
4333 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4334 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4335 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4336 tcg_temp_free(t3);
4337 tcg_temp_free(t2);
4339 break;
4340 case R6_OPC_DIVU:
4342 TCGv t2 = tcg_const_tl(0);
4343 TCGv t3 = tcg_const_tl(1);
4344 tcg_gen_ext32u_tl(t0, t0);
4345 tcg_gen_ext32u_tl(t1, t1);
4346 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4347 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4348 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4349 tcg_temp_free(t3);
4350 tcg_temp_free(t2);
4352 break;
4353 case R6_OPC_MODU:
4355 TCGv t2 = tcg_const_tl(0);
4356 TCGv t3 = tcg_const_tl(1);
4357 tcg_gen_ext32u_tl(t0, t0);
4358 tcg_gen_ext32u_tl(t1, t1);
4359 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4360 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4361 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4362 tcg_temp_free(t3);
4363 tcg_temp_free(t2);
4365 break;
4366 case R6_OPC_MUL:
4368 TCGv_i32 t2 = tcg_temp_new_i32();
4369 TCGv_i32 t3 = tcg_temp_new_i32();
4370 tcg_gen_trunc_tl_i32(t2, t0);
4371 tcg_gen_trunc_tl_i32(t3, t1);
4372 tcg_gen_mul_i32(t2, t2, t3);
4373 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4374 tcg_temp_free_i32(t2);
4375 tcg_temp_free_i32(t3);
4377 break;
4378 case R6_OPC_MUH:
4380 TCGv_i32 t2 = tcg_temp_new_i32();
4381 TCGv_i32 t3 = tcg_temp_new_i32();
4382 tcg_gen_trunc_tl_i32(t2, t0);
4383 tcg_gen_trunc_tl_i32(t3, t1);
4384 tcg_gen_muls2_i32(t2, t3, t2, t3);
4385 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4386 tcg_temp_free_i32(t2);
4387 tcg_temp_free_i32(t3);
4389 break;
4390 case R6_OPC_MULU:
4392 TCGv_i32 t2 = tcg_temp_new_i32();
4393 TCGv_i32 t3 = tcg_temp_new_i32();
4394 tcg_gen_trunc_tl_i32(t2, t0);
4395 tcg_gen_trunc_tl_i32(t3, t1);
4396 tcg_gen_mul_i32(t2, t2, t3);
4397 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4398 tcg_temp_free_i32(t2);
4399 tcg_temp_free_i32(t3);
4401 break;
4402 case R6_OPC_MUHU:
4404 TCGv_i32 t2 = tcg_temp_new_i32();
4405 TCGv_i32 t3 = tcg_temp_new_i32();
4406 tcg_gen_trunc_tl_i32(t2, t0);
4407 tcg_gen_trunc_tl_i32(t3, t1);
4408 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4409 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4410 tcg_temp_free_i32(t2);
4411 tcg_temp_free_i32(t3);
4413 break;
4414 #if defined(TARGET_MIPS64)
4415 case R6_OPC_DDIV:
4417 TCGv t2 = tcg_temp_new();
4418 TCGv t3 = tcg_temp_new();
4419 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4420 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4421 tcg_gen_and_tl(t2, t2, t3);
4422 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4423 tcg_gen_or_tl(t2, t2, t3);
4424 tcg_gen_movi_tl(t3, 0);
4425 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4426 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4427 tcg_temp_free(t3);
4428 tcg_temp_free(t2);
4430 break;
4431 case R6_OPC_DMOD:
4433 TCGv t2 = tcg_temp_new();
4434 TCGv t3 = tcg_temp_new();
4435 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4436 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4437 tcg_gen_and_tl(t2, t2, t3);
4438 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4439 tcg_gen_or_tl(t2, t2, t3);
4440 tcg_gen_movi_tl(t3, 0);
4441 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4442 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4443 tcg_temp_free(t3);
4444 tcg_temp_free(t2);
4446 break;
4447 case R6_OPC_DDIVU:
4449 TCGv t2 = tcg_const_tl(0);
4450 TCGv t3 = tcg_const_tl(1);
4451 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4452 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4453 tcg_temp_free(t3);
4454 tcg_temp_free(t2);
4456 break;
4457 case R6_OPC_DMODU:
4459 TCGv t2 = tcg_const_tl(0);
4460 TCGv t3 = tcg_const_tl(1);
4461 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4462 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4463 tcg_temp_free(t3);
4464 tcg_temp_free(t2);
4466 break;
4467 case R6_OPC_DMUL:
4468 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4469 break;
4470 case R6_OPC_DMUH:
4472 TCGv t2 = tcg_temp_new();
4473 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4474 tcg_temp_free(t2);
4476 break;
4477 case R6_OPC_DMULU:
4478 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4479 break;
4480 case R6_OPC_DMUHU:
4482 TCGv t2 = tcg_temp_new();
4483 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4484 tcg_temp_free(t2);
4486 break;
4487 #endif
4488 default:
4489 MIPS_INVAL("r6 mul/div");
4490 gen_reserved_instruction(ctx);
4491 goto out;
4493 out:
4494 tcg_temp_free(t0);
4495 tcg_temp_free(t1);
4498 #if defined(TARGET_MIPS64)
4499 static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
4501 TCGv t0, t1;
4503 t0 = tcg_temp_new();
4504 t1 = tcg_temp_new();
4506 gen_load_gpr(t0, rs);
4507 gen_load_gpr(t1, rt);
4509 switch (opc) {
4510 case MMI_OPC_DIV1:
4512 TCGv t2 = tcg_temp_new();
4513 TCGv t3 = tcg_temp_new();
4514 tcg_gen_ext32s_tl(t0, t0);
4515 tcg_gen_ext32s_tl(t1, t1);
4516 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4517 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4518 tcg_gen_and_tl(t2, t2, t3);
4519 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4520 tcg_gen_or_tl(t2, t2, t3);
4521 tcg_gen_movi_tl(t3, 0);
4522 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4523 tcg_gen_div_tl(cpu_LO[1], t0, t1);
4524 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
4525 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4526 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4527 tcg_temp_free(t3);
4528 tcg_temp_free(t2);
4530 break;
4531 case MMI_OPC_DIVU1:
4533 TCGv t2 = tcg_const_tl(0);
4534 TCGv t3 = tcg_const_tl(1);
4535 tcg_gen_ext32u_tl(t0, t0);
4536 tcg_gen_ext32u_tl(t1, t1);
4537 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4538 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
4539 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
4540 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4541 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4542 tcg_temp_free(t3);
4543 tcg_temp_free(t2);
4545 break;
4546 default:
4547 MIPS_INVAL("div1 TX79");
4548 gen_reserved_instruction(ctx);
4549 goto out;
4551 out:
4552 tcg_temp_free(t0);
4553 tcg_temp_free(t1);
4555 #endif
4557 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4558 int acc, int rs, int rt)
4560 TCGv t0, t1;
4562 t0 = tcg_temp_new();
4563 t1 = tcg_temp_new();
4565 gen_load_gpr(t0, rs);
4566 gen_load_gpr(t1, rt);
4568 if (acc != 0) {
4569 check_dsp(ctx);
4572 switch (opc) {
4573 case OPC_DIV:
4575 TCGv t2 = tcg_temp_new();
4576 TCGv t3 = tcg_temp_new();
4577 tcg_gen_ext32s_tl(t0, t0);
4578 tcg_gen_ext32s_tl(t1, t1);
4579 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4580 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4581 tcg_gen_and_tl(t2, t2, t3);
4582 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4583 tcg_gen_or_tl(t2, t2, t3);
4584 tcg_gen_movi_tl(t3, 0);
4585 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4586 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4587 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4588 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4589 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4590 tcg_temp_free(t3);
4591 tcg_temp_free(t2);
4593 break;
4594 case OPC_DIVU:
4596 TCGv t2 = tcg_const_tl(0);
4597 TCGv t3 = tcg_const_tl(1);
4598 tcg_gen_ext32u_tl(t0, t0);
4599 tcg_gen_ext32u_tl(t1, t1);
4600 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4601 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4602 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4603 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4604 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4605 tcg_temp_free(t3);
4606 tcg_temp_free(t2);
4608 break;
4609 case OPC_MULT:
4611 TCGv_i32 t2 = tcg_temp_new_i32();
4612 TCGv_i32 t3 = tcg_temp_new_i32();
4613 tcg_gen_trunc_tl_i32(t2, t0);
4614 tcg_gen_trunc_tl_i32(t3, t1);
4615 tcg_gen_muls2_i32(t2, t3, t2, t3);
4616 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4617 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4618 tcg_temp_free_i32(t2);
4619 tcg_temp_free_i32(t3);
4621 break;
4622 case OPC_MULTU:
4624 TCGv_i32 t2 = tcg_temp_new_i32();
4625 TCGv_i32 t3 = tcg_temp_new_i32();
4626 tcg_gen_trunc_tl_i32(t2, t0);
4627 tcg_gen_trunc_tl_i32(t3, t1);
4628 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4629 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4630 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4631 tcg_temp_free_i32(t2);
4632 tcg_temp_free_i32(t3);
4634 break;
4635 #if defined(TARGET_MIPS64)
4636 case OPC_DDIV:
4638 TCGv t2 = tcg_temp_new();
4639 TCGv t3 = tcg_temp_new();
4640 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4641 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4642 tcg_gen_and_tl(t2, t2, t3);
4643 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4644 tcg_gen_or_tl(t2, t2, t3);
4645 tcg_gen_movi_tl(t3, 0);
4646 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4647 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4648 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4649 tcg_temp_free(t3);
4650 tcg_temp_free(t2);
4652 break;
4653 case OPC_DDIVU:
4655 TCGv t2 = tcg_const_tl(0);
4656 TCGv t3 = tcg_const_tl(1);
4657 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4658 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
4659 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
4660 tcg_temp_free(t3);
4661 tcg_temp_free(t2);
4663 break;
4664 case OPC_DMULT:
4665 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4666 break;
4667 case OPC_DMULTU:
4668 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4669 break;
4670 #endif
4671 case OPC_MADD:
4673 TCGv_i64 t2 = tcg_temp_new_i64();
4674 TCGv_i64 t3 = tcg_temp_new_i64();
4676 tcg_gen_ext_tl_i64(t2, t0);
4677 tcg_gen_ext_tl_i64(t3, t1);
4678 tcg_gen_mul_i64(t2, t2, t3);
4679 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4680 tcg_gen_add_i64(t2, t2, t3);
4681 tcg_temp_free_i64(t3);
4682 gen_move_low32(cpu_LO[acc], t2);
4683 gen_move_high32(cpu_HI[acc], t2);
4684 tcg_temp_free_i64(t2);
4686 break;
4687 case OPC_MADDU:
4689 TCGv_i64 t2 = tcg_temp_new_i64();
4690 TCGv_i64 t3 = tcg_temp_new_i64();
4692 tcg_gen_ext32u_tl(t0, t0);
4693 tcg_gen_ext32u_tl(t1, t1);
4694 tcg_gen_extu_tl_i64(t2, t0);
4695 tcg_gen_extu_tl_i64(t3, t1);
4696 tcg_gen_mul_i64(t2, t2, t3);
4697 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4698 tcg_gen_add_i64(t2, t2, t3);
4699 tcg_temp_free_i64(t3);
4700 gen_move_low32(cpu_LO[acc], t2);
4701 gen_move_high32(cpu_HI[acc], t2);
4702 tcg_temp_free_i64(t2);
4704 break;
4705 case OPC_MSUB:
4707 TCGv_i64 t2 = tcg_temp_new_i64();
4708 TCGv_i64 t3 = tcg_temp_new_i64();
4710 tcg_gen_ext_tl_i64(t2, t0);
4711 tcg_gen_ext_tl_i64(t3, t1);
4712 tcg_gen_mul_i64(t2, t2, t3);
4713 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4714 tcg_gen_sub_i64(t2, t3, t2);
4715 tcg_temp_free_i64(t3);
4716 gen_move_low32(cpu_LO[acc], t2);
4717 gen_move_high32(cpu_HI[acc], t2);
4718 tcg_temp_free_i64(t2);
4720 break;
4721 case OPC_MSUBU:
4723 TCGv_i64 t2 = tcg_temp_new_i64();
4724 TCGv_i64 t3 = tcg_temp_new_i64();
4726 tcg_gen_ext32u_tl(t0, t0);
4727 tcg_gen_ext32u_tl(t1, t1);
4728 tcg_gen_extu_tl_i64(t2, t0);
4729 tcg_gen_extu_tl_i64(t3, t1);
4730 tcg_gen_mul_i64(t2, t2, t3);
4731 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4732 tcg_gen_sub_i64(t2, t3, t2);
4733 tcg_temp_free_i64(t3);
4734 gen_move_low32(cpu_LO[acc], t2);
4735 gen_move_high32(cpu_HI[acc], t2);
4736 tcg_temp_free_i64(t2);
4738 break;
4739 default:
4740 MIPS_INVAL("mul/div");
4741 gen_reserved_instruction(ctx);
4742 goto out;
4744 out:
4745 tcg_temp_free(t0);
4746 tcg_temp_free(t1);
4750 * These MULT[U] and MADD[U] instructions implemented in for example
4751 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
4752 * architectures are special three-operand variants with the syntax
4754 * MULT[U][1] rd, rs, rt
4756 * such that
4758 * (rd, LO, HI) <- rs * rt
4760 * and
4762 * MADD[U][1] rd, rs, rt
4764 * such that
4766 * (rd, LO, HI) <- (LO, HI) + rs * rt
4768 * where the low-order 32-bits of the result is placed into both the
4769 * GPR rd and the special register LO. The high-order 32-bits of the
4770 * result is placed into the special register HI.
4772 * If the GPR rd is omitted in assembly language, it is taken to be 0,
4773 * which is the zero register that always reads as 0.
4775 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
4776 int rd, int rs, int rt)
4778 TCGv t0 = tcg_temp_new();
4779 TCGv t1 = tcg_temp_new();
4780 int acc = 0;
4782 gen_load_gpr(t0, rs);
4783 gen_load_gpr(t1, rt);
4785 switch (opc) {
4786 case MMI_OPC_MULT1:
4787 acc = 1;
4788 /* Fall through */
4789 case OPC_MULT:
4791 TCGv_i32 t2 = tcg_temp_new_i32();
4792 TCGv_i32 t3 = tcg_temp_new_i32();
4793 tcg_gen_trunc_tl_i32(t2, t0);
4794 tcg_gen_trunc_tl_i32(t3, t1);
4795 tcg_gen_muls2_i32(t2, t3, t2, t3);
4796 if (rd) {
4797 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4799 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4800 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4801 tcg_temp_free_i32(t2);
4802 tcg_temp_free_i32(t3);
4804 break;
4805 case MMI_OPC_MULTU1:
4806 acc = 1;
4807 /* Fall through */
4808 case OPC_MULTU:
4810 TCGv_i32 t2 = tcg_temp_new_i32();
4811 TCGv_i32 t3 = tcg_temp_new_i32();
4812 tcg_gen_trunc_tl_i32(t2, t0);
4813 tcg_gen_trunc_tl_i32(t3, t1);
4814 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4815 if (rd) {
4816 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4818 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4819 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4820 tcg_temp_free_i32(t2);
4821 tcg_temp_free_i32(t3);
4823 break;
4824 case MMI_OPC_MADD1:
4825 acc = 1;
4826 /* Fall through */
4827 case MMI_OPC_MADD:
4829 TCGv_i64 t2 = tcg_temp_new_i64();
4830 TCGv_i64 t3 = tcg_temp_new_i64();
4832 tcg_gen_ext_tl_i64(t2, t0);
4833 tcg_gen_ext_tl_i64(t3, t1);
4834 tcg_gen_mul_i64(t2, t2, t3);
4835 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4836 tcg_gen_add_i64(t2, t2, t3);
4837 tcg_temp_free_i64(t3);
4838 gen_move_low32(cpu_LO[acc], t2);
4839 gen_move_high32(cpu_HI[acc], t2);
4840 if (rd) {
4841 gen_move_low32(cpu_gpr[rd], t2);
4843 tcg_temp_free_i64(t2);
4845 break;
4846 case MMI_OPC_MADDU1:
4847 acc = 1;
4848 /* Fall through */
4849 case MMI_OPC_MADDU:
4851 TCGv_i64 t2 = tcg_temp_new_i64();
4852 TCGv_i64 t3 = tcg_temp_new_i64();
4854 tcg_gen_ext32u_tl(t0, t0);
4855 tcg_gen_ext32u_tl(t1, t1);
4856 tcg_gen_extu_tl_i64(t2, t0);
4857 tcg_gen_extu_tl_i64(t3, t1);
4858 tcg_gen_mul_i64(t2, t2, t3);
4859 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4860 tcg_gen_add_i64(t2, t2, t3);
4861 tcg_temp_free_i64(t3);
4862 gen_move_low32(cpu_LO[acc], t2);
4863 gen_move_high32(cpu_HI[acc], t2);
4864 if (rd) {
4865 gen_move_low32(cpu_gpr[rd], t2);
4867 tcg_temp_free_i64(t2);
4869 break;
4870 default:
4871 MIPS_INVAL("mul/madd TXx9");
4872 gen_reserved_instruction(ctx);
4873 goto out;
4876 out:
4877 tcg_temp_free(t0);
4878 tcg_temp_free(t1);
4881 static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc,
4882 int rd, int rs, int rt)
4884 TCGv t0 = tcg_temp_new();
4885 TCGv t1 = tcg_temp_new();
4887 gen_load_gpr(t0, rs);
4888 gen_load_gpr(t1, rt);
4890 switch (opc) {
4891 case OPC_VR54XX_MULS:
4892 gen_helper_muls(t0, cpu_env, t0, t1);
4893 break;
4894 case OPC_VR54XX_MULSU:
4895 gen_helper_mulsu(t0, cpu_env, t0, t1);
4896 break;
4897 case OPC_VR54XX_MACC:
4898 gen_helper_macc(t0, cpu_env, t0, t1);
4899 break;
4900 case OPC_VR54XX_MACCU:
4901 gen_helper_maccu(t0, cpu_env, t0, t1);
4902 break;
4903 case OPC_VR54XX_MSAC:
4904 gen_helper_msac(t0, cpu_env, t0, t1);
4905 break;
4906 case OPC_VR54XX_MSACU:
4907 gen_helper_msacu(t0, cpu_env, t0, t1);
4908 break;
4909 case OPC_VR54XX_MULHI:
4910 gen_helper_mulhi(t0, cpu_env, t0, t1);
4911 break;
4912 case OPC_VR54XX_MULHIU:
4913 gen_helper_mulhiu(t0, cpu_env, t0, t1);
4914 break;
4915 case OPC_VR54XX_MULSHI:
4916 gen_helper_mulshi(t0, cpu_env, t0, t1);
4917 break;
4918 case OPC_VR54XX_MULSHIU:
4919 gen_helper_mulshiu(t0, cpu_env, t0, t1);
4920 break;
4921 case OPC_VR54XX_MACCHI:
4922 gen_helper_macchi(t0, cpu_env, t0, t1);
4923 break;
4924 case OPC_VR54XX_MACCHIU:
4925 gen_helper_macchiu(t0, cpu_env, t0, t1);
4926 break;
4927 case OPC_VR54XX_MSACHI:
4928 gen_helper_msachi(t0, cpu_env, t0, t1);
4929 break;
4930 case OPC_VR54XX_MSACHIU:
4931 gen_helper_msachiu(t0, cpu_env, t0, t1);
4932 break;
4933 default:
4934 MIPS_INVAL("mul vr54xx");
4935 gen_reserved_instruction(ctx);
4936 goto out;
4938 gen_store_gpr(t0, rd);
4940 out:
4941 tcg_temp_free(t0);
4942 tcg_temp_free(t1);
4945 static void gen_cl(DisasContext *ctx, uint32_t opc,
4946 int rd, int rs)
4948 TCGv t0;
4950 if (rd == 0) {
4951 /* Treat as NOP. */
4952 return;
4954 t0 = cpu_gpr[rd];
4955 gen_load_gpr(t0, rs);
4957 switch (opc) {
4958 case OPC_CLO:
4959 case R6_OPC_CLO:
4960 #if defined(TARGET_MIPS64)
4961 case OPC_DCLO:
4962 case R6_OPC_DCLO:
4963 #endif
4964 tcg_gen_not_tl(t0, t0);
4965 break;
4968 switch (opc) {
4969 case OPC_CLO:
4970 case R6_OPC_CLO:
4971 case OPC_CLZ:
4972 case R6_OPC_CLZ:
4973 tcg_gen_ext32u_tl(t0, t0);
4974 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
4975 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
4976 break;
4977 #if defined(TARGET_MIPS64)
4978 case OPC_DCLO:
4979 case R6_OPC_DCLO:
4980 case OPC_DCLZ:
4981 case R6_OPC_DCLZ:
4982 tcg_gen_clzi_i64(t0, t0, 64);
4983 break;
4984 #endif
4988 /* Godson integer instructions */
4989 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
4990 int rd, int rs, int rt)
4992 TCGv t0, t1;
4994 if (rd == 0) {
4995 /* Treat as NOP. */
4996 return;
4999 switch (opc) {
5000 case OPC_MULT_G_2E:
5001 case OPC_MULT_G_2F:
5002 case OPC_MULTU_G_2E:
5003 case OPC_MULTU_G_2F:
5004 #if defined(TARGET_MIPS64)
5005 case OPC_DMULT_G_2E:
5006 case OPC_DMULT_G_2F:
5007 case OPC_DMULTU_G_2E:
5008 case OPC_DMULTU_G_2F:
5009 #endif
5010 t0 = tcg_temp_new();
5011 t1 = tcg_temp_new();
5012 break;
5013 default:
5014 t0 = tcg_temp_local_new();
5015 t1 = tcg_temp_local_new();
5016 break;
5019 gen_load_gpr(t0, rs);
5020 gen_load_gpr(t1, rt);
5022 switch (opc) {
5023 case OPC_MULT_G_2E:
5024 case OPC_MULT_G_2F:
5025 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5026 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5027 break;
5028 case OPC_MULTU_G_2E:
5029 case OPC_MULTU_G_2F:
5030 tcg_gen_ext32u_tl(t0, t0);
5031 tcg_gen_ext32u_tl(t1, t1);
5032 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5033 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5034 break;
5035 case OPC_DIV_G_2E:
5036 case OPC_DIV_G_2F:
5038 TCGLabel *l1 = gen_new_label();
5039 TCGLabel *l2 = gen_new_label();
5040 TCGLabel *l3 = gen_new_label();
5041 tcg_gen_ext32s_tl(t0, t0);
5042 tcg_gen_ext32s_tl(t1, t1);
5043 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5044 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5045 tcg_gen_br(l3);
5046 gen_set_label(l1);
5047 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5048 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5049 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5050 tcg_gen_br(l3);
5051 gen_set_label(l2);
5052 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5053 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5054 gen_set_label(l3);
5056 break;
5057 case OPC_DIVU_G_2E:
5058 case OPC_DIVU_G_2F:
5060 TCGLabel *l1 = gen_new_label();
5061 TCGLabel *l2 = gen_new_label();
5062 tcg_gen_ext32u_tl(t0, t0);
5063 tcg_gen_ext32u_tl(t1, t1);
5064 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5065 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5066 tcg_gen_br(l2);
5067 gen_set_label(l1);
5068 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5069 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5070 gen_set_label(l2);
5072 break;
5073 case OPC_MOD_G_2E:
5074 case OPC_MOD_G_2F:
5076 TCGLabel *l1 = gen_new_label();
5077 TCGLabel *l2 = gen_new_label();
5078 TCGLabel *l3 = gen_new_label();
5079 tcg_gen_ext32u_tl(t0, t0);
5080 tcg_gen_ext32u_tl(t1, t1);
5081 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5082 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5083 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5084 gen_set_label(l1);
5085 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5086 tcg_gen_br(l3);
5087 gen_set_label(l2);
5088 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5089 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5090 gen_set_label(l3);
5092 break;
5093 case OPC_MODU_G_2E:
5094 case OPC_MODU_G_2F:
5096 TCGLabel *l1 = gen_new_label();
5097 TCGLabel *l2 = gen_new_label();
5098 tcg_gen_ext32u_tl(t0, t0);
5099 tcg_gen_ext32u_tl(t1, t1);
5100 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5101 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5102 tcg_gen_br(l2);
5103 gen_set_label(l1);
5104 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5105 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5106 gen_set_label(l2);
5108 break;
5109 #if defined(TARGET_MIPS64)
5110 case OPC_DMULT_G_2E:
5111 case OPC_DMULT_G_2F:
5112 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5113 break;
5114 case OPC_DMULTU_G_2E:
5115 case OPC_DMULTU_G_2F:
5116 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5117 break;
5118 case OPC_DDIV_G_2E:
5119 case OPC_DDIV_G_2F:
5121 TCGLabel *l1 = gen_new_label();
5122 TCGLabel *l2 = gen_new_label();
5123 TCGLabel *l3 = gen_new_label();
5124 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5125 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5126 tcg_gen_br(l3);
5127 gen_set_label(l1);
5128 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5129 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5130 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5131 tcg_gen_br(l3);
5132 gen_set_label(l2);
5133 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5134 gen_set_label(l3);
5136 break;
5137 case OPC_DDIVU_G_2E:
5138 case OPC_DDIVU_G_2F:
5140 TCGLabel *l1 = gen_new_label();
5141 TCGLabel *l2 = gen_new_label();
5142 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5143 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5144 tcg_gen_br(l2);
5145 gen_set_label(l1);
5146 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5147 gen_set_label(l2);
5149 break;
5150 case OPC_DMOD_G_2E:
5151 case OPC_DMOD_G_2F:
5153 TCGLabel *l1 = gen_new_label();
5154 TCGLabel *l2 = gen_new_label();
5155 TCGLabel *l3 = gen_new_label();
5156 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5157 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5158 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5159 gen_set_label(l1);
5160 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5161 tcg_gen_br(l3);
5162 gen_set_label(l2);
5163 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5164 gen_set_label(l3);
5166 break;
5167 case OPC_DMODU_G_2E:
5168 case OPC_DMODU_G_2F:
5170 TCGLabel *l1 = gen_new_label();
5171 TCGLabel *l2 = gen_new_label();
5172 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5173 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5174 tcg_gen_br(l2);
5175 gen_set_label(l1);
5176 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5177 gen_set_label(l2);
5179 break;
5180 #endif
5183 tcg_temp_free(t0);
5184 tcg_temp_free(t1);
5187 /* Loongson multimedia instructions */
5188 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
5190 uint32_t opc, shift_max;
5191 TCGv_i64 t0, t1;
5192 TCGCond cond;
5194 opc = MASK_LMMI(ctx->opcode);
5195 switch (opc) {
5196 case OPC_ADD_CP2:
5197 case OPC_SUB_CP2:
5198 case OPC_DADD_CP2:
5199 case OPC_DSUB_CP2:
5200 t0 = tcg_temp_local_new_i64();
5201 t1 = tcg_temp_local_new_i64();
5202 break;
5203 default:
5204 t0 = tcg_temp_new_i64();
5205 t1 = tcg_temp_new_i64();
5206 break;
5209 check_cp1_enabled(ctx);
5210 gen_load_fpr64(ctx, t0, rs);
5211 gen_load_fpr64(ctx, t1, rt);
5213 switch (opc) {
5214 case OPC_PADDSH:
5215 gen_helper_paddsh(t0, t0, t1);
5216 break;
5217 case OPC_PADDUSH:
5218 gen_helper_paddush(t0, t0, t1);
5219 break;
5220 case OPC_PADDH:
5221 gen_helper_paddh(t0, t0, t1);
5222 break;
5223 case OPC_PADDW:
5224 gen_helper_paddw(t0, t0, t1);
5225 break;
5226 case OPC_PADDSB:
5227 gen_helper_paddsb(t0, t0, t1);
5228 break;
5229 case OPC_PADDUSB:
5230 gen_helper_paddusb(t0, t0, t1);
5231 break;
5232 case OPC_PADDB:
5233 gen_helper_paddb(t0, t0, t1);
5234 break;
5236 case OPC_PSUBSH:
5237 gen_helper_psubsh(t0, t0, t1);
5238 break;
5239 case OPC_PSUBUSH:
5240 gen_helper_psubush(t0, t0, t1);
5241 break;
5242 case OPC_PSUBH:
5243 gen_helper_psubh(t0, t0, t1);
5244 break;
5245 case OPC_PSUBW:
5246 gen_helper_psubw(t0, t0, t1);
5247 break;
5248 case OPC_PSUBSB:
5249 gen_helper_psubsb(t0, t0, t1);
5250 break;
5251 case OPC_PSUBUSB:
5252 gen_helper_psubusb(t0, t0, t1);
5253 break;
5254 case OPC_PSUBB:
5255 gen_helper_psubb(t0, t0, t1);
5256 break;
5258 case OPC_PSHUFH:
5259 gen_helper_pshufh(t0, t0, t1);
5260 break;
5261 case OPC_PACKSSWH:
5262 gen_helper_packsswh(t0, t0, t1);
5263 break;
5264 case OPC_PACKSSHB:
5265 gen_helper_packsshb(t0, t0, t1);
5266 break;
5267 case OPC_PACKUSHB:
5268 gen_helper_packushb(t0, t0, t1);
5269 break;
5271 case OPC_PUNPCKLHW:
5272 gen_helper_punpcklhw(t0, t0, t1);
5273 break;
5274 case OPC_PUNPCKHHW:
5275 gen_helper_punpckhhw(t0, t0, t1);
5276 break;
5277 case OPC_PUNPCKLBH:
5278 gen_helper_punpcklbh(t0, t0, t1);
5279 break;
5280 case OPC_PUNPCKHBH:
5281 gen_helper_punpckhbh(t0, t0, t1);
5282 break;
5283 case OPC_PUNPCKLWD:
5284 gen_helper_punpcklwd(t0, t0, t1);
5285 break;
5286 case OPC_PUNPCKHWD:
5287 gen_helper_punpckhwd(t0, t0, t1);
5288 break;
5290 case OPC_PAVGH:
5291 gen_helper_pavgh(t0, t0, t1);
5292 break;
5293 case OPC_PAVGB:
5294 gen_helper_pavgb(t0, t0, t1);
5295 break;
5296 case OPC_PMAXSH:
5297 gen_helper_pmaxsh(t0, t0, t1);
5298 break;
5299 case OPC_PMINSH:
5300 gen_helper_pminsh(t0, t0, t1);
5301 break;
5302 case OPC_PMAXUB:
5303 gen_helper_pmaxub(t0, t0, t1);
5304 break;
5305 case OPC_PMINUB:
5306 gen_helper_pminub(t0, t0, t1);
5307 break;
5309 case OPC_PCMPEQW:
5310 gen_helper_pcmpeqw(t0, t0, t1);
5311 break;
5312 case OPC_PCMPGTW:
5313 gen_helper_pcmpgtw(t0, t0, t1);
5314 break;
5315 case OPC_PCMPEQH:
5316 gen_helper_pcmpeqh(t0, t0, t1);
5317 break;
5318 case OPC_PCMPGTH:
5319 gen_helper_pcmpgth(t0, t0, t1);
5320 break;
5321 case OPC_PCMPEQB:
5322 gen_helper_pcmpeqb(t0, t0, t1);
5323 break;
5324 case OPC_PCMPGTB:
5325 gen_helper_pcmpgtb(t0, t0, t1);
5326 break;
5328 case OPC_PSLLW:
5329 gen_helper_psllw(t0, t0, t1);
5330 break;
5331 case OPC_PSLLH:
5332 gen_helper_psllh(t0, t0, t1);
5333 break;
5334 case OPC_PSRLW:
5335 gen_helper_psrlw(t0, t0, t1);
5336 break;
5337 case OPC_PSRLH:
5338 gen_helper_psrlh(t0, t0, t1);
5339 break;
5340 case OPC_PSRAW:
5341 gen_helper_psraw(t0, t0, t1);
5342 break;
5343 case OPC_PSRAH:
5344 gen_helper_psrah(t0, t0, t1);
5345 break;
5347 case OPC_PMULLH:
5348 gen_helper_pmullh(t0, t0, t1);
5349 break;
5350 case OPC_PMULHH:
5351 gen_helper_pmulhh(t0, t0, t1);
5352 break;
5353 case OPC_PMULHUH:
5354 gen_helper_pmulhuh(t0, t0, t1);
5355 break;
5356 case OPC_PMADDHW:
5357 gen_helper_pmaddhw(t0, t0, t1);
5358 break;
5360 case OPC_PASUBUB:
5361 gen_helper_pasubub(t0, t0, t1);
5362 break;
5363 case OPC_BIADD:
5364 gen_helper_biadd(t0, t0);
5365 break;
5366 case OPC_PMOVMSKB:
5367 gen_helper_pmovmskb(t0, t0);
5368 break;
5370 case OPC_PADDD:
5371 tcg_gen_add_i64(t0, t0, t1);
5372 break;
5373 case OPC_PSUBD:
5374 tcg_gen_sub_i64(t0, t0, t1);
5375 break;
5376 case OPC_XOR_CP2:
5377 tcg_gen_xor_i64(t0, t0, t1);
5378 break;
5379 case OPC_NOR_CP2:
5380 tcg_gen_nor_i64(t0, t0, t1);
5381 break;
5382 case OPC_AND_CP2:
5383 tcg_gen_and_i64(t0, t0, t1);
5384 break;
5385 case OPC_OR_CP2:
5386 tcg_gen_or_i64(t0, t0, t1);
5387 break;
5389 case OPC_PANDN:
5390 tcg_gen_andc_i64(t0, t1, t0);
5391 break;
5393 case OPC_PINSRH_0:
5394 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
5395 break;
5396 case OPC_PINSRH_1:
5397 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
5398 break;
5399 case OPC_PINSRH_2:
5400 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
5401 break;
5402 case OPC_PINSRH_3:
5403 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
5404 break;
5406 case OPC_PEXTRH:
5407 tcg_gen_andi_i64(t1, t1, 3);
5408 tcg_gen_shli_i64(t1, t1, 4);
5409 tcg_gen_shr_i64(t0, t0, t1);
5410 tcg_gen_ext16u_i64(t0, t0);
5411 break;
5413 case OPC_ADDU_CP2:
5414 tcg_gen_add_i64(t0, t0, t1);
5415 tcg_gen_ext32s_i64(t0, t0);
5416 break;
5417 case OPC_SUBU_CP2:
5418 tcg_gen_sub_i64(t0, t0, t1);
5419 tcg_gen_ext32s_i64(t0, t0);
5420 break;
5422 case OPC_SLL_CP2:
5423 shift_max = 32;
5424 goto do_shift;
5425 case OPC_SRL_CP2:
5426 shift_max = 32;
5427 goto do_shift;
5428 case OPC_SRA_CP2:
5429 shift_max = 32;
5430 goto do_shift;
5431 case OPC_DSLL_CP2:
5432 shift_max = 64;
5433 goto do_shift;
5434 case OPC_DSRL_CP2:
5435 shift_max = 64;
5436 goto do_shift;
5437 case OPC_DSRA_CP2:
5438 shift_max = 64;
5439 goto do_shift;
5440 do_shift:
5441 /* Make sure shift count isn't TCG undefined behaviour. */
5442 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5444 switch (opc) {
5445 case OPC_SLL_CP2:
5446 case OPC_DSLL_CP2:
5447 tcg_gen_shl_i64(t0, t0, t1);
5448 break;
5449 case OPC_SRA_CP2:
5450 case OPC_DSRA_CP2:
5452 * Since SRA is UndefinedResult without sign-extended inputs,
5453 * we can treat SRA and DSRA the same.
5455 tcg_gen_sar_i64(t0, t0, t1);
5456 break;
5457 case OPC_SRL_CP2:
5458 /* We want to shift in zeros for SRL; zero-extend first. */
5459 tcg_gen_ext32u_i64(t0, t0);
5460 /* FALLTHRU */
5461 case OPC_DSRL_CP2:
5462 tcg_gen_shr_i64(t0, t0, t1);
5463 break;
5466 if (shift_max == 32) {
5467 tcg_gen_ext32s_i64(t0, t0);
5470 /* Shifts larger than MAX produce zero. */
5471 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5472 tcg_gen_neg_i64(t1, t1);
5473 tcg_gen_and_i64(t0, t0, t1);
5474 break;
5476 case OPC_ADD_CP2:
5477 case OPC_DADD_CP2:
5479 TCGv_i64 t2 = tcg_temp_new_i64();
5480 TCGLabel *lab = gen_new_label();
5482 tcg_gen_mov_i64(t2, t0);
5483 tcg_gen_add_i64(t0, t1, t2);
5484 if (opc == OPC_ADD_CP2) {
5485 tcg_gen_ext32s_i64(t0, t0);
5487 tcg_gen_xor_i64(t1, t1, t2);
5488 tcg_gen_xor_i64(t2, t2, t0);
5489 tcg_gen_andc_i64(t1, t2, t1);
5490 tcg_temp_free_i64(t2);
5491 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5492 generate_exception(ctx, EXCP_OVERFLOW);
5493 gen_set_label(lab);
5494 break;
5497 case OPC_SUB_CP2:
5498 case OPC_DSUB_CP2:
5500 TCGv_i64 t2 = tcg_temp_new_i64();
5501 TCGLabel *lab = gen_new_label();
5503 tcg_gen_mov_i64(t2, t0);
5504 tcg_gen_sub_i64(t0, t1, t2);
5505 if (opc == OPC_SUB_CP2) {
5506 tcg_gen_ext32s_i64(t0, t0);
5508 tcg_gen_xor_i64(t1, t1, t2);
5509 tcg_gen_xor_i64(t2, t2, t0);
5510 tcg_gen_and_i64(t1, t1, t2);
5511 tcg_temp_free_i64(t2);
5512 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5513 generate_exception(ctx, EXCP_OVERFLOW);
5514 gen_set_label(lab);
5515 break;
5518 case OPC_PMULUW:
5519 tcg_gen_ext32u_i64(t0, t0);
5520 tcg_gen_ext32u_i64(t1, t1);
5521 tcg_gen_mul_i64(t0, t0, t1);
5522 break;
5524 case OPC_SEQU_CP2:
5525 case OPC_SEQ_CP2:
5526 cond = TCG_COND_EQ;
5527 goto do_cc_cond;
5528 break;
5529 case OPC_SLTU_CP2:
5530 cond = TCG_COND_LTU;
5531 goto do_cc_cond;
5532 break;
5533 case OPC_SLT_CP2:
5534 cond = TCG_COND_LT;
5535 goto do_cc_cond;
5536 break;
5537 case OPC_SLEU_CP2:
5538 cond = TCG_COND_LEU;
5539 goto do_cc_cond;
5540 break;
5541 case OPC_SLE_CP2:
5542 cond = TCG_COND_LE;
5543 do_cc_cond:
5545 int cc = (ctx->opcode >> 8) & 0x7;
5546 TCGv_i64 t64 = tcg_temp_new_i64();
5547 TCGv_i32 t32 = tcg_temp_new_i32();
5549 tcg_gen_setcond_i64(cond, t64, t0, t1);
5550 tcg_gen_extrl_i64_i32(t32, t64);
5551 tcg_gen_deposit_i32(fpu_fcr31, fpu_fcr31, t32,
5552 get_fp_bit(cc), 1);
5554 tcg_temp_free_i32(t32);
5555 tcg_temp_free_i64(t64);
5557 goto no_rd;
5558 break;
5559 default:
5560 MIPS_INVAL("loongson_cp2");
5561 gen_reserved_instruction(ctx);
5562 return;
5565 gen_store_fpr64(ctx, t0, rd);
5567 no_rd:
5568 tcg_temp_free_i64(t0);
5569 tcg_temp_free_i64(t1);
5572 static void gen_loongson_lswc2(DisasContext *ctx, int rt,
5573 int rs, int rd)
5575 TCGv t0, t1, t2;
5576 TCGv_i32 fp0;
5577 #if defined(TARGET_MIPS64)
5578 int lsq_rt1 = ctx->opcode & 0x1f;
5579 int lsq_offset = sextract32(ctx->opcode, 6, 9) << 4;
5580 #endif
5581 int shf_offset = sextract32(ctx->opcode, 6, 8);
5583 t0 = tcg_temp_new();
5585 switch (MASK_LOONGSON_GSLSQ(ctx->opcode)) {
5586 #if defined(TARGET_MIPS64)
5587 case OPC_GSLQ:
5588 t1 = tcg_temp_new();
5589 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5590 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5591 ctx->default_tcg_memop_mask);
5592 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5593 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
5594 ctx->default_tcg_memop_mask);
5595 gen_store_gpr(t1, rt);
5596 gen_store_gpr(t0, lsq_rt1);
5597 tcg_temp_free(t1);
5598 break;
5599 case OPC_GSLQC1:
5600 check_cp1_enabled(ctx);
5601 t1 = tcg_temp_new();
5602 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5603 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5604 ctx->default_tcg_memop_mask);
5605 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5606 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
5607 ctx->default_tcg_memop_mask);
5608 gen_store_fpr64(ctx, t1, rt);
5609 gen_store_fpr64(ctx, t0, lsq_rt1);
5610 tcg_temp_free(t1);
5611 break;
5612 case OPC_GSSQ:
5613 t1 = tcg_temp_new();
5614 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5615 gen_load_gpr(t1, rt);
5616 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5617 ctx->default_tcg_memop_mask);
5618 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5619 gen_load_gpr(t1, lsq_rt1);
5620 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5621 ctx->default_tcg_memop_mask);
5622 tcg_temp_free(t1);
5623 break;
5624 case OPC_GSSQC1:
5625 check_cp1_enabled(ctx);
5626 t1 = tcg_temp_new();
5627 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5628 gen_load_fpr64(ctx, t1, rt);
5629 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5630 ctx->default_tcg_memop_mask);
5631 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5632 gen_load_fpr64(ctx, t1, lsq_rt1);
5633 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5634 ctx->default_tcg_memop_mask);
5635 tcg_temp_free(t1);
5636 break;
5637 #endif
5638 case OPC_GSSHFL:
5639 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
5640 case OPC_GSLWLC1:
5641 check_cp1_enabled(ctx);
5642 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5643 t1 = tcg_temp_new();
5644 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
5645 tcg_gen_andi_tl(t1, t0, 3);
5646 #ifndef TARGET_WORDS_BIGENDIAN
5647 tcg_gen_xori_tl(t1, t1, 3);
5648 #endif
5649 tcg_gen_shli_tl(t1, t1, 3);
5650 tcg_gen_andi_tl(t0, t0, ~3);
5651 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
5652 tcg_gen_shl_tl(t0, t0, t1);
5653 t2 = tcg_const_tl(-1);
5654 tcg_gen_shl_tl(t2, t2, t1);
5655 fp0 = tcg_temp_new_i32();
5656 gen_load_fpr32(ctx, fp0, rt);
5657 tcg_gen_ext_i32_tl(t1, fp0);
5658 tcg_gen_andc_tl(t1, t1, t2);
5659 tcg_temp_free(t2);
5660 tcg_gen_or_tl(t0, t0, t1);
5661 tcg_temp_free(t1);
5662 #if defined(TARGET_MIPS64)
5663 tcg_gen_extrl_i64_i32(fp0, t0);
5664 #else
5665 tcg_gen_ext32s_tl(fp0, t0);
5666 #endif
5667 gen_store_fpr32(ctx, fp0, rt);
5668 tcg_temp_free_i32(fp0);
5669 break;
5670 case OPC_GSLWRC1:
5671 check_cp1_enabled(ctx);
5672 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5673 t1 = tcg_temp_new();
5674 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
5675 tcg_gen_andi_tl(t1, t0, 3);
5676 #ifdef TARGET_WORDS_BIGENDIAN
5677 tcg_gen_xori_tl(t1, t1, 3);
5678 #endif
5679 tcg_gen_shli_tl(t1, t1, 3);
5680 tcg_gen_andi_tl(t0, t0, ~3);
5681 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
5682 tcg_gen_shr_tl(t0, t0, t1);
5683 tcg_gen_xori_tl(t1, t1, 31);
5684 t2 = tcg_const_tl(0xfffffffeull);
5685 tcg_gen_shl_tl(t2, t2, t1);
5686 fp0 = tcg_temp_new_i32();
5687 gen_load_fpr32(ctx, fp0, rt);
5688 tcg_gen_ext_i32_tl(t1, fp0);
5689 tcg_gen_and_tl(t1, t1, t2);
5690 tcg_temp_free(t2);
5691 tcg_gen_or_tl(t0, t0, t1);
5692 tcg_temp_free(t1);
5693 #if defined(TARGET_MIPS64)
5694 tcg_gen_extrl_i64_i32(fp0, t0);
5695 #else
5696 tcg_gen_ext32s_tl(fp0, t0);
5697 #endif
5698 gen_store_fpr32(ctx, fp0, rt);
5699 tcg_temp_free_i32(fp0);
5700 break;
5701 #if defined(TARGET_MIPS64)
5702 case OPC_GSLDLC1:
5703 check_cp1_enabled(ctx);
5704 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5705 t1 = tcg_temp_new();
5706 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
5707 tcg_gen_andi_tl(t1, t0, 7);
5708 #ifndef TARGET_WORDS_BIGENDIAN
5709 tcg_gen_xori_tl(t1, t1, 7);
5710 #endif
5711 tcg_gen_shli_tl(t1, t1, 3);
5712 tcg_gen_andi_tl(t0, t0, ~7);
5713 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
5714 tcg_gen_shl_tl(t0, t0, t1);
5715 t2 = tcg_const_tl(-1);
5716 tcg_gen_shl_tl(t2, t2, t1);
5717 gen_load_fpr64(ctx, t1, rt);
5718 tcg_gen_andc_tl(t1, t1, t2);
5719 tcg_temp_free(t2);
5720 tcg_gen_or_tl(t0, t0, t1);
5721 tcg_temp_free(t1);
5722 gen_store_fpr64(ctx, t0, rt);
5723 break;
5724 case OPC_GSLDRC1:
5725 check_cp1_enabled(ctx);
5726 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5727 t1 = tcg_temp_new();
5728 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
5729 tcg_gen_andi_tl(t1, t0, 7);
5730 #ifdef TARGET_WORDS_BIGENDIAN
5731 tcg_gen_xori_tl(t1, t1, 7);
5732 #endif
5733 tcg_gen_shli_tl(t1, t1, 3);
5734 tcg_gen_andi_tl(t0, t0, ~7);
5735 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
5736 tcg_gen_shr_tl(t0, t0, t1);
5737 tcg_gen_xori_tl(t1, t1, 63);
5738 t2 = tcg_const_tl(0xfffffffffffffffeull);
5739 tcg_gen_shl_tl(t2, t2, t1);
5740 gen_load_fpr64(ctx, t1, rt);
5741 tcg_gen_and_tl(t1, t1, t2);
5742 tcg_temp_free(t2);
5743 tcg_gen_or_tl(t0, t0, t1);
5744 tcg_temp_free(t1);
5745 gen_store_fpr64(ctx, t0, rt);
5746 break;
5747 #endif
5748 default:
5749 MIPS_INVAL("loongson_gsshfl");
5750 gen_reserved_instruction(ctx);
5751 break;
5753 break;
5754 case OPC_GSSHFS:
5755 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
5756 case OPC_GSSWLC1:
5757 check_cp1_enabled(ctx);
5758 t1 = tcg_temp_new();
5759 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5760 fp0 = tcg_temp_new_i32();
5761 gen_load_fpr32(ctx, fp0, rt);
5762 tcg_gen_ext_i32_tl(t1, fp0);
5763 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
5764 tcg_temp_free_i32(fp0);
5765 tcg_temp_free(t1);
5766 break;
5767 case OPC_GSSWRC1:
5768 check_cp1_enabled(ctx);
5769 t1 = tcg_temp_new();
5770 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5771 fp0 = tcg_temp_new_i32();
5772 gen_load_fpr32(ctx, fp0, rt);
5773 tcg_gen_ext_i32_tl(t1, fp0);
5774 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
5775 tcg_temp_free_i32(fp0);
5776 tcg_temp_free(t1);
5777 break;
5778 #if defined(TARGET_MIPS64)
5779 case OPC_GSSDLC1:
5780 check_cp1_enabled(ctx);
5781 t1 = tcg_temp_new();
5782 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5783 gen_load_fpr64(ctx, t1, rt);
5784 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
5785 tcg_temp_free(t1);
5786 break;
5787 case OPC_GSSDRC1:
5788 check_cp1_enabled(ctx);
5789 t1 = tcg_temp_new();
5790 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5791 gen_load_fpr64(ctx, t1, rt);
5792 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
5793 tcg_temp_free(t1);
5794 break;
5795 #endif
5796 default:
5797 MIPS_INVAL("loongson_gsshfs");
5798 gen_reserved_instruction(ctx);
5799 break;
5801 break;
5802 default:
5803 MIPS_INVAL("loongson_gslsq");
5804 gen_reserved_instruction(ctx);
5805 break;
5807 tcg_temp_free(t0);
5810 /* Loongson EXT LDC2/SDC2 */
5811 static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
5812 int rs, int rd)
5814 int offset = sextract32(ctx->opcode, 3, 8);
5815 uint32_t opc = MASK_LOONGSON_LSDC2(ctx->opcode);
5816 TCGv t0, t1;
5817 TCGv_i32 fp0;
5819 /* Pre-conditions */
5820 switch (opc) {
5821 case OPC_GSLBX:
5822 case OPC_GSLHX:
5823 case OPC_GSLWX:
5824 case OPC_GSLDX:
5825 /* prefetch, implement as NOP */
5826 if (rt == 0) {
5827 return;
5829 break;
5830 case OPC_GSSBX:
5831 case OPC_GSSHX:
5832 case OPC_GSSWX:
5833 case OPC_GSSDX:
5834 break;
5835 case OPC_GSLWXC1:
5836 #if defined(TARGET_MIPS64)
5837 case OPC_GSLDXC1:
5838 #endif
5839 check_cp1_enabled(ctx);
5840 /* prefetch, implement as NOP */
5841 if (rt == 0) {
5842 return;
5844 break;
5845 case OPC_GSSWXC1:
5846 #if defined(TARGET_MIPS64)
5847 case OPC_GSSDXC1:
5848 #endif
5849 check_cp1_enabled(ctx);
5850 break;
5851 default:
5852 MIPS_INVAL("loongson_lsdc2");
5853 gen_reserved_instruction(ctx);
5854 return;
5855 break;
5858 t0 = tcg_temp_new();
5860 gen_base_offset_addr(ctx, t0, rs, offset);
5861 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
5863 switch (opc) {
5864 case OPC_GSLBX:
5865 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
5866 gen_store_gpr(t0, rt);
5867 break;
5868 case OPC_GSLHX:
5869 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
5870 ctx->default_tcg_memop_mask);
5871 gen_store_gpr(t0, rt);
5872 break;
5873 case OPC_GSLWX:
5874 gen_base_offset_addr(ctx, t0, rs, offset);
5875 if (rd) {
5876 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
5878 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
5879 ctx->default_tcg_memop_mask);
5880 gen_store_gpr(t0, rt);
5881 break;
5882 #if defined(TARGET_MIPS64)
5883 case OPC_GSLDX:
5884 gen_base_offset_addr(ctx, t0, rs, offset);
5885 if (rd) {
5886 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
5888 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
5889 ctx->default_tcg_memop_mask);
5890 gen_store_gpr(t0, rt);
5891 break;
5892 #endif
5893 case OPC_GSLWXC1:
5894 check_cp1_enabled(ctx);
5895 gen_base_offset_addr(ctx, t0, rs, offset);
5896 if (rd) {
5897 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
5899 fp0 = tcg_temp_new_i32();
5900 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
5901 ctx->default_tcg_memop_mask);
5902 gen_store_fpr32(ctx, fp0, rt);
5903 tcg_temp_free_i32(fp0);
5904 break;
5905 #if defined(TARGET_MIPS64)
5906 case OPC_GSLDXC1:
5907 check_cp1_enabled(ctx);
5908 gen_base_offset_addr(ctx, t0, rs, offset);
5909 if (rd) {
5910 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
5912 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
5913 ctx->default_tcg_memop_mask);
5914 gen_store_fpr64(ctx, t0, rt);
5915 break;
5916 #endif
5917 case OPC_GSSBX:
5918 t1 = tcg_temp_new();
5919 gen_load_gpr(t1, rt);
5920 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_SB);
5921 tcg_temp_free(t1);
5922 break;
5923 case OPC_GSSHX:
5924 t1 = tcg_temp_new();
5925 gen_load_gpr(t1, rt);
5926 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
5927 ctx->default_tcg_memop_mask);
5928 tcg_temp_free(t1);
5929 break;
5930 case OPC_GSSWX:
5931 t1 = tcg_temp_new();
5932 gen_load_gpr(t1, rt);
5933 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
5934 ctx->default_tcg_memop_mask);
5935 tcg_temp_free(t1);
5936 break;
5937 #if defined(TARGET_MIPS64)
5938 case OPC_GSSDX:
5939 t1 = tcg_temp_new();
5940 gen_load_gpr(t1, rt);
5941 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5942 ctx->default_tcg_memop_mask);
5943 tcg_temp_free(t1);
5944 break;
5945 #endif
5946 case OPC_GSSWXC1:
5947 fp0 = tcg_temp_new_i32();
5948 gen_load_fpr32(ctx, fp0, rt);
5949 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
5950 ctx->default_tcg_memop_mask);
5951 tcg_temp_free_i32(fp0);
5952 break;
5953 #if defined(TARGET_MIPS64)
5954 case OPC_GSSDXC1:
5955 t1 = tcg_temp_new();
5956 gen_load_fpr64(ctx, t1, rt);
5957 tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, MO_TEQ |
5958 ctx->default_tcg_memop_mask);
5959 tcg_temp_free(t1);
5960 break;
5961 #endif
5962 default:
5963 break;
5966 tcg_temp_free(t0);
5969 /* Traps */
5970 static void gen_trap(DisasContext *ctx, uint32_t opc,
5971 int rs, int rt, int16_t imm)
5973 int cond;
5974 TCGv t0 = tcg_temp_new();
5975 TCGv t1 = tcg_temp_new();
5977 cond = 0;
5978 /* Load needed operands */
5979 switch (opc) {
5980 case OPC_TEQ:
5981 case OPC_TGE:
5982 case OPC_TGEU:
5983 case OPC_TLT:
5984 case OPC_TLTU:
5985 case OPC_TNE:
5986 /* Compare two registers */
5987 if (rs != rt) {
5988 gen_load_gpr(t0, rs);
5989 gen_load_gpr(t1, rt);
5990 cond = 1;
5992 break;
5993 case OPC_TEQI:
5994 case OPC_TGEI:
5995 case OPC_TGEIU:
5996 case OPC_TLTI:
5997 case OPC_TLTIU:
5998 case OPC_TNEI:
5999 /* Compare register to immediate */
6000 if (rs != 0 || imm != 0) {
6001 gen_load_gpr(t0, rs);
6002 tcg_gen_movi_tl(t1, (int32_t)imm);
6003 cond = 1;
6005 break;
6007 if (cond == 0) {
6008 switch (opc) {
6009 case OPC_TEQ: /* rs == rs */
6010 case OPC_TEQI: /* r0 == 0 */
6011 case OPC_TGE: /* rs >= rs */
6012 case OPC_TGEI: /* r0 >= 0 */
6013 case OPC_TGEU: /* rs >= rs unsigned */
6014 case OPC_TGEIU: /* r0 >= 0 unsigned */
6015 /* Always trap */
6016 generate_exception_end(ctx, EXCP_TRAP);
6017 break;
6018 case OPC_TLT: /* rs < rs */
6019 case OPC_TLTI: /* r0 < 0 */
6020 case OPC_TLTU: /* rs < rs unsigned */
6021 case OPC_TLTIU: /* r0 < 0 unsigned */
6022 case OPC_TNE: /* rs != rs */
6023 case OPC_TNEI: /* r0 != 0 */
6024 /* Never trap: treat as NOP. */
6025 break;
6027 } else {
6028 TCGLabel *l1 = gen_new_label();
6030 switch (opc) {
6031 case OPC_TEQ:
6032 case OPC_TEQI:
6033 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
6034 break;
6035 case OPC_TGE:
6036 case OPC_TGEI:
6037 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
6038 break;
6039 case OPC_TGEU:
6040 case OPC_TGEIU:
6041 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
6042 break;
6043 case OPC_TLT:
6044 case OPC_TLTI:
6045 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
6046 break;
6047 case OPC_TLTU:
6048 case OPC_TLTIU:
6049 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
6050 break;
6051 case OPC_TNE:
6052 case OPC_TNEI:
6053 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
6054 break;
6056 generate_exception(ctx, EXCP_TRAP);
6057 gen_set_label(l1);
6059 tcg_temp_free(t0);
6060 tcg_temp_free(t1);
6063 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
6065 if (unlikely(ctx->base.singlestep_enabled)) {
6066 return false;
6069 #ifndef CONFIG_USER_ONLY
6070 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
6071 #else
6072 return true;
6073 #endif
6076 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
6078 if (use_goto_tb(ctx, dest)) {
6079 tcg_gen_goto_tb(n);
6080 gen_save_pc(dest);
6081 tcg_gen_exit_tb(ctx->base.tb, n);
6082 } else {
6083 gen_save_pc(dest);
6084 if (ctx->base.singlestep_enabled) {
6085 save_cpu_state(ctx, 0);
6086 gen_helper_raise_exception_debug(cpu_env);
6088 tcg_gen_lookup_and_goto_ptr();
6092 /* Branches (before delay slot) */
6093 static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
6094 int insn_bytes,
6095 int rs, int rt, int32_t offset,
6096 int delayslot_size)
6098 target_ulong btgt = -1;
6099 int blink = 0;
6100 int bcond_compute = 0;
6101 TCGv t0 = tcg_temp_new();
6102 TCGv t1 = tcg_temp_new();
6104 if (ctx->hflags & MIPS_HFLAG_BMASK) {
6105 #ifdef MIPS_DEBUG_DISAS
6106 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
6107 TARGET_FMT_lx "\n", ctx->base.pc_next);
6108 #endif
6109 gen_reserved_instruction(ctx);
6110 goto out;
6113 /* Load needed operands */
6114 switch (opc) {
6115 case OPC_BEQ:
6116 case OPC_BEQL:
6117 case OPC_BNE:
6118 case OPC_BNEL:
6119 /* Compare two registers */
6120 if (rs != rt) {
6121 gen_load_gpr(t0, rs);
6122 gen_load_gpr(t1, rt);
6123 bcond_compute = 1;
6125 btgt = ctx->base.pc_next + insn_bytes + offset;
6126 break;
6127 case OPC_BGEZ:
6128 case OPC_BGEZAL:
6129 case OPC_BGEZALL:
6130 case OPC_BGEZL:
6131 case OPC_BGTZ:
6132 case OPC_BGTZL:
6133 case OPC_BLEZ:
6134 case OPC_BLEZL:
6135 case OPC_BLTZ:
6136 case OPC_BLTZAL:
6137 case OPC_BLTZALL:
6138 case OPC_BLTZL:
6139 /* Compare to zero */
6140 if (rs != 0) {
6141 gen_load_gpr(t0, rs);
6142 bcond_compute = 1;
6144 btgt = ctx->base.pc_next + insn_bytes + offset;
6145 break;
6146 case OPC_BPOSGE32:
6147 #if defined(TARGET_MIPS64)
6148 case OPC_BPOSGE64:
6149 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
6150 #else
6151 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6152 #endif
6153 bcond_compute = 1;
6154 btgt = ctx->base.pc_next + insn_bytes + offset;
6155 break;
6156 case OPC_J:
6157 case OPC_JAL:
6158 case OPC_JALX:
6159 /* Jump to immediate */
6160 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
6161 (uint32_t)offset;
6162 break;
6163 case OPC_JR:
6164 case OPC_JALR:
6165 /* Jump to register */
6166 if (offset != 0 && offset != 16) {
6168 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6169 * others are reserved.
6171 MIPS_INVAL("jump hint");
6172 gen_reserved_instruction(ctx);
6173 goto out;
6175 gen_load_gpr(btarget, rs);
6176 break;
6177 default:
6178 MIPS_INVAL("branch/jump");
6179 gen_reserved_instruction(ctx);
6180 goto out;
6182 if (bcond_compute == 0) {
6183 /* No condition to be computed */
6184 switch (opc) {
6185 case OPC_BEQ: /* rx == rx */
6186 case OPC_BEQL: /* rx == rx likely */
6187 case OPC_BGEZ: /* 0 >= 0 */
6188 case OPC_BGEZL: /* 0 >= 0 likely */
6189 case OPC_BLEZ: /* 0 <= 0 */
6190 case OPC_BLEZL: /* 0 <= 0 likely */
6191 /* Always take */
6192 ctx->hflags |= MIPS_HFLAG_B;
6193 break;
6194 case OPC_BGEZAL: /* 0 >= 0 */
6195 case OPC_BGEZALL: /* 0 >= 0 likely */
6196 /* Always take and link */
6197 blink = 31;
6198 ctx->hflags |= MIPS_HFLAG_B;
6199 break;
6200 case OPC_BNE: /* rx != rx */
6201 case OPC_BGTZ: /* 0 > 0 */
6202 case OPC_BLTZ: /* 0 < 0 */
6203 /* Treat as NOP. */
6204 goto out;
6205 case OPC_BLTZAL: /* 0 < 0 */
6207 * Handle as an unconditional branch to get correct delay
6208 * slot checking.
6210 blink = 31;
6211 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
6212 ctx->hflags |= MIPS_HFLAG_B;
6213 break;
6214 case OPC_BLTZALL: /* 0 < 0 likely */
6215 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6216 /* Skip the instruction in the delay slot */
6217 ctx->base.pc_next += 4;
6218 goto out;
6219 case OPC_BNEL: /* rx != rx likely */
6220 case OPC_BGTZL: /* 0 > 0 likely */
6221 case OPC_BLTZL: /* 0 < 0 likely */
6222 /* Skip the instruction in the delay slot */
6223 ctx->base.pc_next += 4;
6224 goto out;
6225 case OPC_J:
6226 ctx->hflags |= MIPS_HFLAG_B;
6227 break;
6228 case OPC_JALX:
6229 ctx->hflags |= MIPS_HFLAG_BX;
6230 /* Fallthrough */
6231 case OPC_JAL:
6232 blink = 31;
6233 ctx->hflags |= MIPS_HFLAG_B;
6234 break;
6235 case OPC_JR:
6236 ctx->hflags |= MIPS_HFLAG_BR;
6237 break;
6238 case OPC_JALR:
6239 blink = rt;
6240 ctx->hflags |= MIPS_HFLAG_BR;
6241 break;
6242 default:
6243 MIPS_INVAL("branch/jump");
6244 gen_reserved_instruction(ctx);
6245 goto out;
6247 } else {
6248 switch (opc) {
6249 case OPC_BEQ:
6250 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6251 goto not_likely;
6252 case OPC_BEQL:
6253 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6254 goto likely;
6255 case OPC_BNE:
6256 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6257 goto not_likely;
6258 case OPC_BNEL:
6259 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6260 goto likely;
6261 case OPC_BGEZ:
6262 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6263 goto not_likely;
6264 case OPC_BGEZL:
6265 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6266 goto likely;
6267 case OPC_BGEZAL:
6268 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6269 blink = 31;
6270 goto not_likely;
6271 case OPC_BGEZALL:
6272 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6273 blink = 31;
6274 goto likely;
6275 case OPC_BGTZ:
6276 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6277 goto not_likely;
6278 case OPC_BGTZL:
6279 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6280 goto likely;
6281 case OPC_BLEZ:
6282 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6283 goto not_likely;
6284 case OPC_BLEZL:
6285 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6286 goto likely;
6287 case OPC_BLTZ:
6288 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6289 goto not_likely;
6290 case OPC_BLTZL:
6291 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6292 goto likely;
6293 case OPC_BPOSGE32:
6294 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6295 goto not_likely;
6296 #if defined(TARGET_MIPS64)
6297 case OPC_BPOSGE64:
6298 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
6299 goto not_likely;
6300 #endif
6301 case OPC_BLTZAL:
6302 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6303 blink = 31;
6304 not_likely:
6305 ctx->hflags |= MIPS_HFLAG_BC;
6306 break;
6307 case OPC_BLTZALL:
6308 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6309 blink = 31;
6310 likely:
6311 ctx->hflags |= MIPS_HFLAG_BL;
6312 break;
6313 default:
6314 MIPS_INVAL("conditional branch/jump");
6315 gen_reserved_instruction(ctx);
6316 goto out;
6320 ctx->btarget = btgt;
6322 switch (delayslot_size) {
6323 case 2:
6324 ctx->hflags |= MIPS_HFLAG_BDS16;
6325 break;
6326 case 4:
6327 ctx->hflags |= MIPS_HFLAG_BDS32;
6328 break;
6331 if (blink > 0) {
6332 int post_delay = insn_bytes + delayslot_size;
6333 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
6335 tcg_gen_movi_tl(cpu_gpr[blink],
6336 ctx->base.pc_next + post_delay + lowbit);
6339 out:
6340 if (insn_bytes == 2) {
6341 ctx->hflags |= MIPS_HFLAG_B16;
6343 tcg_temp_free(t0);
6344 tcg_temp_free(t1);
6348 /* nanoMIPS Branches */
6349 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
6350 int insn_bytes,
6351 int rs, int rt, int32_t offset)
6353 target_ulong btgt = -1;
6354 int bcond_compute = 0;
6355 TCGv t0 = tcg_temp_new();
6356 TCGv t1 = tcg_temp_new();
6358 /* Load needed operands */
6359 switch (opc) {
6360 case OPC_BEQ:
6361 case OPC_BNE:
6362 /* Compare two registers */
6363 if (rs != rt) {
6364 gen_load_gpr(t0, rs);
6365 gen_load_gpr(t1, rt);
6366 bcond_compute = 1;
6368 btgt = ctx->base.pc_next + insn_bytes + offset;
6369 break;
6370 case OPC_BGEZAL:
6371 /* Compare to zero */
6372 if (rs != 0) {
6373 gen_load_gpr(t0, rs);
6374 bcond_compute = 1;
6376 btgt = ctx->base.pc_next + insn_bytes + offset;
6377 break;
6378 case OPC_BPOSGE32:
6379 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6380 bcond_compute = 1;
6381 btgt = ctx->base.pc_next + insn_bytes + offset;
6382 break;
6383 case OPC_JR:
6384 case OPC_JALR:
6385 /* Jump to register */
6386 if (offset != 0 && offset != 16) {
6388 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6389 * others are reserved.
6391 MIPS_INVAL("jump hint");
6392 gen_reserved_instruction(ctx);
6393 goto out;
6395 gen_load_gpr(btarget, rs);
6396 break;
6397 default:
6398 MIPS_INVAL("branch/jump");
6399 gen_reserved_instruction(ctx);
6400 goto out;
6402 if (bcond_compute == 0) {
6403 /* No condition to be computed */
6404 switch (opc) {
6405 case OPC_BEQ: /* rx == rx */
6406 /* Always take */
6407 ctx->hflags |= MIPS_HFLAG_B;
6408 break;
6409 case OPC_BGEZAL: /* 0 >= 0 */
6410 /* Always take and link */
6411 tcg_gen_movi_tl(cpu_gpr[31],
6412 ctx->base.pc_next + insn_bytes);
6413 ctx->hflags |= MIPS_HFLAG_B;
6414 break;
6415 case OPC_BNE: /* rx != rx */
6416 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6417 /* Skip the instruction in the delay slot */
6418 ctx->base.pc_next += 4;
6419 goto out;
6420 case OPC_JR:
6421 ctx->hflags |= MIPS_HFLAG_BR;
6422 break;
6423 case OPC_JALR:
6424 if (rt > 0) {
6425 tcg_gen_movi_tl(cpu_gpr[rt],
6426 ctx->base.pc_next + insn_bytes);
6428 ctx->hflags |= MIPS_HFLAG_BR;
6429 break;
6430 default:
6431 MIPS_INVAL("branch/jump");
6432 gen_reserved_instruction(ctx);
6433 goto out;
6435 } else {
6436 switch (opc) {
6437 case OPC_BEQ:
6438 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6439 goto not_likely;
6440 case OPC_BNE:
6441 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6442 goto not_likely;
6443 case OPC_BGEZAL:
6444 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6445 tcg_gen_movi_tl(cpu_gpr[31],
6446 ctx->base.pc_next + insn_bytes);
6447 goto not_likely;
6448 case OPC_BPOSGE32:
6449 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6450 not_likely:
6451 ctx->hflags |= MIPS_HFLAG_BC;
6452 break;
6453 default:
6454 MIPS_INVAL("conditional branch/jump");
6455 gen_reserved_instruction(ctx);
6456 goto out;
6460 ctx->btarget = btgt;
6462 out:
6463 if (insn_bytes == 2) {
6464 ctx->hflags |= MIPS_HFLAG_B16;
6466 tcg_temp_free(t0);
6467 tcg_temp_free(t1);
6471 /* special3 bitfield operations */
6472 static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
6473 int rs, int lsb, int msb)
6475 TCGv t0 = tcg_temp_new();
6476 TCGv t1 = tcg_temp_new();
6478 gen_load_gpr(t1, rs);
6479 switch (opc) {
6480 case OPC_EXT:
6481 if (lsb + msb > 31) {
6482 goto fail;
6484 if (msb != 31) {
6485 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6486 } else {
6488 * The two checks together imply that lsb == 0,
6489 * so this is a simple sign-extension.
6491 tcg_gen_ext32s_tl(t0, t1);
6493 break;
6494 #if defined(TARGET_MIPS64)
6495 case OPC_DEXTU:
6496 lsb += 32;
6497 goto do_dext;
6498 case OPC_DEXTM:
6499 msb += 32;
6500 goto do_dext;
6501 case OPC_DEXT:
6502 do_dext:
6503 if (lsb + msb > 63) {
6504 goto fail;
6506 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6507 break;
6508 #endif
6509 case OPC_INS:
6510 if (lsb > msb) {
6511 goto fail;
6513 gen_load_gpr(t0, rt);
6514 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6515 tcg_gen_ext32s_tl(t0, t0);
6516 break;
6517 #if defined(TARGET_MIPS64)
6518 case OPC_DINSU:
6519 lsb += 32;
6520 /* FALLTHRU */
6521 case OPC_DINSM:
6522 msb += 32;
6523 /* FALLTHRU */
6524 case OPC_DINS:
6525 if (lsb > msb) {
6526 goto fail;
6528 gen_load_gpr(t0, rt);
6529 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6530 break;
6531 #endif
6532 default:
6533 fail:
6534 MIPS_INVAL("bitops");
6535 gen_reserved_instruction(ctx);
6536 tcg_temp_free(t0);
6537 tcg_temp_free(t1);
6538 return;
6540 gen_store_gpr(t0, rt);
6541 tcg_temp_free(t0);
6542 tcg_temp_free(t1);
6545 static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
6547 TCGv t0;
6549 if (rd == 0) {
6550 /* If no destination, treat it as a NOP. */
6551 return;
6554 t0 = tcg_temp_new();
6555 gen_load_gpr(t0, rt);
6556 switch (op2) {
6557 case OPC_WSBH:
6559 TCGv t1 = tcg_temp_new();
6560 TCGv t2 = tcg_const_tl(0x00FF00FF);
6562 tcg_gen_shri_tl(t1, t0, 8);
6563 tcg_gen_and_tl(t1, t1, t2);
6564 tcg_gen_and_tl(t0, t0, t2);
6565 tcg_gen_shli_tl(t0, t0, 8);
6566 tcg_gen_or_tl(t0, t0, t1);
6567 tcg_temp_free(t2);
6568 tcg_temp_free(t1);
6569 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6571 break;
6572 case OPC_SEB:
6573 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
6574 break;
6575 case OPC_SEH:
6576 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
6577 break;
6578 #if defined(TARGET_MIPS64)
6579 case OPC_DSBH:
6581 TCGv t1 = tcg_temp_new();
6582 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
6584 tcg_gen_shri_tl(t1, t0, 8);
6585 tcg_gen_and_tl(t1, t1, t2);
6586 tcg_gen_and_tl(t0, t0, t2);
6587 tcg_gen_shli_tl(t0, t0, 8);
6588 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6589 tcg_temp_free(t2);
6590 tcg_temp_free(t1);
6592 break;
6593 case OPC_DSHD:
6595 TCGv t1 = tcg_temp_new();
6596 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
6598 tcg_gen_shri_tl(t1, t0, 16);
6599 tcg_gen_and_tl(t1, t1, t2);
6600 tcg_gen_and_tl(t0, t0, t2);
6601 tcg_gen_shli_tl(t0, t0, 16);
6602 tcg_gen_or_tl(t0, t0, t1);
6603 tcg_gen_shri_tl(t1, t0, 32);
6604 tcg_gen_shli_tl(t0, t0, 32);
6605 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6606 tcg_temp_free(t2);
6607 tcg_temp_free(t1);
6609 break;
6610 #endif
6611 default:
6612 MIPS_INVAL("bsfhl");
6613 gen_reserved_instruction(ctx);
6614 tcg_temp_free(t0);
6615 return;
6617 tcg_temp_free(t0);
6620 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
6621 int rt, int bits)
6623 TCGv t0;
6624 if (rd == 0) {
6625 /* Treat as NOP. */
6626 return;
6628 t0 = tcg_temp_new();
6629 if (bits == 0 || bits == wordsz) {
6630 if (bits == 0) {
6631 gen_load_gpr(t0, rt);
6632 } else {
6633 gen_load_gpr(t0, rs);
6635 switch (wordsz) {
6636 case 32:
6637 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6638 break;
6639 #if defined(TARGET_MIPS64)
6640 case 64:
6641 tcg_gen_mov_tl(cpu_gpr[rd], t0);
6642 break;
6643 #endif
6645 } else {
6646 TCGv t1 = tcg_temp_new();
6647 gen_load_gpr(t0, rt);
6648 gen_load_gpr(t1, rs);
6649 switch (wordsz) {
6650 case 32:
6652 TCGv_i64 t2 = tcg_temp_new_i64();
6653 tcg_gen_concat_tl_i64(t2, t1, t0);
6654 tcg_gen_shri_i64(t2, t2, 32 - bits);
6655 gen_move_low32(cpu_gpr[rd], t2);
6656 tcg_temp_free_i64(t2);
6658 break;
6659 #if defined(TARGET_MIPS64)
6660 case 64:
6661 tcg_gen_shli_tl(t0, t0, bits);
6662 tcg_gen_shri_tl(t1, t1, 64 - bits);
6663 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
6664 break;
6665 #endif
6667 tcg_temp_free(t1);
6670 tcg_temp_free(t0);
6673 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6674 int bp)
6676 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
6679 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6680 int shift)
6682 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
6685 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
6687 TCGv t0;
6688 if (rd == 0) {
6689 /* Treat as NOP. */
6690 return;
6692 t0 = tcg_temp_new();
6693 gen_load_gpr(t0, rt);
6694 switch (opc) {
6695 case OPC_BITSWAP:
6696 gen_helper_bitswap(cpu_gpr[rd], t0);
6697 break;
6698 #if defined(TARGET_MIPS64)
6699 case OPC_DBITSWAP:
6700 gen_helper_dbitswap(cpu_gpr[rd], t0);
6701 break;
6702 #endif
6704 tcg_temp_free(t0);
6707 #ifndef CONFIG_USER_ONLY
6708 /* CP0 (MMU and control) */
6709 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
6711 TCGv_i64 t0 = tcg_temp_new_i64();
6712 TCGv_i64 t1 = tcg_temp_new_i64();
6714 tcg_gen_ext_tl_i64(t0, arg);
6715 tcg_gen_ld_i64(t1, cpu_env, off);
6716 #if defined(TARGET_MIPS64)
6717 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
6718 #else
6719 tcg_gen_concat32_i64(t1, t1, t0);
6720 #endif
6721 tcg_gen_st_i64(t1, cpu_env, off);
6722 tcg_temp_free_i64(t1);
6723 tcg_temp_free_i64(t0);
6726 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
6728 TCGv_i64 t0 = tcg_temp_new_i64();
6729 TCGv_i64 t1 = tcg_temp_new_i64();
6731 tcg_gen_ext_tl_i64(t0, arg);
6732 tcg_gen_ld_i64(t1, cpu_env, off);
6733 tcg_gen_concat32_i64(t1, t1, t0);
6734 tcg_gen_st_i64(t1, cpu_env, off);
6735 tcg_temp_free_i64(t1);
6736 tcg_temp_free_i64(t0);
6739 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
6741 TCGv_i64 t0 = tcg_temp_new_i64();
6743 tcg_gen_ld_i64(t0, cpu_env, off);
6744 #if defined(TARGET_MIPS64)
6745 tcg_gen_shri_i64(t0, t0, 30);
6746 #else
6747 tcg_gen_shri_i64(t0, t0, 32);
6748 #endif
6749 gen_move_low32(arg, t0);
6750 tcg_temp_free_i64(t0);
6753 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
6755 TCGv_i64 t0 = tcg_temp_new_i64();
6757 tcg_gen_ld_i64(t0, cpu_env, off);
6758 tcg_gen_shri_i64(t0, t0, 32 + shift);
6759 gen_move_low32(arg, t0);
6760 tcg_temp_free_i64(t0);
6763 static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
6765 TCGv_i32 t0 = tcg_temp_new_i32();
6767 tcg_gen_ld_i32(t0, cpu_env, off);
6768 tcg_gen_ext_i32_tl(arg, t0);
6769 tcg_temp_free_i32(t0);
6772 static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
6774 tcg_gen_ld_tl(arg, cpu_env, off);
6775 tcg_gen_ext32s_tl(arg, arg);
6778 static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
6780 TCGv_i32 t0 = tcg_temp_new_i32();
6782 tcg_gen_trunc_tl_i32(t0, arg);
6783 tcg_gen_st_i32(t0, cpu_env, off);
6784 tcg_temp_free_i32(t0);
6787 #define CP0_CHECK(c) \
6788 do { \
6789 if (!(c)) { \
6790 goto cp0_unimplemented; \
6792 } while (0)
6794 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6796 const char *register_name = "invalid";
6798 switch (reg) {
6799 case CP0_REGISTER_02:
6800 switch (sel) {
6801 case 0:
6802 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6803 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6804 register_name = "EntryLo0";
6805 break;
6806 default:
6807 goto cp0_unimplemented;
6809 break;
6810 case CP0_REGISTER_03:
6811 switch (sel) {
6812 case CP0_REG03__ENTRYLO1:
6813 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6814 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6815 register_name = "EntryLo1";
6816 break;
6817 default:
6818 goto cp0_unimplemented;
6820 break;
6821 case CP0_REGISTER_09:
6822 switch (sel) {
6823 case CP0_REG09__SAAR:
6824 CP0_CHECK(ctx->saar);
6825 gen_helper_mfhc0_saar(arg, cpu_env);
6826 register_name = "SAAR";
6827 break;
6828 default:
6829 goto cp0_unimplemented;
6831 break;
6832 case CP0_REGISTER_17:
6833 switch (sel) {
6834 case CP0_REG17__LLADDR:
6835 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
6836 ctx->CP0_LLAddr_shift);
6837 register_name = "LLAddr";
6838 break;
6839 case CP0_REG17__MAAR:
6840 CP0_CHECK(ctx->mrp);
6841 gen_helper_mfhc0_maar(arg, cpu_env);
6842 register_name = "MAAR";
6843 break;
6844 default:
6845 goto cp0_unimplemented;
6847 break;
6848 case CP0_REGISTER_19:
6849 switch (sel) {
6850 case CP0_REG19__WATCHHI0:
6851 case CP0_REG19__WATCHHI1:
6852 case CP0_REG19__WATCHHI2:
6853 case CP0_REG19__WATCHHI3:
6854 case CP0_REG19__WATCHHI4:
6855 case CP0_REG19__WATCHHI5:
6856 case CP0_REG19__WATCHHI6:
6857 case CP0_REG19__WATCHHI7:
6858 /* upper 32 bits are only available when Config5MI != 0 */
6859 CP0_CHECK(ctx->mi);
6860 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_WatchHi[sel]), 0);
6861 register_name = "WatchHi";
6862 break;
6863 default:
6864 goto cp0_unimplemented;
6866 break;
6867 case CP0_REGISTER_28:
6868 switch (sel) {
6869 case 0:
6870 case 2:
6871 case 4:
6872 case 6:
6873 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
6874 register_name = "TagLo";
6875 break;
6876 default:
6877 goto cp0_unimplemented;
6879 break;
6880 default:
6881 goto cp0_unimplemented;
6883 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
6884 return;
6886 cp0_unimplemented:
6887 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
6888 register_name, reg, sel);
6889 tcg_gen_movi_tl(arg, 0);
6892 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6894 const char *register_name = "invalid";
6895 uint64_t mask = ctx->PAMask >> 36;
6897 switch (reg) {
6898 case CP0_REGISTER_02:
6899 switch (sel) {
6900 case 0:
6901 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6902 tcg_gen_andi_tl(arg, arg, mask);
6903 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6904 register_name = "EntryLo0";
6905 break;
6906 default:
6907 goto cp0_unimplemented;
6909 break;
6910 case CP0_REGISTER_03:
6911 switch (sel) {
6912 case CP0_REG03__ENTRYLO1:
6913 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6914 tcg_gen_andi_tl(arg, arg, mask);
6915 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6916 register_name = "EntryLo1";
6917 break;
6918 default:
6919 goto cp0_unimplemented;
6921 break;
6922 case CP0_REGISTER_09:
6923 switch (sel) {
6924 case CP0_REG09__SAAR:
6925 CP0_CHECK(ctx->saar);
6926 gen_helper_mthc0_saar(cpu_env, arg);
6927 register_name = "SAAR";
6928 break;
6929 default:
6930 goto cp0_unimplemented;
6932 break;
6933 case CP0_REGISTER_17:
6934 switch (sel) {
6935 case CP0_REG17__LLADDR:
6937 * LLAddr is read-only (the only exception is bit 0 if LLB is
6938 * supported); the CP0_LLAddr_rw_bitmask does not seem to be
6939 * relevant for modern MIPS cores supporting MTHC0, therefore
6940 * treating MTHC0 to LLAddr as NOP.
6942 register_name = "LLAddr";
6943 break;
6944 case CP0_REG17__MAAR:
6945 CP0_CHECK(ctx->mrp);
6946 gen_helper_mthc0_maar(cpu_env, arg);
6947 register_name = "MAAR";
6948 break;
6949 default:
6950 goto cp0_unimplemented;
6952 break;
6953 case CP0_REGISTER_19:
6954 switch (sel) {
6955 case CP0_REG19__WATCHHI0:
6956 case CP0_REG19__WATCHHI1:
6957 case CP0_REG19__WATCHHI2:
6958 case CP0_REG19__WATCHHI3:
6959 case CP0_REG19__WATCHHI4:
6960 case CP0_REG19__WATCHHI5:
6961 case CP0_REG19__WATCHHI6:
6962 case CP0_REG19__WATCHHI7:
6963 /* upper 32 bits are only available when Config5MI != 0 */
6964 CP0_CHECK(ctx->mi);
6965 gen_helper_0e1i(mthc0_watchhi, arg, sel);
6966 register_name = "WatchHi";
6967 break;
6968 default:
6969 goto cp0_unimplemented;
6971 break;
6972 case CP0_REGISTER_28:
6973 switch (sel) {
6974 case 0:
6975 case 2:
6976 case 4:
6977 case 6:
6978 tcg_gen_andi_tl(arg, arg, mask);
6979 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
6980 register_name = "TagLo";
6981 break;
6982 default:
6983 goto cp0_unimplemented;
6985 break;
6986 default:
6987 goto cp0_unimplemented;
6989 trace_mips_translate_c0("mthc0", register_name, reg, sel);
6991 cp0_unimplemented:
6992 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
6993 register_name, reg, sel);
6996 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
6998 if (ctx->insn_flags & ISA_MIPS_R6) {
6999 tcg_gen_movi_tl(arg, 0);
7000 } else {
7001 tcg_gen_movi_tl(arg, ~0);
7005 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7007 const char *register_name = "invalid";
7009 if (sel != 0) {
7010 check_insn(ctx, ISA_MIPS_R1);
7013 switch (reg) {
7014 case CP0_REGISTER_00:
7015 switch (sel) {
7016 case CP0_REG00__INDEX:
7017 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
7018 register_name = "Index";
7019 break;
7020 case CP0_REG00__MVPCONTROL:
7021 CP0_CHECK(ctx->insn_flags & ASE_MT);
7022 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
7023 register_name = "MVPControl";
7024 break;
7025 case CP0_REG00__MVPCONF0:
7026 CP0_CHECK(ctx->insn_flags & ASE_MT);
7027 gen_helper_mfc0_mvpconf0(arg, cpu_env);
7028 register_name = "MVPConf0";
7029 break;
7030 case CP0_REG00__MVPCONF1:
7031 CP0_CHECK(ctx->insn_flags & ASE_MT);
7032 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7033 register_name = "MVPConf1";
7034 break;
7035 case CP0_REG00__VPCONTROL:
7036 CP0_CHECK(ctx->vp);
7037 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
7038 register_name = "VPControl";
7039 break;
7040 default:
7041 goto cp0_unimplemented;
7043 break;
7044 case CP0_REGISTER_01:
7045 switch (sel) {
7046 case CP0_REG01__RANDOM:
7047 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7048 gen_helper_mfc0_random(arg, cpu_env);
7049 register_name = "Random";
7050 break;
7051 case CP0_REG01__VPECONTROL:
7052 CP0_CHECK(ctx->insn_flags & ASE_MT);
7053 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7054 register_name = "VPEControl";
7055 break;
7056 case CP0_REG01__VPECONF0:
7057 CP0_CHECK(ctx->insn_flags & ASE_MT);
7058 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7059 register_name = "VPEConf0";
7060 break;
7061 case CP0_REG01__VPECONF1:
7062 CP0_CHECK(ctx->insn_flags & ASE_MT);
7063 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7064 register_name = "VPEConf1";
7065 break;
7066 case CP0_REG01__YQMASK:
7067 CP0_CHECK(ctx->insn_flags & ASE_MT);
7068 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
7069 register_name = "YQMask";
7070 break;
7071 case CP0_REG01__VPESCHEDULE:
7072 CP0_CHECK(ctx->insn_flags & ASE_MT);
7073 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
7074 register_name = "VPESchedule";
7075 break;
7076 case CP0_REG01__VPESCHEFBACK:
7077 CP0_CHECK(ctx->insn_flags & ASE_MT);
7078 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7079 register_name = "VPEScheFBack";
7080 break;
7081 case CP0_REG01__VPEOPT:
7082 CP0_CHECK(ctx->insn_flags & ASE_MT);
7083 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
7084 register_name = "VPEOpt";
7085 break;
7086 default:
7087 goto cp0_unimplemented;
7089 break;
7090 case CP0_REGISTER_02:
7091 switch (sel) {
7092 case CP0_REG02__ENTRYLO0:
7094 TCGv_i64 tmp = tcg_temp_new_i64();
7095 tcg_gen_ld_i64(tmp, cpu_env,
7096 offsetof(CPUMIPSState, CP0_EntryLo0));
7097 #if defined(TARGET_MIPS64)
7098 if (ctx->rxi) {
7099 /* Move RI/XI fields to bits 31:30 */
7100 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
7101 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
7103 #endif
7104 gen_move_low32(arg, tmp);
7105 tcg_temp_free_i64(tmp);
7107 register_name = "EntryLo0";
7108 break;
7109 case CP0_REG02__TCSTATUS:
7110 CP0_CHECK(ctx->insn_flags & ASE_MT);
7111 gen_helper_mfc0_tcstatus(arg, cpu_env);
7112 register_name = "TCStatus";
7113 break;
7114 case CP0_REG02__TCBIND:
7115 CP0_CHECK(ctx->insn_flags & ASE_MT);
7116 gen_helper_mfc0_tcbind(arg, cpu_env);
7117 register_name = "TCBind";
7118 break;
7119 case CP0_REG02__TCRESTART:
7120 CP0_CHECK(ctx->insn_flags & ASE_MT);
7121 gen_helper_mfc0_tcrestart(arg, cpu_env);
7122 register_name = "TCRestart";
7123 break;
7124 case CP0_REG02__TCHALT:
7125 CP0_CHECK(ctx->insn_flags & ASE_MT);
7126 gen_helper_mfc0_tchalt(arg, cpu_env);
7127 register_name = "TCHalt";
7128 break;
7129 case CP0_REG02__TCCONTEXT:
7130 CP0_CHECK(ctx->insn_flags & ASE_MT);
7131 gen_helper_mfc0_tccontext(arg, cpu_env);
7132 register_name = "TCContext";
7133 break;
7134 case CP0_REG02__TCSCHEDULE:
7135 CP0_CHECK(ctx->insn_flags & ASE_MT);
7136 gen_helper_mfc0_tcschedule(arg, cpu_env);
7137 register_name = "TCSchedule";
7138 break;
7139 case CP0_REG02__TCSCHEFBACK:
7140 CP0_CHECK(ctx->insn_flags & ASE_MT);
7141 gen_helper_mfc0_tcschefback(arg, cpu_env);
7142 register_name = "TCScheFBack";
7143 break;
7144 default:
7145 goto cp0_unimplemented;
7147 break;
7148 case CP0_REGISTER_03:
7149 switch (sel) {
7150 case CP0_REG03__ENTRYLO1:
7152 TCGv_i64 tmp = tcg_temp_new_i64();
7153 tcg_gen_ld_i64(tmp, cpu_env,
7154 offsetof(CPUMIPSState, CP0_EntryLo1));
7155 #if defined(TARGET_MIPS64)
7156 if (ctx->rxi) {
7157 /* Move RI/XI fields to bits 31:30 */
7158 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
7159 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
7161 #endif
7162 gen_move_low32(arg, tmp);
7163 tcg_temp_free_i64(tmp);
7165 register_name = "EntryLo1";
7166 break;
7167 case CP0_REG03__GLOBALNUM:
7168 CP0_CHECK(ctx->vp);
7169 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
7170 register_name = "GlobalNumber";
7171 break;
7172 default:
7173 goto cp0_unimplemented;
7175 break;
7176 case CP0_REGISTER_04:
7177 switch (sel) {
7178 case CP0_REG04__CONTEXT:
7179 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
7180 tcg_gen_ext32s_tl(arg, arg);
7181 register_name = "Context";
7182 break;
7183 case CP0_REG04__CONTEXTCONFIG:
7184 /* SmartMIPS ASE */
7185 /* gen_helper_mfc0_contextconfig(arg); */
7186 register_name = "ContextConfig";
7187 goto cp0_unimplemented;
7188 case CP0_REG04__USERLOCAL:
7189 CP0_CHECK(ctx->ulri);
7190 tcg_gen_ld_tl(arg, cpu_env,
7191 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7192 tcg_gen_ext32s_tl(arg, arg);
7193 register_name = "UserLocal";
7194 break;
7195 case CP0_REG04__MMID:
7196 CP0_CHECK(ctx->mi);
7197 gen_helper_mtc0_memorymapid(cpu_env, arg);
7198 register_name = "MMID";
7199 break;
7200 default:
7201 goto cp0_unimplemented;
7203 break;
7204 case CP0_REGISTER_05:
7205 switch (sel) {
7206 case CP0_REG05__PAGEMASK:
7207 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
7208 register_name = "PageMask";
7209 break;
7210 case CP0_REG05__PAGEGRAIN:
7211 check_insn(ctx, ISA_MIPS_R2);
7212 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
7213 register_name = "PageGrain";
7214 break;
7215 case CP0_REG05__SEGCTL0:
7216 CP0_CHECK(ctx->sc);
7217 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
7218 tcg_gen_ext32s_tl(arg, arg);
7219 register_name = "SegCtl0";
7220 break;
7221 case CP0_REG05__SEGCTL1:
7222 CP0_CHECK(ctx->sc);
7223 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
7224 tcg_gen_ext32s_tl(arg, arg);
7225 register_name = "SegCtl1";
7226 break;
7227 case CP0_REG05__SEGCTL2:
7228 CP0_CHECK(ctx->sc);
7229 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
7230 tcg_gen_ext32s_tl(arg, arg);
7231 register_name = "SegCtl2";
7232 break;
7233 case CP0_REG05__PWBASE:
7234 check_pw(ctx);
7235 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7236 register_name = "PWBase";
7237 break;
7238 case CP0_REG05__PWFIELD:
7239 check_pw(ctx);
7240 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
7241 register_name = "PWField";
7242 break;
7243 case CP0_REG05__PWSIZE:
7244 check_pw(ctx);
7245 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
7246 register_name = "PWSize";
7247 break;
7248 default:
7249 goto cp0_unimplemented;
7251 break;
7252 case CP0_REGISTER_06:
7253 switch (sel) {
7254 case CP0_REG06__WIRED:
7255 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
7256 register_name = "Wired";
7257 break;
7258 case CP0_REG06__SRSCONF0:
7259 check_insn(ctx, ISA_MIPS_R2);
7260 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
7261 register_name = "SRSConf0";
7262 break;
7263 case CP0_REG06__SRSCONF1:
7264 check_insn(ctx, ISA_MIPS_R2);
7265 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
7266 register_name = "SRSConf1";
7267 break;
7268 case CP0_REG06__SRSCONF2:
7269 check_insn(ctx, ISA_MIPS_R2);
7270 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
7271 register_name = "SRSConf2";
7272 break;
7273 case CP0_REG06__SRSCONF3:
7274 check_insn(ctx, ISA_MIPS_R2);
7275 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
7276 register_name = "SRSConf3";
7277 break;
7278 case CP0_REG06__SRSCONF4:
7279 check_insn(ctx, ISA_MIPS_R2);
7280 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
7281 register_name = "SRSConf4";
7282 break;
7283 case CP0_REG06__PWCTL:
7284 check_pw(ctx);
7285 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
7286 register_name = "PWCtl";
7287 break;
7288 default:
7289 goto cp0_unimplemented;
7291 break;
7292 case CP0_REGISTER_07:
7293 switch (sel) {
7294 case CP0_REG07__HWRENA:
7295 check_insn(ctx, ISA_MIPS_R2);
7296 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
7297 register_name = "HWREna";
7298 break;
7299 default:
7300 goto cp0_unimplemented;
7302 break;
7303 case CP0_REGISTER_08:
7304 switch (sel) {
7305 case CP0_REG08__BADVADDR:
7306 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
7307 tcg_gen_ext32s_tl(arg, arg);
7308 register_name = "BadVAddr";
7309 break;
7310 case CP0_REG08__BADINSTR:
7311 CP0_CHECK(ctx->bi);
7312 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
7313 register_name = "BadInstr";
7314 break;
7315 case CP0_REG08__BADINSTRP:
7316 CP0_CHECK(ctx->bp);
7317 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
7318 register_name = "BadInstrP";
7319 break;
7320 case CP0_REG08__BADINSTRX:
7321 CP0_CHECK(ctx->bi);
7322 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7323 tcg_gen_andi_tl(arg, arg, ~0xffff);
7324 register_name = "BadInstrX";
7325 break;
7326 default:
7327 goto cp0_unimplemented;
7329 break;
7330 case CP0_REGISTER_09:
7331 switch (sel) {
7332 case CP0_REG09__COUNT:
7333 /* Mark as an IO operation because we read the time. */
7334 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7335 gen_io_start();
7337 gen_helper_mfc0_count(arg, cpu_env);
7339 * Break the TB to be able to take timer interrupts immediately
7340 * after reading count. DISAS_STOP isn't sufficient, we need to
7341 * ensure we break completely out of translated code.
7343 gen_save_pc(ctx->base.pc_next + 4);
7344 ctx->base.is_jmp = DISAS_EXIT;
7345 register_name = "Count";
7346 break;
7347 case CP0_REG09__SAARI:
7348 CP0_CHECK(ctx->saar);
7349 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
7350 register_name = "SAARI";
7351 break;
7352 case CP0_REG09__SAAR:
7353 CP0_CHECK(ctx->saar);
7354 gen_helper_mfc0_saar(arg, cpu_env);
7355 register_name = "SAAR";
7356 break;
7357 default:
7358 goto cp0_unimplemented;
7360 break;
7361 case CP0_REGISTER_10:
7362 switch (sel) {
7363 case CP0_REG10__ENTRYHI:
7364 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
7365 tcg_gen_ext32s_tl(arg, arg);
7366 register_name = "EntryHi";
7367 break;
7368 default:
7369 goto cp0_unimplemented;
7371 break;
7372 case CP0_REGISTER_11:
7373 switch (sel) {
7374 case CP0_REG11__COMPARE:
7375 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
7376 register_name = "Compare";
7377 break;
7378 /* 6,7 are implementation dependent */
7379 default:
7380 goto cp0_unimplemented;
7382 break;
7383 case CP0_REGISTER_12:
7384 switch (sel) {
7385 case CP0_REG12__STATUS:
7386 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
7387 register_name = "Status";
7388 break;
7389 case CP0_REG12__INTCTL:
7390 check_insn(ctx, ISA_MIPS_R2);
7391 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
7392 register_name = "IntCtl";
7393 break;
7394 case CP0_REG12__SRSCTL:
7395 check_insn(ctx, ISA_MIPS_R2);
7396 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
7397 register_name = "SRSCtl";
7398 break;
7399 case CP0_REG12__SRSMAP:
7400 check_insn(ctx, ISA_MIPS_R2);
7401 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7402 register_name = "SRSMap";
7403 break;
7404 default:
7405 goto cp0_unimplemented;
7407 break;
7408 case CP0_REGISTER_13:
7409 switch (sel) {
7410 case CP0_REG13__CAUSE:
7411 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
7412 register_name = "Cause";
7413 break;
7414 default:
7415 goto cp0_unimplemented;
7417 break;
7418 case CP0_REGISTER_14:
7419 switch (sel) {
7420 case CP0_REG14__EPC:
7421 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7422 tcg_gen_ext32s_tl(arg, arg);
7423 register_name = "EPC";
7424 break;
7425 default:
7426 goto cp0_unimplemented;
7428 break;
7429 case CP0_REGISTER_15:
7430 switch (sel) {
7431 case CP0_REG15__PRID:
7432 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
7433 register_name = "PRid";
7434 break;
7435 case CP0_REG15__EBASE:
7436 check_insn(ctx, ISA_MIPS_R2);
7437 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7438 tcg_gen_ext32s_tl(arg, arg);
7439 register_name = "EBase";
7440 break;
7441 case CP0_REG15__CMGCRBASE:
7442 check_insn(ctx, ISA_MIPS_R2);
7443 CP0_CHECK(ctx->cmgcr);
7444 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7445 tcg_gen_ext32s_tl(arg, arg);
7446 register_name = "CMGCRBase";
7447 break;
7448 default:
7449 goto cp0_unimplemented;
7451 break;
7452 case CP0_REGISTER_16:
7453 switch (sel) {
7454 case CP0_REG16__CONFIG:
7455 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
7456 register_name = "Config";
7457 break;
7458 case CP0_REG16__CONFIG1:
7459 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
7460 register_name = "Config1";
7461 break;
7462 case CP0_REG16__CONFIG2:
7463 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7464 register_name = "Config2";
7465 break;
7466 case CP0_REG16__CONFIG3:
7467 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7468 register_name = "Config3";
7469 break;
7470 case CP0_REG16__CONFIG4:
7471 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7472 register_name = "Config4";
7473 break;
7474 case CP0_REG16__CONFIG5:
7475 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7476 register_name = "Config5";
7477 break;
7478 /* 6,7 are implementation dependent */
7479 case CP0_REG16__CONFIG6:
7480 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
7481 register_name = "Config6";
7482 break;
7483 case CP0_REG16__CONFIG7:
7484 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
7485 register_name = "Config7";
7486 break;
7487 default:
7488 goto cp0_unimplemented;
7490 break;
7491 case CP0_REGISTER_17:
7492 switch (sel) {
7493 case CP0_REG17__LLADDR:
7494 gen_helper_mfc0_lladdr(arg, cpu_env);
7495 register_name = "LLAddr";
7496 break;
7497 case CP0_REG17__MAAR:
7498 CP0_CHECK(ctx->mrp);
7499 gen_helper_mfc0_maar(arg, cpu_env);
7500 register_name = "MAAR";
7501 break;
7502 case CP0_REG17__MAARI:
7503 CP0_CHECK(ctx->mrp);
7504 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7505 register_name = "MAARI";
7506 break;
7507 default:
7508 goto cp0_unimplemented;
7510 break;
7511 case CP0_REGISTER_18:
7512 switch (sel) {
7513 case CP0_REG18__WATCHLO0:
7514 case CP0_REG18__WATCHLO1:
7515 case CP0_REG18__WATCHLO2:
7516 case CP0_REG18__WATCHLO3:
7517 case CP0_REG18__WATCHLO4:
7518 case CP0_REG18__WATCHLO5:
7519 case CP0_REG18__WATCHLO6:
7520 case CP0_REG18__WATCHLO7:
7521 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7522 gen_helper_1e0i(mfc0_watchlo, arg, sel);
7523 register_name = "WatchLo";
7524 break;
7525 default:
7526 goto cp0_unimplemented;
7528 break;
7529 case CP0_REGISTER_19:
7530 switch (sel) {
7531 case CP0_REG19__WATCHHI0:
7532 case CP0_REG19__WATCHHI1:
7533 case CP0_REG19__WATCHHI2:
7534 case CP0_REG19__WATCHHI3:
7535 case CP0_REG19__WATCHHI4:
7536 case CP0_REG19__WATCHHI5:
7537 case CP0_REG19__WATCHHI6:
7538 case CP0_REG19__WATCHHI7:
7539 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7540 gen_helper_1e0i(mfc0_watchhi, arg, sel);
7541 register_name = "WatchHi";
7542 break;
7543 default:
7544 goto cp0_unimplemented;
7546 break;
7547 case CP0_REGISTER_20:
7548 switch (sel) {
7549 case CP0_REG20__XCONTEXT:
7550 #if defined(TARGET_MIPS64)
7551 check_insn(ctx, ISA_MIPS3);
7552 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
7553 tcg_gen_ext32s_tl(arg, arg);
7554 register_name = "XContext";
7555 break;
7556 #endif
7557 default:
7558 goto cp0_unimplemented;
7560 break;
7561 case CP0_REGISTER_21:
7562 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7563 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7564 switch (sel) {
7565 case 0:
7566 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
7567 register_name = "Framemask";
7568 break;
7569 default:
7570 goto cp0_unimplemented;
7572 break;
7573 case CP0_REGISTER_22:
7574 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7575 register_name = "'Diagnostic"; /* implementation dependent */
7576 break;
7577 case CP0_REGISTER_23:
7578 switch (sel) {
7579 case CP0_REG23__DEBUG:
7580 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
7581 register_name = "Debug";
7582 break;
7583 case CP0_REG23__TRACECONTROL:
7584 /* PDtrace support */
7585 /* gen_helper_mfc0_tracecontrol(arg); */
7586 register_name = "TraceControl";
7587 goto cp0_unimplemented;
7588 case CP0_REG23__TRACECONTROL2:
7589 /* PDtrace support */
7590 /* gen_helper_mfc0_tracecontrol2(arg); */
7591 register_name = "TraceControl2";
7592 goto cp0_unimplemented;
7593 case CP0_REG23__USERTRACEDATA1:
7594 /* PDtrace support */
7595 /* gen_helper_mfc0_usertracedata1(arg);*/
7596 register_name = "UserTraceData1";
7597 goto cp0_unimplemented;
7598 case CP0_REG23__TRACEIBPC:
7599 /* PDtrace support */
7600 /* gen_helper_mfc0_traceibpc(arg); */
7601 register_name = "TraceIBPC";
7602 goto cp0_unimplemented;
7603 case CP0_REG23__TRACEDBPC:
7604 /* PDtrace support */
7605 /* gen_helper_mfc0_tracedbpc(arg); */
7606 register_name = "TraceDBPC";
7607 goto cp0_unimplemented;
7608 default:
7609 goto cp0_unimplemented;
7611 break;
7612 case CP0_REGISTER_24:
7613 switch (sel) {
7614 case CP0_REG24__DEPC:
7615 /* EJTAG support */
7616 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7617 tcg_gen_ext32s_tl(arg, arg);
7618 register_name = "DEPC";
7619 break;
7620 default:
7621 goto cp0_unimplemented;
7623 break;
7624 case CP0_REGISTER_25:
7625 switch (sel) {
7626 case CP0_REG25__PERFCTL0:
7627 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
7628 register_name = "Performance0";
7629 break;
7630 case CP0_REG25__PERFCNT0:
7631 /* gen_helper_mfc0_performance1(arg); */
7632 register_name = "Performance1";
7633 goto cp0_unimplemented;
7634 case CP0_REG25__PERFCTL1:
7635 /* gen_helper_mfc0_performance2(arg); */
7636 register_name = "Performance2";
7637 goto cp0_unimplemented;
7638 case CP0_REG25__PERFCNT1:
7639 /* gen_helper_mfc0_performance3(arg); */
7640 register_name = "Performance3";
7641 goto cp0_unimplemented;
7642 case CP0_REG25__PERFCTL2:
7643 /* gen_helper_mfc0_performance4(arg); */
7644 register_name = "Performance4";
7645 goto cp0_unimplemented;
7646 case CP0_REG25__PERFCNT2:
7647 /* gen_helper_mfc0_performance5(arg); */
7648 register_name = "Performance5";
7649 goto cp0_unimplemented;
7650 case CP0_REG25__PERFCTL3:
7651 /* gen_helper_mfc0_performance6(arg); */
7652 register_name = "Performance6";
7653 goto cp0_unimplemented;
7654 case CP0_REG25__PERFCNT3:
7655 /* gen_helper_mfc0_performance7(arg); */
7656 register_name = "Performance7";
7657 goto cp0_unimplemented;
7658 default:
7659 goto cp0_unimplemented;
7661 break;
7662 case CP0_REGISTER_26:
7663 switch (sel) {
7664 case CP0_REG26__ERRCTL:
7665 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7666 register_name = "ErrCtl";
7667 break;
7668 default:
7669 goto cp0_unimplemented;
7671 break;
7672 case CP0_REGISTER_27:
7673 switch (sel) {
7674 case CP0_REG27__CACHERR:
7675 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7676 register_name = "CacheErr";
7677 break;
7678 default:
7679 goto cp0_unimplemented;
7681 break;
7682 case CP0_REGISTER_28:
7683 switch (sel) {
7684 case CP0_REG28__TAGLO:
7685 case CP0_REG28__TAGLO1:
7686 case CP0_REG28__TAGLO2:
7687 case CP0_REG28__TAGLO3:
7689 TCGv_i64 tmp = tcg_temp_new_i64();
7690 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
7691 gen_move_low32(arg, tmp);
7692 tcg_temp_free_i64(tmp);
7694 register_name = "TagLo";
7695 break;
7696 case CP0_REG28__DATALO:
7697 case CP0_REG28__DATALO1:
7698 case CP0_REG28__DATALO2:
7699 case CP0_REG28__DATALO3:
7700 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7701 register_name = "DataLo";
7702 break;
7703 default:
7704 goto cp0_unimplemented;
7706 break;
7707 case CP0_REGISTER_29:
7708 switch (sel) {
7709 case CP0_REG29__TAGHI:
7710 case CP0_REG29__TAGHI1:
7711 case CP0_REG29__TAGHI2:
7712 case CP0_REG29__TAGHI3:
7713 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7714 register_name = "TagHi";
7715 break;
7716 case CP0_REG29__DATAHI:
7717 case CP0_REG29__DATAHI1:
7718 case CP0_REG29__DATAHI2:
7719 case CP0_REG29__DATAHI3:
7720 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7721 register_name = "DataHi";
7722 break;
7723 default:
7724 goto cp0_unimplemented;
7726 break;
7727 case CP0_REGISTER_30:
7728 switch (sel) {
7729 case CP0_REG30__ERROREPC:
7730 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7731 tcg_gen_ext32s_tl(arg, arg);
7732 register_name = "ErrorEPC";
7733 break;
7734 default:
7735 goto cp0_unimplemented;
7737 break;
7738 case CP0_REGISTER_31:
7739 switch (sel) {
7740 case CP0_REG31__DESAVE:
7741 /* EJTAG support */
7742 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7743 register_name = "DESAVE";
7744 break;
7745 case CP0_REG31__KSCRATCH1:
7746 case CP0_REG31__KSCRATCH2:
7747 case CP0_REG31__KSCRATCH3:
7748 case CP0_REG31__KSCRATCH4:
7749 case CP0_REG31__KSCRATCH5:
7750 case CP0_REG31__KSCRATCH6:
7751 CP0_CHECK(ctx->kscrexist & (1 << sel));
7752 tcg_gen_ld_tl(arg, cpu_env,
7753 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
7754 tcg_gen_ext32s_tl(arg, arg);
7755 register_name = "KScratch";
7756 break;
7757 default:
7758 goto cp0_unimplemented;
7760 break;
7761 default:
7762 goto cp0_unimplemented;
7764 trace_mips_translate_c0("mfc0", register_name, reg, sel);
7765 return;
7767 cp0_unimplemented:
7768 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
7769 register_name, reg, sel);
7770 gen_mfc0_unimplemented(ctx, arg);
7773 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7775 const char *register_name = "invalid";
7777 if (sel != 0) {
7778 check_insn(ctx, ISA_MIPS_R1);
7781 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7782 gen_io_start();
7785 switch (reg) {
7786 case CP0_REGISTER_00:
7787 switch (sel) {
7788 case CP0_REG00__INDEX:
7789 gen_helper_mtc0_index(cpu_env, arg);
7790 register_name = "Index";
7791 break;
7792 case CP0_REG00__MVPCONTROL:
7793 CP0_CHECK(ctx->insn_flags & ASE_MT);
7794 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7795 register_name = "MVPControl";
7796 break;
7797 case CP0_REG00__MVPCONF0:
7798 CP0_CHECK(ctx->insn_flags & ASE_MT);
7799 /* ignored */
7800 register_name = "MVPConf0";
7801 break;
7802 case CP0_REG00__MVPCONF1:
7803 CP0_CHECK(ctx->insn_flags & ASE_MT);
7804 /* ignored */
7805 register_name = "MVPConf1";
7806 break;
7807 case CP0_REG00__VPCONTROL:
7808 CP0_CHECK(ctx->vp);
7809 /* ignored */
7810 register_name = "VPControl";
7811 break;
7812 default:
7813 goto cp0_unimplemented;
7815 break;
7816 case CP0_REGISTER_01:
7817 switch (sel) {
7818 case CP0_REG01__RANDOM:
7819 /* ignored */
7820 register_name = "Random";
7821 break;
7822 case CP0_REG01__VPECONTROL:
7823 CP0_CHECK(ctx->insn_flags & ASE_MT);
7824 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7825 register_name = "VPEControl";
7826 break;
7827 case CP0_REG01__VPECONF0:
7828 CP0_CHECK(ctx->insn_flags & ASE_MT);
7829 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7830 register_name = "VPEConf0";
7831 break;
7832 case CP0_REG01__VPECONF1:
7833 CP0_CHECK(ctx->insn_flags & ASE_MT);
7834 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7835 register_name = "VPEConf1";
7836 break;
7837 case CP0_REG01__YQMASK:
7838 CP0_CHECK(ctx->insn_flags & ASE_MT);
7839 gen_helper_mtc0_yqmask(cpu_env, arg);
7840 register_name = "YQMask";
7841 break;
7842 case CP0_REG01__VPESCHEDULE:
7843 CP0_CHECK(ctx->insn_flags & ASE_MT);
7844 tcg_gen_st_tl(arg, cpu_env,
7845 offsetof(CPUMIPSState, CP0_VPESchedule));
7846 register_name = "VPESchedule";
7847 break;
7848 case CP0_REG01__VPESCHEFBACK:
7849 CP0_CHECK(ctx->insn_flags & ASE_MT);
7850 tcg_gen_st_tl(arg, cpu_env,
7851 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7852 register_name = "VPEScheFBack";
7853 break;
7854 case CP0_REG01__VPEOPT:
7855 CP0_CHECK(ctx->insn_flags & ASE_MT);
7856 gen_helper_mtc0_vpeopt(cpu_env, arg);
7857 register_name = "VPEOpt";
7858 break;
7859 default:
7860 goto cp0_unimplemented;
7862 break;
7863 case CP0_REGISTER_02:
7864 switch (sel) {
7865 case CP0_REG02__ENTRYLO0:
7866 gen_helper_mtc0_entrylo0(cpu_env, arg);
7867 register_name = "EntryLo0";
7868 break;
7869 case CP0_REG02__TCSTATUS:
7870 CP0_CHECK(ctx->insn_flags & ASE_MT);
7871 gen_helper_mtc0_tcstatus(cpu_env, arg);
7872 register_name = "TCStatus";
7873 break;
7874 case CP0_REG02__TCBIND:
7875 CP0_CHECK(ctx->insn_flags & ASE_MT);
7876 gen_helper_mtc0_tcbind(cpu_env, arg);
7877 register_name = "TCBind";
7878 break;
7879 case CP0_REG02__TCRESTART:
7880 CP0_CHECK(ctx->insn_flags & ASE_MT);
7881 gen_helper_mtc0_tcrestart(cpu_env, arg);
7882 register_name = "TCRestart";
7883 break;
7884 case CP0_REG02__TCHALT:
7885 CP0_CHECK(ctx->insn_flags & ASE_MT);
7886 gen_helper_mtc0_tchalt(cpu_env, arg);
7887 register_name = "TCHalt";
7888 break;
7889 case CP0_REG02__TCCONTEXT:
7890 CP0_CHECK(ctx->insn_flags & ASE_MT);
7891 gen_helper_mtc0_tccontext(cpu_env, arg);
7892 register_name = "TCContext";
7893 break;
7894 case CP0_REG02__TCSCHEDULE:
7895 CP0_CHECK(ctx->insn_flags & ASE_MT);
7896 gen_helper_mtc0_tcschedule(cpu_env, arg);
7897 register_name = "TCSchedule";
7898 break;
7899 case CP0_REG02__TCSCHEFBACK:
7900 CP0_CHECK(ctx->insn_flags & ASE_MT);
7901 gen_helper_mtc0_tcschefback(cpu_env, arg);
7902 register_name = "TCScheFBack";
7903 break;
7904 default:
7905 goto cp0_unimplemented;
7907 break;
7908 case CP0_REGISTER_03:
7909 switch (sel) {
7910 case CP0_REG03__ENTRYLO1:
7911 gen_helper_mtc0_entrylo1(cpu_env, arg);
7912 register_name = "EntryLo1";
7913 break;
7914 case CP0_REG03__GLOBALNUM:
7915 CP0_CHECK(ctx->vp);
7916 /* ignored */
7917 register_name = "GlobalNumber";
7918 break;
7919 default:
7920 goto cp0_unimplemented;
7922 break;
7923 case CP0_REGISTER_04:
7924 switch (sel) {
7925 case CP0_REG04__CONTEXT:
7926 gen_helper_mtc0_context(cpu_env, arg);
7927 register_name = "Context";
7928 break;
7929 case CP0_REG04__CONTEXTCONFIG:
7930 /* SmartMIPS ASE */
7931 /* gen_helper_mtc0_contextconfig(arg); */
7932 register_name = "ContextConfig";
7933 goto cp0_unimplemented;
7934 case CP0_REG04__USERLOCAL:
7935 CP0_CHECK(ctx->ulri);
7936 tcg_gen_st_tl(arg, cpu_env,
7937 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7938 register_name = "UserLocal";
7939 break;
7940 case CP0_REG04__MMID:
7941 CP0_CHECK(ctx->mi);
7942 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
7943 register_name = "MMID";
7944 break;
7945 default:
7946 goto cp0_unimplemented;
7948 break;
7949 case CP0_REGISTER_05:
7950 switch (sel) {
7951 case CP0_REG05__PAGEMASK:
7952 gen_helper_mtc0_pagemask(cpu_env, arg);
7953 register_name = "PageMask";
7954 break;
7955 case CP0_REG05__PAGEGRAIN:
7956 check_insn(ctx, ISA_MIPS_R2);
7957 gen_helper_mtc0_pagegrain(cpu_env, arg);
7958 register_name = "PageGrain";
7959 ctx->base.is_jmp = DISAS_STOP;
7960 break;
7961 case CP0_REG05__SEGCTL0:
7962 CP0_CHECK(ctx->sc);
7963 gen_helper_mtc0_segctl0(cpu_env, arg);
7964 register_name = "SegCtl0";
7965 break;
7966 case CP0_REG05__SEGCTL1:
7967 CP0_CHECK(ctx->sc);
7968 gen_helper_mtc0_segctl1(cpu_env, arg);
7969 register_name = "SegCtl1";
7970 break;
7971 case CP0_REG05__SEGCTL2:
7972 CP0_CHECK(ctx->sc);
7973 gen_helper_mtc0_segctl2(cpu_env, arg);
7974 register_name = "SegCtl2";
7975 break;
7976 case CP0_REG05__PWBASE:
7977 check_pw(ctx);
7978 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7979 register_name = "PWBase";
7980 break;
7981 case CP0_REG05__PWFIELD:
7982 check_pw(ctx);
7983 gen_helper_mtc0_pwfield(cpu_env, arg);
7984 register_name = "PWField";
7985 break;
7986 case CP0_REG05__PWSIZE:
7987 check_pw(ctx);
7988 gen_helper_mtc0_pwsize(cpu_env, arg);
7989 register_name = "PWSize";
7990 break;
7991 default:
7992 goto cp0_unimplemented;
7994 break;
7995 case CP0_REGISTER_06:
7996 switch (sel) {
7997 case CP0_REG06__WIRED:
7998 gen_helper_mtc0_wired(cpu_env, arg);
7999 register_name = "Wired";
8000 break;
8001 case CP0_REG06__SRSCONF0:
8002 check_insn(ctx, ISA_MIPS_R2);
8003 gen_helper_mtc0_srsconf0(cpu_env, arg);
8004 register_name = "SRSConf0";
8005 break;
8006 case CP0_REG06__SRSCONF1:
8007 check_insn(ctx, ISA_MIPS_R2);
8008 gen_helper_mtc0_srsconf1(cpu_env, arg);
8009 register_name = "SRSConf1";
8010 break;
8011 case CP0_REG06__SRSCONF2:
8012 check_insn(ctx, ISA_MIPS_R2);
8013 gen_helper_mtc0_srsconf2(cpu_env, arg);
8014 register_name = "SRSConf2";
8015 break;
8016 case CP0_REG06__SRSCONF3:
8017 check_insn(ctx, ISA_MIPS_R2);
8018 gen_helper_mtc0_srsconf3(cpu_env, arg);
8019 register_name = "SRSConf3";
8020 break;
8021 case CP0_REG06__SRSCONF4:
8022 check_insn(ctx, ISA_MIPS_R2);
8023 gen_helper_mtc0_srsconf4(cpu_env, arg);
8024 register_name = "SRSConf4";
8025 break;
8026 case CP0_REG06__PWCTL:
8027 check_pw(ctx);
8028 gen_helper_mtc0_pwctl(cpu_env, arg);
8029 register_name = "PWCtl";
8030 break;
8031 default:
8032 goto cp0_unimplemented;
8034 break;
8035 case CP0_REGISTER_07:
8036 switch (sel) {
8037 case CP0_REG07__HWRENA:
8038 check_insn(ctx, ISA_MIPS_R2);
8039 gen_helper_mtc0_hwrena(cpu_env, arg);
8040 ctx->base.is_jmp = DISAS_STOP;
8041 register_name = "HWREna";
8042 break;
8043 default:
8044 goto cp0_unimplemented;
8046 break;
8047 case CP0_REGISTER_08:
8048 switch (sel) {
8049 case CP0_REG08__BADVADDR:
8050 /* ignored */
8051 register_name = "BadVAddr";
8052 break;
8053 case CP0_REG08__BADINSTR:
8054 /* ignored */
8055 register_name = "BadInstr";
8056 break;
8057 case CP0_REG08__BADINSTRP:
8058 /* ignored */
8059 register_name = "BadInstrP";
8060 break;
8061 case CP0_REG08__BADINSTRX:
8062 /* ignored */
8063 register_name = "BadInstrX";
8064 break;
8065 default:
8066 goto cp0_unimplemented;
8068 break;
8069 case CP0_REGISTER_09:
8070 switch (sel) {
8071 case CP0_REG09__COUNT:
8072 gen_helper_mtc0_count(cpu_env, arg);
8073 register_name = "Count";
8074 break;
8075 case CP0_REG09__SAARI:
8076 CP0_CHECK(ctx->saar);
8077 gen_helper_mtc0_saari(cpu_env, arg);
8078 register_name = "SAARI";
8079 break;
8080 case CP0_REG09__SAAR:
8081 CP0_CHECK(ctx->saar);
8082 gen_helper_mtc0_saar(cpu_env, arg);
8083 register_name = "SAAR";
8084 break;
8085 default:
8086 goto cp0_unimplemented;
8088 break;
8089 case CP0_REGISTER_10:
8090 switch (sel) {
8091 case CP0_REG10__ENTRYHI:
8092 gen_helper_mtc0_entryhi(cpu_env, arg);
8093 register_name = "EntryHi";
8094 break;
8095 default:
8096 goto cp0_unimplemented;
8098 break;
8099 case CP0_REGISTER_11:
8100 switch (sel) {
8101 case CP0_REG11__COMPARE:
8102 gen_helper_mtc0_compare(cpu_env, arg);
8103 register_name = "Compare";
8104 break;
8105 /* 6,7 are implementation dependent */
8106 default:
8107 goto cp0_unimplemented;
8109 break;
8110 case CP0_REGISTER_12:
8111 switch (sel) {
8112 case CP0_REG12__STATUS:
8113 save_cpu_state(ctx, 1);
8114 gen_helper_mtc0_status(cpu_env, arg);
8115 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8116 gen_save_pc(ctx->base.pc_next + 4);
8117 ctx->base.is_jmp = DISAS_EXIT;
8118 register_name = "Status";
8119 break;
8120 case CP0_REG12__INTCTL:
8121 check_insn(ctx, ISA_MIPS_R2);
8122 gen_helper_mtc0_intctl(cpu_env, arg);
8123 /* Stop translation as we may have switched the execution mode */
8124 ctx->base.is_jmp = DISAS_STOP;
8125 register_name = "IntCtl";
8126 break;
8127 case CP0_REG12__SRSCTL:
8128 check_insn(ctx, ISA_MIPS_R2);
8129 gen_helper_mtc0_srsctl(cpu_env, arg);
8130 /* Stop translation as we may have switched the execution mode */
8131 ctx->base.is_jmp = DISAS_STOP;
8132 register_name = "SRSCtl";
8133 break;
8134 case CP0_REG12__SRSMAP:
8135 check_insn(ctx, ISA_MIPS_R2);
8136 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8137 /* Stop translation as we may have switched the execution mode */
8138 ctx->base.is_jmp = DISAS_STOP;
8139 register_name = "SRSMap";
8140 break;
8141 default:
8142 goto cp0_unimplemented;
8144 break;
8145 case CP0_REGISTER_13:
8146 switch (sel) {
8147 case CP0_REG13__CAUSE:
8148 save_cpu_state(ctx, 1);
8149 gen_helper_mtc0_cause(cpu_env, arg);
8151 * Stop translation as we may have triggered an interrupt.
8152 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8153 * translated code to check for pending interrupts.
8155 gen_save_pc(ctx->base.pc_next + 4);
8156 ctx->base.is_jmp = DISAS_EXIT;
8157 register_name = "Cause";
8158 break;
8159 default:
8160 goto cp0_unimplemented;
8162 break;
8163 case CP0_REGISTER_14:
8164 switch (sel) {
8165 case CP0_REG14__EPC:
8166 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8167 register_name = "EPC";
8168 break;
8169 default:
8170 goto cp0_unimplemented;
8172 break;
8173 case CP0_REGISTER_15:
8174 switch (sel) {
8175 case CP0_REG15__PRID:
8176 /* ignored */
8177 register_name = "PRid";
8178 break;
8179 case CP0_REG15__EBASE:
8180 check_insn(ctx, ISA_MIPS_R2);
8181 gen_helper_mtc0_ebase(cpu_env, arg);
8182 register_name = "EBase";
8183 break;
8184 default:
8185 goto cp0_unimplemented;
8187 break;
8188 case CP0_REGISTER_16:
8189 switch (sel) {
8190 case CP0_REG16__CONFIG:
8191 gen_helper_mtc0_config0(cpu_env, arg);
8192 register_name = "Config";
8193 /* Stop translation as we may have switched the execution mode */
8194 ctx->base.is_jmp = DISAS_STOP;
8195 break;
8196 case CP0_REG16__CONFIG1:
8197 /* ignored, read only */
8198 register_name = "Config1";
8199 break;
8200 case CP0_REG16__CONFIG2:
8201 gen_helper_mtc0_config2(cpu_env, arg);
8202 register_name = "Config2";
8203 /* Stop translation as we may have switched the execution mode */
8204 ctx->base.is_jmp = DISAS_STOP;
8205 break;
8206 case CP0_REG16__CONFIG3:
8207 gen_helper_mtc0_config3(cpu_env, arg);
8208 register_name = "Config3";
8209 /* Stop translation as we may have switched the execution mode */
8210 ctx->base.is_jmp = DISAS_STOP;
8211 break;
8212 case CP0_REG16__CONFIG4:
8213 gen_helper_mtc0_config4(cpu_env, arg);
8214 register_name = "Config4";
8215 ctx->base.is_jmp = DISAS_STOP;
8216 break;
8217 case CP0_REG16__CONFIG5:
8218 gen_helper_mtc0_config5(cpu_env, arg);
8219 register_name = "Config5";
8220 /* Stop translation as we may have switched the execution mode */
8221 ctx->base.is_jmp = DISAS_STOP;
8222 break;
8223 /* 6,7 are implementation dependent */
8224 case CP0_REG16__CONFIG6:
8225 /* ignored */
8226 register_name = "Config6";
8227 break;
8228 case CP0_REG16__CONFIG7:
8229 /* ignored */
8230 register_name = "Config7";
8231 break;
8232 default:
8233 register_name = "Invalid config selector";
8234 goto cp0_unimplemented;
8236 break;
8237 case CP0_REGISTER_17:
8238 switch (sel) {
8239 case CP0_REG17__LLADDR:
8240 gen_helper_mtc0_lladdr(cpu_env, arg);
8241 register_name = "LLAddr";
8242 break;
8243 case CP0_REG17__MAAR:
8244 CP0_CHECK(ctx->mrp);
8245 gen_helper_mtc0_maar(cpu_env, arg);
8246 register_name = "MAAR";
8247 break;
8248 case CP0_REG17__MAARI:
8249 CP0_CHECK(ctx->mrp);
8250 gen_helper_mtc0_maari(cpu_env, arg);
8251 register_name = "MAARI";
8252 break;
8253 default:
8254 goto cp0_unimplemented;
8256 break;
8257 case CP0_REGISTER_18:
8258 switch (sel) {
8259 case CP0_REG18__WATCHLO0:
8260 case CP0_REG18__WATCHLO1:
8261 case CP0_REG18__WATCHLO2:
8262 case CP0_REG18__WATCHLO3:
8263 case CP0_REG18__WATCHLO4:
8264 case CP0_REG18__WATCHLO5:
8265 case CP0_REG18__WATCHLO6:
8266 case CP0_REG18__WATCHLO7:
8267 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8268 gen_helper_0e1i(mtc0_watchlo, arg, sel);
8269 register_name = "WatchLo";
8270 break;
8271 default:
8272 goto cp0_unimplemented;
8274 break;
8275 case CP0_REGISTER_19:
8276 switch (sel) {
8277 case CP0_REG19__WATCHHI0:
8278 case CP0_REG19__WATCHHI1:
8279 case CP0_REG19__WATCHHI2:
8280 case CP0_REG19__WATCHHI3:
8281 case CP0_REG19__WATCHHI4:
8282 case CP0_REG19__WATCHHI5:
8283 case CP0_REG19__WATCHHI6:
8284 case CP0_REG19__WATCHHI7:
8285 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8286 gen_helper_0e1i(mtc0_watchhi, arg, sel);
8287 register_name = "WatchHi";
8288 break;
8289 default:
8290 goto cp0_unimplemented;
8292 break;
8293 case CP0_REGISTER_20:
8294 switch (sel) {
8295 case CP0_REG20__XCONTEXT:
8296 #if defined(TARGET_MIPS64)
8297 check_insn(ctx, ISA_MIPS3);
8298 gen_helper_mtc0_xcontext(cpu_env, arg);
8299 register_name = "XContext";
8300 break;
8301 #endif
8302 default:
8303 goto cp0_unimplemented;
8305 break;
8306 case CP0_REGISTER_21:
8307 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8308 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
8309 switch (sel) {
8310 case 0:
8311 gen_helper_mtc0_framemask(cpu_env, arg);
8312 register_name = "Framemask";
8313 break;
8314 default:
8315 goto cp0_unimplemented;
8317 break;
8318 case CP0_REGISTER_22:
8319 /* ignored */
8320 register_name = "Diagnostic"; /* implementation dependent */
8321 break;
8322 case CP0_REGISTER_23:
8323 switch (sel) {
8324 case CP0_REG23__DEBUG:
8325 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8326 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8327 gen_save_pc(ctx->base.pc_next + 4);
8328 ctx->base.is_jmp = DISAS_EXIT;
8329 register_name = "Debug";
8330 break;
8331 case CP0_REG23__TRACECONTROL:
8332 /* PDtrace support */
8333 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
8334 register_name = "TraceControl";
8335 /* Stop translation as we may have switched the execution mode */
8336 ctx->base.is_jmp = DISAS_STOP;
8337 goto cp0_unimplemented;
8338 case CP0_REG23__TRACECONTROL2:
8339 /* PDtrace support */
8340 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
8341 register_name = "TraceControl2";
8342 /* Stop translation as we may have switched the execution mode */
8343 ctx->base.is_jmp = DISAS_STOP;
8344 goto cp0_unimplemented;
8345 case CP0_REG23__USERTRACEDATA1:
8346 /* Stop translation as we may have switched the execution mode */
8347 ctx->base.is_jmp = DISAS_STOP;
8348 /* PDtrace support */
8349 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
8350 register_name = "UserTraceData";
8351 /* Stop translation as we may have switched the execution mode */
8352 ctx->base.is_jmp = DISAS_STOP;
8353 goto cp0_unimplemented;
8354 case CP0_REG23__TRACEIBPC:
8355 /* PDtrace support */
8356 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
8357 /* Stop translation as we may have switched the execution mode */
8358 ctx->base.is_jmp = DISAS_STOP;
8359 register_name = "TraceIBPC";
8360 goto cp0_unimplemented;
8361 case CP0_REG23__TRACEDBPC:
8362 /* PDtrace support */
8363 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
8364 /* Stop translation as we may have switched the execution mode */
8365 ctx->base.is_jmp = DISAS_STOP;
8366 register_name = "TraceDBPC";
8367 goto cp0_unimplemented;
8368 default:
8369 goto cp0_unimplemented;
8371 break;
8372 case CP0_REGISTER_24:
8373 switch (sel) {
8374 case CP0_REG24__DEPC:
8375 /* EJTAG support */
8376 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8377 register_name = "DEPC";
8378 break;
8379 default:
8380 goto cp0_unimplemented;
8382 break;
8383 case CP0_REGISTER_25:
8384 switch (sel) {
8385 case CP0_REG25__PERFCTL0:
8386 gen_helper_mtc0_performance0(cpu_env, arg);
8387 register_name = "Performance0";
8388 break;
8389 case CP0_REG25__PERFCNT0:
8390 /* gen_helper_mtc0_performance1(arg); */
8391 register_name = "Performance1";
8392 goto cp0_unimplemented;
8393 case CP0_REG25__PERFCTL1:
8394 /* gen_helper_mtc0_performance2(arg); */
8395 register_name = "Performance2";
8396 goto cp0_unimplemented;
8397 case CP0_REG25__PERFCNT1:
8398 /* gen_helper_mtc0_performance3(arg); */
8399 register_name = "Performance3";
8400 goto cp0_unimplemented;
8401 case CP0_REG25__PERFCTL2:
8402 /* gen_helper_mtc0_performance4(arg); */
8403 register_name = "Performance4";
8404 goto cp0_unimplemented;
8405 case CP0_REG25__PERFCNT2:
8406 /* gen_helper_mtc0_performance5(arg); */
8407 register_name = "Performance5";
8408 goto cp0_unimplemented;
8409 case CP0_REG25__PERFCTL3:
8410 /* gen_helper_mtc0_performance6(arg); */
8411 register_name = "Performance6";
8412 goto cp0_unimplemented;
8413 case CP0_REG25__PERFCNT3:
8414 /* gen_helper_mtc0_performance7(arg); */
8415 register_name = "Performance7";
8416 goto cp0_unimplemented;
8417 default:
8418 goto cp0_unimplemented;
8420 break;
8421 case CP0_REGISTER_26:
8422 switch (sel) {
8423 case CP0_REG26__ERRCTL:
8424 gen_helper_mtc0_errctl(cpu_env, arg);
8425 ctx->base.is_jmp = DISAS_STOP;
8426 register_name = "ErrCtl";
8427 break;
8428 default:
8429 goto cp0_unimplemented;
8431 break;
8432 case CP0_REGISTER_27:
8433 switch (sel) {
8434 case CP0_REG27__CACHERR:
8435 /* ignored */
8436 register_name = "CacheErr";
8437 break;
8438 default:
8439 goto cp0_unimplemented;
8441 break;
8442 case CP0_REGISTER_28:
8443 switch (sel) {
8444 case CP0_REG28__TAGLO:
8445 case CP0_REG28__TAGLO1:
8446 case CP0_REG28__TAGLO2:
8447 case CP0_REG28__TAGLO3:
8448 gen_helper_mtc0_taglo(cpu_env, arg);
8449 register_name = "TagLo";
8450 break;
8451 case CP0_REG28__DATALO:
8452 case CP0_REG28__DATALO1:
8453 case CP0_REG28__DATALO2:
8454 case CP0_REG28__DATALO3:
8455 gen_helper_mtc0_datalo(cpu_env, arg);
8456 register_name = "DataLo";
8457 break;
8458 default:
8459 goto cp0_unimplemented;
8461 break;
8462 case CP0_REGISTER_29:
8463 switch (sel) {
8464 case CP0_REG29__TAGHI:
8465 case CP0_REG29__TAGHI1:
8466 case CP0_REG29__TAGHI2:
8467 case CP0_REG29__TAGHI3:
8468 gen_helper_mtc0_taghi(cpu_env, arg);
8469 register_name = "TagHi";
8470 break;
8471 case CP0_REG29__DATAHI:
8472 case CP0_REG29__DATAHI1:
8473 case CP0_REG29__DATAHI2:
8474 case CP0_REG29__DATAHI3:
8475 gen_helper_mtc0_datahi(cpu_env, arg);
8476 register_name = "DataHi";
8477 break;
8478 default:
8479 register_name = "invalid sel";
8480 goto cp0_unimplemented;
8482 break;
8483 case CP0_REGISTER_30:
8484 switch (sel) {
8485 case CP0_REG30__ERROREPC:
8486 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8487 register_name = "ErrorEPC";
8488 break;
8489 default:
8490 goto cp0_unimplemented;
8492 break;
8493 case CP0_REGISTER_31:
8494 switch (sel) {
8495 case CP0_REG31__DESAVE:
8496 /* EJTAG support */
8497 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8498 register_name = "DESAVE";
8499 break;
8500 case CP0_REG31__KSCRATCH1:
8501 case CP0_REG31__KSCRATCH2:
8502 case CP0_REG31__KSCRATCH3:
8503 case CP0_REG31__KSCRATCH4:
8504 case CP0_REG31__KSCRATCH5:
8505 case CP0_REG31__KSCRATCH6:
8506 CP0_CHECK(ctx->kscrexist & (1 << sel));
8507 tcg_gen_st_tl(arg, cpu_env,
8508 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
8509 register_name = "KScratch";
8510 break;
8511 default:
8512 goto cp0_unimplemented;
8514 break;
8515 default:
8516 goto cp0_unimplemented;
8518 trace_mips_translate_c0("mtc0", register_name, reg, sel);
8520 /* For simplicity assume that all writes can cause interrupts. */
8521 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8523 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8524 * translated code to check for pending interrupts.
8526 gen_save_pc(ctx->base.pc_next + 4);
8527 ctx->base.is_jmp = DISAS_EXIT;
8529 return;
8531 cp0_unimplemented:
8532 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
8533 register_name, reg, sel);
8536 #if defined(TARGET_MIPS64)
8537 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8539 const char *register_name = "invalid";
8541 if (sel != 0) {
8542 check_insn(ctx, ISA_MIPS_R1);
8545 switch (reg) {
8546 case CP0_REGISTER_00:
8547 switch (sel) {
8548 case CP0_REG00__INDEX:
8549 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
8550 register_name = "Index";
8551 break;
8552 case CP0_REG00__MVPCONTROL:
8553 CP0_CHECK(ctx->insn_flags & ASE_MT);
8554 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
8555 register_name = "MVPControl";
8556 break;
8557 case CP0_REG00__MVPCONF0:
8558 CP0_CHECK(ctx->insn_flags & ASE_MT);
8559 gen_helper_mfc0_mvpconf0(arg, cpu_env);
8560 register_name = "MVPConf0";
8561 break;
8562 case CP0_REG00__MVPCONF1:
8563 CP0_CHECK(ctx->insn_flags & ASE_MT);
8564 gen_helper_mfc0_mvpconf1(arg, cpu_env);
8565 register_name = "MVPConf1";
8566 break;
8567 case CP0_REG00__VPCONTROL:
8568 CP0_CHECK(ctx->vp);
8569 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
8570 register_name = "VPControl";
8571 break;
8572 default:
8573 goto cp0_unimplemented;
8575 break;
8576 case CP0_REGISTER_01:
8577 switch (sel) {
8578 case CP0_REG01__RANDOM:
8579 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
8580 gen_helper_mfc0_random(arg, cpu_env);
8581 register_name = "Random";
8582 break;
8583 case CP0_REG01__VPECONTROL:
8584 CP0_CHECK(ctx->insn_flags & ASE_MT);
8585 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
8586 register_name = "VPEControl";
8587 break;
8588 case CP0_REG01__VPECONF0:
8589 CP0_CHECK(ctx->insn_flags & ASE_MT);
8590 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
8591 register_name = "VPEConf0";
8592 break;
8593 case CP0_REG01__VPECONF1:
8594 CP0_CHECK(ctx->insn_flags & ASE_MT);
8595 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
8596 register_name = "VPEConf1";
8597 break;
8598 case CP0_REG01__YQMASK:
8599 CP0_CHECK(ctx->insn_flags & ASE_MT);
8600 tcg_gen_ld_tl(arg, cpu_env,
8601 offsetof(CPUMIPSState, CP0_YQMask));
8602 register_name = "YQMask";
8603 break;
8604 case CP0_REG01__VPESCHEDULE:
8605 CP0_CHECK(ctx->insn_flags & ASE_MT);
8606 tcg_gen_ld_tl(arg, cpu_env,
8607 offsetof(CPUMIPSState, CP0_VPESchedule));
8608 register_name = "VPESchedule";
8609 break;
8610 case CP0_REG01__VPESCHEFBACK:
8611 CP0_CHECK(ctx->insn_flags & ASE_MT);
8612 tcg_gen_ld_tl(arg, cpu_env,
8613 offsetof(CPUMIPSState, CP0_VPEScheFBack));
8614 register_name = "VPEScheFBack";
8615 break;
8616 case CP0_REG01__VPEOPT:
8617 CP0_CHECK(ctx->insn_flags & ASE_MT);
8618 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
8619 register_name = "VPEOpt";
8620 break;
8621 default:
8622 goto cp0_unimplemented;
8624 break;
8625 case CP0_REGISTER_02:
8626 switch (sel) {
8627 case CP0_REG02__ENTRYLO0:
8628 tcg_gen_ld_tl(arg, cpu_env,
8629 offsetof(CPUMIPSState, CP0_EntryLo0));
8630 register_name = "EntryLo0";
8631 break;
8632 case CP0_REG02__TCSTATUS:
8633 CP0_CHECK(ctx->insn_flags & ASE_MT);
8634 gen_helper_mfc0_tcstatus(arg, cpu_env);
8635 register_name = "TCStatus";
8636 break;
8637 case CP0_REG02__TCBIND:
8638 CP0_CHECK(ctx->insn_flags & ASE_MT);
8639 gen_helper_mfc0_tcbind(arg, cpu_env);
8640 register_name = "TCBind";
8641 break;
8642 case CP0_REG02__TCRESTART:
8643 CP0_CHECK(ctx->insn_flags & ASE_MT);
8644 gen_helper_dmfc0_tcrestart(arg, cpu_env);
8645 register_name = "TCRestart";
8646 break;
8647 case CP0_REG02__TCHALT:
8648 CP0_CHECK(ctx->insn_flags & ASE_MT);
8649 gen_helper_dmfc0_tchalt(arg, cpu_env);
8650 register_name = "TCHalt";
8651 break;
8652 case CP0_REG02__TCCONTEXT:
8653 CP0_CHECK(ctx->insn_flags & ASE_MT);
8654 gen_helper_dmfc0_tccontext(arg, cpu_env);
8655 register_name = "TCContext";
8656 break;
8657 case CP0_REG02__TCSCHEDULE:
8658 CP0_CHECK(ctx->insn_flags & ASE_MT);
8659 gen_helper_dmfc0_tcschedule(arg, cpu_env);
8660 register_name = "TCSchedule";
8661 break;
8662 case CP0_REG02__TCSCHEFBACK:
8663 CP0_CHECK(ctx->insn_flags & ASE_MT);
8664 gen_helper_dmfc0_tcschefback(arg, cpu_env);
8665 register_name = "TCScheFBack";
8666 break;
8667 default:
8668 goto cp0_unimplemented;
8670 break;
8671 case CP0_REGISTER_03:
8672 switch (sel) {
8673 case CP0_REG03__ENTRYLO1:
8674 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
8675 register_name = "EntryLo1";
8676 break;
8677 case CP0_REG03__GLOBALNUM:
8678 CP0_CHECK(ctx->vp);
8679 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
8680 register_name = "GlobalNumber";
8681 break;
8682 default:
8683 goto cp0_unimplemented;
8685 break;
8686 case CP0_REGISTER_04:
8687 switch (sel) {
8688 case CP0_REG04__CONTEXT:
8689 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
8690 register_name = "Context";
8691 break;
8692 case CP0_REG04__CONTEXTCONFIG:
8693 /* SmartMIPS ASE */
8694 /* gen_helper_dmfc0_contextconfig(arg); */
8695 register_name = "ContextConfig";
8696 goto cp0_unimplemented;
8697 case CP0_REG04__USERLOCAL:
8698 CP0_CHECK(ctx->ulri);
8699 tcg_gen_ld_tl(arg, cpu_env,
8700 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8701 register_name = "UserLocal";
8702 break;
8703 case CP0_REG04__MMID:
8704 CP0_CHECK(ctx->mi);
8705 gen_helper_mtc0_memorymapid(cpu_env, arg);
8706 register_name = "MMID";
8707 break;
8708 default:
8709 goto cp0_unimplemented;
8711 break;
8712 case CP0_REGISTER_05:
8713 switch (sel) {
8714 case CP0_REG05__PAGEMASK:
8715 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
8716 register_name = "PageMask";
8717 break;
8718 case CP0_REG05__PAGEGRAIN:
8719 check_insn(ctx, ISA_MIPS_R2);
8720 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
8721 register_name = "PageGrain";
8722 break;
8723 case CP0_REG05__SEGCTL0:
8724 CP0_CHECK(ctx->sc);
8725 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
8726 register_name = "SegCtl0";
8727 break;
8728 case CP0_REG05__SEGCTL1:
8729 CP0_CHECK(ctx->sc);
8730 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
8731 register_name = "SegCtl1";
8732 break;
8733 case CP0_REG05__SEGCTL2:
8734 CP0_CHECK(ctx->sc);
8735 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
8736 register_name = "SegCtl2";
8737 break;
8738 case CP0_REG05__PWBASE:
8739 check_pw(ctx);
8740 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8741 register_name = "PWBase";
8742 break;
8743 case CP0_REG05__PWFIELD:
8744 check_pw(ctx);
8745 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
8746 register_name = "PWField";
8747 break;
8748 case CP0_REG05__PWSIZE:
8749 check_pw(ctx);
8750 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
8751 register_name = "PWSize";
8752 break;
8753 default:
8754 goto cp0_unimplemented;
8756 break;
8757 case CP0_REGISTER_06:
8758 switch (sel) {
8759 case CP0_REG06__WIRED:
8760 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
8761 register_name = "Wired";
8762 break;
8763 case CP0_REG06__SRSCONF0:
8764 check_insn(ctx, ISA_MIPS_R2);
8765 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
8766 register_name = "SRSConf0";
8767 break;
8768 case CP0_REG06__SRSCONF1:
8769 check_insn(ctx, ISA_MIPS_R2);
8770 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
8771 register_name = "SRSConf1";
8772 break;
8773 case CP0_REG06__SRSCONF2:
8774 check_insn(ctx, ISA_MIPS_R2);
8775 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
8776 register_name = "SRSConf2";
8777 break;
8778 case CP0_REG06__SRSCONF3:
8779 check_insn(ctx, ISA_MIPS_R2);
8780 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
8781 register_name = "SRSConf3";
8782 break;
8783 case CP0_REG06__SRSCONF4:
8784 check_insn(ctx, ISA_MIPS_R2);
8785 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
8786 register_name = "SRSConf4";
8787 break;
8788 case CP0_REG06__PWCTL:
8789 check_pw(ctx);
8790 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
8791 register_name = "PWCtl";
8792 break;
8793 default:
8794 goto cp0_unimplemented;
8796 break;
8797 case CP0_REGISTER_07:
8798 switch (sel) {
8799 case CP0_REG07__HWRENA:
8800 check_insn(ctx, ISA_MIPS_R2);
8801 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
8802 register_name = "HWREna";
8803 break;
8804 default:
8805 goto cp0_unimplemented;
8807 break;
8808 case CP0_REGISTER_08:
8809 switch (sel) {
8810 case CP0_REG08__BADVADDR:
8811 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
8812 register_name = "BadVAddr";
8813 break;
8814 case CP0_REG08__BADINSTR:
8815 CP0_CHECK(ctx->bi);
8816 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
8817 register_name = "BadInstr";
8818 break;
8819 case CP0_REG08__BADINSTRP:
8820 CP0_CHECK(ctx->bp);
8821 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
8822 register_name = "BadInstrP";
8823 break;
8824 case CP0_REG08__BADINSTRX:
8825 CP0_CHECK(ctx->bi);
8826 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
8827 tcg_gen_andi_tl(arg, arg, ~0xffff);
8828 register_name = "BadInstrX";
8829 break;
8830 default:
8831 goto cp0_unimplemented;
8833 break;
8834 case CP0_REGISTER_09:
8835 switch (sel) {
8836 case CP0_REG09__COUNT:
8837 /* Mark as an IO operation because we read the time. */
8838 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8839 gen_io_start();
8841 gen_helper_mfc0_count(arg, cpu_env);
8843 * Break the TB to be able to take timer interrupts immediately
8844 * after reading count. DISAS_STOP isn't sufficient, we need to
8845 * ensure we break completely out of translated code.
8847 gen_save_pc(ctx->base.pc_next + 4);
8848 ctx->base.is_jmp = DISAS_EXIT;
8849 register_name = "Count";
8850 break;
8851 case CP0_REG09__SAARI:
8852 CP0_CHECK(ctx->saar);
8853 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
8854 register_name = "SAARI";
8855 break;
8856 case CP0_REG09__SAAR:
8857 CP0_CHECK(ctx->saar);
8858 gen_helper_dmfc0_saar(arg, cpu_env);
8859 register_name = "SAAR";
8860 break;
8861 default:
8862 goto cp0_unimplemented;
8864 break;
8865 case CP0_REGISTER_10:
8866 switch (sel) {
8867 case CP0_REG10__ENTRYHI:
8868 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
8869 register_name = "EntryHi";
8870 break;
8871 default:
8872 goto cp0_unimplemented;
8874 break;
8875 case CP0_REGISTER_11:
8876 switch (sel) {
8877 case CP0_REG11__COMPARE:
8878 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
8879 register_name = "Compare";
8880 break;
8881 /* 6,7 are implementation dependent */
8882 default:
8883 goto cp0_unimplemented;
8885 break;
8886 case CP0_REGISTER_12:
8887 switch (sel) {
8888 case CP0_REG12__STATUS:
8889 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
8890 register_name = "Status";
8891 break;
8892 case CP0_REG12__INTCTL:
8893 check_insn(ctx, ISA_MIPS_R2);
8894 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
8895 register_name = "IntCtl";
8896 break;
8897 case CP0_REG12__SRSCTL:
8898 check_insn(ctx, ISA_MIPS_R2);
8899 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
8900 register_name = "SRSCtl";
8901 break;
8902 case CP0_REG12__SRSMAP:
8903 check_insn(ctx, ISA_MIPS_R2);
8904 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8905 register_name = "SRSMap";
8906 break;
8907 default:
8908 goto cp0_unimplemented;
8910 break;
8911 case CP0_REGISTER_13:
8912 switch (sel) {
8913 case CP0_REG13__CAUSE:
8914 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
8915 register_name = "Cause";
8916 break;
8917 default:
8918 goto cp0_unimplemented;
8920 break;
8921 case CP0_REGISTER_14:
8922 switch (sel) {
8923 case CP0_REG14__EPC:
8924 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8925 register_name = "EPC";
8926 break;
8927 default:
8928 goto cp0_unimplemented;
8930 break;
8931 case CP0_REGISTER_15:
8932 switch (sel) {
8933 case CP0_REG15__PRID:
8934 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
8935 register_name = "PRid";
8936 break;
8937 case CP0_REG15__EBASE:
8938 check_insn(ctx, ISA_MIPS_R2);
8939 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
8940 register_name = "EBase";
8941 break;
8942 case CP0_REG15__CMGCRBASE:
8943 check_insn(ctx, ISA_MIPS_R2);
8944 CP0_CHECK(ctx->cmgcr);
8945 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
8946 register_name = "CMGCRBase";
8947 break;
8948 default:
8949 goto cp0_unimplemented;
8951 break;
8952 case CP0_REGISTER_16:
8953 switch (sel) {
8954 case CP0_REG16__CONFIG:
8955 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
8956 register_name = "Config";
8957 break;
8958 case CP0_REG16__CONFIG1:
8959 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
8960 register_name = "Config1";
8961 break;
8962 case CP0_REG16__CONFIG2:
8963 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
8964 register_name = "Config2";
8965 break;
8966 case CP0_REG16__CONFIG3:
8967 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
8968 register_name = "Config3";
8969 break;
8970 case CP0_REG16__CONFIG4:
8971 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
8972 register_name = "Config4";
8973 break;
8974 case CP0_REG16__CONFIG5:
8975 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
8976 register_name = "Config5";
8977 break;
8978 /* 6,7 are implementation dependent */
8979 case CP0_REG16__CONFIG6:
8980 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
8981 register_name = "Config6";
8982 break;
8983 case CP0_REG16__CONFIG7:
8984 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
8985 register_name = "Config7";
8986 break;
8987 default:
8988 goto cp0_unimplemented;
8990 break;
8991 case CP0_REGISTER_17:
8992 switch (sel) {
8993 case CP0_REG17__LLADDR:
8994 gen_helper_dmfc0_lladdr(arg, cpu_env);
8995 register_name = "LLAddr";
8996 break;
8997 case CP0_REG17__MAAR:
8998 CP0_CHECK(ctx->mrp);
8999 gen_helper_dmfc0_maar(arg, cpu_env);
9000 register_name = "MAAR";
9001 break;
9002 case CP0_REG17__MAARI:
9003 CP0_CHECK(ctx->mrp);
9004 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
9005 register_name = "MAARI";
9006 break;
9007 default:
9008 goto cp0_unimplemented;
9010 break;
9011 case CP0_REGISTER_18:
9012 switch (sel) {
9013 case CP0_REG18__WATCHLO0:
9014 case CP0_REG18__WATCHLO1:
9015 case CP0_REG18__WATCHLO2:
9016 case CP0_REG18__WATCHLO3:
9017 case CP0_REG18__WATCHLO4:
9018 case CP0_REG18__WATCHLO5:
9019 case CP0_REG18__WATCHLO6:
9020 case CP0_REG18__WATCHLO7:
9021 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9022 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
9023 register_name = "WatchLo";
9024 break;
9025 default:
9026 goto cp0_unimplemented;
9028 break;
9029 case CP0_REGISTER_19:
9030 switch (sel) {
9031 case CP0_REG19__WATCHHI0:
9032 case CP0_REG19__WATCHHI1:
9033 case CP0_REG19__WATCHHI2:
9034 case CP0_REG19__WATCHHI3:
9035 case CP0_REG19__WATCHHI4:
9036 case CP0_REG19__WATCHHI5:
9037 case CP0_REG19__WATCHHI6:
9038 case CP0_REG19__WATCHHI7:
9039 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9040 gen_helper_1e0i(dmfc0_watchhi, arg, sel);
9041 register_name = "WatchHi";
9042 break;
9043 default:
9044 goto cp0_unimplemented;
9046 break;
9047 case CP0_REGISTER_20:
9048 switch (sel) {
9049 case CP0_REG20__XCONTEXT:
9050 check_insn(ctx, ISA_MIPS3);
9051 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
9052 register_name = "XContext";
9053 break;
9054 default:
9055 goto cp0_unimplemented;
9057 break;
9058 case CP0_REGISTER_21:
9059 /* Officially reserved, but sel 0 is used for R1x000 framemask */
9060 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
9061 switch (sel) {
9062 case 0:
9063 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
9064 register_name = "Framemask";
9065 break;
9066 default:
9067 goto cp0_unimplemented;
9069 break;
9070 case CP0_REGISTER_22:
9071 tcg_gen_movi_tl(arg, 0); /* unimplemented */
9072 register_name = "'Diagnostic"; /* implementation dependent */
9073 break;
9074 case CP0_REGISTER_23:
9075 switch (sel) {
9076 case CP0_REG23__DEBUG:
9077 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
9078 register_name = "Debug";
9079 break;
9080 case CP0_REG23__TRACECONTROL:
9081 /* PDtrace support */
9082 /* gen_helper_dmfc0_tracecontrol(arg, cpu_env); */
9083 register_name = "TraceControl";
9084 goto cp0_unimplemented;
9085 case CP0_REG23__TRACECONTROL2:
9086 /* PDtrace support */
9087 /* gen_helper_dmfc0_tracecontrol2(arg, cpu_env); */
9088 register_name = "TraceControl2";
9089 goto cp0_unimplemented;
9090 case CP0_REG23__USERTRACEDATA1:
9091 /* PDtrace support */
9092 /* gen_helper_dmfc0_usertracedata1(arg, cpu_env);*/
9093 register_name = "UserTraceData1";
9094 goto cp0_unimplemented;
9095 case CP0_REG23__TRACEIBPC:
9096 /* PDtrace support */
9097 /* gen_helper_dmfc0_traceibpc(arg, cpu_env); */
9098 register_name = "TraceIBPC";
9099 goto cp0_unimplemented;
9100 case CP0_REG23__TRACEDBPC:
9101 /* PDtrace support */
9102 /* gen_helper_dmfc0_tracedbpc(arg, cpu_env); */
9103 register_name = "TraceDBPC";
9104 goto cp0_unimplemented;
9105 default:
9106 goto cp0_unimplemented;
9108 break;
9109 case CP0_REGISTER_24:
9110 switch (sel) {
9111 case CP0_REG24__DEPC:
9112 /* EJTAG support */
9113 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
9114 register_name = "DEPC";
9115 break;
9116 default:
9117 goto cp0_unimplemented;
9119 break;
9120 case CP0_REGISTER_25:
9121 switch (sel) {
9122 case CP0_REG25__PERFCTL0:
9123 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
9124 register_name = "Performance0";
9125 break;
9126 case CP0_REG25__PERFCNT0:
9127 /* gen_helper_dmfc0_performance1(arg); */
9128 register_name = "Performance1";
9129 goto cp0_unimplemented;
9130 case CP0_REG25__PERFCTL1:
9131 /* gen_helper_dmfc0_performance2(arg); */
9132 register_name = "Performance2";
9133 goto cp0_unimplemented;
9134 case CP0_REG25__PERFCNT1:
9135 /* gen_helper_dmfc0_performance3(arg); */
9136 register_name = "Performance3";
9137 goto cp0_unimplemented;
9138 case CP0_REG25__PERFCTL2:
9139 /* gen_helper_dmfc0_performance4(arg); */
9140 register_name = "Performance4";
9141 goto cp0_unimplemented;
9142 case CP0_REG25__PERFCNT2:
9143 /* gen_helper_dmfc0_performance5(arg); */
9144 register_name = "Performance5";
9145 goto cp0_unimplemented;
9146 case CP0_REG25__PERFCTL3:
9147 /* gen_helper_dmfc0_performance6(arg); */
9148 register_name = "Performance6";
9149 goto cp0_unimplemented;
9150 case CP0_REG25__PERFCNT3:
9151 /* gen_helper_dmfc0_performance7(arg); */
9152 register_name = "Performance7";
9153 goto cp0_unimplemented;
9154 default:
9155 goto cp0_unimplemented;
9157 break;
9158 case CP0_REGISTER_26:
9159 switch (sel) {
9160 case CP0_REG26__ERRCTL:
9161 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
9162 register_name = "ErrCtl";
9163 break;
9164 default:
9165 goto cp0_unimplemented;
9167 break;
9168 case CP0_REGISTER_27:
9169 switch (sel) {
9170 /* ignored */
9171 case CP0_REG27__CACHERR:
9172 tcg_gen_movi_tl(arg, 0); /* unimplemented */
9173 register_name = "CacheErr";
9174 break;
9175 default:
9176 goto cp0_unimplemented;
9178 break;
9179 case CP0_REGISTER_28:
9180 switch (sel) {
9181 case CP0_REG28__TAGLO:
9182 case CP0_REG28__TAGLO1:
9183 case CP0_REG28__TAGLO2:
9184 case CP0_REG28__TAGLO3:
9185 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
9186 register_name = "TagLo";
9187 break;
9188 case CP0_REG28__DATALO:
9189 case CP0_REG28__DATALO1:
9190 case CP0_REG28__DATALO2:
9191 case CP0_REG28__DATALO3:
9192 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
9193 register_name = "DataLo";
9194 break;
9195 default:
9196 goto cp0_unimplemented;
9198 break;
9199 case CP0_REGISTER_29:
9200 switch (sel) {
9201 case CP0_REG29__TAGHI:
9202 case CP0_REG29__TAGHI1:
9203 case CP0_REG29__TAGHI2:
9204 case CP0_REG29__TAGHI3:
9205 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
9206 register_name = "TagHi";
9207 break;
9208 case CP0_REG29__DATAHI:
9209 case CP0_REG29__DATAHI1:
9210 case CP0_REG29__DATAHI2:
9211 case CP0_REG29__DATAHI3:
9212 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
9213 register_name = "DataHi";
9214 break;
9215 default:
9216 goto cp0_unimplemented;
9218 break;
9219 case CP0_REGISTER_30:
9220 switch (sel) {
9221 case CP0_REG30__ERROREPC:
9222 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9223 register_name = "ErrorEPC";
9224 break;
9225 default:
9226 goto cp0_unimplemented;
9228 break;
9229 case CP0_REGISTER_31:
9230 switch (sel) {
9231 case CP0_REG31__DESAVE:
9232 /* EJTAG support */
9233 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9234 register_name = "DESAVE";
9235 break;
9236 case CP0_REG31__KSCRATCH1:
9237 case CP0_REG31__KSCRATCH2:
9238 case CP0_REG31__KSCRATCH3:
9239 case CP0_REG31__KSCRATCH4:
9240 case CP0_REG31__KSCRATCH5:
9241 case CP0_REG31__KSCRATCH6:
9242 CP0_CHECK(ctx->kscrexist & (1 << sel));
9243 tcg_gen_ld_tl(arg, cpu_env,
9244 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
9245 register_name = "KScratch";
9246 break;
9247 default:
9248 goto cp0_unimplemented;
9250 break;
9251 default:
9252 goto cp0_unimplemented;
9254 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
9255 return;
9257 cp0_unimplemented:
9258 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
9259 register_name, reg, sel);
9260 gen_mfc0_unimplemented(ctx, arg);
9263 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9265 const char *register_name = "invalid";
9267 if (sel != 0) {
9268 check_insn(ctx, ISA_MIPS_R1);
9271 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9272 gen_io_start();
9275 switch (reg) {
9276 case CP0_REGISTER_00:
9277 switch (sel) {
9278 case CP0_REG00__INDEX:
9279 gen_helper_mtc0_index(cpu_env, arg);
9280 register_name = "Index";
9281 break;
9282 case CP0_REG00__MVPCONTROL:
9283 CP0_CHECK(ctx->insn_flags & ASE_MT);
9284 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
9285 register_name = "MVPControl";
9286 break;
9287 case CP0_REG00__MVPCONF0:
9288 CP0_CHECK(ctx->insn_flags & ASE_MT);
9289 /* ignored */
9290 register_name = "MVPConf0";
9291 break;
9292 case CP0_REG00__MVPCONF1:
9293 CP0_CHECK(ctx->insn_flags & ASE_MT);
9294 /* ignored */
9295 register_name = "MVPConf1";
9296 break;
9297 case CP0_REG00__VPCONTROL:
9298 CP0_CHECK(ctx->vp);
9299 /* ignored */
9300 register_name = "VPControl";
9301 break;
9302 default:
9303 goto cp0_unimplemented;
9305 break;
9306 case CP0_REGISTER_01:
9307 switch (sel) {
9308 case CP0_REG01__RANDOM:
9309 /* ignored */
9310 register_name = "Random";
9311 break;
9312 case CP0_REG01__VPECONTROL:
9313 CP0_CHECK(ctx->insn_flags & ASE_MT);
9314 gen_helper_mtc0_vpecontrol(cpu_env, arg);
9315 register_name = "VPEControl";
9316 break;
9317 case CP0_REG01__VPECONF0:
9318 CP0_CHECK(ctx->insn_flags & ASE_MT);
9319 gen_helper_mtc0_vpeconf0(cpu_env, arg);
9320 register_name = "VPEConf0";
9321 break;
9322 case CP0_REG01__VPECONF1:
9323 CP0_CHECK(ctx->insn_flags & ASE_MT);
9324 gen_helper_mtc0_vpeconf1(cpu_env, arg);
9325 register_name = "VPEConf1";
9326 break;
9327 case CP0_REG01__YQMASK:
9328 CP0_CHECK(ctx->insn_flags & ASE_MT);
9329 gen_helper_mtc0_yqmask(cpu_env, arg);
9330 register_name = "YQMask";
9331 break;
9332 case CP0_REG01__VPESCHEDULE:
9333 CP0_CHECK(ctx->insn_flags & ASE_MT);
9334 tcg_gen_st_tl(arg, cpu_env,
9335 offsetof(CPUMIPSState, CP0_VPESchedule));
9336 register_name = "VPESchedule";
9337 break;
9338 case CP0_REG01__VPESCHEFBACK:
9339 CP0_CHECK(ctx->insn_flags & ASE_MT);
9340 tcg_gen_st_tl(arg, cpu_env,
9341 offsetof(CPUMIPSState, CP0_VPEScheFBack));
9342 register_name = "VPEScheFBack";
9343 break;
9344 case CP0_REG01__VPEOPT:
9345 CP0_CHECK(ctx->insn_flags & ASE_MT);
9346 gen_helper_mtc0_vpeopt(cpu_env, arg);
9347 register_name = "VPEOpt";
9348 break;
9349 default:
9350 goto cp0_unimplemented;
9352 break;
9353 case CP0_REGISTER_02:
9354 switch (sel) {
9355 case CP0_REG02__ENTRYLO0:
9356 gen_helper_dmtc0_entrylo0(cpu_env, arg);
9357 register_name = "EntryLo0";
9358 break;
9359 case CP0_REG02__TCSTATUS:
9360 CP0_CHECK(ctx->insn_flags & ASE_MT);
9361 gen_helper_mtc0_tcstatus(cpu_env, arg);
9362 register_name = "TCStatus";
9363 break;
9364 case CP0_REG02__TCBIND:
9365 CP0_CHECK(ctx->insn_flags & ASE_MT);
9366 gen_helper_mtc0_tcbind(cpu_env, arg);
9367 register_name = "TCBind";
9368 break;
9369 case CP0_REG02__TCRESTART:
9370 CP0_CHECK(ctx->insn_flags & ASE_MT);
9371 gen_helper_mtc0_tcrestart(cpu_env, arg);
9372 register_name = "TCRestart";
9373 break;
9374 case CP0_REG02__TCHALT:
9375 CP0_CHECK(ctx->insn_flags & ASE_MT);
9376 gen_helper_mtc0_tchalt(cpu_env, arg);
9377 register_name = "TCHalt";
9378 break;
9379 case CP0_REG02__TCCONTEXT:
9380 CP0_CHECK(ctx->insn_flags & ASE_MT);
9381 gen_helper_mtc0_tccontext(cpu_env, arg);
9382 register_name = "TCContext";
9383 break;
9384 case CP0_REG02__TCSCHEDULE:
9385 CP0_CHECK(ctx->insn_flags & ASE_MT);
9386 gen_helper_mtc0_tcschedule(cpu_env, arg);
9387 register_name = "TCSchedule";
9388 break;
9389 case CP0_REG02__TCSCHEFBACK:
9390 CP0_CHECK(ctx->insn_flags & ASE_MT);
9391 gen_helper_mtc0_tcschefback(cpu_env, arg);
9392 register_name = "TCScheFBack";
9393 break;
9394 default:
9395 goto cp0_unimplemented;
9397 break;
9398 case CP0_REGISTER_03:
9399 switch (sel) {
9400 case CP0_REG03__ENTRYLO1:
9401 gen_helper_dmtc0_entrylo1(cpu_env, arg);
9402 register_name = "EntryLo1";
9403 break;
9404 case CP0_REG03__GLOBALNUM:
9405 CP0_CHECK(ctx->vp);
9406 /* ignored */
9407 register_name = "GlobalNumber";
9408 break;
9409 default:
9410 goto cp0_unimplemented;
9412 break;
9413 case CP0_REGISTER_04:
9414 switch (sel) {
9415 case CP0_REG04__CONTEXT:
9416 gen_helper_mtc0_context(cpu_env, arg);
9417 register_name = "Context";
9418 break;
9419 case CP0_REG04__CONTEXTCONFIG:
9420 /* SmartMIPS ASE */
9421 /* gen_helper_dmtc0_contextconfig(arg); */
9422 register_name = "ContextConfig";
9423 goto cp0_unimplemented;
9424 case CP0_REG04__USERLOCAL:
9425 CP0_CHECK(ctx->ulri);
9426 tcg_gen_st_tl(arg, cpu_env,
9427 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
9428 register_name = "UserLocal";
9429 break;
9430 case CP0_REG04__MMID:
9431 CP0_CHECK(ctx->mi);
9432 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
9433 register_name = "MMID";
9434 break;
9435 default:
9436 goto cp0_unimplemented;
9438 break;
9439 case CP0_REGISTER_05:
9440 switch (sel) {
9441 case CP0_REG05__PAGEMASK:
9442 gen_helper_mtc0_pagemask(cpu_env, arg);
9443 register_name = "PageMask";
9444 break;
9445 case CP0_REG05__PAGEGRAIN:
9446 check_insn(ctx, ISA_MIPS_R2);
9447 gen_helper_mtc0_pagegrain(cpu_env, arg);
9448 register_name = "PageGrain";
9449 break;
9450 case CP0_REG05__SEGCTL0:
9451 CP0_CHECK(ctx->sc);
9452 gen_helper_mtc0_segctl0(cpu_env, arg);
9453 register_name = "SegCtl0";
9454 break;
9455 case CP0_REG05__SEGCTL1:
9456 CP0_CHECK(ctx->sc);
9457 gen_helper_mtc0_segctl1(cpu_env, arg);
9458 register_name = "SegCtl1";
9459 break;
9460 case CP0_REG05__SEGCTL2:
9461 CP0_CHECK(ctx->sc);
9462 gen_helper_mtc0_segctl2(cpu_env, arg);
9463 register_name = "SegCtl2";
9464 break;
9465 case CP0_REG05__PWBASE:
9466 check_pw(ctx);
9467 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
9468 register_name = "PWBase";
9469 break;
9470 case CP0_REG05__PWFIELD:
9471 check_pw(ctx);
9472 gen_helper_mtc0_pwfield(cpu_env, arg);
9473 register_name = "PWField";
9474 break;
9475 case CP0_REG05__PWSIZE:
9476 check_pw(ctx);
9477 gen_helper_mtc0_pwsize(cpu_env, arg);
9478 register_name = "PWSize";
9479 break;
9480 default:
9481 goto cp0_unimplemented;
9483 break;
9484 case CP0_REGISTER_06:
9485 switch (sel) {
9486 case CP0_REG06__WIRED:
9487 gen_helper_mtc0_wired(cpu_env, arg);
9488 register_name = "Wired";
9489 break;
9490 case CP0_REG06__SRSCONF0:
9491 check_insn(ctx, ISA_MIPS_R2);
9492 gen_helper_mtc0_srsconf0(cpu_env, arg);
9493 register_name = "SRSConf0";
9494 break;
9495 case CP0_REG06__SRSCONF1:
9496 check_insn(ctx, ISA_MIPS_R2);
9497 gen_helper_mtc0_srsconf1(cpu_env, arg);
9498 register_name = "SRSConf1";
9499 break;
9500 case CP0_REG06__SRSCONF2:
9501 check_insn(ctx, ISA_MIPS_R2);
9502 gen_helper_mtc0_srsconf2(cpu_env, arg);
9503 register_name = "SRSConf2";
9504 break;
9505 case CP0_REG06__SRSCONF3:
9506 check_insn(ctx, ISA_MIPS_R2);
9507 gen_helper_mtc0_srsconf3(cpu_env, arg);
9508 register_name = "SRSConf3";
9509 break;
9510 case CP0_REG06__SRSCONF4:
9511 check_insn(ctx, ISA_MIPS_R2);
9512 gen_helper_mtc0_srsconf4(cpu_env, arg);
9513 register_name = "SRSConf4";
9514 break;
9515 case CP0_REG06__PWCTL:
9516 check_pw(ctx);
9517 gen_helper_mtc0_pwctl(cpu_env, arg);
9518 register_name = "PWCtl";
9519 break;
9520 default:
9521 goto cp0_unimplemented;
9523 break;
9524 case CP0_REGISTER_07:
9525 switch (sel) {
9526 case CP0_REG07__HWRENA:
9527 check_insn(ctx, ISA_MIPS_R2);
9528 gen_helper_mtc0_hwrena(cpu_env, arg);
9529 ctx->base.is_jmp = DISAS_STOP;
9530 register_name = "HWREna";
9531 break;
9532 default:
9533 goto cp0_unimplemented;
9535 break;
9536 case CP0_REGISTER_08:
9537 switch (sel) {
9538 case CP0_REG08__BADVADDR:
9539 /* ignored */
9540 register_name = "BadVAddr";
9541 break;
9542 case CP0_REG08__BADINSTR:
9543 /* ignored */
9544 register_name = "BadInstr";
9545 break;
9546 case CP0_REG08__BADINSTRP:
9547 /* ignored */
9548 register_name = "BadInstrP";
9549 break;
9550 case CP0_REG08__BADINSTRX:
9551 /* ignored */
9552 register_name = "BadInstrX";
9553 break;
9554 default:
9555 goto cp0_unimplemented;
9557 break;
9558 case CP0_REGISTER_09:
9559 switch (sel) {
9560 case CP0_REG09__COUNT:
9561 gen_helper_mtc0_count(cpu_env, arg);
9562 register_name = "Count";
9563 break;
9564 case CP0_REG09__SAARI:
9565 CP0_CHECK(ctx->saar);
9566 gen_helper_mtc0_saari(cpu_env, arg);
9567 register_name = "SAARI";
9568 break;
9569 case CP0_REG09__SAAR:
9570 CP0_CHECK(ctx->saar);
9571 gen_helper_mtc0_saar(cpu_env, arg);
9572 register_name = "SAAR";
9573 break;
9574 default:
9575 goto cp0_unimplemented;
9577 /* Stop translation as we may have switched the execution mode */
9578 ctx->base.is_jmp = DISAS_STOP;
9579 break;
9580 case CP0_REGISTER_10:
9581 switch (sel) {
9582 case CP0_REG10__ENTRYHI:
9583 gen_helper_mtc0_entryhi(cpu_env, arg);
9584 register_name = "EntryHi";
9585 break;
9586 default:
9587 goto cp0_unimplemented;
9589 break;
9590 case CP0_REGISTER_11:
9591 switch (sel) {
9592 case CP0_REG11__COMPARE:
9593 gen_helper_mtc0_compare(cpu_env, arg);
9594 register_name = "Compare";
9595 break;
9596 /* 6,7 are implementation dependent */
9597 default:
9598 goto cp0_unimplemented;
9600 /* Stop translation as we may have switched the execution mode */
9601 ctx->base.is_jmp = DISAS_STOP;
9602 break;
9603 case CP0_REGISTER_12:
9604 switch (sel) {
9605 case CP0_REG12__STATUS:
9606 save_cpu_state(ctx, 1);
9607 gen_helper_mtc0_status(cpu_env, arg);
9608 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9609 gen_save_pc(ctx->base.pc_next + 4);
9610 ctx->base.is_jmp = DISAS_EXIT;
9611 register_name = "Status";
9612 break;
9613 case CP0_REG12__INTCTL:
9614 check_insn(ctx, ISA_MIPS_R2);
9615 gen_helper_mtc0_intctl(cpu_env, arg);
9616 /* Stop translation as we may have switched the execution mode */
9617 ctx->base.is_jmp = DISAS_STOP;
9618 register_name = "IntCtl";
9619 break;
9620 case CP0_REG12__SRSCTL:
9621 check_insn(ctx, ISA_MIPS_R2);
9622 gen_helper_mtc0_srsctl(cpu_env, arg);
9623 /* Stop translation as we may have switched the execution mode */
9624 ctx->base.is_jmp = DISAS_STOP;
9625 register_name = "SRSCtl";
9626 break;
9627 case CP0_REG12__SRSMAP:
9628 check_insn(ctx, ISA_MIPS_R2);
9629 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
9630 /* Stop translation as we may have switched the execution mode */
9631 ctx->base.is_jmp = DISAS_STOP;
9632 register_name = "SRSMap";
9633 break;
9634 default:
9635 goto cp0_unimplemented;
9637 break;
9638 case CP0_REGISTER_13:
9639 switch (sel) {
9640 case CP0_REG13__CAUSE:
9641 save_cpu_state(ctx, 1);
9642 gen_helper_mtc0_cause(cpu_env, arg);
9644 * Stop translation as we may have triggered an interrupt.
9645 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9646 * translated code to check for pending interrupts.
9648 gen_save_pc(ctx->base.pc_next + 4);
9649 ctx->base.is_jmp = DISAS_EXIT;
9650 register_name = "Cause";
9651 break;
9652 default:
9653 goto cp0_unimplemented;
9655 break;
9656 case CP0_REGISTER_14:
9657 switch (sel) {
9658 case CP0_REG14__EPC:
9659 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
9660 register_name = "EPC";
9661 break;
9662 default:
9663 goto cp0_unimplemented;
9665 break;
9666 case CP0_REGISTER_15:
9667 switch (sel) {
9668 case CP0_REG15__PRID:
9669 /* ignored */
9670 register_name = "PRid";
9671 break;
9672 case CP0_REG15__EBASE:
9673 check_insn(ctx, ISA_MIPS_R2);
9674 gen_helper_mtc0_ebase(cpu_env, arg);
9675 register_name = "EBase";
9676 break;
9677 default:
9678 goto cp0_unimplemented;
9680 break;
9681 case CP0_REGISTER_16:
9682 switch (sel) {
9683 case CP0_REG16__CONFIG:
9684 gen_helper_mtc0_config0(cpu_env, arg);
9685 register_name = "Config";
9686 /* Stop translation as we may have switched the execution mode */
9687 ctx->base.is_jmp = DISAS_STOP;
9688 break;
9689 case CP0_REG16__CONFIG1:
9690 /* ignored, read only */
9691 register_name = "Config1";
9692 break;
9693 case CP0_REG16__CONFIG2:
9694 gen_helper_mtc0_config2(cpu_env, arg);
9695 register_name = "Config2";
9696 /* Stop translation as we may have switched the execution mode */
9697 ctx->base.is_jmp = DISAS_STOP;
9698 break;
9699 case CP0_REG16__CONFIG3:
9700 gen_helper_mtc0_config3(cpu_env, arg);
9701 register_name = "Config3";
9702 /* Stop translation as we may have switched the execution mode */
9703 ctx->base.is_jmp = DISAS_STOP;
9704 break;
9705 case CP0_REG16__CONFIG4:
9706 /* currently ignored */
9707 register_name = "Config4";
9708 break;
9709 case CP0_REG16__CONFIG5:
9710 gen_helper_mtc0_config5(cpu_env, arg);
9711 register_name = "Config5";
9712 /* Stop translation as we may have switched the execution mode */
9713 ctx->base.is_jmp = DISAS_STOP;
9714 break;
9715 /* 6,7 are implementation dependent */
9716 default:
9717 register_name = "Invalid config selector";
9718 goto cp0_unimplemented;
9720 break;
9721 case CP0_REGISTER_17:
9722 switch (sel) {
9723 case CP0_REG17__LLADDR:
9724 gen_helper_mtc0_lladdr(cpu_env, arg);
9725 register_name = "LLAddr";
9726 break;
9727 case CP0_REG17__MAAR:
9728 CP0_CHECK(ctx->mrp);
9729 gen_helper_mtc0_maar(cpu_env, arg);
9730 register_name = "MAAR";
9731 break;
9732 case CP0_REG17__MAARI:
9733 CP0_CHECK(ctx->mrp);
9734 gen_helper_mtc0_maari(cpu_env, arg);
9735 register_name = "MAARI";
9736 break;
9737 default:
9738 goto cp0_unimplemented;
9740 break;
9741 case CP0_REGISTER_18:
9742 switch (sel) {
9743 case CP0_REG18__WATCHLO0:
9744 case CP0_REG18__WATCHLO1:
9745 case CP0_REG18__WATCHLO2:
9746 case CP0_REG18__WATCHLO3:
9747 case CP0_REG18__WATCHLO4:
9748 case CP0_REG18__WATCHLO5:
9749 case CP0_REG18__WATCHLO6:
9750 case CP0_REG18__WATCHLO7:
9751 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9752 gen_helper_0e1i(mtc0_watchlo, arg, sel);
9753 register_name = "WatchLo";
9754 break;
9755 default:
9756 goto cp0_unimplemented;
9758 break;
9759 case CP0_REGISTER_19:
9760 switch (sel) {
9761 case CP0_REG19__WATCHHI0:
9762 case CP0_REG19__WATCHHI1:
9763 case CP0_REG19__WATCHHI2:
9764 case CP0_REG19__WATCHHI3:
9765 case CP0_REG19__WATCHHI4:
9766 case CP0_REG19__WATCHHI5:
9767 case CP0_REG19__WATCHHI6:
9768 case CP0_REG19__WATCHHI7:
9769 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9770 gen_helper_0e1i(mtc0_watchhi, arg, sel);
9771 register_name = "WatchHi";
9772 break;
9773 default:
9774 goto cp0_unimplemented;
9776 break;
9777 case CP0_REGISTER_20:
9778 switch (sel) {
9779 case CP0_REG20__XCONTEXT:
9780 check_insn(ctx, ISA_MIPS3);
9781 gen_helper_mtc0_xcontext(cpu_env, arg);
9782 register_name = "XContext";
9783 break;
9784 default:
9785 goto cp0_unimplemented;
9787 break;
9788 case CP0_REGISTER_21:
9789 /* Officially reserved, but sel 0 is used for R1x000 framemask */
9790 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
9791 switch (sel) {
9792 case 0:
9793 gen_helper_mtc0_framemask(cpu_env, arg);
9794 register_name = "Framemask";
9795 break;
9796 default:
9797 goto cp0_unimplemented;
9799 break;
9800 case CP0_REGISTER_22:
9801 /* ignored */
9802 register_name = "Diagnostic"; /* implementation dependent */
9803 break;
9804 case CP0_REGISTER_23:
9805 switch (sel) {
9806 case CP0_REG23__DEBUG:
9807 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
9808 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9809 gen_save_pc(ctx->base.pc_next + 4);
9810 ctx->base.is_jmp = DISAS_EXIT;
9811 register_name = "Debug";
9812 break;
9813 case CP0_REG23__TRACECONTROL:
9814 /* PDtrace support */
9815 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
9816 /* Stop translation as we may have switched the execution mode */
9817 ctx->base.is_jmp = DISAS_STOP;
9818 register_name = "TraceControl";
9819 goto cp0_unimplemented;
9820 case CP0_REG23__TRACECONTROL2:
9821 /* PDtrace support */
9822 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
9823 /* Stop translation as we may have switched the execution mode */
9824 ctx->base.is_jmp = DISAS_STOP;
9825 register_name = "TraceControl2";
9826 goto cp0_unimplemented;
9827 case CP0_REG23__USERTRACEDATA1:
9828 /* PDtrace support */
9829 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
9830 /* Stop translation as we may have switched the execution mode */
9831 ctx->base.is_jmp = DISAS_STOP;
9832 register_name = "UserTraceData1";
9833 goto cp0_unimplemented;
9834 case CP0_REG23__TRACEIBPC:
9835 /* PDtrace support */
9836 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
9837 /* Stop translation as we may have switched the execution mode */
9838 ctx->base.is_jmp = DISAS_STOP;
9839 register_name = "TraceIBPC";
9840 goto cp0_unimplemented;
9841 case CP0_REG23__TRACEDBPC:
9842 /* PDtrace support */
9843 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
9844 /* Stop translation as we may have switched the execution mode */
9845 ctx->base.is_jmp = DISAS_STOP;
9846 register_name = "TraceDBPC";
9847 goto cp0_unimplemented;
9848 default:
9849 goto cp0_unimplemented;
9851 break;
9852 case CP0_REGISTER_24:
9853 switch (sel) {
9854 case CP0_REG24__DEPC:
9855 /* EJTAG support */
9856 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
9857 register_name = "DEPC";
9858 break;
9859 default:
9860 goto cp0_unimplemented;
9862 break;
9863 case CP0_REGISTER_25:
9864 switch (sel) {
9865 case CP0_REG25__PERFCTL0:
9866 gen_helper_mtc0_performance0(cpu_env, arg);
9867 register_name = "Performance0";
9868 break;
9869 case CP0_REG25__PERFCNT0:
9870 /* gen_helper_mtc0_performance1(cpu_env, arg); */
9871 register_name = "Performance1";
9872 goto cp0_unimplemented;
9873 case CP0_REG25__PERFCTL1:
9874 /* gen_helper_mtc0_performance2(cpu_env, arg); */
9875 register_name = "Performance2";
9876 goto cp0_unimplemented;
9877 case CP0_REG25__PERFCNT1:
9878 /* gen_helper_mtc0_performance3(cpu_env, arg); */
9879 register_name = "Performance3";
9880 goto cp0_unimplemented;
9881 case CP0_REG25__PERFCTL2:
9882 /* gen_helper_mtc0_performance4(cpu_env, arg); */
9883 register_name = "Performance4";
9884 goto cp0_unimplemented;
9885 case CP0_REG25__PERFCNT2:
9886 /* gen_helper_mtc0_performance5(cpu_env, arg); */
9887 register_name = "Performance5";
9888 goto cp0_unimplemented;
9889 case CP0_REG25__PERFCTL3:
9890 /* gen_helper_mtc0_performance6(cpu_env, arg); */
9891 register_name = "Performance6";
9892 goto cp0_unimplemented;
9893 case CP0_REG25__PERFCNT3:
9894 /* gen_helper_mtc0_performance7(cpu_env, arg); */
9895 register_name = "Performance7";
9896 goto cp0_unimplemented;
9897 default:
9898 goto cp0_unimplemented;
9900 break;
9901 case CP0_REGISTER_26:
9902 switch (sel) {
9903 case CP0_REG26__ERRCTL:
9904 gen_helper_mtc0_errctl(cpu_env, arg);
9905 ctx->base.is_jmp = DISAS_STOP;
9906 register_name = "ErrCtl";
9907 break;
9908 default:
9909 goto cp0_unimplemented;
9911 break;
9912 case CP0_REGISTER_27:
9913 switch (sel) {
9914 case CP0_REG27__CACHERR:
9915 /* ignored */
9916 register_name = "CacheErr";
9917 break;
9918 default:
9919 goto cp0_unimplemented;
9921 break;
9922 case CP0_REGISTER_28:
9923 switch (sel) {
9924 case CP0_REG28__TAGLO:
9925 case CP0_REG28__TAGLO1:
9926 case CP0_REG28__TAGLO2:
9927 case CP0_REG28__TAGLO3:
9928 gen_helper_mtc0_taglo(cpu_env, arg);
9929 register_name = "TagLo";
9930 break;
9931 case CP0_REG28__DATALO:
9932 case CP0_REG28__DATALO1:
9933 case CP0_REG28__DATALO2:
9934 case CP0_REG28__DATALO3:
9935 gen_helper_mtc0_datalo(cpu_env, arg);
9936 register_name = "DataLo";
9937 break;
9938 default:
9939 goto cp0_unimplemented;
9941 break;
9942 case CP0_REGISTER_29:
9943 switch (sel) {
9944 case CP0_REG29__TAGHI:
9945 case CP0_REG29__TAGHI1:
9946 case CP0_REG29__TAGHI2:
9947 case CP0_REG29__TAGHI3:
9948 gen_helper_mtc0_taghi(cpu_env, arg);
9949 register_name = "TagHi";
9950 break;
9951 case CP0_REG29__DATAHI:
9952 case CP0_REG29__DATAHI1:
9953 case CP0_REG29__DATAHI2:
9954 case CP0_REG29__DATAHI3:
9955 gen_helper_mtc0_datahi(cpu_env, arg);
9956 register_name = "DataHi";
9957 break;
9958 default:
9959 register_name = "invalid sel";
9960 goto cp0_unimplemented;
9962 break;
9963 case CP0_REGISTER_30:
9964 switch (sel) {
9965 case CP0_REG30__ERROREPC:
9966 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9967 register_name = "ErrorEPC";
9968 break;
9969 default:
9970 goto cp0_unimplemented;
9972 break;
9973 case CP0_REGISTER_31:
9974 switch (sel) {
9975 case CP0_REG31__DESAVE:
9976 /* EJTAG support */
9977 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9978 register_name = "DESAVE";
9979 break;
9980 case CP0_REG31__KSCRATCH1:
9981 case CP0_REG31__KSCRATCH2:
9982 case CP0_REG31__KSCRATCH3:
9983 case CP0_REG31__KSCRATCH4:
9984 case CP0_REG31__KSCRATCH5:
9985 case CP0_REG31__KSCRATCH6:
9986 CP0_CHECK(ctx->kscrexist & (1 << sel));
9987 tcg_gen_st_tl(arg, cpu_env,
9988 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
9989 register_name = "KScratch";
9990 break;
9991 default:
9992 goto cp0_unimplemented;
9994 break;
9995 default:
9996 goto cp0_unimplemented;
9998 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
10000 /* For simplicity assume that all writes can cause interrupts. */
10001 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
10003 * DISAS_STOP isn't sufficient, we need to ensure we break out of
10004 * translated code to check for pending interrupts.
10006 gen_save_pc(ctx->base.pc_next + 4);
10007 ctx->base.is_jmp = DISAS_EXIT;
10009 return;
10011 cp0_unimplemented:
10012 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
10013 register_name, reg, sel);
10015 #endif /* TARGET_MIPS64 */
10017 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
10018 int u, int sel, int h)
10020 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
10021 TCGv t0 = tcg_temp_local_new();
10023 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
10024 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
10025 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
10026 tcg_gen_movi_tl(t0, -1);
10027 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
10028 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
10029 tcg_gen_movi_tl(t0, -1);
10030 } else if (u == 0) {
10031 switch (rt) {
10032 case 1:
10033 switch (sel) {
10034 case 1:
10035 gen_helper_mftc0_vpecontrol(t0, cpu_env);
10036 break;
10037 case 2:
10038 gen_helper_mftc0_vpeconf0(t0, cpu_env);
10039 break;
10040 default:
10041 goto die;
10042 break;
10044 break;
10045 case 2:
10046 switch (sel) {
10047 case 1:
10048 gen_helper_mftc0_tcstatus(t0, cpu_env);
10049 break;
10050 case 2:
10051 gen_helper_mftc0_tcbind(t0, cpu_env);
10052 break;
10053 case 3:
10054 gen_helper_mftc0_tcrestart(t0, cpu_env);
10055 break;
10056 case 4:
10057 gen_helper_mftc0_tchalt(t0, cpu_env);
10058 break;
10059 case 5:
10060 gen_helper_mftc0_tccontext(t0, cpu_env);
10061 break;
10062 case 6:
10063 gen_helper_mftc0_tcschedule(t0, cpu_env);
10064 break;
10065 case 7:
10066 gen_helper_mftc0_tcschefback(t0, cpu_env);
10067 break;
10068 default:
10069 gen_mfc0(ctx, t0, rt, sel);
10070 break;
10072 break;
10073 case 10:
10074 switch (sel) {
10075 case 0:
10076 gen_helper_mftc0_entryhi(t0, cpu_env);
10077 break;
10078 default:
10079 gen_mfc0(ctx, t0, rt, sel);
10080 break;
10082 break;
10083 case 12:
10084 switch (sel) {
10085 case 0:
10086 gen_helper_mftc0_status(t0, cpu_env);
10087 break;
10088 default:
10089 gen_mfc0(ctx, t0, rt, sel);
10090 break;
10092 break;
10093 case 13:
10094 switch (sel) {
10095 case 0:
10096 gen_helper_mftc0_cause(t0, cpu_env);
10097 break;
10098 default:
10099 goto die;
10100 break;
10102 break;
10103 case 14:
10104 switch (sel) {
10105 case 0:
10106 gen_helper_mftc0_epc(t0, cpu_env);
10107 break;
10108 default:
10109 goto die;
10110 break;
10112 break;
10113 case 15:
10114 switch (sel) {
10115 case 1:
10116 gen_helper_mftc0_ebase(t0, cpu_env);
10117 break;
10118 default:
10119 goto die;
10120 break;
10122 break;
10123 case 16:
10124 switch (sel) {
10125 case 0:
10126 case 1:
10127 case 2:
10128 case 3:
10129 case 4:
10130 case 5:
10131 case 6:
10132 case 7:
10133 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
10134 break;
10135 default:
10136 goto die;
10137 break;
10139 break;
10140 case 23:
10141 switch (sel) {
10142 case 0:
10143 gen_helper_mftc0_debug(t0, cpu_env);
10144 break;
10145 default:
10146 gen_mfc0(ctx, t0, rt, sel);
10147 break;
10149 break;
10150 default:
10151 gen_mfc0(ctx, t0, rt, sel);
10153 } else {
10154 switch (sel) {
10155 /* GPR registers. */
10156 case 0:
10157 gen_helper_1e0i(mftgpr, t0, rt);
10158 break;
10159 /* Auxiliary CPU registers */
10160 case 1:
10161 switch (rt) {
10162 case 0:
10163 gen_helper_1e0i(mftlo, t0, 0);
10164 break;
10165 case 1:
10166 gen_helper_1e0i(mfthi, t0, 0);
10167 break;
10168 case 2:
10169 gen_helper_1e0i(mftacx, t0, 0);
10170 break;
10171 case 4:
10172 gen_helper_1e0i(mftlo, t0, 1);
10173 break;
10174 case 5:
10175 gen_helper_1e0i(mfthi, t0, 1);
10176 break;
10177 case 6:
10178 gen_helper_1e0i(mftacx, t0, 1);
10179 break;
10180 case 8:
10181 gen_helper_1e0i(mftlo, t0, 2);
10182 break;
10183 case 9:
10184 gen_helper_1e0i(mfthi, t0, 2);
10185 break;
10186 case 10:
10187 gen_helper_1e0i(mftacx, t0, 2);
10188 break;
10189 case 12:
10190 gen_helper_1e0i(mftlo, t0, 3);
10191 break;
10192 case 13:
10193 gen_helper_1e0i(mfthi, t0, 3);
10194 break;
10195 case 14:
10196 gen_helper_1e0i(mftacx, t0, 3);
10197 break;
10198 case 16:
10199 gen_helper_mftdsp(t0, cpu_env);
10200 break;
10201 default:
10202 goto die;
10204 break;
10205 /* Floating point (COP1). */
10206 case 2:
10207 /* XXX: For now we support only a single FPU context. */
10208 if (h == 0) {
10209 TCGv_i32 fp0 = tcg_temp_new_i32();
10211 gen_load_fpr32(ctx, fp0, rt);
10212 tcg_gen_ext_i32_tl(t0, fp0);
10213 tcg_temp_free_i32(fp0);
10214 } else {
10215 TCGv_i32 fp0 = tcg_temp_new_i32();
10217 gen_load_fpr32h(ctx, fp0, rt);
10218 tcg_gen_ext_i32_tl(t0, fp0);
10219 tcg_temp_free_i32(fp0);
10221 break;
10222 case 3:
10223 /* XXX: For now we support only a single FPU context. */
10224 gen_helper_1e0i(cfc1, t0, rt);
10225 break;
10226 /* COP2: Not implemented. */
10227 case 4:
10228 case 5:
10229 /* fall through */
10230 default:
10231 goto die;
10234 trace_mips_translate_tr("mftr", rt, u, sel, h);
10235 gen_store_gpr(t0, rd);
10236 tcg_temp_free(t0);
10237 return;
10239 die:
10240 tcg_temp_free(t0);
10241 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
10242 gen_reserved_instruction(ctx);
10245 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
10246 int u, int sel, int h)
10248 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
10249 TCGv t0 = tcg_temp_local_new();
10251 gen_load_gpr(t0, rt);
10252 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
10253 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
10254 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
10255 /* NOP */
10257 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
10258 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
10259 /* NOP */
10261 } else if (u == 0) {
10262 switch (rd) {
10263 case 1:
10264 switch (sel) {
10265 case 1:
10266 gen_helper_mttc0_vpecontrol(cpu_env, t0);
10267 break;
10268 case 2:
10269 gen_helper_mttc0_vpeconf0(cpu_env, t0);
10270 break;
10271 default:
10272 goto die;
10273 break;
10275 break;
10276 case 2:
10277 switch (sel) {
10278 case 1:
10279 gen_helper_mttc0_tcstatus(cpu_env, t0);
10280 break;
10281 case 2:
10282 gen_helper_mttc0_tcbind(cpu_env, t0);
10283 break;
10284 case 3:
10285 gen_helper_mttc0_tcrestart(cpu_env, t0);
10286 break;
10287 case 4:
10288 gen_helper_mttc0_tchalt(cpu_env, t0);
10289 break;
10290 case 5:
10291 gen_helper_mttc0_tccontext(cpu_env, t0);
10292 break;
10293 case 6:
10294 gen_helper_mttc0_tcschedule(cpu_env, t0);
10295 break;
10296 case 7:
10297 gen_helper_mttc0_tcschefback(cpu_env, t0);
10298 break;
10299 default:
10300 gen_mtc0(ctx, t0, rd, sel);
10301 break;
10303 break;
10304 case 10:
10305 switch (sel) {
10306 case 0:
10307 gen_helper_mttc0_entryhi(cpu_env, t0);
10308 break;
10309 default:
10310 gen_mtc0(ctx, t0, rd, sel);
10311 break;
10313 break;
10314 case 12:
10315 switch (sel) {
10316 case 0:
10317 gen_helper_mttc0_status(cpu_env, t0);
10318 break;
10319 default:
10320 gen_mtc0(ctx, t0, rd, sel);
10321 break;
10323 break;
10324 case 13:
10325 switch (sel) {
10326 case 0:
10327 gen_helper_mttc0_cause(cpu_env, t0);
10328 break;
10329 default:
10330 goto die;
10331 break;
10333 break;
10334 case 15:
10335 switch (sel) {
10336 case 1:
10337 gen_helper_mttc0_ebase(cpu_env, t0);
10338 break;
10339 default:
10340 goto die;
10341 break;
10343 break;
10344 case 23:
10345 switch (sel) {
10346 case 0:
10347 gen_helper_mttc0_debug(cpu_env, t0);
10348 break;
10349 default:
10350 gen_mtc0(ctx, t0, rd, sel);
10351 break;
10353 break;
10354 default:
10355 gen_mtc0(ctx, t0, rd, sel);
10357 } else {
10358 switch (sel) {
10359 /* GPR registers. */
10360 case 0:
10361 gen_helper_0e1i(mttgpr, t0, rd);
10362 break;
10363 /* Auxiliary CPU registers */
10364 case 1:
10365 switch (rd) {
10366 case 0:
10367 gen_helper_0e1i(mttlo, t0, 0);
10368 break;
10369 case 1:
10370 gen_helper_0e1i(mtthi, t0, 0);
10371 break;
10372 case 2:
10373 gen_helper_0e1i(mttacx, t0, 0);
10374 break;
10375 case 4:
10376 gen_helper_0e1i(mttlo, t0, 1);
10377 break;
10378 case 5:
10379 gen_helper_0e1i(mtthi, t0, 1);
10380 break;
10381 case 6:
10382 gen_helper_0e1i(mttacx, t0, 1);
10383 break;
10384 case 8:
10385 gen_helper_0e1i(mttlo, t0, 2);
10386 break;
10387 case 9:
10388 gen_helper_0e1i(mtthi, t0, 2);
10389 break;
10390 case 10:
10391 gen_helper_0e1i(mttacx, t0, 2);
10392 break;
10393 case 12:
10394 gen_helper_0e1i(mttlo, t0, 3);
10395 break;
10396 case 13:
10397 gen_helper_0e1i(mtthi, t0, 3);
10398 break;
10399 case 14:
10400 gen_helper_0e1i(mttacx, t0, 3);
10401 break;
10402 case 16:
10403 gen_helper_mttdsp(cpu_env, t0);
10404 break;
10405 default:
10406 goto die;
10408 break;
10409 /* Floating point (COP1). */
10410 case 2:
10411 /* XXX: For now we support only a single FPU context. */
10412 if (h == 0) {
10413 TCGv_i32 fp0 = tcg_temp_new_i32();
10415 tcg_gen_trunc_tl_i32(fp0, t0);
10416 gen_store_fpr32(ctx, fp0, rd);
10417 tcg_temp_free_i32(fp0);
10418 } else {
10419 TCGv_i32 fp0 = tcg_temp_new_i32();
10421 tcg_gen_trunc_tl_i32(fp0, t0);
10422 gen_store_fpr32h(ctx, fp0, rd);
10423 tcg_temp_free_i32(fp0);
10425 break;
10426 case 3:
10427 /* XXX: For now we support only a single FPU context. */
10429 TCGv_i32 fs_tmp = tcg_const_i32(rd);
10431 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10432 tcg_temp_free_i32(fs_tmp);
10434 /* Stop translation as we may have changed hflags */
10435 ctx->base.is_jmp = DISAS_STOP;
10436 break;
10437 /* COP2: Not implemented. */
10438 case 4:
10439 case 5:
10440 /* fall through */
10441 default:
10442 goto die;
10445 trace_mips_translate_tr("mttr", rd, u, sel, h);
10446 tcg_temp_free(t0);
10447 return;
10449 die:
10450 tcg_temp_free(t0);
10451 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
10452 gen_reserved_instruction(ctx);
10455 static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
10456 int rt, int rd)
10458 const char *opn = "ldst";
10460 check_cp0_enabled(ctx);
10461 switch (opc) {
10462 case OPC_MFC0:
10463 if (rt == 0) {
10464 /* Treat as NOP. */
10465 return;
10467 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10468 opn = "mfc0";
10469 break;
10470 case OPC_MTC0:
10472 TCGv t0 = tcg_temp_new();
10474 gen_load_gpr(t0, rt);
10475 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
10476 tcg_temp_free(t0);
10478 opn = "mtc0";
10479 break;
10480 #if defined(TARGET_MIPS64)
10481 case OPC_DMFC0:
10482 check_insn(ctx, ISA_MIPS3);
10483 if (rt == 0) {
10484 /* Treat as NOP. */
10485 return;
10487 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10488 opn = "dmfc0";
10489 break;
10490 case OPC_DMTC0:
10491 check_insn(ctx, ISA_MIPS3);
10493 TCGv t0 = tcg_temp_new();
10495 gen_load_gpr(t0, rt);
10496 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
10497 tcg_temp_free(t0);
10499 opn = "dmtc0";
10500 break;
10501 #endif
10502 case OPC_MFHC0:
10503 check_mvh(ctx);
10504 if (rt == 0) {
10505 /* Treat as NOP. */
10506 return;
10508 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10509 opn = "mfhc0";
10510 break;
10511 case OPC_MTHC0:
10512 check_mvh(ctx);
10514 TCGv t0 = tcg_temp_new();
10515 gen_load_gpr(t0, rt);
10516 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
10517 tcg_temp_free(t0);
10519 opn = "mthc0";
10520 break;
10521 case OPC_MFTR:
10522 check_cp0_enabled(ctx);
10523 if (rd == 0) {
10524 /* Treat as NOP. */
10525 return;
10527 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
10528 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10529 opn = "mftr";
10530 break;
10531 case OPC_MTTR:
10532 check_cp0_enabled(ctx);
10533 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
10534 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10535 opn = "mttr";
10536 break;
10537 case OPC_TLBWI:
10538 opn = "tlbwi";
10539 if (!env->tlb->helper_tlbwi) {
10540 goto die;
10542 gen_helper_tlbwi(cpu_env);
10543 break;
10544 case OPC_TLBINV:
10545 opn = "tlbinv";
10546 if (ctx->ie >= 2) {
10547 if (!env->tlb->helper_tlbinv) {
10548 goto die;
10550 gen_helper_tlbinv(cpu_env);
10551 } /* treat as nop if TLBINV not supported */
10552 break;
10553 case OPC_TLBINVF:
10554 opn = "tlbinvf";
10555 if (ctx->ie >= 2) {
10556 if (!env->tlb->helper_tlbinvf) {
10557 goto die;
10559 gen_helper_tlbinvf(cpu_env);
10560 } /* treat as nop if TLBINV not supported */
10561 break;
10562 case OPC_TLBWR:
10563 opn = "tlbwr";
10564 if (!env->tlb->helper_tlbwr) {
10565 goto die;
10567 gen_helper_tlbwr(cpu_env);
10568 break;
10569 case OPC_TLBP:
10570 opn = "tlbp";
10571 if (!env->tlb->helper_tlbp) {
10572 goto die;
10574 gen_helper_tlbp(cpu_env);
10575 break;
10576 case OPC_TLBR:
10577 opn = "tlbr";
10578 if (!env->tlb->helper_tlbr) {
10579 goto die;
10581 gen_helper_tlbr(cpu_env);
10582 break;
10583 case OPC_ERET: /* OPC_ERETNC */
10584 if ((ctx->insn_flags & ISA_MIPS_R6) &&
10585 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10586 goto die;
10587 } else {
10588 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
10589 if (ctx->opcode & (1 << bit_shift)) {
10590 /* OPC_ERETNC */
10591 opn = "eretnc";
10592 check_insn(ctx, ISA_MIPS_R5);
10593 gen_helper_eretnc(cpu_env);
10594 } else {
10595 /* OPC_ERET */
10596 opn = "eret";
10597 check_insn(ctx, ISA_MIPS2);
10598 gen_helper_eret(cpu_env);
10600 ctx->base.is_jmp = DISAS_EXIT;
10602 break;
10603 case OPC_DERET:
10604 opn = "deret";
10605 check_insn(ctx, ISA_MIPS_R1);
10606 if ((ctx->insn_flags & ISA_MIPS_R6) &&
10607 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10608 goto die;
10610 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10611 MIPS_INVAL(opn);
10612 gen_reserved_instruction(ctx);
10613 } else {
10614 gen_helper_deret(cpu_env);
10615 ctx->base.is_jmp = DISAS_EXIT;
10617 break;
10618 case OPC_WAIT:
10619 opn = "wait";
10620 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
10621 if ((ctx->insn_flags & ISA_MIPS_R6) &&
10622 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10623 goto die;
10625 /* If we get an exception, we want to restart at next instruction */
10626 ctx->base.pc_next += 4;
10627 save_cpu_state(ctx, 1);
10628 ctx->base.pc_next -= 4;
10629 gen_helper_wait(cpu_env);
10630 ctx->base.is_jmp = DISAS_NORETURN;
10631 break;
10632 default:
10633 die:
10634 MIPS_INVAL(opn);
10635 gen_reserved_instruction(ctx);
10636 return;
10638 (void)opn; /* avoid a compiler warning */
10640 #endif /* !CONFIG_USER_ONLY */
10642 /* CP1 Branches (before delay slot) */
10643 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
10644 int32_t cc, int32_t offset)
10646 target_ulong btarget;
10647 TCGv_i32 t0 = tcg_temp_new_i32();
10649 if ((ctx->insn_flags & ISA_MIPS_R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
10650 gen_reserved_instruction(ctx);
10651 goto out;
10654 if (cc != 0) {
10655 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
10658 btarget = ctx->base.pc_next + 4 + offset;
10660 switch (op) {
10661 case OPC_BC1F:
10662 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10663 tcg_gen_not_i32(t0, t0);
10664 tcg_gen_andi_i32(t0, t0, 1);
10665 tcg_gen_extu_i32_tl(bcond, t0);
10666 goto not_likely;
10667 case OPC_BC1FL:
10668 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10669 tcg_gen_not_i32(t0, t0);
10670 tcg_gen_andi_i32(t0, t0, 1);
10671 tcg_gen_extu_i32_tl(bcond, t0);
10672 goto likely;
10673 case OPC_BC1T:
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 goto not_likely;
10678 case OPC_BC1TL:
10679 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10680 tcg_gen_andi_i32(t0, t0, 1);
10681 tcg_gen_extu_i32_tl(bcond, t0);
10682 likely:
10683 ctx->hflags |= MIPS_HFLAG_BL;
10684 break;
10685 case OPC_BC1FANY2:
10687 TCGv_i32 t1 = tcg_temp_new_i32();
10688 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10689 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10690 tcg_gen_nand_i32(t0, t0, t1);
10691 tcg_temp_free_i32(t1);
10692 tcg_gen_andi_i32(t0, t0, 1);
10693 tcg_gen_extu_i32_tl(bcond, t0);
10695 goto not_likely;
10696 case OPC_BC1TANY2:
10698 TCGv_i32 t1 = tcg_temp_new_i32();
10699 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10700 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10701 tcg_gen_or_i32(t0, t0, t1);
10702 tcg_temp_free_i32(t1);
10703 tcg_gen_andi_i32(t0, t0, 1);
10704 tcg_gen_extu_i32_tl(bcond, t0);
10706 goto not_likely;
10707 case OPC_BC1FANY4:
10709 TCGv_i32 t1 = tcg_temp_new_i32();
10710 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10711 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10712 tcg_gen_and_i32(t0, t0, t1);
10713 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
10714 tcg_gen_and_i32(t0, t0, t1);
10715 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
10716 tcg_gen_nand_i32(t0, t0, t1);
10717 tcg_temp_free_i32(t1);
10718 tcg_gen_andi_i32(t0, t0, 1);
10719 tcg_gen_extu_i32_tl(bcond, t0);
10721 goto not_likely;
10722 case OPC_BC1TANY4:
10724 TCGv_i32 t1 = tcg_temp_new_i32();
10725 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10726 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10727 tcg_gen_or_i32(t0, t0, t1);
10728 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
10729 tcg_gen_or_i32(t0, t0, t1);
10730 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
10731 tcg_gen_or_i32(t0, t0, t1);
10732 tcg_temp_free_i32(t1);
10733 tcg_gen_andi_i32(t0, t0, 1);
10734 tcg_gen_extu_i32_tl(bcond, t0);
10736 not_likely:
10737 ctx->hflags |= MIPS_HFLAG_BC;
10738 break;
10739 default:
10740 MIPS_INVAL("cp1 cond branch");
10741 gen_reserved_instruction(ctx);
10742 goto out;
10744 ctx->btarget = btarget;
10745 ctx->hflags |= MIPS_HFLAG_BDS32;
10746 out:
10747 tcg_temp_free_i32(t0);
10750 /* R6 CP1 Branches */
10751 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
10752 int32_t ft, int32_t offset,
10753 int delayslot_size)
10755 target_ulong btarget;
10756 TCGv_i64 t0 = tcg_temp_new_i64();
10758 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10759 #ifdef MIPS_DEBUG_DISAS
10760 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
10761 "\n", ctx->base.pc_next);
10762 #endif
10763 gen_reserved_instruction(ctx);
10764 goto out;
10767 gen_load_fpr64(ctx, t0, ft);
10768 tcg_gen_andi_i64(t0, t0, 1);
10770 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
10772 switch (op) {
10773 case OPC_BC1EQZ:
10774 tcg_gen_xori_i64(t0, t0, 1);
10775 ctx->hflags |= MIPS_HFLAG_BC;
10776 break;
10777 case OPC_BC1NEZ:
10778 /* t0 already set */
10779 ctx->hflags |= MIPS_HFLAG_BC;
10780 break;
10781 default:
10782 MIPS_INVAL("cp1 cond branch");
10783 gen_reserved_instruction(ctx);
10784 goto out;
10787 tcg_gen_trunc_i64_tl(bcond, t0);
10789 ctx->btarget = btarget;
10791 switch (delayslot_size) {
10792 case 2:
10793 ctx->hflags |= MIPS_HFLAG_BDS16;
10794 break;
10795 case 4:
10796 ctx->hflags |= MIPS_HFLAG_BDS32;
10797 break;
10800 out:
10801 tcg_temp_free_i64(t0);
10804 /* Coprocessor 1 (FPU) */
10806 #define FOP(func, fmt) (((fmt) << 21) | (func))
10808 enum fopcode {
10809 OPC_ADD_S = FOP(0, FMT_S),
10810 OPC_SUB_S = FOP(1, FMT_S),
10811 OPC_MUL_S = FOP(2, FMT_S),
10812 OPC_DIV_S = FOP(3, FMT_S),
10813 OPC_SQRT_S = FOP(4, FMT_S),
10814 OPC_ABS_S = FOP(5, FMT_S),
10815 OPC_MOV_S = FOP(6, FMT_S),
10816 OPC_NEG_S = FOP(7, FMT_S),
10817 OPC_ROUND_L_S = FOP(8, FMT_S),
10818 OPC_TRUNC_L_S = FOP(9, FMT_S),
10819 OPC_CEIL_L_S = FOP(10, FMT_S),
10820 OPC_FLOOR_L_S = FOP(11, FMT_S),
10821 OPC_ROUND_W_S = FOP(12, FMT_S),
10822 OPC_TRUNC_W_S = FOP(13, FMT_S),
10823 OPC_CEIL_W_S = FOP(14, FMT_S),
10824 OPC_FLOOR_W_S = FOP(15, FMT_S),
10825 OPC_SEL_S = FOP(16, FMT_S),
10826 OPC_MOVCF_S = FOP(17, FMT_S),
10827 OPC_MOVZ_S = FOP(18, FMT_S),
10828 OPC_MOVN_S = FOP(19, FMT_S),
10829 OPC_SELEQZ_S = FOP(20, FMT_S),
10830 OPC_RECIP_S = FOP(21, FMT_S),
10831 OPC_RSQRT_S = FOP(22, FMT_S),
10832 OPC_SELNEZ_S = FOP(23, FMT_S),
10833 OPC_MADDF_S = FOP(24, FMT_S),
10834 OPC_MSUBF_S = FOP(25, FMT_S),
10835 OPC_RINT_S = FOP(26, FMT_S),
10836 OPC_CLASS_S = FOP(27, FMT_S),
10837 OPC_MIN_S = FOP(28, FMT_S),
10838 OPC_RECIP2_S = FOP(28, FMT_S),
10839 OPC_MINA_S = FOP(29, FMT_S),
10840 OPC_RECIP1_S = FOP(29, FMT_S),
10841 OPC_MAX_S = FOP(30, FMT_S),
10842 OPC_RSQRT1_S = FOP(30, FMT_S),
10843 OPC_MAXA_S = FOP(31, FMT_S),
10844 OPC_RSQRT2_S = FOP(31, FMT_S),
10845 OPC_CVT_D_S = FOP(33, FMT_S),
10846 OPC_CVT_W_S = FOP(36, FMT_S),
10847 OPC_CVT_L_S = FOP(37, FMT_S),
10848 OPC_CVT_PS_S = FOP(38, FMT_S),
10849 OPC_CMP_F_S = FOP(48, FMT_S),
10850 OPC_CMP_UN_S = FOP(49, FMT_S),
10851 OPC_CMP_EQ_S = FOP(50, FMT_S),
10852 OPC_CMP_UEQ_S = FOP(51, FMT_S),
10853 OPC_CMP_OLT_S = FOP(52, FMT_S),
10854 OPC_CMP_ULT_S = FOP(53, FMT_S),
10855 OPC_CMP_OLE_S = FOP(54, FMT_S),
10856 OPC_CMP_ULE_S = FOP(55, FMT_S),
10857 OPC_CMP_SF_S = FOP(56, FMT_S),
10858 OPC_CMP_NGLE_S = FOP(57, FMT_S),
10859 OPC_CMP_SEQ_S = FOP(58, FMT_S),
10860 OPC_CMP_NGL_S = FOP(59, FMT_S),
10861 OPC_CMP_LT_S = FOP(60, FMT_S),
10862 OPC_CMP_NGE_S = FOP(61, FMT_S),
10863 OPC_CMP_LE_S = FOP(62, FMT_S),
10864 OPC_CMP_NGT_S = FOP(63, FMT_S),
10866 OPC_ADD_D = FOP(0, FMT_D),
10867 OPC_SUB_D = FOP(1, FMT_D),
10868 OPC_MUL_D = FOP(2, FMT_D),
10869 OPC_DIV_D = FOP(3, FMT_D),
10870 OPC_SQRT_D = FOP(4, FMT_D),
10871 OPC_ABS_D = FOP(5, FMT_D),
10872 OPC_MOV_D = FOP(6, FMT_D),
10873 OPC_NEG_D = FOP(7, FMT_D),
10874 OPC_ROUND_L_D = FOP(8, FMT_D),
10875 OPC_TRUNC_L_D = FOP(9, FMT_D),
10876 OPC_CEIL_L_D = FOP(10, FMT_D),
10877 OPC_FLOOR_L_D = FOP(11, FMT_D),
10878 OPC_ROUND_W_D = FOP(12, FMT_D),
10879 OPC_TRUNC_W_D = FOP(13, FMT_D),
10880 OPC_CEIL_W_D = FOP(14, FMT_D),
10881 OPC_FLOOR_W_D = FOP(15, FMT_D),
10882 OPC_SEL_D = FOP(16, FMT_D),
10883 OPC_MOVCF_D = FOP(17, FMT_D),
10884 OPC_MOVZ_D = FOP(18, FMT_D),
10885 OPC_MOVN_D = FOP(19, FMT_D),
10886 OPC_SELEQZ_D = FOP(20, FMT_D),
10887 OPC_RECIP_D = FOP(21, FMT_D),
10888 OPC_RSQRT_D = FOP(22, FMT_D),
10889 OPC_SELNEZ_D = FOP(23, FMT_D),
10890 OPC_MADDF_D = FOP(24, FMT_D),
10891 OPC_MSUBF_D = FOP(25, FMT_D),
10892 OPC_RINT_D = FOP(26, FMT_D),
10893 OPC_CLASS_D = FOP(27, FMT_D),
10894 OPC_MIN_D = FOP(28, FMT_D),
10895 OPC_RECIP2_D = FOP(28, FMT_D),
10896 OPC_MINA_D = FOP(29, FMT_D),
10897 OPC_RECIP1_D = FOP(29, FMT_D),
10898 OPC_MAX_D = FOP(30, FMT_D),
10899 OPC_RSQRT1_D = FOP(30, FMT_D),
10900 OPC_MAXA_D = FOP(31, FMT_D),
10901 OPC_RSQRT2_D = FOP(31, FMT_D),
10902 OPC_CVT_S_D = FOP(32, FMT_D),
10903 OPC_CVT_W_D = FOP(36, FMT_D),
10904 OPC_CVT_L_D = FOP(37, FMT_D),
10905 OPC_CMP_F_D = FOP(48, FMT_D),
10906 OPC_CMP_UN_D = FOP(49, FMT_D),
10907 OPC_CMP_EQ_D = FOP(50, FMT_D),
10908 OPC_CMP_UEQ_D = FOP(51, FMT_D),
10909 OPC_CMP_OLT_D = FOP(52, FMT_D),
10910 OPC_CMP_ULT_D = FOP(53, FMT_D),
10911 OPC_CMP_OLE_D = FOP(54, FMT_D),
10912 OPC_CMP_ULE_D = FOP(55, FMT_D),
10913 OPC_CMP_SF_D = FOP(56, FMT_D),
10914 OPC_CMP_NGLE_D = FOP(57, FMT_D),
10915 OPC_CMP_SEQ_D = FOP(58, FMT_D),
10916 OPC_CMP_NGL_D = FOP(59, FMT_D),
10917 OPC_CMP_LT_D = FOP(60, FMT_D),
10918 OPC_CMP_NGE_D = FOP(61, FMT_D),
10919 OPC_CMP_LE_D = FOP(62, FMT_D),
10920 OPC_CMP_NGT_D = FOP(63, FMT_D),
10922 OPC_CVT_S_W = FOP(32, FMT_W),
10923 OPC_CVT_D_W = FOP(33, FMT_W),
10924 OPC_CVT_S_L = FOP(32, FMT_L),
10925 OPC_CVT_D_L = FOP(33, FMT_L),
10926 OPC_CVT_PS_PW = FOP(38, FMT_W),
10928 OPC_ADD_PS = FOP(0, FMT_PS),
10929 OPC_SUB_PS = FOP(1, FMT_PS),
10930 OPC_MUL_PS = FOP(2, FMT_PS),
10931 OPC_DIV_PS = FOP(3, FMT_PS),
10932 OPC_ABS_PS = FOP(5, FMT_PS),
10933 OPC_MOV_PS = FOP(6, FMT_PS),
10934 OPC_NEG_PS = FOP(7, FMT_PS),
10935 OPC_MOVCF_PS = FOP(17, FMT_PS),
10936 OPC_MOVZ_PS = FOP(18, FMT_PS),
10937 OPC_MOVN_PS = FOP(19, FMT_PS),
10938 OPC_ADDR_PS = FOP(24, FMT_PS),
10939 OPC_MULR_PS = FOP(26, FMT_PS),
10940 OPC_RECIP2_PS = FOP(28, FMT_PS),
10941 OPC_RECIP1_PS = FOP(29, FMT_PS),
10942 OPC_RSQRT1_PS = FOP(30, FMT_PS),
10943 OPC_RSQRT2_PS = FOP(31, FMT_PS),
10945 OPC_CVT_S_PU = FOP(32, FMT_PS),
10946 OPC_CVT_PW_PS = FOP(36, FMT_PS),
10947 OPC_CVT_S_PL = FOP(40, FMT_PS),
10948 OPC_PLL_PS = FOP(44, FMT_PS),
10949 OPC_PLU_PS = FOP(45, FMT_PS),
10950 OPC_PUL_PS = FOP(46, FMT_PS),
10951 OPC_PUU_PS = FOP(47, FMT_PS),
10952 OPC_CMP_F_PS = FOP(48, FMT_PS),
10953 OPC_CMP_UN_PS = FOP(49, FMT_PS),
10954 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
10955 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
10956 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
10957 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
10958 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
10959 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
10960 OPC_CMP_SF_PS = FOP(56, FMT_PS),
10961 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
10962 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
10963 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
10964 OPC_CMP_LT_PS = FOP(60, FMT_PS),
10965 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
10966 OPC_CMP_LE_PS = FOP(62, FMT_PS),
10967 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
10970 enum r6_f_cmp_op {
10971 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
10972 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
10973 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
10974 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
10975 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
10976 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
10977 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
10978 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
10979 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
10980 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
10981 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
10982 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
10983 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
10984 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
10985 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
10986 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
10987 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
10988 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
10989 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
10990 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
10991 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
10992 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
10994 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
10995 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
10996 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
10997 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
10998 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
10999 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
11000 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
11001 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
11002 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
11003 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
11004 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
11005 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
11006 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
11007 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
11008 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
11009 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
11010 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
11011 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
11012 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
11013 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
11014 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
11015 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
11018 static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
11020 TCGv t0 = tcg_temp_new();
11022 switch (opc) {
11023 case OPC_MFC1:
11025 TCGv_i32 fp0 = tcg_temp_new_i32();
11027 gen_load_fpr32(ctx, fp0, fs);
11028 tcg_gen_ext_i32_tl(t0, fp0);
11029 tcg_temp_free_i32(fp0);
11031 gen_store_gpr(t0, rt);
11032 break;
11033 case OPC_MTC1:
11034 gen_load_gpr(t0, rt);
11036 TCGv_i32 fp0 = tcg_temp_new_i32();
11038 tcg_gen_trunc_tl_i32(fp0, t0);
11039 gen_store_fpr32(ctx, fp0, fs);
11040 tcg_temp_free_i32(fp0);
11042 break;
11043 case OPC_CFC1:
11044 gen_helper_1e0i(cfc1, t0, fs);
11045 gen_store_gpr(t0, rt);
11046 break;
11047 case OPC_CTC1:
11048 gen_load_gpr(t0, rt);
11049 save_cpu_state(ctx, 0);
11051 TCGv_i32 fs_tmp = tcg_const_i32(fs);
11053 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
11054 tcg_temp_free_i32(fs_tmp);
11056 /* Stop translation as we may have changed hflags */
11057 ctx->base.is_jmp = DISAS_STOP;
11058 break;
11059 #if defined(TARGET_MIPS64)
11060 case OPC_DMFC1:
11061 gen_load_fpr64(ctx, t0, fs);
11062 gen_store_gpr(t0, rt);
11063 break;
11064 case OPC_DMTC1:
11065 gen_load_gpr(t0, rt);
11066 gen_store_fpr64(ctx, t0, fs);
11067 break;
11068 #endif
11069 case OPC_MFHC1:
11071 TCGv_i32 fp0 = tcg_temp_new_i32();
11073 gen_load_fpr32h(ctx, fp0, fs);
11074 tcg_gen_ext_i32_tl(t0, fp0);
11075 tcg_temp_free_i32(fp0);
11077 gen_store_gpr(t0, rt);
11078 break;
11079 case OPC_MTHC1:
11080 gen_load_gpr(t0, rt);
11082 TCGv_i32 fp0 = tcg_temp_new_i32();
11084 tcg_gen_trunc_tl_i32(fp0, t0);
11085 gen_store_fpr32h(ctx, fp0, fs);
11086 tcg_temp_free_i32(fp0);
11088 break;
11089 default:
11090 MIPS_INVAL("cp1 move");
11091 gen_reserved_instruction(ctx);
11092 goto out;
11095 out:
11096 tcg_temp_free(t0);
11099 static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
11101 TCGLabel *l1;
11102 TCGCond cond;
11103 TCGv_i32 t0;
11105 if (rd == 0) {
11106 /* Treat as NOP. */
11107 return;
11110 if (tf) {
11111 cond = TCG_COND_EQ;
11112 } else {
11113 cond = TCG_COND_NE;
11116 l1 = gen_new_label();
11117 t0 = tcg_temp_new_i32();
11118 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11119 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11120 tcg_temp_free_i32(t0);
11121 if (rs == 0) {
11122 tcg_gen_movi_tl(cpu_gpr[rd], 0);
11123 } else {
11124 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
11126 gen_set_label(l1);
11129 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
11130 int tf)
11132 int cond;
11133 TCGv_i32 t0 = tcg_temp_new_i32();
11134 TCGLabel *l1 = gen_new_label();
11136 if (tf) {
11137 cond = TCG_COND_EQ;
11138 } else {
11139 cond = TCG_COND_NE;
11142 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11143 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11144 gen_load_fpr32(ctx, t0, fs);
11145 gen_store_fpr32(ctx, t0, fd);
11146 gen_set_label(l1);
11147 tcg_temp_free_i32(t0);
11150 static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
11151 int tf)
11153 int cond;
11154 TCGv_i32 t0 = tcg_temp_new_i32();
11155 TCGv_i64 fp0;
11156 TCGLabel *l1 = gen_new_label();
11158 if (tf) {
11159 cond = TCG_COND_EQ;
11160 } else {
11161 cond = TCG_COND_NE;
11164 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11165 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11166 tcg_temp_free_i32(t0);
11167 fp0 = tcg_temp_new_i64();
11168 gen_load_fpr64(ctx, fp0, fs);
11169 gen_store_fpr64(ctx, fp0, fd);
11170 tcg_temp_free_i64(fp0);
11171 gen_set_label(l1);
11174 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
11175 int cc, int tf)
11177 int cond;
11178 TCGv_i32 t0 = tcg_temp_new_i32();
11179 TCGLabel *l1 = gen_new_label();
11180 TCGLabel *l2 = gen_new_label();
11182 if (tf) {
11183 cond = TCG_COND_EQ;
11184 } else {
11185 cond = TCG_COND_NE;
11188 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11189 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11190 gen_load_fpr32(ctx, t0, fs);
11191 gen_store_fpr32(ctx, t0, fd);
11192 gen_set_label(l1);
11194 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc + 1));
11195 tcg_gen_brcondi_i32(cond, t0, 0, l2);
11196 gen_load_fpr32h(ctx, t0, fs);
11197 gen_store_fpr32h(ctx, t0, fd);
11198 tcg_temp_free_i32(t0);
11199 gen_set_label(l2);
11202 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
11203 int fs)
11205 TCGv_i32 t1 = tcg_const_i32(0);
11206 TCGv_i32 fp0 = tcg_temp_new_i32();
11207 TCGv_i32 fp1 = tcg_temp_new_i32();
11208 TCGv_i32 fp2 = tcg_temp_new_i32();
11209 gen_load_fpr32(ctx, fp0, fd);
11210 gen_load_fpr32(ctx, fp1, ft);
11211 gen_load_fpr32(ctx, fp2, fs);
11213 switch (op1) {
11214 case OPC_SEL_S:
11215 tcg_gen_andi_i32(fp0, fp0, 1);
11216 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11217 break;
11218 case OPC_SELEQZ_S:
11219 tcg_gen_andi_i32(fp1, fp1, 1);
11220 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11221 break;
11222 case OPC_SELNEZ_S:
11223 tcg_gen_andi_i32(fp1, fp1, 1);
11224 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11225 break;
11226 default:
11227 MIPS_INVAL("gen_sel_s");
11228 gen_reserved_instruction(ctx);
11229 break;
11232 gen_store_fpr32(ctx, fp0, fd);
11233 tcg_temp_free_i32(fp2);
11234 tcg_temp_free_i32(fp1);
11235 tcg_temp_free_i32(fp0);
11236 tcg_temp_free_i32(t1);
11239 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
11240 int fs)
11242 TCGv_i64 t1 = tcg_const_i64(0);
11243 TCGv_i64 fp0 = tcg_temp_new_i64();
11244 TCGv_i64 fp1 = tcg_temp_new_i64();
11245 TCGv_i64 fp2 = tcg_temp_new_i64();
11246 gen_load_fpr64(ctx, fp0, fd);
11247 gen_load_fpr64(ctx, fp1, ft);
11248 gen_load_fpr64(ctx, fp2, fs);
11250 switch (op1) {
11251 case OPC_SEL_D:
11252 tcg_gen_andi_i64(fp0, fp0, 1);
11253 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11254 break;
11255 case OPC_SELEQZ_D:
11256 tcg_gen_andi_i64(fp1, fp1, 1);
11257 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11258 break;
11259 case OPC_SELNEZ_D:
11260 tcg_gen_andi_i64(fp1, fp1, 1);
11261 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11262 break;
11263 default:
11264 MIPS_INVAL("gen_sel_d");
11265 gen_reserved_instruction(ctx);
11266 break;
11269 gen_store_fpr64(ctx, fp0, fd);
11270 tcg_temp_free_i64(fp2);
11271 tcg_temp_free_i64(fp1);
11272 tcg_temp_free_i64(fp0);
11273 tcg_temp_free_i64(t1);
11276 static void gen_farith(DisasContext *ctx, enum fopcode op1,
11277 int ft, int fs, int fd, int cc)
11279 uint32_t func = ctx->opcode & 0x3f;
11280 switch (op1) {
11281 case OPC_ADD_S:
11283 TCGv_i32 fp0 = tcg_temp_new_i32();
11284 TCGv_i32 fp1 = tcg_temp_new_i32();
11286 gen_load_fpr32(ctx, fp0, fs);
11287 gen_load_fpr32(ctx, fp1, ft);
11288 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
11289 tcg_temp_free_i32(fp1);
11290 gen_store_fpr32(ctx, fp0, fd);
11291 tcg_temp_free_i32(fp0);
11293 break;
11294 case OPC_SUB_S:
11296 TCGv_i32 fp0 = tcg_temp_new_i32();
11297 TCGv_i32 fp1 = tcg_temp_new_i32();
11299 gen_load_fpr32(ctx, fp0, fs);
11300 gen_load_fpr32(ctx, fp1, ft);
11301 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
11302 tcg_temp_free_i32(fp1);
11303 gen_store_fpr32(ctx, fp0, fd);
11304 tcg_temp_free_i32(fp0);
11306 break;
11307 case OPC_MUL_S:
11309 TCGv_i32 fp0 = tcg_temp_new_i32();
11310 TCGv_i32 fp1 = tcg_temp_new_i32();
11312 gen_load_fpr32(ctx, fp0, fs);
11313 gen_load_fpr32(ctx, fp1, ft);
11314 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
11315 tcg_temp_free_i32(fp1);
11316 gen_store_fpr32(ctx, fp0, fd);
11317 tcg_temp_free_i32(fp0);
11319 break;
11320 case OPC_DIV_S:
11322 TCGv_i32 fp0 = tcg_temp_new_i32();
11323 TCGv_i32 fp1 = tcg_temp_new_i32();
11325 gen_load_fpr32(ctx, fp0, fs);
11326 gen_load_fpr32(ctx, fp1, ft);
11327 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
11328 tcg_temp_free_i32(fp1);
11329 gen_store_fpr32(ctx, fp0, fd);
11330 tcg_temp_free_i32(fp0);
11332 break;
11333 case OPC_SQRT_S:
11335 TCGv_i32 fp0 = tcg_temp_new_i32();
11337 gen_load_fpr32(ctx, fp0, fs);
11338 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
11339 gen_store_fpr32(ctx, fp0, fd);
11340 tcg_temp_free_i32(fp0);
11342 break;
11343 case OPC_ABS_S:
11345 TCGv_i32 fp0 = tcg_temp_new_i32();
11347 gen_load_fpr32(ctx, fp0, fs);
11348 if (ctx->abs2008) {
11349 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
11350 } else {
11351 gen_helper_float_abs_s(fp0, fp0);
11353 gen_store_fpr32(ctx, fp0, fd);
11354 tcg_temp_free_i32(fp0);
11356 break;
11357 case OPC_MOV_S:
11359 TCGv_i32 fp0 = tcg_temp_new_i32();
11361 gen_load_fpr32(ctx, fp0, fs);
11362 gen_store_fpr32(ctx, fp0, fd);
11363 tcg_temp_free_i32(fp0);
11365 break;
11366 case OPC_NEG_S:
11368 TCGv_i32 fp0 = tcg_temp_new_i32();
11370 gen_load_fpr32(ctx, fp0, fs);
11371 if (ctx->abs2008) {
11372 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
11373 } else {
11374 gen_helper_float_chs_s(fp0, fp0);
11376 gen_store_fpr32(ctx, fp0, fd);
11377 tcg_temp_free_i32(fp0);
11379 break;
11380 case OPC_ROUND_L_S:
11381 check_cp1_64bitmode(ctx);
11383 TCGv_i32 fp32 = tcg_temp_new_i32();
11384 TCGv_i64 fp64 = tcg_temp_new_i64();
11386 gen_load_fpr32(ctx, fp32, fs);
11387 if (ctx->nan2008) {
11388 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
11389 } else {
11390 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
11392 tcg_temp_free_i32(fp32);
11393 gen_store_fpr64(ctx, fp64, fd);
11394 tcg_temp_free_i64(fp64);
11396 break;
11397 case OPC_TRUNC_L_S:
11398 check_cp1_64bitmode(ctx);
11400 TCGv_i32 fp32 = tcg_temp_new_i32();
11401 TCGv_i64 fp64 = tcg_temp_new_i64();
11403 gen_load_fpr32(ctx, fp32, fs);
11404 if (ctx->nan2008) {
11405 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
11406 } else {
11407 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
11409 tcg_temp_free_i32(fp32);
11410 gen_store_fpr64(ctx, fp64, fd);
11411 tcg_temp_free_i64(fp64);
11413 break;
11414 case OPC_CEIL_L_S:
11415 check_cp1_64bitmode(ctx);
11417 TCGv_i32 fp32 = tcg_temp_new_i32();
11418 TCGv_i64 fp64 = tcg_temp_new_i64();
11420 gen_load_fpr32(ctx, fp32, fs);
11421 if (ctx->nan2008) {
11422 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
11423 } else {
11424 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
11426 tcg_temp_free_i32(fp32);
11427 gen_store_fpr64(ctx, fp64, fd);
11428 tcg_temp_free_i64(fp64);
11430 break;
11431 case OPC_FLOOR_L_S:
11432 check_cp1_64bitmode(ctx);
11434 TCGv_i32 fp32 = tcg_temp_new_i32();
11435 TCGv_i64 fp64 = tcg_temp_new_i64();
11437 gen_load_fpr32(ctx, fp32, fs);
11438 if (ctx->nan2008) {
11439 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
11440 } else {
11441 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
11443 tcg_temp_free_i32(fp32);
11444 gen_store_fpr64(ctx, fp64, fd);
11445 tcg_temp_free_i64(fp64);
11447 break;
11448 case OPC_ROUND_W_S:
11450 TCGv_i32 fp0 = tcg_temp_new_i32();
11452 gen_load_fpr32(ctx, fp0, fs);
11453 if (ctx->nan2008) {
11454 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
11455 } else {
11456 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
11458 gen_store_fpr32(ctx, fp0, fd);
11459 tcg_temp_free_i32(fp0);
11461 break;
11462 case OPC_TRUNC_W_S:
11464 TCGv_i32 fp0 = tcg_temp_new_i32();
11466 gen_load_fpr32(ctx, fp0, fs);
11467 if (ctx->nan2008) {
11468 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
11469 } else {
11470 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
11472 gen_store_fpr32(ctx, fp0, fd);
11473 tcg_temp_free_i32(fp0);
11475 break;
11476 case OPC_CEIL_W_S:
11478 TCGv_i32 fp0 = tcg_temp_new_i32();
11480 gen_load_fpr32(ctx, fp0, fs);
11481 if (ctx->nan2008) {
11482 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
11483 } else {
11484 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
11486 gen_store_fpr32(ctx, fp0, fd);
11487 tcg_temp_free_i32(fp0);
11489 break;
11490 case OPC_FLOOR_W_S:
11492 TCGv_i32 fp0 = tcg_temp_new_i32();
11494 gen_load_fpr32(ctx, fp0, fs);
11495 if (ctx->nan2008) {
11496 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
11497 } else {
11498 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
11500 gen_store_fpr32(ctx, fp0, fd);
11501 tcg_temp_free_i32(fp0);
11503 break;
11504 case OPC_SEL_S:
11505 check_insn(ctx, ISA_MIPS_R6);
11506 gen_sel_s(ctx, op1, fd, ft, fs);
11507 break;
11508 case OPC_SELEQZ_S:
11509 check_insn(ctx, ISA_MIPS_R6);
11510 gen_sel_s(ctx, op1, fd, ft, fs);
11511 break;
11512 case OPC_SELNEZ_S:
11513 check_insn(ctx, ISA_MIPS_R6);
11514 gen_sel_s(ctx, op1, fd, ft, fs);
11515 break;
11516 case OPC_MOVCF_S:
11517 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11518 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11519 break;
11520 case OPC_MOVZ_S:
11521 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11523 TCGLabel *l1 = gen_new_label();
11524 TCGv_i32 fp0;
11526 if (ft != 0) {
11527 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11529 fp0 = tcg_temp_new_i32();
11530 gen_load_fpr32(ctx, fp0, fs);
11531 gen_store_fpr32(ctx, fp0, fd);
11532 tcg_temp_free_i32(fp0);
11533 gen_set_label(l1);
11535 break;
11536 case OPC_MOVN_S:
11537 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11539 TCGLabel *l1 = gen_new_label();
11540 TCGv_i32 fp0;
11542 if (ft != 0) {
11543 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11544 fp0 = tcg_temp_new_i32();
11545 gen_load_fpr32(ctx, fp0, fs);
11546 gen_store_fpr32(ctx, fp0, fd);
11547 tcg_temp_free_i32(fp0);
11548 gen_set_label(l1);
11551 break;
11552 case OPC_RECIP_S:
11554 TCGv_i32 fp0 = tcg_temp_new_i32();
11556 gen_load_fpr32(ctx, fp0, fs);
11557 gen_helper_float_recip_s(fp0, cpu_env, fp0);
11558 gen_store_fpr32(ctx, fp0, fd);
11559 tcg_temp_free_i32(fp0);
11561 break;
11562 case OPC_RSQRT_S:
11564 TCGv_i32 fp0 = tcg_temp_new_i32();
11566 gen_load_fpr32(ctx, fp0, fs);
11567 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
11568 gen_store_fpr32(ctx, fp0, fd);
11569 tcg_temp_free_i32(fp0);
11571 break;
11572 case OPC_MADDF_S:
11573 check_insn(ctx, ISA_MIPS_R6);
11575 TCGv_i32 fp0 = tcg_temp_new_i32();
11576 TCGv_i32 fp1 = tcg_temp_new_i32();
11577 TCGv_i32 fp2 = tcg_temp_new_i32();
11578 gen_load_fpr32(ctx, fp0, fs);
11579 gen_load_fpr32(ctx, fp1, ft);
11580 gen_load_fpr32(ctx, fp2, fd);
11581 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
11582 gen_store_fpr32(ctx, fp2, fd);
11583 tcg_temp_free_i32(fp2);
11584 tcg_temp_free_i32(fp1);
11585 tcg_temp_free_i32(fp0);
11587 break;
11588 case OPC_MSUBF_S:
11589 check_insn(ctx, ISA_MIPS_R6);
11591 TCGv_i32 fp0 = tcg_temp_new_i32();
11592 TCGv_i32 fp1 = tcg_temp_new_i32();
11593 TCGv_i32 fp2 = tcg_temp_new_i32();
11594 gen_load_fpr32(ctx, fp0, fs);
11595 gen_load_fpr32(ctx, fp1, ft);
11596 gen_load_fpr32(ctx, fp2, fd);
11597 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
11598 gen_store_fpr32(ctx, fp2, fd);
11599 tcg_temp_free_i32(fp2);
11600 tcg_temp_free_i32(fp1);
11601 tcg_temp_free_i32(fp0);
11603 break;
11604 case OPC_RINT_S:
11605 check_insn(ctx, ISA_MIPS_R6);
11607 TCGv_i32 fp0 = tcg_temp_new_i32();
11608 gen_load_fpr32(ctx, fp0, fs);
11609 gen_helper_float_rint_s(fp0, cpu_env, fp0);
11610 gen_store_fpr32(ctx, fp0, fd);
11611 tcg_temp_free_i32(fp0);
11613 break;
11614 case OPC_CLASS_S:
11615 check_insn(ctx, ISA_MIPS_R6);
11617 TCGv_i32 fp0 = tcg_temp_new_i32();
11618 gen_load_fpr32(ctx, fp0, fs);
11619 gen_helper_float_class_s(fp0, cpu_env, fp0);
11620 gen_store_fpr32(ctx, fp0, fd);
11621 tcg_temp_free_i32(fp0);
11623 break;
11624 case OPC_MIN_S: /* OPC_RECIP2_S */
11625 if (ctx->insn_flags & ISA_MIPS_R6) {
11626 /* OPC_MIN_S */
11627 TCGv_i32 fp0 = tcg_temp_new_i32();
11628 TCGv_i32 fp1 = tcg_temp_new_i32();
11629 TCGv_i32 fp2 = tcg_temp_new_i32();
11630 gen_load_fpr32(ctx, fp0, fs);
11631 gen_load_fpr32(ctx, fp1, ft);
11632 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
11633 gen_store_fpr32(ctx, fp2, fd);
11634 tcg_temp_free_i32(fp2);
11635 tcg_temp_free_i32(fp1);
11636 tcg_temp_free_i32(fp0);
11637 } else {
11638 /* OPC_RECIP2_S */
11639 check_cp1_64bitmode(ctx);
11641 TCGv_i32 fp0 = tcg_temp_new_i32();
11642 TCGv_i32 fp1 = tcg_temp_new_i32();
11644 gen_load_fpr32(ctx, fp0, fs);
11645 gen_load_fpr32(ctx, fp1, ft);
11646 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
11647 tcg_temp_free_i32(fp1);
11648 gen_store_fpr32(ctx, fp0, fd);
11649 tcg_temp_free_i32(fp0);
11652 break;
11653 case OPC_MINA_S: /* OPC_RECIP1_S */
11654 if (ctx->insn_flags & ISA_MIPS_R6) {
11655 /* OPC_MINA_S */
11656 TCGv_i32 fp0 = tcg_temp_new_i32();
11657 TCGv_i32 fp1 = tcg_temp_new_i32();
11658 TCGv_i32 fp2 = tcg_temp_new_i32();
11659 gen_load_fpr32(ctx, fp0, fs);
11660 gen_load_fpr32(ctx, fp1, ft);
11661 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
11662 gen_store_fpr32(ctx, fp2, fd);
11663 tcg_temp_free_i32(fp2);
11664 tcg_temp_free_i32(fp1);
11665 tcg_temp_free_i32(fp0);
11666 } else {
11667 /* OPC_RECIP1_S */
11668 check_cp1_64bitmode(ctx);
11670 TCGv_i32 fp0 = tcg_temp_new_i32();
11672 gen_load_fpr32(ctx, fp0, fs);
11673 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
11674 gen_store_fpr32(ctx, fp0, fd);
11675 tcg_temp_free_i32(fp0);
11678 break;
11679 case OPC_MAX_S: /* OPC_RSQRT1_S */
11680 if (ctx->insn_flags & ISA_MIPS_R6) {
11681 /* OPC_MAX_S */
11682 TCGv_i32 fp0 = tcg_temp_new_i32();
11683 TCGv_i32 fp1 = tcg_temp_new_i32();
11684 gen_load_fpr32(ctx, fp0, fs);
11685 gen_load_fpr32(ctx, fp1, ft);
11686 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
11687 gen_store_fpr32(ctx, fp1, fd);
11688 tcg_temp_free_i32(fp1);
11689 tcg_temp_free_i32(fp0);
11690 } else {
11691 /* OPC_RSQRT1_S */
11692 check_cp1_64bitmode(ctx);
11694 TCGv_i32 fp0 = tcg_temp_new_i32();
11696 gen_load_fpr32(ctx, fp0, fs);
11697 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
11698 gen_store_fpr32(ctx, fp0, fd);
11699 tcg_temp_free_i32(fp0);
11702 break;
11703 case OPC_MAXA_S: /* OPC_RSQRT2_S */
11704 if (ctx->insn_flags & ISA_MIPS_R6) {
11705 /* OPC_MAXA_S */
11706 TCGv_i32 fp0 = tcg_temp_new_i32();
11707 TCGv_i32 fp1 = tcg_temp_new_i32();
11708 gen_load_fpr32(ctx, fp0, fs);
11709 gen_load_fpr32(ctx, fp1, ft);
11710 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
11711 gen_store_fpr32(ctx, fp1, fd);
11712 tcg_temp_free_i32(fp1);
11713 tcg_temp_free_i32(fp0);
11714 } else {
11715 /* OPC_RSQRT2_S */
11716 check_cp1_64bitmode(ctx);
11718 TCGv_i32 fp0 = tcg_temp_new_i32();
11719 TCGv_i32 fp1 = tcg_temp_new_i32();
11721 gen_load_fpr32(ctx, fp0, fs);
11722 gen_load_fpr32(ctx, fp1, ft);
11723 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
11724 tcg_temp_free_i32(fp1);
11725 gen_store_fpr32(ctx, fp0, fd);
11726 tcg_temp_free_i32(fp0);
11729 break;
11730 case OPC_CVT_D_S:
11731 check_cp1_registers(ctx, fd);
11733 TCGv_i32 fp32 = tcg_temp_new_i32();
11734 TCGv_i64 fp64 = tcg_temp_new_i64();
11736 gen_load_fpr32(ctx, fp32, fs);
11737 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
11738 tcg_temp_free_i32(fp32);
11739 gen_store_fpr64(ctx, fp64, fd);
11740 tcg_temp_free_i64(fp64);
11742 break;
11743 case OPC_CVT_W_S:
11745 TCGv_i32 fp0 = tcg_temp_new_i32();
11747 gen_load_fpr32(ctx, fp0, fs);
11748 if (ctx->nan2008) {
11749 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
11750 } else {
11751 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
11753 gen_store_fpr32(ctx, fp0, fd);
11754 tcg_temp_free_i32(fp0);
11756 break;
11757 case OPC_CVT_L_S:
11758 check_cp1_64bitmode(ctx);
11760 TCGv_i32 fp32 = tcg_temp_new_i32();
11761 TCGv_i64 fp64 = tcg_temp_new_i64();
11763 gen_load_fpr32(ctx, fp32, fs);
11764 if (ctx->nan2008) {
11765 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
11766 } else {
11767 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
11769 tcg_temp_free_i32(fp32);
11770 gen_store_fpr64(ctx, fp64, fd);
11771 tcg_temp_free_i64(fp64);
11773 break;
11774 case OPC_CVT_PS_S:
11775 check_ps(ctx);
11777 TCGv_i64 fp64 = tcg_temp_new_i64();
11778 TCGv_i32 fp32_0 = tcg_temp_new_i32();
11779 TCGv_i32 fp32_1 = tcg_temp_new_i32();
11781 gen_load_fpr32(ctx, fp32_0, fs);
11782 gen_load_fpr32(ctx, fp32_1, ft);
11783 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
11784 tcg_temp_free_i32(fp32_1);
11785 tcg_temp_free_i32(fp32_0);
11786 gen_store_fpr64(ctx, fp64, fd);
11787 tcg_temp_free_i64(fp64);
11789 break;
11790 case OPC_CMP_F_S:
11791 case OPC_CMP_UN_S:
11792 case OPC_CMP_EQ_S:
11793 case OPC_CMP_UEQ_S:
11794 case OPC_CMP_OLT_S:
11795 case OPC_CMP_ULT_S:
11796 case OPC_CMP_OLE_S:
11797 case OPC_CMP_ULE_S:
11798 case OPC_CMP_SF_S:
11799 case OPC_CMP_NGLE_S:
11800 case OPC_CMP_SEQ_S:
11801 case OPC_CMP_NGL_S:
11802 case OPC_CMP_LT_S:
11803 case OPC_CMP_NGE_S:
11804 case OPC_CMP_LE_S:
11805 case OPC_CMP_NGT_S:
11806 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11807 if (ctx->opcode & (1 << 6)) {
11808 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
11809 } else {
11810 gen_cmp_s(ctx, func - 48, ft, fs, cc);
11812 break;
11813 case OPC_ADD_D:
11814 check_cp1_registers(ctx, fs | ft | fd);
11816 TCGv_i64 fp0 = tcg_temp_new_i64();
11817 TCGv_i64 fp1 = tcg_temp_new_i64();
11819 gen_load_fpr64(ctx, fp0, fs);
11820 gen_load_fpr64(ctx, fp1, ft);
11821 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
11822 tcg_temp_free_i64(fp1);
11823 gen_store_fpr64(ctx, fp0, fd);
11824 tcg_temp_free_i64(fp0);
11826 break;
11827 case OPC_SUB_D:
11828 check_cp1_registers(ctx, fs | ft | fd);
11830 TCGv_i64 fp0 = tcg_temp_new_i64();
11831 TCGv_i64 fp1 = tcg_temp_new_i64();
11833 gen_load_fpr64(ctx, fp0, fs);
11834 gen_load_fpr64(ctx, fp1, ft);
11835 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
11836 tcg_temp_free_i64(fp1);
11837 gen_store_fpr64(ctx, fp0, fd);
11838 tcg_temp_free_i64(fp0);
11840 break;
11841 case OPC_MUL_D:
11842 check_cp1_registers(ctx, fs | ft | fd);
11844 TCGv_i64 fp0 = tcg_temp_new_i64();
11845 TCGv_i64 fp1 = tcg_temp_new_i64();
11847 gen_load_fpr64(ctx, fp0, fs);
11848 gen_load_fpr64(ctx, fp1, ft);
11849 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
11850 tcg_temp_free_i64(fp1);
11851 gen_store_fpr64(ctx, fp0, fd);
11852 tcg_temp_free_i64(fp0);
11854 break;
11855 case OPC_DIV_D:
11856 check_cp1_registers(ctx, fs | ft | fd);
11858 TCGv_i64 fp0 = tcg_temp_new_i64();
11859 TCGv_i64 fp1 = tcg_temp_new_i64();
11861 gen_load_fpr64(ctx, fp0, fs);
11862 gen_load_fpr64(ctx, fp1, ft);
11863 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
11864 tcg_temp_free_i64(fp1);
11865 gen_store_fpr64(ctx, fp0, fd);
11866 tcg_temp_free_i64(fp0);
11868 break;
11869 case OPC_SQRT_D:
11870 check_cp1_registers(ctx, fs | fd);
11872 TCGv_i64 fp0 = tcg_temp_new_i64();
11874 gen_load_fpr64(ctx, fp0, fs);
11875 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
11876 gen_store_fpr64(ctx, fp0, fd);
11877 tcg_temp_free_i64(fp0);
11879 break;
11880 case OPC_ABS_D:
11881 check_cp1_registers(ctx, fs | fd);
11883 TCGv_i64 fp0 = tcg_temp_new_i64();
11885 gen_load_fpr64(ctx, fp0, fs);
11886 if (ctx->abs2008) {
11887 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
11888 } else {
11889 gen_helper_float_abs_d(fp0, fp0);
11891 gen_store_fpr64(ctx, fp0, fd);
11892 tcg_temp_free_i64(fp0);
11894 break;
11895 case OPC_MOV_D:
11896 check_cp1_registers(ctx, fs | fd);
11898 TCGv_i64 fp0 = tcg_temp_new_i64();
11900 gen_load_fpr64(ctx, fp0, fs);
11901 gen_store_fpr64(ctx, fp0, fd);
11902 tcg_temp_free_i64(fp0);
11904 break;
11905 case OPC_NEG_D:
11906 check_cp1_registers(ctx, fs | fd);
11908 TCGv_i64 fp0 = tcg_temp_new_i64();
11910 gen_load_fpr64(ctx, fp0, fs);
11911 if (ctx->abs2008) {
11912 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
11913 } else {
11914 gen_helper_float_chs_d(fp0, fp0);
11916 gen_store_fpr64(ctx, fp0, fd);
11917 tcg_temp_free_i64(fp0);
11919 break;
11920 case OPC_ROUND_L_D:
11921 check_cp1_64bitmode(ctx);
11923 TCGv_i64 fp0 = tcg_temp_new_i64();
11925 gen_load_fpr64(ctx, fp0, fs);
11926 if (ctx->nan2008) {
11927 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
11928 } else {
11929 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
11931 gen_store_fpr64(ctx, fp0, fd);
11932 tcg_temp_free_i64(fp0);
11934 break;
11935 case OPC_TRUNC_L_D:
11936 check_cp1_64bitmode(ctx);
11938 TCGv_i64 fp0 = tcg_temp_new_i64();
11940 gen_load_fpr64(ctx, fp0, fs);
11941 if (ctx->nan2008) {
11942 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
11943 } else {
11944 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
11946 gen_store_fpr64(ctx, fp0, fd);
11947 tcg_temp_free_i64(fp0);
11949 break;
11950 case OPC_CEIL_L_D:
11951 check_cp1_64bitmode(ctx);
11953 TCGv_i64 fp0 = tcg_temp_new_i64();
11955 gen_load_fpr64(ctx, fp0, fs);
11956 if (ctx->nan2008) {
11957 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
11958 } else {
11959 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
11961 gen_store_fpr64(ctx, fp0, fd);
11962 tcg_temp_free_i64(fp0);
11964 break;
11965 case OPC_FLOOR_L_D:
11966 check_cp1_64bitmode(ctx);
11968 TCGv_i64 fp0 = tcg_temp_new_i64();
11970 gen_load_fpr64(ctx, fp0, fs);
11971 if (ctx->nan2008) {
11972 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
11973 } else {
11974 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
11976 gen_store_fpr64(ctx, fp0, fd);
11977 tcg_temp_free_i64(fp0);
11979 break;
11980 case OPC_ROUND_W_D:
11981 check_cp1_registers(ctx, fs);
11983 TCGv_i32 fp32 = tcg_temp_new_i32();
11984 TCGv_i64 fp64 = tcg_temp_new_i64();
11986 gen_load_fpr64(ctx, fp64, fs);
11987 if (ctx->nan2008) {
11988 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
11989 } else {
11990 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
11992 tcg_temp_free_i64(fp64);
11993 gen_store_fpr32(ctx, fp32, fd);
11994 tcg_temp_free_i32(fp32);
11996 break;
11997 case OPC_TRUNC_W_D:
11998 check_cp1_registers(ctx, fs);
12000 TCGv_i32 fp32 = tcg_temp_new_i32();
12001 TCGv_i64 fp64 = tcg_temp_new_i64();
12003 gen_load_fpr64(ctx, fp64, fs);
12004 if (ctx->nan2008) {
12005 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
12006 } else {
12007 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
12009 tcg_temp_free_i64(fp64);
12010 gen_store_fpr32(ctx, fp32, fd);
12011 tcg_temp_free_i32(fp32);
12013 break;
12014 case OPC_CEIL_W_D:
12015 check_cp1_registers(ctx, fs);
12017 TCGv_i32 fp32 = tcg_temp_new_i32();
12018 TCGv_i64 fp64 = tcg_temp_new_i64();
12020 gen_load_fpr64(ctx, fp64, fs);
12021 if (ctx->nan2008) {
12022 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
12023 } else {
12024 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
12026 tcg_temp_free_i64(fp64);
12027 gen_store_fpr32(ctx, fp32, fd);
12028 tcg_temp_free_i32(fp32);
12030 break;
12031 case OPC_FLOOR_W_D:
12032 check_cp1_registers(ctx, fs);
12034 TCGv_i32 fp32 = tcg_temp_new_i32();
12035 TCGv_i64 fp64 = tcg_temp_new_i64();
12037 gen_load_fpr64(ctx, fp64, fs);
12038 if (ctx->nan2008) {
12039 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
12040 } else {
12041 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
12043 tcg_temp_free_i64(fp64);
12044 gen_store_fpr32(ctx, fp32, fd);
12045 tcg_temp_free_i32(fp32);
12047 break;
12048 case OPC_SEL_D:
12049 check_insn(ctx, ISA_MIPS_R6);
12050 gen_sel_d(ctx, op1, fd, ft, fs);
12051 break;
12052 case OPC_SELEQZ_D:
12053 check_insn(ctx, ISA_MIPS_R6);
12054 gen_sel_d(ctx, op1, fd, ft, fs);
12055 break;
12056 case OPC_SELNEZ_D:
12057 check_insn(ctx, ISA_MIPS_R6);
12058 gen_sel_d(ctx, op1, fd, ft, fs);
12059 break;
12060 case OPC_MOVCF_D:
12061 check_insn_opc_removed(ctx, ISA_MIPS_R6);
12062 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
12063 break;
12064 case OPC_MOVZ_D:
12065 check_insn_opc_removed(ctx, ISA_MIPS_R6);
12067 TCGLabel *l1 = gen_new_label();
12068 TCGv_i64 fp0;
12070 if (ft != 0) {
12071 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
12073 fp0 = tcg_temp_new_i64();
12074 gen_load_fpr64(ctx, fp0, fs);
12075 gen_store_fpr64(ctx, fp0, fd);
12076 tcg_temp_free_i64(fp0);
12077 gen_set_label(l1);
12079 break;
12080 case OPC_MOVN_D:
12081 check_insn_opc_removed(ctx, ISA_MIPS_R6);
12083 TCGLabel *l1 = gen_new_label();
12084 TCGv_i64 fp0;
12086 if (ft != 0) {
12087 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12088 fp0 = tcg_temp_new_i64();
12089 gen_load_fpr64(ctx, fp0, fs);
12090 gen_store_fpr64(ctx, fp0, fd);
12091 tcg_temp_free_i64(fp0);
12092 gen_set_label(l1);
12095 break;
12096 case OPC_RECIP_D:
12097 check_cp1_registers(ctx, fs | fd);
12099 TCGv_i64 fp0 = tcg_temp_new_i64();
12101 gen_load_fpr64(ctx, fp0, fs);
12102 gen_helper_float_recip_d(fp0, cpu_env, fp0);
12103 gen_store_fpr64(ctx, fp0, fd);
12104 tcg_temp_free_i64(fp0);
12106 break;
12107 case OPC_RSQRT_D:
12108 check_cp1_registers(ctx, fs | fd);
12110 TCGv_i64 fp0 = tcg_temp_new_i64();
12112 gen_load_fpr64(ctx, fp0, fs);
12113 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
12114 gen_store_fpr64(ctx, fp0, fd);
12115 tcg_temp_free_i64(fp0);
12117 break;
12118 case OPC_MADDF_D:
12119 check_insn(ctx, ISA_MIPS_R6);
12121 TCGv_i64 fp0 = tcg_temp_new_i64();
12122 TCGv_i64 fp1 = tcg_temp_new_i64();
12123 TCGv_i64 fp2 = tcg_temp_new_i64();
12124 gen_load_fpr64(ctx, fp0, fs);
12125 gen_load_fpr64(ctx, fp1, ft);
12126 gen_load_fpr64(ctx, fp2, fd);
12127 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
12128 gen_store_fpr64(ctx, fp2, fd);
12129 tcg_temp_free_i64(fp2);
12130 tcg_temp_free_i64(fp1);
12131 tcg_temp_free_i64(fp0);
12133 break;
12134 case OPC_MSUBF_D:
12135 check_insn(ctx, ISA_MIPS_R6);
12137 TCGv_i64 fp0 = tcg_temp_new_i64();
12138 TCGv_i64 fp1 = tcg_temp_new_i64();
12139 TCGv_i64 fp2 = tcg_temp_new_i64();
12140 gen_load_fpr64(ctx, fp0, fs);
12141 gen_load_fpr64(ctx, fp1, ft);
12142 gen_load_fpr64(ctx, fp2, fd);
12143 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
12144 gen_store_fpr64(ctx, fp2, fd);
12145 tcg_temp_free_i64(fp2);
12146 tcg_temp_free_i64(fp1);
12147 tcg_temp_free_i64(fp0);
12149 break;
12150 case OPC_RINT_D:
12151 check_insn(ctx, ISA_MIPS_R6);
12153 TCGv_i64 fp0 = tcg_temp_new_i64();
12154 gen_load_fpr64(ctx, fp0, fs);
12155 gen_helper_float_rint_d(fp0, cpu_env, fp0);
12156 gen_store_fpr64(ctx, fp0, fd);
12157 tcg_temp_free_i64(fp0);
12159 break;
12160 case OPC_CLASS_D:
12161 check_insn(ctx, ISA_MIPS_R6);
12163 TCGv_i64 fp0 = tcg_temp_new_i64();
12164 gen_load_fpr64(ctx, fp0, fs);
12165 gen_helper_float_class_d(fp0, cpu_env, fp0);
12166 gen_store_fpr64(ctx, fp0, fd);
12167 tcg_temp_free_i64(fp0);
12169 break;
12170 case OPC_MIN_D: /* OPC_RECIP2_D */
12171 if (ctx->insn_flags & ISA_MIPS_R6) {
12172 /* OPC_MIN_D */
12173 TCGv_i64 fp0 = tcg_temp_new_i64();
12174 TCGv_i64 fp1 = tcg_temp_new_i64();
12175 gen_load_fpr64(ctx, fp0, fs);
12176 gen_load_fpr64(ctx, fp1, ft);
12177 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
12178 gen_store_fpr64(ctx, fp1, fd);
12179 tcg_temp_free_i64(fp1);
12180 tcg_temp_free_i64(fp0);
12181 } else {
12182 /* OPC_RECIP2_D */
12183 check_cp1_64bitmode(ctx);
12185 TCGv_i64 fp0 = tcg_temp_new_i64();
12186 TCGv_i64 fp1 = tcg_temp_new_i64();
12188 gen_load_fpr64(ctx, fp0, fs);
12189 gen_load_fpr64(ctx, fp1, ft);
12190 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
12191 tcg_temp_free_i64(fp1);
12192 gen_store_fpr64(ctx, fp0, fd);
12193 tcg_temp_free_i64(fp0);
12196 break;
12197 case OPC_MINA_D: /* OPC_RECIP1_D */
12198 if (ctx->insn_flags & ISA_MIPS_R6) {
12199 /* OPC_MINA_D */
12200 TCGv_i64 fp0 = tcg_temp_new_i64();
12201 TCGv_i64 fp1 = tcg_temp_new_i64();
12202 gen_load_fpr64(ctx, fp0, fs);
12203 gen_load_fpr64(ctx, fp1, ft);
12204 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
12205 gen_store_fpr64(ctx, fp1, fd);
12206 tcg_temp_free_i64(fp1);
12207 tcg_temp_free_i64(fp0);
12208 } else {
12209 /* OPC_RECIP1_D */
12210 check_cp1_64bitmode(ctx);
12212 TCGv_i64 fp0 = tcg_temp_new_i64();
12214 gen_load_fpr64(ctx, fp0, fs);
12215 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
12216 gen_store_fpr64(ctx, fp0, fd);
12217 tcg_temp_free_i64(fp0);
12220 break;
12221 case OPC_MAX_D: /* OPC_RSQRT1_D */
12222 if (ctx->insn_flags & ISA_MIPS_R6) {
12223 /* OPC_MAX_D */
12224 TCGv_i64 fp0 = tcg_temp_new_i64();
12225 TCGv_i64 fp1 = tcg_temp_new_i64();
12226 gen_load_fpr64(ctx, fp0, fs);
12227 gen_load_fpr64(ctx, fp1, ft);
12228 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
12229 gen_store_fpr64(ctx, fp1, fd);
12230 tcg_temp_free_i64(fp1);
12231 tcg_temp_free_i64(fp0);
12232 } else {
12233 /* OPC_RSQRT1_D */
12234 check_cp1_64bitmode(ctx);
12236 TCGv_i64 fp0 = tcg_temp_new_i64();
12238 gen_load_fpr64(ctx, fp0, fs);
12239 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
12240 gen_store_fpr64(ctx, fp0, fd);
12241 tcg_temp_free_i64(fp0);
12244 break;
12245 case OPC_MAXA_D: /* OPC_RSQRT2_D */
12246 if (ctx->insn_flags & ISA_MIPS_R6) {
12247 /* OPC_MAXA_D */
12248 TCGv_i64 fp0 = tcg_temp_new_i64();
12249 TCGv_i64 fp1 = tcg_temp_new_i64();
12250 gen_load_fpr64(ctx, fp0, fs);
12251 gen_load_fpr64(ctx, fp1, ft);
12252 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
12253 gen_store_fpr64(ctx, fp1, fd);
12254 tcg_temp_free_i64(fp1);
12255 tcg_temp_free_i64(fp0);
12256 } else {
12257 /* OPC_RSQRT2_D */
12258 check_cp1_64bitmode(ctx);
12260 TCGv_i64 fp0 = tcg_temp_new_i64();
12261 TCGv_i64 fp1 = tcg_temp_new_i64();
12263 gen_load_fpr64(ctx, fp0, fs);
12264 gen_load_fpr64(ctx, fp1, ft);
12265 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
12266 tcg_temp_free_i64(fp1);
12267 gen_store_fpr64(ctx, fp0, fd);
12268 tcg_temp_free_i64(fp0);
12271 break;
12272 case OPC_CMP_F_D:
12273 case OPC_CMP_UN_D:
12274 case OPC_CMP_EQ_D:
12275 case OPC_CMP_UEQ_D:
12276 case OPC_CMP_OLT_D:
12277 case OPC_CMP_ULT_D:
12278 case OPC_CMP_OLE_D:
12279 case OPC_CMP_ULE_D:
12280 case OPC_CMP_SF_D:
12281 case OPC_CMP_NGLE_D:
12282 case OPC_CMP_SEQ_D:
12283 case OPC_CMP_NGL_D:
12284 case OPC_CMP_LT_D:
12285 case OPC_CMP_NGE_D:
12286 case OPC_CMP_LE_D:
12287 case OPC_CMP_NGT_D:
12288 check_insn_opc_removed(ctx, ISA_MIPS_R6);
12289 if (ctx->opcode & (1 << 6)) {
12290 gen_cmpabs_d(ctx, func - 48, ft, fs, cc);
12291 } else {
12292 gen_cmp_d(ctx, func - 48, ft, fs, cc);
12294 break;
12295 case OPC_CVT_S_D:
12296 check_cp1_registers(ctx, fs);
12298 TCGv_i32 fp32 = tcg_temp_new_i32();
12299 TCGv_i64 fp64 = tcg_temp_new_i64();
12301 gen_load_fpr64(ctx, fp64, fs);
12302 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
12303 tcg_temp_free_i64(fp64);
12304 gen_store_fpr32(ctx, fp32, fd);
12305 tcg_temp_free_i32(fp32);
12307 break;
12308 case OPC_CVT_W_D:
12309 check_cp1_registers(ctx, fs);
12311 TCGv_i32 fp32 = tcg_temp_new_i32();
12312 TCGv_i64 fp64 = tcg_temp_new_i64();
12314 gen_load_fpr64(ctx, fp64, fs);
12315 if (ctx->nan2008) {
12316 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
12317 } else {
12318 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
12320 tcg_temp_free_i64(fp64);
12321 gen_store_fpr32(ctx, fp32, fd);
12322 tcg_temp_free_i32(fp32);
12324 break;
12325 case OPC_CVT_L_D:
12326 check_cp1_64bitmode(ctx);
12328 TCGv_i64 fp0 = tcg_temp_new_i64();
12330 gen_load_fpr64(ctx, fp0, fs);
12331 if (ctx->nan2008) {
12332 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
12333 } else {
12334 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
12336 gen_store_fpr64(ctx, fp0, fd);
12337 tcg_temp_free_i64(fp0);
12339 break;
12340 case OPC_CVT_S_W:
12342 TCGv_i32 fp0 = tcg_temp_new_i32();
12344 gen_load_fpr32(ctx, fp0, fs);
12345 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
12346 gen_store_fpr32(ctx, fp0, fd);
12347 tcg_temp_free_i32(fp0);
12349 break;
12350 case OPC_CVT_D_W:
12351 check_cp1_registers(ctx, fd);
12353 TCGv_i32 fp32 = tcg_temp_new_i32();
12354 TCGv_i64 fp64 = tcg_temp_new_i64();
12356 gen_load_fpr32(ctx, fp32, fs);
12357 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
12358 tcg_temp_free_i32(fp32);
12359 gen_store_fpr64(ctx, fp64, fd);
12360 tcg_temp_free_i64(fp64);
12362 break;
12363 case OPC_CVT_S_L:
12364 check_cp1_64bitmode(ctx);
12366 TCGv_i32 fp32 = tcg_temp_new_i32();
12367 TCGv_i64 fp64 = tcg_temp_new_i64();
12369 gen_load_fpr64(ctx, fp64, fs);
12370 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
12371 tcg_temp_free_i64(fp64);
12372 gen_store_fpr32(ctx, fp32, fd);
12373 tcg_temp_free_i32(fp32);
12375 break;
12376 case OPC_CVT_D_L:
12377 check_cp1_64bitmode(ctx);
12379 TCGv_i64 fp0 = tcg_temp_new_i64();
12381 gen_load_fpr64(ctx, fp0, fs);
12382 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
12383 gen_store_fpr64(ctx, fp0, fd);
12384 tcg_temp_free_i64(fp0);
12386 break;
12387 case OPC_CVT_PS_PW:
12388 check_ps(ctx);
12390 TCGv_i64 fp0 = tcg_temp_new_i64();
12392 gen_load_fpr64(ctx, fp0, fs);
12393 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
12394 gen_store_fpr64(ctx, fp0, fd);
12395 tcg_temp_free_i64(fp0);
12397 break;
12398 case OPC_ADD_PS:
12399 check_ps(ctx);
12401 TCGv_i64 fp0 = tcg_temp_new_i64();
12402 TCGv_i64 fp1 = tcg_temp_new_i64();
12404 gen_load_fpr64(ctx, fp0, fs);
12405 gen_load_fpr64(ctx, fp1, ft);
12406 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
12407 tcg_temp_free_i64(fp1);
12408 gen_store_fpr64(ctx, fp0, fd);
12409 tcg_temp_free_i64(fp0);
12411 break;
12412 case OPC_SUB_PS:
12413 check_ps(ctx);
12415 TCGv_i64 fp0 = tcg_temp_new_i64();
12416 TCGv_i64 fp1 = tcg_temp_new_i64();
12418 gen_load_fpr64(ctx, fp0, fs);
12419 gen_load_fpr64(ctx, fp1, ft);
12420 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
12421 tcg_temp_free_i64(fp1);
12422 gen_store_fpr64(ctx, fp0, fd);
12423 tcg_temp_free_i64(fp0);
12425 break;
12426 case OPC_MUL_PS:
12427 check_ps(ctx);
12429 TCGv_i64 fp0 = tcg_temp_new_i64();
12430 TCGv_i64 fp1 = tcg_temp_new_i64();
12432 gen_load_fpr64(ctx, fp0, fs);
12433 gen_load_fpr64(ctx, fp1, ft);
12434 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
12435 tcg_temp_free_i64(fp1);
12436 gen_store_fpr64(ctx, fp0, fd);
12437 tcg_temp_free_i64(fp0);
12439 break;
12440 case OPC_ABS_PS:
12441 check_ps(ctx);
12443 TCGv_i64 fp0 = tcg_temp_new_i64();
12445 gen_load_fpr64(ctx, fp0, fs);
12446 gen_helper_float_abs_ps(fp0, fp0);
12447 gen_store_fpr64(ctx, fp0, fd);
12448 tcg_temp_free_i64(fp0);
12450 break;
12451 case OPC_MOV_PS:
12452 check_ps(ctx);
12454 TCGv_i64 fp0 = tcg_temp_new_i64();
12456 gen_load_fpr64(ctx, fp0, fs);
12457 gen_store_fpr64(ctx, fp0, fd);
12458 tcg_temp_free_i64(fp0);
12460 break;
12461 case OPC_NEG_PS:
12462 check_ps(ctx);
12464 TCGv_i64 fp0 = tcg_temp_new_i64();
12466 gen_load_fpr64(ctx, fp0, fs);
12467 gen_helper_float_chs_ps(fp0, fp0);
12468 gen_store_fpr64(ctx, fp0, fd);
12469 tcg_temp_free_i64(fp0);
12471 break;
12472 case OPC_MOVCF_PS:
12473 check_ps(ctx);
12474 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
12475 break;
12476 case OPC_MOVZ_PS:
12477 check_ps(ctx);
12479 TCGLabel *l1 = gen_new_label();
12480 TCGv_i64 fp0;
12482 if (ft != 0) {
12483 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
12485 fp0 = tcg_temp_new_i64();
12486 gen_load_fpr64(ctx, fp0, fs);
12487 gen_store_fpr64(ctx, fp0, fd);
12488 tcg_temp_free_i64(fp0);
12489 gen_set_label(l1);
12491 break;
12492 case OPC_MOVN_PS:
12493 check_ps(ctx);
12495 TCGLabel *l1 = gen_new_label();
12496 TCGv_i64 fp0;
12498 if (ft != 0) {
12499 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12500 fp0 = tcg_temp_new_i64();
12501 gen_load_fpr64(ctx, fp0, fs);
12502 gen_store_fpr64(ctx, fp0, fd);
12503 tcg_temp_free_i64(fp0);
12504 gen_set_label(l1);
12507 break;
12508 case OPC_ADDR_PS:
12509 check_ps(ctx);
12511 TCGv_i64 fp0 = tcg_temp_new_i64();
12512 TCGv_i64 fp1 = tcg_temp_new_i64();
12514 gen_load_fpr64(ctx, fp0, ft);
12515 gen_load_fpr64(ctx, fp1, fs);
12516 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
12517 tcg_temp_free_i64(fp1);
12518 gen_store_fpr64(ctx, fp0, fd);
12519 tcg_temp_free_i64(fp0);
12521 break;
12522 case OPC_MULR_PS:
12523 check_ps(ctx);
12525 TCGv_i64 fp0 = tcg_temp_new_i64();
12526 TCGv_i64 fp1 = tcg_temp_new_i64();
12528 gen_load_fpr64(ctx, fp0, ft);
12529 gen_load_fpr64(ctx, fp1, fs);
12530 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
12531 tcg_temp_free_i64(fp1);
12532 gen_store_fpr64(ctx, fp0, fd);
12533 tcg_temp_free_i64(fp0);
12535 break;
12536 case OPC_RECIP2_PS:
12537 check_ps(ctx);
12539 TCGv_i64 fp0 = tcg_temp_new_i64();
12540 TCGv_i64 fp1 = tcg_temp_new_i64();
12542 gen_load_fpr64(ctx, fp0, fs);
12543 gen_load_fpr64(ctx, fp1, ft);
12544 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
12545 tcg_temp_free_i64(fp1);
12546 gen_store_fpr64(ctx, fp0, fd);
12547 tcg_temp_free_i64(fp0);
12549 break;
12550 case OPC_RECIP1_PS:
12551 check_ps(ctx);
12553 TCGv_i64 fp0 = tcg_temp_new_i64();
12555 gen_load_fpr64(ctx, fp0, fs);
12556 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
12557 gen_store_fpr64(ctx, fp0, fd);
12558 tcg_temp_free_i64(fp0);
12560 break;
12561 case OPC_RSQRT1_PS:
12562 check_ps(ctx);
12564 TCGv_i64 fp0 = tcg_temp_new_i64();
12566 gen_load_fpr64(ctx, fp0, fs);
12567 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
12568 gen_store_fpr64(ctx, fp0, fd);
12569 tcg_temp_free_i64(fp0);
12571 break;
12572 case OPC_RSQRT2_PS:
12573 check_ps(ctx);
12575 TCGv_i64 fp0 = tcg_temp_new_i64();
12576 TCGv_i64 fp1 = tcg_temp_new_i64();
12578 gen_load_fpr64(ctx, fp0, fs);
12579 gen_load_fpr64(ctx, fp1, ft);
12580 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
12581 tcg_temp_free_i64(fp1);
12582 gen_store_fpr64(ctx, fp0, fd);
12583 tcg_temp_free_i64(fp0);
12585 break;
12586 case OPC_CVT_S_PU:
12587 check_cp1_64bitmode(ctx);
12589 TCGv_i32 fp0 = tcg_temp_new_i32();
12591 gen_load_fpr32h(ctx, fp0, fs);
12592 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
12593 gen_store_fpr32(ctx, fp0, fd);
12594 tcg_temp_free_i32(fp0);
12596 break;
12597 case OPC_CVT_PW_PS:
12598 check_ps(ctx);
12600 TCGv_i64 fp0 = tcg_temp_new_i64();
12602 gen_load_fpr64(ctx, fp0, fs);
12603 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
12604 gen_store_fpr64(ctx, fp0, fd);
12605 tcg_temp_free_i64(fp0);
12607 break;
12608 case OPC_CVT_S_PL:
12609 check_cp1_64bitmode(ctx);
12611 TCGv_i32 fp0 = tcg_temp_new_i32();
12613 gen_load_fpr32(ctx, fp0, fs);
12614 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
12615 gen_store_fpr32(ctx, fp0, fd);
12616 tcg_temp_free_i32(fp0);
12618 break;
12619 case OPC_PLL_PS:
12620 check_ps(ctx);
12622 TCGv_i32 fp0 = tcg_temp_new_i32();
12623 TCGv_i32 fp1 = tcg_temp_new_i32();
12625 gen_load_fpr32(ctx, fp0, fs);
12626 gen_load_fpr32(ctx, fp1, ft);
12627 gen_store_fpr32h(ctx, fp0, fd);
12628 gen_store_fpr32(ctx, fp1, fd);
12629 tcg_temp_free_i32(fp0);
12630 tcg_temp_free_i32(fp1);
12632 break;
12633 case OPC_PLU_PS:
12634 check_ps(ctx);
12636 TCGv_i32 fp0 = tcg_temp_new_i32();
12637 TCGv_i32 fp1 = tcg_temp_new_i32();
12639 gen_load_fpr32(ctx, fp0, fs);
12640 gen_load_fpr32h(ctx, fp1, ft);
12641 gen_store_fpr32(ctx, fp1, fd);
12642 gen_store_fpr32h(ctx, fp0, fd);
12643 tcg_temp_free_i32(fp0);
12644 tcg_temp_free_i32(fp1);
12646 break;
12647 case OPC_PUL_PS:
12648 check_ps(ctx);
12650 TCGv_i32 fp0 = tcg_temp_new_i32();
12651 TCGv_i32 fp1 = tcg_temp_new_i32();
12653 gen_load_fpr32h(ctx, fp0, fs);
12654 gen_load_fpr32(ctx, fp1, ft);
12655 gen_store_fpr32(ctx, fp1, fd);
12656 gen_store_fpr32h(ctx, fp0, fd);
12657 tcg_temp_free_i32(fp0);
12658 tcg_temp_free_i32(fp1);
12660 break;
12661 case OPC_PUU_PS:
12662 check_ps(ctx);
12664 TCGv_i32 fp0 = tcg_temp_new_i32();
12665 TCGv_i32 fp1 = tcg_temp_new_i32();
12667 gen_load_fpr32h(ctx, fp0, fs);
12668 gen_load_fpr32h(ctx, fp1, ft);
12669 gen_store_fpr32(ctx, fp1, fd);
12670 gen_store_fpr32h(ctx, fp0, fd);
12671 tcg_temp_free_i32(fp0);
12672 tcg_temp_free_i32(fp1);
12674 break;
12675 case OPC_CMP_F_PS:
12676 case OPC_CMP_UN_PS:
12677 case OPC_CMP_EQ_PS:
12678 case OPC_CMP_UEQ_PS:
12679 case OPC_CMP_OLT_PS:
12680 case OPC_CMP_ULT_PS:
12681 case OPC_CMP_OLE_PS:
12682 case OPC_CMP_ULE_PS:
12683 case OPC_CMP_SF_PS:
12684 case OPC_CMP_NGLE_PS:
12685 case OPC_CMP_SEQ_PS:
12686 case OPC_CMP_NGL_PS:
12687 case OPC_CMP_LT_PS:
12688 case OPC_CMP_NGE_PS:
12689 case OPC_CMP_LE_PS:
12690 case OPC_CMP_NGT_PS:
12691 if (ctx->opcode & (1 << 6)) {
12692 gen_cmpabs_ps(ctx, func - 48, ft, fs, cc);
12693 } else {
12694 gen_cmp_ps(ctx, func - 48, ft, fs, cc);
12696 break;
12697 default:
12698 MIPS_INVAL("farith");
12699 gen_reserved_instruction(ctx);
12700 return;
12704 /* Coprocessor 3 (FPU) */
12705 static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
12706 int fd, int fs, int base, int index)
12708 TCGv t0 = tcg_temp_new();
12710 if (base == 0) {
12711 gen_load_gpr(t0, index);
12712 } else if (index == 0) {
12713 gen_load_gpr(t0, base);
12714 } else {
12715 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
12718 * Don't do NOP if destination is zero: we must perform the actual
12719 * memory access.
12721 switch (opc) {
12722 case OPC_LWXC1:
12723 check_cop1x(ctx);
12725 TCGv_i32 fp0 = tcg_temp_new_i32();
12727 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
12728 tcg_gen_trunc_tl_i32(fp0, t0);
12729 gen_store_fpr32(ctx, fp0, fd);
12730 tcg_temp_free_i32(fp0);
12732 break;
12733 case OPC_LDXC1:
12734 check_cop1x(ctx);
12735 check_cp1_registers(ctx, fd);
12737 TCGv_i64 fp0 = tcg_temp_new_i64();
12738 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12739 gen_store_fpr64(ctx, fp0, fd);
12740 tcg_temp_free_i64(fp0);
12742 break;
12743 case OPC_LUXC1:
12744 check_cp1_64bitmode(ctx);
12745 tcg_gen_andi_tl(t0, t0, ~0x7);
12747 TCGv_i64 fp0 = tcg_temp_new_i64();
12749 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12750 gen_store_fpr64(ctx, fp0, fd);
12751 tcg_temp_free_i64(fp0);
12753 break;
12754 case OPC_SWXC1:
12755 check_cop1x(ctx);
12757 TCGv_i32 fp0 = tcg_temp_new_i32();
12758 gen_load_fpr32(ctx, fp0, fs);
12759 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
12760 tcg_temp_free_i32(fp0);
12762 break;
12763 case OPC_SDXC1:
12764 check_cop1x(ctx);
12765 check_cp1_registers(ctx, fs);
12767 TCGv_i64 fp0 = tcg_temp_new_i64();
12768 gen_load_fpr64(ctx, fp0, fs);
12769 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12770 tcg_temp_free_i64(fp0);
12772 break;
12773 case OPC_SUXC1:
12774 check_cp1_64bitmode(ctx);
12775 tcg_gen_andi_tl(t0, t0, ~0x7);
12777 TCGv_i64 fp0 = tcg_temp_new_i64();
12778 gen_load_fpr64(ctx, fp0, fs);
12779 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12780 tcg_temp_free_i64(fp0);
12782 break;
12784 tcg_temp_free(t0);
12787 static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
12788 int fd, int fr, int fs, int ft)
12790 switch (opc) {
12791 case OPC_ALNV_PS:
12792 check_ps(ctx);
12794 TCGv t0 = tcg_temp_local_new();
12795 TCGv_i32 fp = tcg_temp_new_i32();
12796 TCGv_i32 fph = tcg_temp_new_i32();
12797 TCGLabel *l1 = gen_new_label();
12798 TCGLabel *l2 = gen_new_label();
12800 gen_load_gpr(t0, fr);
12801 tcg_gen_andi_tl(t0, t0, 0x7);
12803 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
12804 gen_load_fpr32(ctx, fp, fs);
12805 gen_load_fpr32h(ctx, fph, fs);
12806 gen_store_fpr32(ctx, fp, fd);
12807 gen_store_fpr32h(ctx, fph, fd);
12808 tcg_gen_br(l2);
12809 gen_set_label(l1);
12810 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
12811 tcg_temp_free(t0);
12812 #ifdef TARGET_WORDS_BIGENDIAN
12813 gen_load_fpr32(ctx, fp, fs);
12814 gen_load_fpr32h(ctx, fph, ft);
12815 gen_store_fpr32h(ctx, fp, fd);
12816 gen_store_fpr32(ctx, fph, fd);
12817 #else
12818 gen_load_fpr32h(ctx, fph, fs);
12819 gen_load_fpr32(ctx, fp, ft);
12820 gen_store_fpr32(ctx, fph, fd);
12821 gen_store_fpr32h(ctx, fp, fd);
12822 #endif
12823 gen_set_label(l2);
12824 tcg_temp_free_i32(fp);
12825 tcg_temp_free_i32(fph);
12827 break;
12828 case OPC_MADD_S:
12829 check_cop1x(ctx);
12831 TCGv_i32 fp0 = tcg_temp_new_i32();
12832 TCGv_i32 fp1 = tcg_temp_new_i32();
12833 TCGv_i32 fp2 = tcg_temp_new_i32();
12835 gen_load_fpr32(ctx, fp0, fs);
12836 gen_load_fpr32(ctx, fp1, ft);
12837 gen_load_fpr32(ctx, fp2, fr);
12838 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
12839 tcg_temp_free_i32(fp0);
12840 tcg_temp_free_i32(fp1);
12841 gen_store_fpr32(ctx, fp2, fd);
12842 tcg_temp_free_i32(fp2);
12844 break;
12845 case OPC_MADD_D:
12846 check_cop1x(ctx);
12847 check_cp1_registers(ctx, fd | fs | ft | fr);
12849 TCGv_i64 fp0 = tcg_temp_new_i64();
12850 TCGv_i64 fp1 = tcg_temp_new_i64();
12851 TCGv_i64 fp2 = tcg_temp_new_i64();
12853 gen_load_fpr64(ctx, fp0, fs);
12854 gen_load_fpr64(ctx, fp1, ft);
12855 gen_load_fpr64(ctx, fp2, fr);
12856 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
12857 tcg_temp_free_i64(fp0);
12858 tcg_temp_free_i64(fp1);
12859 gen_store_fpr64(ctx, fp2, fd);
12860 tcg_temp_free_i64(fp2);
12862 break;
12863 case OPC_MADD_PS:
12864 check_ps(ctx);
12866 TCGv_i64 fp0 = tcg_temp_new_i64();
12867 TCGv_i64 fp1 = tcg_temp_new_i64();
12868 TCGv_i64 fp2 = tcg_temp_new_i64();
12870 gen_load_fpr64(ctx, fp0, fs);
12871 gen_load_fpr64(ctx, fp1, ft);
12872 gen_load_fpr64(ctx, fp2, fr);
12873 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
12874 tcg_temp_free_i64(fp0);
12875 tcg_temp_free_i64(fp1);
12876 gen_store_fpr64(ctx, fp2, fd);
12877 tcg_temp_free_i64(fp2);
12879 break;
12880 case OPC_MSUB_S:
12881 check_cop1x(ctx);
12883 TCGv_i32 fp0 = tcg_temp_new_i32();
12884 TCGv_i32 fp1 = tcg_temp_new_i32();
12885 TCGv_i32 fp2 = tcg_temp_new_i32();
12887 gen_load_fpr32(ctx, fp0, fs);
12888 gen_load_fpr32(ctx, fp1, ft);
12889 gen_load_fpr32(ctx, fp2, fr);
12890 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
12891 tcg_temp_free_i32(fp0);
12892 tcg_temp_free_i32(fp1);
12893 gen_store_fpr32(ctx, fp2, fd);
12894 tcg_temp_free_i32(fp2);
12896 break;
12897 case OPC_MSUB_D:
12898 check_cop1x(ctx);
12899 check_cp1_registers(ctx, fd | fs | ft | fr);
12901 TCGv_i64 fp0 = tcg_temp_new_i64();
12902 TCGv_i64 fp1 = tcg_temp_new_i64();
12903 TCGv_i64 fp2 = tcg_temp_new_i64();
12905 gen_load_fpr64(ctx, fp0, fs);
12906 gen_load_fpr64(ctx, fp1, ft);
12907 gen_load_fpr64(ctx, fp2, fr);
12908 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
12909 tcg_temp_free_i64(fp0);
12910 tcg_temp_free_i64(fp1);
12911 gen_store_fpr64(ctx, fp2, fd);
12912 tcg_temp_free_i64(fp2);
12914 break;
12915 case OPC_MSUB_PS:
12916 check_ps(ctx);
12918 TCGv_i64 fp0 = tcg_temp_new_i64();
12919 TCGv_i64 fp1 = tcg_temp_new_i64();
12920 TCGv_i64 fp2 = tcg_temp_new_i64();
12922 gen_load_fpr64(ctx, fp0, fs);
12923 gen_load_fpr64(ctx, fp1, ft);
12924 gen_load_fpr64(ctx, fp2, fr);
12925 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
12926 tcg_temp_free_i64(fp0);
12927 tcg_temp_free_i64(fp1);
12928 gen_store_fpr64(ctx, fp2, fd);
12929 tcg_temp_free_i64(fp2);
12931 break;
12932 case OPC_NMADD_S:
12933 check_cop1x(ctx);
12935 TCGv_i32 fp0 = tcg_temp_new_i32();
12936 TCGv_i32 fp1 = tcg_temp_new_i32();
12937 TCGv_i32 fp2 = tcg_temp_new_i32();
12939 gen_load_fpr32(ctx, fp0, fs);
12940 gen_load_fpr32(ctx, fp1, ft);
12941 gen_load_fpr32(ctx, fp2, fr);
12942 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
12943 tcg_temp_free_i32(fp0);
12944 tcg_temp_free_i32(fp1);
12945 gen_store_fpr32(ctx, fp2, fd);
12946 tcg_temp_free_i32(fp2);
12948 break;
12949 case OPC_NMADD_D:
12950 check_cop1x(ctx);
12951 check_cp1_registers(ctx, fd | fs | ft | fr);
12953 TCGv_i64 fp0 = tcg_temp_new_i64();
12954 TCGv_i64 fp1 = tcg_temp_new_i64();
12955 TCGv_i64 fp2 = tcg_temp_new_i64();
12957 gen_load_fpr64(ctx, fp0, fs);
12958 gen_load_fpr64(ctx, fp1, ft);
12959 gen_load_fpr64(ctx, fp2, fr);
12960 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
12961 tcg_temp_free_i64(fp0);
12962 tcg_temp_free_i64(fp1);
12963 gen_store_fpr64(ctx, fp2, fd);
12964 tcg_temp_free_i64(fp2);
12966 break;
12967 case OPC_NMADD_PS:
12968 check_ps(ctx);
12970 TCGv_i64 fp0 = tcg_temp_new_i64();
12971 TCGv_i64 fp1 = tcg_temp_new_i64();
12972 TCGv_i64 fp2 = tcg_temp_new_i64();
12974 gen_load_fpr64(ctx, fp0, fs);
12975 gen_load_fpr64(ctx, fp1, ft);
12976 gen_load_fpr64(ctx, fp2, fr);
12977 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
12978 tcg_temp_free_i64(fp0);
12979 tcg_temp_free_i64(fp1);
12980 gen_store_fpr64(ctx, fp2, fd);
12981 tcg_temp_free_i64(fp2);
12983 break;
12984 case OPC_NMSUB_S:
12985 check_cop1x(ctx);
12987 TCGv_i32 fp0 = tcg_temp_new_i32();
12988 TCGv_i32 fp1 = tcg_temp_new_i32();
12989 TCGv_i32 fp2 = tcg_temp_new_i32();
12991 gen_load_fpr32(ctx, fp0, fs);
12992 gen_load_fpr32(ctx, fp1, ft);
12993 gen_load_fpr32(ctx, fp2, fr);
12994 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
12995 tcg_temp_free_i32(fp0);
12996 tcg_temp_free_i32(fp1);
12997 gen_store_fpr32(ctx, fp2, fd);
12998 tcg_temp_free_i32(fp2);
13000 break;
13001 case OPC_NMSUB_D:
13002 check_cop1x(ctx);
13003 check_cp1_registers(ctx, fd | fs | ft | fr);
13005 TCGv_i64 fp0 = tcg_temp_new_i64();
13006 TCGv_i64 fp1 = tcg_temp_new_i64();
13007 TCGv_i64 fp2 = tcg_temp_new_i64();
13009 gen_load_fpr64(ctx, fp0, fs);
13010 gen_load_fpr64(ctx, fp1, ft);
13011 gen_load_fpr64(ctx, fp2, fr);
13012 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
13013 tcg_temp_free_i64(fp0);
13014 tcg_temp_free_i64(fp1);
13015 gen_store_fpr64(ctx, fp2, fd);
13016 tcg_temp_free_i64(fp2);
13018 break;
13019 case OPC_NMSUB_PS:
13020 check_ps(ctx);
13022 TCGv_i64 fp0 = tcg_temp_new_i64();
13023 TCGv_i64 fp1 = tcg_temp_new_i64();
13024 TCGv_i64 fp2 = tcg_temp_new_i64();
13026 gen_load_fpr64(ctx, fp0, fs);
13027 gen_load_fpr64(ctx, fp1, ft);
13028 gen_load_fpr64(ctx, fp2, fr);
13029 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
13030 tcg_temp_free_i64(fp0);
13031 tcg_temp_free_i64(fp1);
13032 gen_store_fpr64(ctx, fp2, fd);
13033 tcg_temp_free_i64(fp2);
13035 break;
13036 default:
13037 MIPS_INVAL("flt3_arith");
13038 gen_reserved_instruction(ctx);
13039 return;
13043 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
13045 TCGv t0;
13047 #if !defined(CONFIG_USER_ONLY)
13049 * The Linux kernel will emulate rdhwr if it's not supported natively.
13050 * Therefore only check the ISA in system mode.
13052 check_insn(ctx, ISA_MIPS_R2);
13053 #endif
13054 t0 = tcg_temp_new();
13056 switch (rd) {
13057 case 0:
13058 gen_helper_rdhwr_cpunum(t0, cpu_env);
13059 gen_store_gpr(t0, rt);
13060 break;
13061 case 1:
13062 gen_helper_rdhwr_synci_step(t0, cpu_env);
13063 gen_store_gpr(t0, rt);
13064 break;
13065 case 2:
13066 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
13067 gen_io_start();
13069 gen_helper_rdhwr_cc(t0, cpu_env);
13070 gen_store_gpr(t0, rt);
13072 * Break the TB to be able to take timer interrupts immediately
13073 * after reading count. DISAS_STOP isn't sufficient, we need to ensure
13074 * we break completely out of translated code.
13076 gen_save_pc(ctx->base.pc_next + 4);
13077 ctx->base.is_jmp = DISAS_EXIT;
13078 break;
13079 case 3:
13080 gen_helper_rdhwr_ccres(t0, cpu_env);
13081 gen_store_gpr(t0, rt);
13082 break;
13083 case 4:
13084 check_insn(ctx, ISA_MIPS_R6);
13085 if (sel != 0) {
13087 * Performance counter registers are not implemented other than
13088 * control register 0.
13090 generate_exception(ctx, EXCP_RI);
13092 gen_helper_rdhwr_performance(t0, cpu_env);
13093 gen_store_gpr(t0, rt);
13094 break;
13095 case 5:
13096 check_insn(ctx, ISA_MIPS_R6);
13097 gen_helper_rdhwr_xnp(t0, cpu_env);
13098 gen_store_gpr(t0, rt);
13099 break;
13100 case 29:
13101 #if defined(CONFIG_USER_ONLY)
13102 tcg_gen_ld_tl(t0, cpu_env,
13103 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
13104 gen_store_gpr(t0, rt);
13105 break;
13106 #else
13107 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
13108 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
13109 tcg_gen_ld_tl(t0, cpu_env,
13110 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
13111 gen_store_gpr(t0, rt);
13112 } else {
13113 gen_reserved_instruction(ctx);
13115 break;
13116 #endif
13117 default: /* Invalid */
13118 MIPS_INVAL("rdhwr");
13119 gen_reserved_instruction(ctx);
13120 break;
13122 tcg_temp_free(t0);
13125 static inline void clear_branch_hflags(DisasContext *ctx)
13127 ctx->hflags &= ~MIPS_HFLAG_BMASK;
13128 if (ctx->base.is_jmp == DISAS_NEXT) {
13129 save_cpu_state(ctx, 0);
13130 } else {
13132 * It is not safe to save ctx->hflags as hflags may be changed
13133 * in execution time by the instruction in delay / forbidden slot.
13135 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
13139 static void gen_branch(DisasContext *ctx, int insn_bytes)
13141 if (ctx->hflags & MIPS_HFLAG_BMASK) {
13142 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
13143 /* Branches completion */
13144 clear_branch_hflags(ctx);
13145 ctx->base.is_jmp = DISAS_NORETURN;
13146 /* FIXME: Need to clear can_do_io. */
13147 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
13148 case MIPS_HFLAG_FBNSLOT:
13149 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
13150 break;
13151 case MIPS_HFLAG_B:
13152 /* unconditional branch */
13153 if (proc_hflags & MIPS_HFLAG_BX) {
13154 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
13156 gen_goto_tb(ctx, 0, ctx->btarget);
13157 break;
13158 case MIPS_HFLAG_BL:
13159 /* blikely taken case */
13160 gen_goto_tb(ctx, 0, ctx->btarget);
13161 break;
13162 case MIPS_HFLAG_BC:
13163 /* Conditional branch */
13165 TCGLabel *l1 = gen_new_label();
13167 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
13168 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
13169 gen_set_label(l1);
13170 gen_goto_tb(ctx, 0, ctx->btarget);
13172 break;
13173 case MIPS_HFLAG_BR:
13174 /* unconditional branch to register */
13175 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
13176 TCGv t0 = tcg_temp_new();
13177 TCGv_i32 t1 = tcg_temp_new_i32();
13179 tcg_gen_andi_tl(t0, btarget, 0x1);
13180 tcg_gen_trunc_tl_i32(t1, t0);
13181 tcg_temp_free(t0);
13182 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
13183 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
13184 tcg_gen_or_i32(hflags, hflags, t1);
13185 tcg_temp_free_i32(t1);
13187 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
13188 } else {
13189 tcg_gen_mov_tl(cpu_PC, btarget);
13191 if (ctx->base.singlestep_enabled) {
13192 save_cpu_state(ctx, 0);
13193 gen_helper_raise_exception_debug(cpu_env);
13195 tcg_gen_lookup_and_goto_ptr();
13196 break;
13197 default:
13198 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
13199 abort();
13204 /* Compact Branches */
13205 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
13206 int rs, int rt, int32_t offset)
13208 int bcond_compute = 0;
13209 TCGv t0 = tcg_temp_new();
13210 TCGv t1 = tcg_temp_new();
13211 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
13213 if (ctx->hflags & MIPS_HFLAG_BMASK) {
13214 #ifdef MIPS_DEBUG_DISAS
13215 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
13216 "\n", ctx->base.pc_next);
13217 #endif
13218 gen_reserved_instruction(ctx);
13219 goto out;
13222 /* Load needed operands and calculate btarget */
13223 switch (opc) {
13224 /* compact branch */
13225 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13226 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13227 gen_load_gpr(t0, rs);
13228 gen_load_gpr(t1, rt);
13229 bcond_compute = 1;
13230 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13231 if (rs <= rt && rs == 0) {
13232 /* OPC_BEQZALC, OPC_BNEZALC */
13233 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13235 break;
13236 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13237 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13238 gen_load_gpr(t0, rs);
13239 gen_load_gpr(t1, rt);
13240 bcond_compute = 1;
13241 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13242 break;
13243 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13244 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13245 if (rs == 0 || rs == rt) {
13246 /* OPC_BLEZALC, OPC_BGEZALC */
13247 /* OPC_BGTZALC, OPC_BLTZALC */
13248 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13250 gen_load_gpr(t0, rs);
13251 gen_load_gpr(t1, rt);
13252 bcond_compute = 1;
13253 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13254 break;
13255 case OPC_BC:
13256 case OPC_BALC:
13257 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13258 break;
13259 case OPC_BEQZC:
13260 case OPC_BNEZC:
13261 if (rs != 0) {
13262 /* OPC_BEQZC, OPC_BNEZC */
13263 gen_load_gpr(t0, rs);
13264 bcond_compute = 1;
13265 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13266 } else {
13267 /* OPC_JIC, OPC_JIALC */
13268 TCGv tbase = tcg_temp_new();
13269 TCGv toffset = tcg_temp_new();
13271 gen_load_gpr(tbase, rt);
13272 tcg_gen_movi_tl(toffset, offset);
13273 gen_op_addr_add(ctx, btarget, tbase, toffset);
13274 tcg_temp_free(tbase);
13275 tcg_temp_free(toffset);
13277 break;
13278 default:
13279 MIPS_INVAL("Compact branch/jump");
13280 gen_reserved_instruction(ctx);
13281 goto out;
13284 if (bcond_compute == 0) {
13285 /* Uncoditional compact branch */
13286 switch (opc) {
13287 case OPC_JIALC:
13288 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13289 /* Fallthrough */
13290 case OPC_JIC:
13291 ctx->hflags |= MIPS_HFLAG_BR;
13292 break;
13293 case OPC_BALC:
13294 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13295 /* Fallthrough */
13296 case OPC_BC:
13297 ctx->hflags |= MIPS_HFLAG_B;
13298 break;
13299 default:
13300 MIPS_INVAL("Compact branch/jump");
13301 gen_reserved_instruction(ctx);
13302 goto out;
13305 /* Generating branch here as compact branches don't have delay slot */
13306 gen_branch(ctx, 4);
13307 } else {
13308 /* Conditional compact branch */
13309 TCGLabel *fs = gen_new_label();
13310 save_cpu_state(ctx, 0);
13312 switch (opc) {
13313 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13314 if (rs == 0 && rt != 0) {
13315 /* OPC_BLEZALC */
13316 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13317 } else if (rs != 0 && rt != 0 && rs == rt) {
13318 /* OPC_BGEZALC */
13319 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13320 } else {
13321 /* OPC_BGEUC */
13322 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
13324 break;
13325 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13326 if (rs == 0 && rt != 0) {
13327 /* OPC_BGTZALC */
13328 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13329 } else if (rs != 0 && rt != 0 && rs == rt) {
13330 /* OPC_BLTZALC */
13331 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13332 } else {
13333 /* OPC_BLTUC */
13334 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
13336 break;
13337 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13338 if (rs == 0 && rt != 0) {
13339 /* OPC_BLEZC */
13340 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13341 } else if (rs != 0 && rt != 0 && rs == rt) {
13342 /* OPC_BGEZC */
13343 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13344 } else {
13345 /* OPC_BGEC */
13346 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
13348 break;
13349 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13350 if (rs == 0 && rt != 0) {
13351 /* OPC_BGTZC */
13352 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13353 } else if (rs != 0 && rt != 0 && rs == rt) {
13354 /* OPC_BLTZC */
13355 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13356 } else {
13357 /* OPC_BLTC */
13358 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
13360 break;
13361 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13362 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13363 if (rs >= rt) {
13364 /* OPC_BOVC, OPC_BNVC */
13365 TCGv t2 = tcg_temp_new();
13366 TCGv t3 = tcg_temp_new();
13367 TCGv t4 = tcg_temp_new();
13368 TCGv input_overflow = tcg_temp_new();
13370 gen_load_gpr(t0, rs);
13371 gen_load_gpr(t1, rt);
13372 tcg_gen_ext32s_tl(t2, t0);
13373 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
13374 tcg_gen_ext32s_tl(t3, t1);
13375 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
13376 tcg_gen_or_tl(input_overflow, input_overflow, t4);
13378 tcg_gen_add_tl(t4, t2, t3);
13379 tcg_gen_ext32s_tl(t4, t4);
13380 tcg_gen_xor_tl(t2, t2, t3);
13381 tcg_gen_xor_tl(t3, t4, t3);
13382 tcg_gen_andc_tl(t2, t3, t2);
13383 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
13384 tcg_gen_or_tl(t4, t4, input_overflow);
13385 if (opc == OPC_BOVC) {
13386 /* OPC_BOVC */
13387 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
13388 } else {
13389 /* OPC_BNVC */
13390 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
13392 tcg_temp_free(input_overflow);
13393 tcg_temp_free(t4);
13394 tcg_temp_free(t3);
13395 tcg_temp_free(t2);
13396 } else if (rs < rt && rs == 0) {
13397 /* OPC_BEQZALC, OPC_BNEZALC */
13398 if (opc == OPC_BEQZALC) {
13399 /* OPC_BEQZALC */
13400 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
13401 } else {
13402 /* OPC_BNEZALC */
13403 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
13405 } else {
13406 /* OPC_BEQC, OPC_BNEC */
13407 if (opc == OPC_BEQC) {
13408 /* OPC_BEQC */
13409 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
13410 } else {
13411 /* OPC_BNEC */
13412 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
13415 break;
13416 case OPC_BEQZC:
13417 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
13418 break;
13419 case OPC_BNEZC:
13420 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
13421 break;
13422 default:
13423 MIPS_INVAL("Compact conditional branch/jump");
13424 gen_reserved_instruction(ctx);
13425 goto out;
13428 /* Generating branch here as compact branches don't have delay slot */
13429 gen_goto_tb(ctx, 1, ctx->btarget);
13430 gen_set_label(fs);
13432 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
13435 out:
13436 tcg_temp_free(t0);
13437 tcg_temp_free(t1);
13440 /* ISA extensions (ASEs) */
13441 /* MIPS16 extension to MIPS32 */
13443 /* MIPS16 major opcodes */
13444 enum {
13445 M16_OPC_ADDIUSP = 0x00,
13446 M16_OPC_ADDIUPC = 0x01,
13447 M16_OPC_B = 0x02,
13448 M16_OPC_JAL = 0x03,
13449 M16_OPC_BEQZ = 0x04,
13450 M16_OPC_BNEQZ = 0x05,
13451 M16_OPC_SHIFT = 0x06,
13452 M16_OPC_LD = 0x07,
13453 M16_OPC_RRIA = 0x08,
13454 M16_OPC_ADDIU8 = 0x09,
13455 M16_OPC_SLTI = 0x0a,
13456 M16_OPC_SLTIU = 0x0b,
13457 M16_OPC_I8 = 0x0c,
13458 M16_OPC_LI = 0x0d,
13459 M16_OPC_CMPI = 0x0e,
13460 M16_OPC_SD = 0x0f,
13461 M16_OPC_LB = 0x10,
13462 M16_OPC_LH = 0x11,
13463 M16_OPC_LWSP = 0x12,
13464 M16_OPC_LW = 0x13,
13465 M16_OPC_LBU = 0x14,
13466 M16_OPC_LHU = 0x15,
13467 M16_OPC_LWPC = 0x16,
13468 M16_OPC_LWU = 0x17,
13469 M16_OPC_SB = 0x18,
13470 M16_OPC_SH = 0x19,
13471 M16_OPC_SWSP = 0x1a,
13472 M16_OPC_SW = 0x1b,
13473 M16_OPC_RRR = 0x1c,
13474 M16_OPC_RR = 0x1d,
13475 M16_OPC_EXTEND = 0x1e,
13476 M16_OPC_I64 = 0x1f
13479 /* I8 funct field */
13480 enum {
13481 I8_BTEQZ = 0x0,
13482 I8_BTNEZ = 0x1,
13483 I8_SWRASP = 0x2,
13484 I8_ADJSP = 0x3,
13485 I8_SVRS = 0x4,
13486 I8_MOV32R = 0x5,
13487 I8_MOVR32 = 0x7
13490 /* RRR f field */
13491 enum {
13492 RRR_DADDU = 0x0,
13493 RRR_ADDU = 0x1,
13494 RRR_DSUBU = 0x2,
13495 RRR_SUBU = 0x3
13498 /* RR funct field */
13499 enum {
13500 RR_JR = 0x00,
13501 RR_SDBBP = 0x01,
13502 RR_SLT = 0x02,
13503 RR_SLTU = 0x03,
13504 RR_SLLV = 0x04,
13505 RR_BREAK = 0x05,
13506 RR_SRLV = 0x06,
13507 RR_SRAV = 0x07,
13508 RR_DSRL = 0x08,
13509 RR_CMP = 0x0a,
13510 RR_NEG = 0x0b,
13511 RR_AND = 0x0c,
13512 RR_OR = 0x0d,
13513 RR_XOR = 0x0e,
13514 RR_NOT = 0x0f,
13515 RR_MFHI = 0x10,
13516 RR_CNVT = 0x11,
13517 RR_MFLO = 0x12,
13518 RR_DSRA = 0x13,
13519 RR_DSLLV = 0x14,
13520 RR_DSRLV = 0x16,
13521 RR_DSRAV = 0x17,
13522 RR_MULT = 0x18,
13523 RR_MULTU = 0x19,
13524 RR_DIV = 0x1a,
13525 RR_DIVU = 0x1b,
13526 RR_DMULT = 0x1c,
13527 RR_DMULTU = 0x1d,
13528 RR_DDIV = 0x1e,
13529 RR_DDIVU = 0x1f
13532 /* I64 funct field */
13533 enum {
13534 I64_LDSP = 0x0,
13535 I64_SDSP = 0x1,
13536 I64_SDRASP = 0x2,
13537 I64_DADJSP = 0x3,
13538 I64_LDPC = 0x4,
13539 I64_DADDIU5 = 0x5,
13540 I64_DADDIUPC = 0x6,
13541 I64_DADDIUSP = 0x7
13544 /* RR ry field for CNVT */
13545 enum {
13546 RR_RY_CNVT_ZEB = 0x0,
13547 RR_RY_CNVT_ZEH = 0x1,
13548 RR_RY_CNVT_ZEW = 0x2,
13549 RR_RY_CNVT_SEB = 0x4,
13550 RR_RY_CNVT_SEH = 0x5,
13551 RR_RY_CNVT_SEW = 0x6,
13554 static int xlat(int r)
13556 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
13558 return map[r];
13561 static void gen_mips16_save(DisasContext *ctx,
13562 int xsregs, int aregs,
13563 int do_ra, int do_s0, int do_s1,
13564 int framesize)
13566 TCGv t0 = tcg_temp_new();
13567 TCGv t1 = tcg_temp_new();
13568 TCGv t2 = tcg_temp_new();
13569 int args, astatic;
13571 switch (aregs) {
13572 case 0:
13573 case 1:
13574 case 2:
13575 case 3:
13576 case 11:
13577 args = 0;
13578 break;
13579 case 4:
13580 case 5:
13581 case 6:
13582 case 7:
13583 args = 1;
13584 break;
13585 case 8:
13586 case 9:
13587 case 10:
13588 args = 2;
13589 break;
13590 case 12:
13591 case 13:
13592 args = 3;
13593 break;
13594 case 14:
13595 args = 4;
13596 break;
13597 default:
13598 gen_reserved_instruction(ctx);
13599 return;
13602 switch (args) {
13603 case 4:
13604 gen_base_offset_addr(ctx, t0, 29, 12);
13605 gen_load_gpr(t1, 7);
13606 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13607 /* Fall through */
13608 case 3:
13609 gen_base_offset_addr(ctx, t0, 29, 8);
13610 gen_load_gpr(t1, 6);
13611 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13612 /* Fall through */
13613 case 2:
13614 gen_base_offset_addr(ctx, t0, 29, 4);
13615 gen_load_gpr(t1, 5);
13616 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13617 /* Fall through */
13618 case 1:
13619 gen_base_offset_addr(ctx, t0, 29, 0);
13620 gen_load_gpr(t1, 4);
13621 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13624 gen_load_gpr(t0, 29);
13626 #define DECR_AND_STORE(reg) do { \
13627 tcg_gen_movi_tl(t2, -4); \
13628 gen_op_addr_add(ctx, t0, t0, t2); \
13629 gen_load_gpr(t1, reg); \
13630 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
13631 } while (0)
13633 if (do_ra) {
13634 DECR_AND_STORE(31);
13637 switch (xsregs) {
13638 case 7:
13639 DECR_AND_STORE(30);
13640 /* Fall through */
13641 case 6:
13642 DECR_AND_STORE(23);
13643 /* Fall through */
13644 case 5:
13645 DECR_AND_STORE(22);
13646 /* Fall through */
13647 case 4:
13648 DECR_AND_STORE(21);
13649 /* Fall through */
13650 case 3:
13651 DECR_AND_STORE(20);
13652 /* Fall through */
13653 case 2:
13654 DECR_AND_STORE(19);
13655 /* Fall through */
13656 case 1:
13657 DECR_AND_STORE(18);
13660 if (do_s1) {
13661 DECR_AND_STORE(17);
13663 if (do_s0) {
13664 DECR_AND_STORE(16);
13667 switch (aregs) {
13668 case 0:
13669 case 4:
13670 case 8:
13671 case 12:
13672 case 14:
13673 astatic = 0;
13674 break;
13675 case 1:
13676 case 5:
13677 case 9:
13678 case 13:
13679 astatic = 1;
13680 break;
13681 case 2:
13682 case 6:
13683 case 10:
13684 astatic = 2;
13685 break;
13686 case 3:
13687 case 7:
13688 astatic = 3;
13689 break;
13690 case 11:
13691 astatic = 4;
13692 break;
13693 default:
13694 gen_reserved_instruction(ctx);
13695 return;
13698 if (astatic > 0) {
13699 DECR_AND_STORE(7);
13700 if (astatic > 1) {
13701 DECR_AND_STORE(6);
13702 if (astatic > 2) {
13703 DECR_AND_STORE(5);
13704 if (astatic > 3) {
13705 DECR_AND_STORE(4);
13710 #undef DECR_AND_STORE
13712 tcg_gen_movi_tl(t2, -framesize);
13713 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13714 tcg_temp_free(t0);
13715 tcg_temp_free(t1);
13716 tcg_temp_free(t2);
13719 static void gen_mips16_restore(DisasContext *ctx,
13720 int xsregs, int aregs,
13721 int do_ra, int do_s0, int do_s1,
13722 int framesize)
13724 int astatic;
13725 TCGv t0 = tcg_temp_new();
13726 TCGv t1 = tcg_temp_new();
13727 TCGv t2 = tcg_temp_new();
13729 tcg_gen_movi_tl(t2, framesize);
13730 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
13732 #define DECR_AND_LOAD(reg) do { \
13733 tcg_gen_movi_tl(t2, -4); \
13734 gen_op_addr_add(ctx, t0, t0, t2); \
13735 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
13736 gen_store_gpr(t1, reg); \
13737 } while (0)
13739 if (do_ra) {
13740 DECR_AND_LOAD(31);
13743 switch (xsregs) {
13744 case 7:
13745 DECR_AND_LOAD(30);
13746 /* Fall through */
13747 case 6:
13748 DECR_AND_LOAD(23);
13749 /* Fall through */
13750 case 5:
13751 DECR_AND_LOAD(22);
13752 /* Fall through */
13753 case 4:
13754 DECR_AND_LOAD(21);
13755 /* Fall through */
13756 case 3:
13757 DECR_AND_LOAD(20);
13758 /* Fall through */
13759 case 2:
13760 DECR_AND_LOAD(19);
13761 /* Fall through */
13762 case 1:
13763 DECR_AND_LOAD(18);
13766 if (do_s1) {
13767 DECR_AND_LOAD(17);
13769 if (do_s0) {
13770 DECR_AND_LOAD(16);
13773 switch (aregs) {
13774 case 0:
13775 case 4:
13776 case 8:
13777 case 12:
13778 case 14:
13779 astatic = 0;
13780 break;
13781 case 1:
13782 case 5:
13783 case 9:
13784 case 13:
13785 astatic = 1;
13786 break;
13787 case 2:
13788 case 6:
13789 case 10:
13790 astatic = 2;
13791 break;
13792 case 3:
13793 case 7:
13794 astatic = 3;
13795 break;
13796 case 11:
13797 astatic = 4;
13798 break;
13799 default:
13800 gen_reserved_instruction(ctx);
13801 return;
13804 if (astatic > 0) {
13805 DECR_AND_LOAD(7);
13806 if (astatic > 1) {
13807 DECR_AND_LOAD(6);
13808 if (astatic > 2) {
13809 DECR_AND_LOAD(5);
13810 if (astatic > 3) {
13811 DECR_AND_LOAD(4);
13816 #undef DECR_AND_LOAD
13818 tcg_gen_movi_tl(t2, framesize);
13819 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13820 tcg_temp_free(t0);
13821 tcg_temp_free(t1);
13822 tcg_temp_free(t2);
13825 static void gen_addiupc(DisasContext *ctx, int rx, int imm,
13826 int is_64_bit, int extended)
13828 TCGv t0;
13830 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13831 gen_reserved_instruction(ctx);
13832 return;
13835 t0 = tcg_temp_new();
13837 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
13838 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
13839 if (!is_64_bit) {
13840 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13843 tcg_temp_free(t0);
13846 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
13847 int16_t offset)
13849 TCGv_i32 t0 = tcg_const_i32(op);
13850 TCGv t1 = tcg_temp_new();
13851 gen_base_offset_addr(ctx, t1, base, offset);
13852 gen_helper_cache(cpu_env, t1, t0);
13855 #if defined(TARGET_MIPS64)
13856 static void decode_i64_mips16(DisasContext *ctx,
13857 int ry, int funct, int16_t offset,
13858 int extended)
13860 switch (funct) {
13861 case I64_LDSP:
13862 check_insn(ctx, ISA_MIPS3);
13863 check_mips_64(ctx);
13864 offset = extended ? offset : offset << 3;
13865 gen_ld(ctx, OPC_LD, ry, 29, offset);
13866 break;
13867 case I64_SDSP:
13868 check_insn(ctx, ISA_MIPS3);
13869 check_mips_64(ctx);
13870 offset = extended ? offset : offset << 3;
13871 gen_st(ctx, OPC_SD, ry, 29, offset);
13872 break;
13873 case I64_SDRASP:
13874 check_insn(ctx, ISA_MIPS3);
13875 check_mips_64(ctx);
13876 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
13877 gen_st(ctx, OPC_SD, 31, 29, offset);
13878 break;
13879 case I64_DADJSP:
13880 check_insn(ctx, ISA_MIPS3);
13881 check_mips_64(ctx);
13882 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
13883 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
13884 break;
13885 case I64_LDPC:
13886 check_insn(ctx, ISA_MIPS3);
13887 check_mips_64(ctx);
13888 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13889 gen_reserved_instruction(ctx);
13890 } else {
13891 offset = extended ? offset : offset << 3;
13892 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
13894 break;
13895 case I64_DADDIU5:
13896 check_insn(ctx, ISA_MIPS3);
13897 check_mips_64(ctx);
13898 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
13899 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
13900 break;
13901 case I64_DADDIUPC:
13902 check_insn(ctx, ISA_MIPS3);
13903 check_mips_64(ctx);
13904 offset = extended ? offset : offset << 2;
13905 gen_addiupc(ctx, ry, offset, 1, extended);
13906 break;
13907 case I64_DADDIUSP:
13908 check_insn(ctx, ISA_MIPS3);
13909 check_mips_64(ctx);
13910 offset = extended ? offset : offset << 2;
13911 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
13912 break;
13915 #endif
13917 static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
13919 int extend = translator_lduw(env, ctx->base.pc_next + 2);
13920 int op, rx, ry, funct, sa;
13921 int16_t imm, offset;
13923 ctx->opcode = (ctx->opcode << 16) | extend;
13924 op = (ctx->opcode >> 11) & 0x1f;
13925 sa = (ctx->opcode >> 22) & 0x1f;
13926 funct = (ctx->opcode >> 8) & 0x7;
13927 rx = xlat((ctx->opcode >> 8) & 0x7);
13928 ry = xlat((ctx->opcode >> 5) & 0x7);
13929 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
13930 | ((ctx->opcode >> 21) & 0x3f) << 5
13931 | (ctx->opcode & 0x1f));
13934 * The extended opcodes cleverly reuse the opcodes from their 16-bit
13935 * counterparts.
13937 switch (op) {
13938 case M16_OPC_ADDIUSP:
13939 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13940 break;
13941 case M16_OPC_ADDIUPC:
13942 gen_addiupc(ctx, rx, imm, 0, 1);
13943 break;
13944 case M16_OPC_B:
13945 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
13946 /* No delay slot, so just process as a normal instruction */
13947 break;
13948 case M16_OPC_BEQZ:
13949 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
13950 /* No delay slot, so just process as a normal instruction */
13951 break;
13952 case M16_OPC_BNEQZ:
13953 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
13954 /* No delay slot, so just process as a normal instruction */
13955 break;
13956 case M16_OPC_SHIFT:
13957 switch (ctx->opcode & 0x3) {
13958 case 0x0:
13959 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13960 break;
13961 case 0x1:
13962 #if defined(TARGET_MIPS64)
13963 check_mips_64(ctx);
13964 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13965 #else
13966 gen_reserved_instruction(ctx);
13967 #endif
13968 break;
13969 case 0x2:
13970 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13971 break;
13972 case 0x3:
13973 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13974 break;
13976 break;
13977 #if defined(TARGET_MIPS64)
13978 case M16_OPC_LD:
13979 check_insn(ctx, ISA_MIPS3);
13980 check_mips_64(ctx);
13981 gen_ld(ctx, OPC_LD, ry, rx, offset);
13982 break;
13983 #endif
13984 case M16_OPC_RRIA:
13985 imm = ctx->opcode & 0xf;
13986 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
13987 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
13988 imm = (int16_t) (imm << 1) >> 1;
13989 if ((ctx->opcode >> 4) & 0x1) {
13990 #if defined(TARGET_MIPS64)
13991 check_mips_64(ctx);
13992 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13993 #else
13994 gen_reserved_instruction(ctx);
13995 #endif
13996 } else {
13997 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13999 break;
14000 case M16_OPC_ADDIU8:
14001 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
14002 break;
14003 case M16_OPC_SLTI:
14004 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
14005 break;
14006 case M16_OPC_SLTIU:
14007 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
14008 break;
14009 case M16_OPC_I8:
14010 switch (funct) {
14011 case I8_BTEQZ:
14012 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
14013 break;
14014 case I8_BTNEZ:
14015 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
14016 break;
14017 case I8_SWRASP:
14018 gen_st(ctx, OPC_SW, 31, 29, imm);
14019 break;
14020 case I8_ADJSP:
14021 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
14022 break;
14023 case I8_SVRS:
14024 check_insn(ctx, ISA_MIPS_R1);
14026 int xsregs = (ctx->opcode >> 24) & 0x7;
14027 int aregs = (ctx->opcode >> 16) & 0xf;
14028 int do_ra = (ctx->opcode >> 6) & 0x1;
14029 int do_s0 = (ctx->opcode >> 5) & 0x1;
14030 int do_s1 = (ctx->opcode >> 4) & 0x1;
14031 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
14032 | (ctx->opcode & 0xf)) << 3;
14034 if (ctx->opcode & (1 << 7)) {
14035 gen_mips16_save(ctx, xsregs, aregs,
14036 do_ra, do_s0, do_s1,
14037 framesize);
14038 } else {
14039 gen_mips16_restore(ctx, xsregs, aregs,
14040 do_ra, do_s0, do_s1,
14041 framesize);
14044 break;
14045 default:
14046 gen_reserved_instruction(ctx);
14047 break;
14049 break;
14050 case M16_OPC_LI:
14051 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
14052 break;
14053 case M16_OPC_CMPI:
14054 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
14055 break;
14056 #if defined(TARGET_MIPS64)
14057 case M16_OPC_SD:
14058 check_insn(ctx, ISA_MIPS3);
14059 check_mips_64(ctx);
14060 gen_st(ctx, OPC_SD, ry, rx, offset);
14061 break;
14062 #endif
14063 case M16_OPC_LB:
14064 gen_ld(ctx, OPC_LB, ry, rx, offset);
14065 break;
14066 case M16_OPC_LH:
14067 gen_ld(ctx, OPC_LH, ry, rx, offset);
14068 break;
14069 case M16_OPC_LWSP:
14070 gen_ld(ctx, OPC_LW, rx, 29, offset);
14071 break;
14072 case M16_OPC_LW:
14073 gen_ld(ctx, OPC_LW, ry, rx, offset);
14074 break;
14075 case M16_OPC_LBU:
14076 gen_ld(ctx, OPC_LBU, ry, rx, offset);
14077 break;
14078 case M16_OPC_LHU:
14079 gen_ld(ctx, OPC_LHU, ry, rx, offset);
14080 break;
14081 case M16_OPC_LWPC:
14082 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
14083 break;
14084 #if defined(TARGET_MIPS64)
14085 case M16_OPC_LWU:
14086 check_insn(ctx, ISA_MIPS3);
14087 check_mips_64(ctx);
14088 gen_ld(ctx, OPC_LWU, ry, rx, offset);
14089 break;
14090 #endif
14091 case M16_OPC_SB:
14092 gen_st(ctx, OPC_SB, ry, rx, offset);
14093 break;
14094 case M16_OPC_SH:
14095 gen_st(ctx, OPC_SH, ry, rx, offset);
14096 break;
14097 case M16_OPC_SWSP:
14098 gen_st(ctx, OPC_SW, rx, 29, offset);
14099 break;
14100 case M16_OPC_SW:
14101 gen_st(ctx, OPC_SW, ry, rx, offset);
14102 break;
14103 #if defined(TARGET_MIPS64)
14104 case M16_OPC_I64:
14105 decode_i64_mips16(ctx, ry, funct, offset, 1);
14106 break;
14107 #endif
14108 default:
14109 gen_reserved_instruction(ctx);
14110 break;
14113 return 4;
14116 static inline bool is_uhi(int sdbbp_code)
14118 #ifdef CONFIG_USER_ONLY
14119 return false;
14120 #else
14121 return semihosting_enabled() && sdbbp_code == 1;
14122 #endif
14125 #ifdef CONFIG_USER_ONLY
14126 /* The above should dead-code away any calls to this..*/
14127 static inline void gen_helper_do_semihosting(void *env)
14129 g_assert_not_reached();
14131 #endif
14133 static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
14135 int rx, ry;
14136 int sa;
14137 int op, cnvt_op, op1, offset;
14138 int funct;
14139 int n_bytes;
14141 op = (ctx->opcode >> 11) & 0x1f;
14142 sa = (ctx->opcode >> 2) & 0x7;
14143 sa = sa == 0 ? 8 : sa;
14144 rx = xlat((ctx->opcode >> 8) & 0x7);
14145 cnvt_op = (ctx->opcode >> 5) & 0x7;
14146 ry = xlat((ctx->opcode >> 5) & 0x7);
14147 op1 = offset = ctx->opcode & 0x1f;
14149 n_bytes = 2;
14151 switch (op) {
14152 case M16_OPC_ADDIUSP:
14154 int16_t imm = ((uint8_t) ctx->opcode) << 2;
14156 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
14158 break;
14159 case M16_OPC_ADDIUPC:
14160 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
14161 break;
14162 case M16_OPC_B:
14163 offset = (ctx->opcode & 0x7ff) << 1;
14164 offset = (int16_t)(offset << 4) >> 4;
14165 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
14166 /* No delay slot, so just process as a normal instruction */
14167 break;
14168 case M16_OPC_JAL:
14169 offset = translator_lduw(env, ctx->base.pc_next + 2);
14170 offset = (((ctx->opcode & 0x1f) << 21)
14171 | ((ctx->opcode >> 5) & 0x1f) << 16
14172 | offset) << 2;
14173 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
14174 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
14175 n_bytes = 4;
14176 break;
14177 case M16_OPC_BEQZ:
14178 gen_compute_branch(ctx, OPC_BEQ, 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_BNEQZ:
14183 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
14184 ((int8_t)ctx->opcode) << 1, 0);
14185 /* No delay slot, so just process as a normal instruction */
14186 break;
14187 case M16_OPC_SHIFT:
14188 switch (ctx->opcode & 0x3) {
14189 case 0x0:
14190 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
14191 break;
14192 case 0x1:
14193 #if defined(TARGET_MIPS64)
14194 check_insn(ctx, ISA_MIPS3);
14195 check_mips_64(ctx);
14196 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
14197 #else
14198 gen_reserved_instruction(ctx);
14199 #endif
14200 break;
14201 case 0x2:
14202 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
14203 break;
14204 case 0x3:
14205 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
14206 break;
14208 break;
14209 #if defined(TARGET_MIPS64)
14210 case M16_OPC_LD:
14211 check_insn(ctx, ISA_MIPS3);
14212 check_mips_64(ctx);
14213 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
14214 break;
14215 #endif
14216 case M16_OPC_RRIA:
14218 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
14220 if ((ctx->opcode >> 4) & 1) {
14221 #if defined(TARGET_MIPS64)
14222 check_insn(ctx, ISA_MIPS3);
14223 check_mips_64(ctx);
14224 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
14225 #else
14226 gen_reserved_instruction(ctx);
14227 #endif
14228 } else {
14229 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
14232 break;
14233 case M16_OPC_ADDIU8:
14235 int16_t imm = (int8_t) ctx->opcode;
14237 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
14239 break;
14240 case M16_OPC_SLTI:
14242 int16_t imm = (uint8_t) ctx->opcode;
14243 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
14245 break;
14246 case M16_OPC_SLTIU:
14248 int16_t imm = (uint8_t) ctx->opcode;
14249 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
14251 break;
14252 case M16_OPC_I8:
14254 int reg32;
14256 funct = (ctx->opcode >> 8) & 0x7;
14257 switch (funct) {
14258 case I8_BTEQZ:
14259 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
14260 ((int8_t)ctx->opcode) << 1, 0);
14261 break;
14262 case I8_BTNEZ:
14263 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
14264 ((int8_t)ctx->opcode) << 1, 0);
14265 break;
14266 case I8_SWRASP:
14267 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
14268 break;
14269 case I8_ADJSP:
14270 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
14271 ((int8_t)ctx->opcode) << 3);
14272 break;
14273 case I8_SVRS:
14274 check_insn(ctx, ISA_MIPS_R1);
14276 int do_ra = ctx->opcode & (1 << 6);
14277 int do_s0 = ctx->opcode & (1 << 5);
14278 int do_s1 = ctx->opcode & (1 << 4);
14279 int framesize = ctx->opcode & 0xf;
14281 if (framesize == 0) {
14282 framesize = 128;
14283 } else {
14284 framesize = framesize << 3;
14287 if (ctx->opcode & (1 << 7)) {
14288 gen_mips16_save(ctx, 0, 0,
14289 do_ra, do_s0, do_s1, framesize);
14290 } else {
14291 gen_mips16_restore(ctx, 0, 0,
14292 do_ra, do_s0, do_s1, framesize);
14295 break;
14296 case I8_MOV32R:
14298 int rz = xlat(ctx->opcode & 0x7);
14300 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
14301 ((ctx->opcode >> 5) & 0x7);
14302 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
14304 break;
14305 case I8_MOVR32:
14306 reg32 = ctx->opcode & 0x1f;
14307 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
14308 break;
14309 default:
14310 gen_reserved_instruction(ctx);
14311 break;
14314 break;
14315 case M16_OPC_LI:
14317 int16_t imm = (uint8_t) ctx->opcode;
14319 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
14321 break;
14322 case M16_OPC_CMPI:
14324 int16_t imm = (uint8_t) ctx->opcode;
14325 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
14327 break;
14328 #if defined(TARGET_MIPS64)
14329 case M16_OPC_SD:
14330 check_insn(ctx, ISA_MIPS3);
14331 check_mips_64(ctx);
14332 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
14333 break;
14334 #endif
14335 case M16_OPC_LB:
14336 gen_ld(ctx, OPC_LB, ry, rx, offset);
14337 break;
14338 case M16_OPC_LH:
14339 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
14340 break;
14341 case M16_OPC_LWSP:
14342 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14343 break;
14344 case M16_OPC_LW:
14345 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
14346 break;
14347 case M16_OPC_LBU:
14348 gen_ld(ctx, OPC_LBU, ry, rx, offset);
14349 break;
14350 case M16_OPC_LHU:
14351 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
14352 break;
14353 case M16_OPC_LWPC:
14354 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
14355 break;
14356 #if defined(TARGET_MIPS64)
14357 case M16_OPC_LWU:
14358 check_insn(ctx, ISA_MIPS3);
14359 check_mips_64(ctx);
14360 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
14361 break;
14362 #endif
14363 case M16_OPC_SB:
14364 gen_st(ctx, OPC_SB, ry, rx, offset);
14365 break;
14366 case M16_OPC_SH:
14367 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
14368 break;
14369 case M16_OPC_SWSP:
14370 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14371 break;
14372 case M16_OPC_SW:
14373 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
14374 break;
14375 case M16_OPC_RRR:
14377 int rz = xlat((ctx->opcode >> 2) & 0x7);
14378 int mips32_op;
14380 switch (ctx->opcode & 0x3) {
14381 case RRR_ADDU:
14382 mips32_op = OPC_ADDU;
14383 break;
14384 case RRR_SUBU:
14385 mips32_op = OPC_SUBU;
14386 break;
14387 #if defined(TARGET_MIPS64)
14388 case RRR_DADDU:
14389 mips32_op = OPC_DADDU;
14390 check_insn(ctx, ISA_MIPS3);
14391 check_mips_64(ctx);
14392 break;
14393 case RRR_DSUBU:
14394 mips32_op = OPC_DSUBU;
14395 check_insn(ctx, ISA_MIPS3);
14396 check_mips_64(ctx);
14397 break;
14398 #endif
14399 default:
14400 gen_reserved_instruction(ctx);
14401 goto done;
14404 gen_arith(ctx, mips32_op, rz, rx, ry);
14405 done:
14408 break;
14409 case M16_OPC_RR:
14410 switch (op1) {
14411 case RR_JR:
14413 int nd = (ctx->opcode >> 7) & 0x1;
14414 int link = (ctx->opcode >> 6) & 0x1;
14415 int ra = (ctx->opcode >> 5) & 0x1;
14417 if (nd) {
14418 check_insn(ctx, ISA_MIPS_R1);
14421 if (link) {
14422 op = OPC_JALR;
14423 } else {
14424 op = OPC_JR;
14427 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
14428 (nd ? 0 : 2));
14430 break;
14431 case RR_SDBBP:
14432 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
14433 gen_helper_do_semihosting(cpu_env);
14434 } else {
14436 * XXX: not clear which exception should be raised
14437 * when in debug mode...
14439 check_insn(ctx, ISA_MIPS_R1);
14440 generate_exception_end(ctx, EXCP_DBp);
14442 break;
14443 case RR_SLT:
14444 gen_slt(ctx, OPC_SLT, 24, rx, ry);
14445 break;
14446 case RR_SLTU:
14447 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
14448 break;
14449 case RR_BREAK:
14450 generate_exception_end(ctx, EXCP_BREAK);
14451 break;
14452 case RR_SLLV:
14453 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
14454 break;
14455 case RR_SRLV:
14456 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
14457 break;
14458 case RR_SRAV:
14459 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
14460 break;
14461 #if defined(TARGET_MIPS64)
14462 case RR_DSRL:
14463 check_insn(ctx, ISA_MIPS3);
14464 check_mips_64(ctx);
14465 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
14466 break;
14467 #endif
14468 case RR_CMP:
14469 gen_logic(ctx, OPC_XOR, 24, rx, ry);
14470 break;
14471 case RR_NEG:
14472 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
14473 break;
14474 case RR_AND:
14475 gen_logic(ctx, OPC_AND, rx, rx, ry);
14476 break;
14477 case RR_OR:
14478 gen_logic(ctx, OPC_OR, rx, rx, ry);
14479 break;
14480 case RR_XOR:
14481 gen_logic(ctx, OPC_XOR, rx, rx, ry);
14482 break;
14483 case RR_NOT:
14484 gen_logic(ctx, OPC_NOR, rx, ry, 0);
14485 break;
14486 case RR_MFHI:
14487 gen_HILO(ctx, OPC_MFHI, 0, rx);
14488 break;
14489 case RR_CNVT:
14490 check_insn(ctx, ISA_MIPS_R1);
14491 switch (cnvt_op) {
14492 case RR_RY_CNVT_ZEB:
14493 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14494 break;
14495 case RR_RY_CNVT_ZEH:
14496 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14497 break;
14498 case RR_RY_CNVT_SEB:
14499 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14500 break;
14501 case RR_RY_CNVT_SEH:
14502 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14503 break;
14504 #if defined(TARGET_MIPS64)
14505 case RR_RY_CNVT_ZEW:
14506 check_insn(ctx, ISA_MIPS_R1);
14507 check_mips_64(ctx);
14508 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14509 break;
14510 case RR_RY_CNVT_SEW:
14511 check_insn(ctx, ISA_MIPS_R1);
14512 check_mips_64(ctx);
14513 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14514 break;
14515 #endif
14516 default:
14517 gen_reserved_instruction(ctx);
14518 break;
14520 break;
14521 case RR_MFLO:
14522 gen_HILO(ctx, OPC_MFLO, 0, rx);
14523 break;
14524 #if defined(TARGET_MIPS64)
14525 case RR_DSRA:
14526 check_insn(ctx, ISA_MIPS3);
14527 check_mips_64(ctx);
14528 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
14529 break;
14530 case RR_DSLLV:
14531 check_insn(ctx, ISA_MIPS3);
14532 check_mips_64(ctx);
14533 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
14534 break;
14535 case RR_DSRLV:
14536 check_insn(ctx, ISA_MIPS3);
14537 check_mips_64(ctx);
14538 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
14539 break;
14540 case RR_DSRAV:
14541 check_insn(ctx, ISA_MIPS3);
14542 check_mips_64(ctx);
14543 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
14544 break;
14545 #endif
14546 case RR_MULT:
14547 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
14548 break;
14549 case RR_MULTU:
14550 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
14551 break;
14552 case RR_DIV:
14553 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
14554 break;
14555 case RR_DIVU:
14556 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
14557 break;
14558 #if defined(TARGET_MIPS64)
14559 case RR_DMULT:
14560 check_insn(ctx, ISA_MIPS3);
14561 check_mips_64(ctx);
14562 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
14563 break;
14564 case RR_DMULTU:
14565 check_insn(ctx, ISA_MIPS3);
14566 check_mips_64(ctx);
14567 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
14568 break;
14569 case RR_DDIV:
14570 check_insn(ctx, ISA_MIPS3);
14571 check_mips_64(ctx);
14572 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
14573 break;
14574 case RR_DDIVU:
14575 check_insn(ctx, ISA_MIPS3);
14576 check_mips_64(ctx);
14577 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
14578 break;
14579 #endif
14580 default:
14581 gen_reserved_instruction(ctx);
14582 break;
14584 break;
14585 case M16_OPC_EXTEND:
14586 decode_extended_mips16_opc(env, ctx);
14587 n_bytes = 4;
14588 break;
14589 #if defined(TARGET_MIPS64)
14590 case M16_OPC_I64:
14591 funct = (ctx->opcode >> 8) & 0x7;
14592 decode_i64_mips16(ctx, ry, funct, offset, 0);
14593 break;
14594 #endif
14595 default:
14596 gen_reserved_instruction(ctx);
14597 break;
14600 return n_bytes;
14603 /* microMIPS extension to MIPS32/MIPS64 */
14606 * microMIPS32/microMIPS64 major opcodes
14608 * 1. MIPS Architecture for Programmers Volume II-B:
14609 * The microMIPS32 Instruction Set (Revision 3.05)
14611 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
14613 * 2. MIPS Architecture For Programmers Volume II-A:
14614 * The MIPS64 Instruction Set (Revision 3.51)
14617 enum {
14618 POOL32A = 0x00,
14619 POOL16A = 0x01,
14620 LBU16 = 0x02,
14621 MOVE16 = 0x03,
14622 ADDI32 = 0x04,
14623 R6_LUI = 0x04,
14624 AUI = 0x04,
14625 LBU32 = 0x05,
14626 SB32 = 0x06,
14627 LB32 = 0x07,
14629 POOL32B = 0x08,
14630 POOL16B = 0x09,
14631 LHU16 = 0x0a,
14632 ANDI16 = 0x0b,
14633 ADDIU32 = 0x0c,
14634 LHU32 = 0x0d,
14635 SH32 = 0x0e,
14636 LH32 = 0x0f,
14638 POOL32I = 0x10,
14639 POOL16C = 0x11,
14640 LWSP16 = 0x12,
14641 POOL16D = 0x13,
14642 ORI32 = 0x14,
14643 POOL32F = 0x15,
14644 POOL32S = 0x16, /* MIPS64 */
14645 DADDIU32 = 0x17, /* MIPS64 */
14647 POOL32C = 0x18,
14648 LWGP16 = 0x19,
14649 LW16 = 0x1a,
14650 POOL16E = 0x1b,
14651 XORI32 = 0x1c,
14652 JALS32 = 0x1d,
14653 BOVC = 0x1d,
14654 BEQC = 0x1d,
14655 BEQZALC = 0x1d,
14656 ADDIUPC = 0x1e,
14657 PCREL = 0x1e,
14658 BNVC = 0x1f,
14659 BNEC = 0x1f,
14660 BNEZALC = 0x1f,
14662 R6_BEQZC = 0x20,
14663 JIC = 0x20,
14664 POOL16F = 0x21,
14665 SB16 = 0x22,
14666 BEQZ16 = 0x23,
14667 BEQZC16 = 0x23,
14668 SLTI32 = 0x24,
14669 BEQ32 = 0x25,
14670 BC = 0x25,
14671 SWC132 = 0x26,
14672 LWC132 = 0x27,
14674 /* 0x29 is reserved */
14675 RES_29 = 0x29,
14676 R6_BNEZC = 0x28,
14677 JIALC = 0x28,
14678 SH16 = 0x2a,
14679 BNEZ16 = 0x2b,
14680 BNEZC16 = 0x2b,
14681 SLTIU32 = 0x2c,
14682 BNE32 = 0x2d,
14683 BALC = 0x2d,
14684 SDC132 = 0x2e,
14685 LDC132 = 0x2f,
14687 /* 0x31 is reserved */
14688 RES_31 = 0x31,
14689 BLEZALC = 0x30,
14690 BGEZALC = 0x30,
14691 BGEUC = 0x30,
14692 SWSP16 = 0x32,
14693 B16 = 0x33,
14694 BC16 = 0x33,
14695 ANDI32 = 0x34,
14696 J32 = 0x35,
14697 BGTZC = 0x35,
14698 BLTZC = 0x35,
14699 BLTC = 0x35,
14700 SD32 = 0x36, /* MIPS64 */
14701 LD32 = 0x37, /* MIPS64 */
14703 /* 0x39 is reserved */
14704 RES_39 = 0x39,
14705 BGTZALC = 0x38,
14706 BLTZALC = 0x38,
14707 BLTUC = 0x38,
14708 SW16 = 0x3a,
14709 LI16 = 0x3b,
14710 JALX32 = 0x3c,
14711 JAL32 = 0x3d,
14712 BLEZC = 0x3d,
14713 BGEZC = 0x3d,
14714 BGEC = 0x3d,
14715 SW32 = 0x3e,
14716 LW32 = 0x3f
14719 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
14720 enum {
14721 ADDIUPC_00 = 0x00,
14722 ADDIUPC_01 = 0x01,
14723 ADDIUPC_02 = 0x02,
14724 ADDIUPC_03 = 0x03,
14725 ADDIUPC_04 = 0x04,
14726 ADDIUPC_05 = 0x05,
14727 ADDIUPC_06 = 0x06,
14728 ADDIUPC_07 = 0x07,
14729 AUIPC = 0x1e,
14730 ALUIPC = 0x1f,
14731 LWPC_08 = 0x08,
14732 LWPC_09 = 0x09,
14733 LWPC_0A = 0x0A,
14734 LWPC_0B = 0x0B,
14735 LWPC_0C = 0x0C,
14736 LWPC_0D = 0x0D,
14737 LWPC_0E = 0x0E,
14738 LWPC_0F = 0x0F,
14741 /* POOL32A encoding of minor opcode field */
14743 enum {
14745 * These opcodes are distinguished only by bits 9..6; those bits are
14746 * what are recorded below.
14748 SLL32 = 0x0,
14749 SRL32 = 0x1,
14750 SRA = 0x2,
14751 ROTR = 0x3,
14752 SELEQZ = 0x5,
14753 SELNEZ = 0x6,
14754 R6_RDHWR = 0x7,
14756 SLLV = 0x0,
14757 SRLV = 0x1,
14758 SRAV = 0x2,
14759 ROTRV = 0x3,
14760 ADD = 0x4,
14761 ADDU32 = 0x5,
14762 SUB = 0x6,
14763 SUBU32 = 0x7,
14764 MUL = 0x8,
14765 AND = 0x9,
14766 OR32 = 0xa,
14767 NOR = 0xb,
14768 XOR32 = 0xc,
14769 SLT = 0xd,
14770 SLTU = 0xe,
14772 MOVN = 0x0,
14773 R6_MUL = 0x0,
14774 MOVZ = 0x1,
14775 MUH = 0x1,
14776 MULU = 0x2,
14777 MUHU = 0x3,
14778 LWXS = 0x4,
14779 R6_DIV = 0x4,
14780 MOD = 0x5,
14781 R6_DIVU = 0x6,
14782 MODU = 0x7,
14784 /* The following can be distinguished by their lower 6 bits. */
14785 BREAK32 = 0x07,
14786 INS = 0x0c,
14787 LSA = 0x0f,
14788 ALIGN = 0x1f,
14789 EXT = 0x2c,
14790 POOL32AXF = 0x3c,
14791 SIGRIE = 0x3f
14794 /* POOL32AXF encoding of minor opcode field extension */
14797 * 1. MIPS Architecture for Programmers Volume II-B:
14798 * The microMIPS32 Instruction Set (Revision 3.05)
14800 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
14802 * 2. MIPS Architecture for Programmers VolumeIV-e:
14803 * The MIPS DSP Application-Specific Extension
14804 * to the microMIPS32 Architecture (Revision 2.34)
14806 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
14809 enum {
14810 /* bits 11..6 */
14811 TEQ = 0x00,
14812 TGE = 0x08,
14813 TGEU = 0x10,
14814 TLT = 0x20,
14815 TLTU = 0x28,
14816 TNE = 0x30,
14818 MFC0 = 0x03,
14819 MTC0 = 0x0b,
14821 /* begin of microMIPS32 DSP */
14823 /* bits 13..12 for 0x01 */
14824 MFHI_ACC = 0x0,
14825 MFLO_ACC = 0x1,
14826 MTHI_ACC = 0x2,
14827 MTLO_ACC = 0x3,
14829 /* bits 13..12 for 0x2a */
14830 MADD_ACC = 0x0,
14831 MADDU_ACC = 0x1,
14832 MSUB_ACC = 0x2,
14833 MSUBU_ACC = 0x3,
14835 /* bits 13..12 for 0x32 */
14836 MULT_ACC = 0x0,
14837 MULTU_ACC = 0x1,
14839 /* end of microMIPS32 DSP */
14841 /* bits 15..12 for 0x2c */
14842 BITSWAP = 0x0,
14843 SEB = 0x2,
14844 SEH = 0x3,
14845 CLO = 0x4,
14846 CLZ = 0x5,
14847 RDHWR = 0x6,
14848 WSBH = 0x7,
14849 MULT = 0x8,
14850 MULTU = 0x9,
14851 DIV = 0xa,
14852 DIVU = 0xb,
14853 MADD = 0xc,
14854 MADDU = 0xd,
14855 MSUB = 0xe,
14856 MSUBU = 0xf,
14858 /* bits 15..12 for 0x34 */
14859 MFC2 = 0x4,
14860 MTC2 = 0x5,
14861 MFHC2 = 0x8,
14862 MTHC2 = 0x9,
14863 CFC2 = 0xc,
14864 CTC2 = 0xd,
14866 /* bits 15..12 for 0x3c */
14867 JALR = 0x0,
14868 JR = 0x0, /* alias */
14869 JALRC = 0x0,
14870 JRC = 0x0,
14871 JALR_HB = 0x1,
14872 JALRC_HB = 0x1,
14873 JALRS = 0x4,
14874 JALRS_HB = 0x5,
14876 /* bits 15..12 for 0x05 */
14877 RDPGPR = 0xe,
14878 WRPGPR = 0xf,
14880 /* bits 15..12 for 0x0d */
14881 TLBP = 0x0,
14882 TLBR = 0x1,
14883 TLBWI = 0x2,
14884 TLBWR = 0x3,
14885 TLBINV = 0x4,
14886 TLBINVF = 0x5,
14887 WAIT = 0x9,
14888 IRET = 0xd,
14889 DERET = 0xe,
14890 ERET = 0xf,
14892 /* bits 15..12 for 0x15 */
14893 DMT = 0x0,
14894 DVPE = 0x1,
14895 EMT = 0x2,
14896 EVPE = 0x3,
14898 /* bits 15..12 for 0x1d */
14899 DI = 0x4,
14900 EI = 0x5,
14902 /* bits 15..12 for 0x2d */
14903 SYNC = 0x6,
14904 SYSCALL = 0x8,
14905 SDBBP = 0xd,
14907 /* bits 15..12 for 0x35 */
14908 MFHI32 = 0x0,
14909 MFLO32 = 0x1,
14910 MTHI32 = 0x2,
14911 MTLO32 = 0x3,
14914 /* POOL32B encoding of minor opcode field (bits 15..12) */
14916 enum {
14917 LWC2 = 0x0,
14918 LWP = 0x1,
14919 LDP = 0x4,
14920 LWM32 = 0x5,
14921 CACHE = 0x6,
14922 LDM = 0x7,
14923 SWC2 = 0x8,
14924 SWP = 0x9,
14925 SDP = 0xc,
14926 SWM32 = 0xd,
14927 SDM = 0xf
14930 /* POOL32C encoding of minor opcode field (bits 15..12) */
14932 enum {
14933 LWL = 0x0,
14934 SWL = 0x8,
14935 LWR = 0x1,
14936 SWR = 0x9,
14937 PREF = 0x2,
14938 ST_EVA = 0xa,
14939 LL = 0x3,
14940 SC = 0xb,
14941 LDL = 0x4,
14942 SDL = 0xc,
14943 LDR = 0x5,
14944 SDR = 0xd,
14945 LD_EVA = 0x6,
14946 LWU = 0xe,
14947 LLD = 0x7,
14948 SCD = 0xf
14951 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
14953 enum {
14954 LBUE = 0x0,
14955 LHUE = 0x1,
14956 LWLE = 0x2,
14957 LWRE = 0x3,
14958 LBE = 0x4,
14959 LHE = 0x5,
14960 LLE = 0x6,
14961 LWE = 0x7,
14964 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
14966 enum {
14967 SWLE = 0x0,
14968 SWRE = 0x1,
14969 PREFE = 0x2,
14970 CACHEE = 0x3,
14971 SBE = 0x4,
14972 SHE = 0x5,
14973 SCE = 0x6,
14974 SWE = 0x7,
14977 /* POOL32F encoding of minor opcode field (bits 5..0) */
14979 enum {
14980 /* These are the bit 7..6 values */
14981 ADD_FMT = 0x0,
14983 SUB_FMT = 0x1,
14985 MUL_FMT = 0x2,
14987 DIV_FMT = 0x3,
14989 /* These are the bit 8..6 values */
14990 MOVN_FMT = 0x0,
14991 RSQRT2_FMT = 0x0,
14992 MOVF_FMT = 0x0,
14993 RINT_FMT = 0x0,
14994 SELNEZ_FMT = 0x0,
14996 MOVZ_FMT = 0x1,
14997 LWXC1 = 0x1,
14998 MOVT_FMT = 0x1,
14999 CLASS_FMT = 0x1,
15000 SELEQZ_FMT = 0x1,
15002 PLL_PS = 0x2,
15003 SWXC1 = 0x2,
15004 SEL_FMT = 0x2,
15006 PLU_PS = 0x3,
15007 LDXC1 = 0x3,
15009 MOVN_FMT_04 = 0x4,
15010 PUL_PS = 0x4,
15011 SDXC1 = 0x4,
15012 RECIP2_FMT = 0x4,
15014 MOVZ_FMT_05 = 0x05,
15015 PUU_PS = 0x5,
15016 LUXC1 = 0x5,
15018 CVT_PS_S = 0x6,
15019 SUXC1 = 0x6,
15020 ADDR_PS = 0x6,
15021 PREFX = 0x6,
15022 MADDF_FMT = 0x6,
15024 MULR_PS = 0x7,
15025 MSUBF_FMT = 0x7,
15027 MADD_S = 0x01,
15028 MADD_D = 0x09,
15029 MADD_PS = 0x11,
15030 ALNV_PS = 0x19,
15031 MSUB_S = 0x21,
15032 MSUB_D = 0x29,
15033 MSUB_PS = 0x31,
15035 NMADD_S = 0x02,
15036 NMADD_D = 0x0a,
15037 NMADD_PS = 0x12,
15038 NMSUB_S = 0x22,
15039 NMSUB_D = 0x2a,
15040 NMSUB_PS = 0x32,
15042 MIN_FMT = 0x3,
15043 MAX_FMT = 0xb,
15044 MINA_FMT = 0x23,
15045 MAXA_FMT = 0x2b,
15046 POOL32FXF = 0x3b,
15048 CABS_COND_FMT = 0x1c, /* MIPS3D */
15049 C_COND_FMT = 0x3c,
15051 CMP_CONDN_S = 0x5,
15052 CMP_CONDN_D = 0x15
15055 /* POOL32Fxf encoding of minor opcode extension field */
15057 enum {
15058 CVT_L = 0x04,
15059 RSQRT_FMT = 0x08,
15060 FLOOR_L = 0x0c,
15061 CVT_PW_PS = 0x1c,
15062 CVT_W = 0x24,
15063 SQRT_FMT = 0x28,
15064 FLOOR_W = 0x2c,
15065 CVT_PS_PW = 0x3c,
15066 CFC1 = 0x40,
15067 RECIP_FMT = 0x48,
15068 CEIL_L = 0x4c,
15069 CTC1 = 0x60,
15070 CEIL_W = 0x6c,
15071 MFC1 = 0x80,
15072 CVT_S_PL = 0x84,
15073 TRUNC_L = 0x8c,
15074 MTC1 = 0xa0,
15075 CVT_S_PU = 0xa4,
15076 TRUNC_W = 0xac,
15077 MFHC1 = 0xc0,
15078 ROUND_L = 0xcc,
15079 MTHC1 = 0xe0,
15080 ROUND_W = 0xec,
15082 MOV_FMT = 0x01,
15083 MOVF = 0x05,
15084 ABS_FMT = 0x0d,
15085 RSQRT1_FMT = 0x1d,
15086 MOVT = 0x25,
15087 NEG_FMT = 0x2d,
15088 CVT_D = 0x4d,
15089 RECIP1_FMT = 0x5d,
15090 CVT_S = 0x6d
15093 /* POOL32I encoding of minor opcode field (bits 25..21) */
15095 enum {
15096 BLTZ = 0x00,
15097 BLTZAL = 0x01,
15098 BGEZ = 0x02,
15099 BGEZAL = 0x03,
15100 BLEZ = 0x04,
15101 BNEZC = 0x05,
15102 BGTZ = 0x06,
15103 BEQZC = 0x07,
15104 TLTI = 0x08,
15105 BC1EQZC = 0x08,
15106 TGEI = 0x09,
15107 BC1NEZC = 0x09,
15108 TLTIU = 0x0a,
15109 BC2EQZC = 0x0a,
15110 TGEIU = 0x0b,
15111 BC2NEZC = 0x0a,
15112 TNEI = 0x0c,
15113 R6_SYNCI = 0x0c,
15114 LUI = 0x0d,
15115 TEQI = 0x0e,
15116 SYNCI = 0x10,
15117 BLTZALS = 0x11,
15118 BGEZALS = 0x13,
15119 BC2F = 0x14,
15120 BC2T = 0x15,
15121 BPOSGE64 = 0x1a,
15122 BPOSGE32 = 0x1b,
15123 /* These overlap and are distinguished by bit16 of the instruction */
15124 BC1F = 0x1c,
15125 BC1T = 0x1d,
15126 BC1ANY2F = 0x1c,
15127 BC1ANY2T = 0x1d,
15128 BC1ANY4F = 0x1e,
15129 BC1ANY4T = 0x1f
15132 /* POOL16A encoding of minor opcode field */
15134 enum {
15135 ADDU16 = 0x0,
15136 SUBU16 = 0x1
15139 /* POOL16B encoding of minor opcode field */
15141 enum {
15142 SLL16 = 0x0,
15143 SRL16 = 0x1
15146 /* POOL16C encoding of minor opcode field */
15148 enum {
15149 NOT16 = 0x00,
15150 XOR16 = 0x04,
15151 AND16 = 0x08,
15152 OR16 = 0x0c,
15153 LWM16 = 0x10,
15154 SWM16 = 0x14,
15155 JR16 = 0x18,
15156 JRC16 = 0x1a,
15157 JALR16 = 0x1c,
15158 JALR16S = 0x1e,
15159 MFHI16 = 0x20,
15160 MFLO16 = 0x24,
15161 BREAK16 = 0x28,
15162 SDBBP16 = 0x2c,
15163 JRADDIUSP = 0x30
15166 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
15168 enum {
15169 R6_NOT16 = 0x00,
15170 R6_AND16 = 0x01,
15171 R6_LWM16 = 0x02,
15172 R6_JRC16 = 0x03,
15173 MOVEP = 0x04,
15174 MOVEP_05 = 0x05,
15175 MOVEP_06 = 0x06,
15176 MOVEP_07 = 0x07,
15177 R6_XOR16 = 0x08,
15178 R6_OR16 = 0x09,
15179 R6_SWM16 = 0x0a,
15180 JALRC16 = 0x0b,
15181 MOVEP_0C = 0x0c,
15182 MOVEP_0D = 0x0d,
15183 MOVEP_0E = 0x0e,
15184 MOVEP_0F = 0x0f,
15185 JRCADDIUSP = 0x13,
15186 R6_BREAK16 = 0x1b,
15187 R6_SDBBP16 = 0x3b
15190 /* POOL16D encoding of minor opcode field */
15192 enum {
15193 ADDIUS5 = 0x0,
15194 ADDIUSP = 0x1
15197 /* POOL16E encoding of minor opcode field */
15199 enum {
15200 ADDIUR2 = 0x0,
15201 ADDIUR1SP = 0x1
15204 static int mmreg(int r)
15206 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
15208 return map[r];
15211 /* Used for 16-bit store instructions. */
15212 static int mmreg2(int r)
15214 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
15216 return map[r];
15219 #define uMIPS_RD(op) ((op >> 7) & 0x7)
15220 #define uMIPS_RS(op) ((op >> 4) & 0x7)
15221 #define uMIPS_RS2(op) uMIPS_RS(op)
15222 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
15223 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
15224 #define uMIPS_RS5(op) (op & 0x1f)
15226 /* Signed immediate */
15227 #define SIMM(op, start, width) \
15228 ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \
15229 << (32 - width)) \
15230 >> (32 - width))
15231 /* Zero-extended immediate */
15232 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width)))
15234 static void gen_addiur1sp(DisasContext *ctx)
15236 int rd = mmreg(uMIPS_RD(ctx->opcode));
15238 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
15241 static void gen_addiur2(DisasContext *ctx)
15243 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
15244 int rd = mmreg(uMIPS_RD(ctx->opcode));
15245 int rs = mmreg(uMIPS_RS(ctx->opcode));
15247 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
15250 static void gen_addiusp(DisasContext *ctx)
15252 int encoded = ZIMM(ctx->opcode, 1, 9);
15253 int decoded;
15255 if (encoded <= 1) {
15256 decoded = 256 + encoded;
15257 } else if (encoded <= 255) {
15258 decoded = encoded;
15259 } else if (encoded <= 509) {
15260 decoded = encoded - 512;
15261 } else {
15262 decoded = encoded - 768;
15265 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
15268 static void gen_addius5(DisasContext *ctx)
15270 int imm = SIMM(ctx->opcode, 1, 4);
15271 int rd = (ctx->opcode >> 5) & 0x1f;
15273 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
15276 static void gen_andi16(DisasContext *ctx)
15278 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
15279 31, 32, 63, 64, 255, 32768, 65535 };
15280 int rd = mmreg(uMIPS_RD(ctx->opcode));
15281 int rs = mmreg(uMIPS_RS(ctx->opcode));
15282 int encoded = ZIMM(ctx->opcode, 0, 4);
15284 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
15287 static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist,
15288 int base, int16_t offset)
15290 TCGv t0, t1;
15291 TCGv_i32 t2;
15293 if (ctx->hflags & MIPS_HFLAG_BMASK) {
15294 gen_reserved_instruction(ctx);
15295 return;
15298 t0 = tcg_temp_new();
15300 gen_base_offset_addr(ctx, t0, base, offset);
15302 t1 = tcg_const_tl(reglist);
15303 t2 = tcg_const_i32(ctx->mem_idx);
15305 save_cpu_state(ctx, 1);
15306 switch (opc) {
15307 case LWM32:
15308 gen_helper_lwm(cpu_env, t0, t1, t2);
15309 break;
15310 case SWM32:
15311 gen_helper_swm(cpu_env, t0, t1, t2);
15312 break;
15313 #ifdef TARGET_MIPS64
15314 case LDM:
15315 gen_helper_ldm(cpu_env, t0, t1, t2);
15316 break;
15317 case SDM:
15318 gen_helper_sdm(cpu_env, t0, t1, t2);
15319 break;
15320 #endif
15322 tcg_temp_free(t0);
15323 tcg_temp_free(t1);
15324 tcg_temp_free_i32(t2);
15328 static void gen_pool16c_insn(DisasContext *ctx)
15330 int rd = mmreg((ctx->opcode >> 3) & 0x7);
15331 int rs = mmreg(ctx->opcode & 0x7);
15333 switch (((ctx->opcode) >> 4) & 0x3f) {
15334 case NOT16 + 0:
15335 case NOT16 + 1:
15336 case NOT16 + 2:
15337 case NOT16 + 3:
15338 gen_logic(ctx, OPC_NOR, rd, rs, 0);
15339 break;
15340 case XOR16 + 0:
15341 case XOR16 + 1:
15342 case XOR16 + 2:
15343 case XOR16 + 3:
15344 gen_logic(ctx, OPC_XOR, rd, rd, rs);
15345 break;
15346 case AND16 + 0:
15347 case AND16 + 1:
15348 case AND16 + 2:
15349 case AND16 + 3:
15350 gen_logic(ctx, OPC_AND, rd, rd, rs);
15351 break;
15352 case OR16 + 0:
15353 case OR16 + 1:
15354 case OR16 + 2:
15355 case OR16 + 3:
15356 gen_logic(ctx, OPC_OR, rd, rd, rs);
15357 break;
15358 case LWM16 + 0:
15359 case LWM16 + 1:
15360 case LWM16 + 2:
15361 case LWM16 + 3:
15363 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15364 int offset = ZIMM(ctx->opcode, 0, 4);
15366 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
15367 29, offset << 2);
15369 break;
15370 case SWM16 + 0:
15371 case SWM16 + 1:
15372 case SWM16 + 2:
15373 case SWM16 + 3:
15375 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15376 int offset = ZIMM(ctx->opcode, 0, 4);
15378 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
15379 29, offset << 2);
15381 break;
15382 case JR16 + 0:
15383 case JR16 + 1:
15385 int reg = ctx->opcode & 0x1f;
15387 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
15389 break;
15390 case JRC16 + 0:
15391 case JRC16 + 1:
15393 int reg = ctx->opcode & 0x1f;
15394 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
15396 * Let normal delay slot handling in our caller take us
15397 * to the branch target.
15400 break;
15401 case JALR16 + 0:
15402 case JALR16 + 1:
15403 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
15404 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15405 break;
15406 case JALR16S + 0:
15407 case JALR16S + 1:
15408 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
15409 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15410 break;
15411 case MFHI16 + 0:
15412 case MFHI16 + 1:
15413 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
15414 break;
15415 case MFLO16 + 0:
15416 case MFLO16 + 1:
15417 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
15418 break;
15419 case BREAK16:
15420 generate_exception_end(ctx, EXCP_BREAK);
15421 break;
15422 case SDBBP16:
15423 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
15424 gen_helper_do_semihosting(cpu_env);
15425 } else {
15427 * XXX: not clear which exception should be raised
15428 * when in debug mode...
15430 check_insn(ctx, ISA_MIPS_R1);
15431 generate_exception_end(ctx, EXCP_DBp);
15433 break;
15434 case JRADDIUSP + 0:
15435 case JRADDIUSP + 1:
15437 int imm = ZIMM(ctx->opcode, 0, 5);
15438 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15439 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15441 * Let normal delay slot handling in our caller take us
15442 * to the branch target.
15445 break;
15446 default:
15447 gen_reserved_instruction(ctx);
15448 break;
15452 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
15453 int enc_rs)
15455 int rd, rs, re, rt;
15456 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
15457 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
15458 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
15459 rd = rd_enc[enc_dest];
15460 re = re_enc[enc_dest];
15461 rs = rs_rt_enc[enc_rs];
15462 rt = rs_rt_enc[enc_rt];
15463 if (rs) {
15464 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
15465 } else {
15466 tcg_gen_movi_tl(cpu_gpr[rd], 0);
15468 if (rt) {
15469 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
15470 } else {
15471 tcg_gen_movi_tl(cpu_gpr[re], 0);
15475 static void gen_pool16c_r6_insn(DisasContext *ctx)
15477 int rt = mmreg((ctx->opcode >> 7) & 0x7);
15478 int rs = mmreg((ctx->opcode >> 4) & 0x7);
15480 switch (ctx->opcode & 0xf) {
15481 case R6_NOT16:
15482 gen_logic(ctx, OPC_NOR, rt, rs, 0);
15483 break;
15484 case R6_AND16:
15485 gen_logic(ctx, OPC_AND, rt, rt, rs);
15486 break;
15487 case R6_LWM16:
15489 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15490 int offset = extract32(ctx->opcode, 4, 4);
15491 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
15493 break;
15494 case R6_JRC16: /* JRCADDIUSP */
15495 if ((ctx->opcode >> 4) & 1) {
15496 /* JRCADDIUSP */
15497 int imm = extract32(ctx->opcode, 5, 5);
15498 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15499 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15500 } else {
15501 /* JRC16 */
15502 rs = extract32(ctx->opcode, 5, 5);
15503 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
15505 break;
15506 case MOVEP:
15507 case MOVEP_05:
15508 case MOVEP_06:
15509 case MOVEP_07:
15510 case MOVEP_0C:
15511 case MOVEP_0D:
15512 case MOVEP_0E:
15513 case MOVEP_0F:
15515 int enc_dest = uMIPS_RD(ctx->opcode);
15516 int enc_rt = uMIPS_RS2(ctx->opcode);
15517 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
15518 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15520 break;
15521 case R6_XOR16:
15522 gen_logic(ctx, OPC_XOR, rt, rt, rs);
15523 break;
15524 case R6_OR16:
15525 gen_logic(ctx, OPC_OR, rt, rt, rs);
15526 break;
15527 case R6_SWM16:
15529 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15530 int offset = extract32(ctx->opcode, 4, 4);
15531 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
15533 break;
15534 case JALRC16: /* BREAK16, SDBBP16 */
15535 switch (ctx->opcode & 0x3f) {
15536 case JALRC16:
15537 case JALRC16 + 0x20:
15538 /* JALRC16 */
15539 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
15540 31, 0, 0);
15541 break;
15542 case R6_BREAK16:
15543 /* BREAK16 */
15544 generate_exception(ctx, EXCP_BREAK);
15545 break;
15546 case R6_SDBBP16:
15547 /* SDBBP16 */
15548 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
15549 gen_helper_do_semihosting(cpu_env);
15550 } else {
15551 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15552 generate_exception(ctx, EXCP_RI);
15553 } else {
15554 generate_exception(ctx, EXCP_DBp);
15557 break;
15559 break;
15560 default:
15561 generate_exception(ctx, EXCP_RI);
15562 break;
15566 static void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
15568 TCGv t0 = tcg_temp_new();
15569 TCGv t1 = tcg_temp_new();
15571 gen_load_gpr(t0, base);
15573 if (index != 0) {
15574 gen_load_gpr(t1, index);
15575 tcg_gen_shli_tl(t1, t1, 2);
15576 gen_op_addr_add(ctx, t0, t1, t0);
15579 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15580 gen_store_gpr(t1, rd);
15582 tcg_temp_free(t0);
15583 tcg_temp_free(t1);
15586 static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd,
15587 int base, int16_t offset)
15589 TCGv t0, t1;
15591 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
15592 gen_reserved_instruction(ctx);
15593 return;
15596 t0 = tcg_temp_new();
15597 t1 = tcg_temp_new();
15599 gen_base_offset_addr(ctx, t0, base, offset);
15601 switch (opc) {
15602 case LWP:
15603 if (rd == base) {
15604 gen_reserved_instruction(ctx);
15605 return;
15607 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15608 gen_store_gpr(t1, rd);
15609 tcg_gen_movi_tl(t1, 4);
15610 gen_op_addr_add(ctx, t0, t0, t1);
15611 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15612 gen_store_gpr(t1, rd + 1);
15613 break;
15614 case SWP:
15615 gen_load_gpr(t1, rd);
15616 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15617 tcg_gen_movi_tl(t1, 4);
15618 gen_op_addr_add(ctx, t0, t0, t1);
15619 gen_load_gpr(t1, rd + 1);
15620 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15621 break;
15622 #ifdef TARGET_MIPS64
15623 case LDP:
15624 if (rd == base) {
15625 gen_reserved_instruction(ctx);
15626 return;
15628 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15629 gen_store_gpr(t1, rd);
15630 tcg_gen_movi_tl(t1, 8);
15631 gen_op_addr_add(ctx, t0, t0, t1);
15632 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15633 gen_store_gpr(t1, rd + 1);
15634 break;
15635 case SDP:
15636 gen_load_gpr(t1, rd);
15637 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15638 tcg_gen_movi_tl(t1, 8);
15639 gen_op_addr_add(ctx, t0, t0, t1);
15640 gen_load_gpr(t1, rd + 1);
15641 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15642 break;
15643 #endif
15645 tcg_temp_free(t0);
15646 tcg_temp_free(t1);
15649 static void gen_sync(int stype)
15651 TCGBar tcg_mo = TCG_BAR_SC;
15653 switch (stype) {
15654 case 0x4: /* SYNC_WMB */
15655 tcg_mo |= TCG_MO_ST_ST;
15656 break;
15657 case 0x10: /* SYNC_MB */
15658 tcg_mo |= TCG_MO_ALL;
15659 break;
15660 case 0x11: /* SYNC_ACQUIRE */
15661 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
15662 break;
15663 case 0x12: /* SYNC_RELEASE */
15664 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
15665 break;
15666 case 0x13: /* SYNC_RMB */
15667 tcg_mo |= TCG_MO_LD_LD;
15668 break;
15669 default:
15670 tcg_mo |= TCG_MO_ALL;
15671 break;
15674 tcg_gen_mb(tcg_mo);
15677 static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
15679 int extension = (ctx->opcode >> 6) & 0x3f;
15680 int minor = (ctx->opcode >> 12) & 0xf;
15681 uint32_t mips32_op;
15683 switch (extension) {
15684 case TEQ:
15685 mips32_op = OPC_TEQ;
15686 goto do_trap;
15687 case TGE:
15688 mips32_op = OPC_TGE;
15689 goto do_trap;
15690 case TGEU:
15691 mips32_op = OPC_TGEU;
15692 goto do_trap;
15693 case TLT:
15694 mips32_op = OPC_TLT;
15695 goto do_trap;
15696 case TLTU:
15697 mips32_op = OPC_TLTU;
15698 goto do_trap;
15699 case TNE:
15700 mips32_op = OPC_TNE;
15701 do_trap:
15702 gen_trap(ctx, mips32_op, rs, rt, -1);
15703 break;
15704 #ifndef CONFIG_USER_ONLY
15705 case MFC0:
15706 case MFC0 + 32:
15707 check_cp0_enabled(ctx);
15708 if (rt == 0) {
15709 /* Treat as NOP. */
15710 break;
15712 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
15713 break;
15714 case MTC0:
15715 case MTC0 + 32:
15716 check_cp0_enabled(ctx);
15718 TCGv t0 = tcg_temp_new();
15720 gen_load_gpr(t0, rt);
15721 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
15722 tcg_temp_free(t0);
15724 break;
15725 #endif
15726 case 0x2a:
15727 switch (minor & 3) {
15728 case MADD_ACC:
15729 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
15730 break;
15731 case MADDU_ACC:
15732 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
15733 break;
15734 case MSUB_ACC:
15735 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
15736 break;
15737 case MSUBU_ACC:
15738 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
15739 break;
15740 default:
15741 goto pool32axf_invalid;
15743 break;
15744 case 0x32:
15745 switch (minor & 3) {
15746 case MULT_ACC:
15747 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
15748 break;
15749 case MULTU_ACC:
15750 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
15751 break;
15752 default:
15753 goto pool32axf_invalid;
15755 break;
15756 case 0x2c:
15757 switch (minor) {
15758 case BITSWAP:
15759 check_insn(ctx, ISA_MIPS_R6);
15760 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
15761 break;
15762 case SEB:
15763 gen_bshfl(ctx, OPC_SEB, rs, rt);
15764 break;
15765 case SEH:
15766 gen_bshfl(ctx, OPC_SEH, rs, rt);
15767 break;
15768 case CLO:
15769 mips32_op = OPC_CLO;
15770 goto do_cl;
15771 case CLZ:
15772 mips32_op = OPC_CLZ;
15773 do_cl:
15774 check_insn(ctx, ISA_MIPS_R1);
15775 gen_cl(ctx, mips32_op, rt, rs);
15776 break;
15777 case RDHWR:
15778 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15779 gen_rdhwr(ctx, rt, rs, 0);
15780 break;
15781 case WSBH:
15782 gen_bshfl(ctx, OPC_WSBH, rs, rt);
15783 break;
15784 case MULT:
15785 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15786 mips32_op = OPC_MULT;
15787 goto do_mul;
15788 case MULTU:
15789 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15790 mips32_op = OPC_MULTU;
15791 goto do_mul;
15792 case DIV:
15793 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15794 mips32_op = OPC_DIV;
15795 goto do_div;
15796 case DIVU:
15797 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15798 mips32_op = OPC_DIVU;
15799 goto do_div;
15800 do_div:
15801 check_insn(ctx, ISA_MIPS_R1);
15802 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15803 break;
15804 case MADD:
15805 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15806 mips32_op = OPC_MADD;
15807 goto do_mul;
15808 case MADDU:
15809 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15810 mips32_op = OPC_MADDU;
15811 goto do_mul;
15812 case MSUB:
15813 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15814 mips32_op = OPC_MSUB;
15815 goto do_mul;
15816 case MSUBU:
15817 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15818 mips32_op = OPC_MSUBU;
15819 do_mul:
15820 check_insn(ctx, ISA_MIPS_R1);
15821 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15822 break;
15823 default:
15824 goto pool32axf_invalid;
15826 break;
15827 case 0x34:
15828 switch (minor) {
15829 case MFC2:
15830 case MTC2:
15831 case MFHC2:
15832 case MTHC2:
15833 case CFC2:
15834 case CTC2:
15835 generate_exception_err(ctx, EXCP_CpU, 2);
15836 break;
15837 default:
15838 goto pool32axf_invalid;
15840 break;
15841 case 0x3c:
15842 switch (minor) {
15843 case JALR: /* JALRC */
15844 case JALR_HB: /* JALRC_HB */
15845 if (ctx->insn_flags & ISA_MIPS_R6) {
15846 /* JALRC, JALRC_HB */
15847 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
15848 } else {
15849 /* JALR, JALR_HB */
15850 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
15851 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15853 break;
15854 case JALRS:
15855 case JALRS_HB:
15856 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15857 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
15858 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15859 break;
15860 default:
15861 goto pool32axf_invalid;
15863 break;
15864 case 0x05:
15865 switch (minor) {
15866 case RDPGPR:
15867 check_cp0_enabled(ctx);
15868 check_insn(ctx, ISA_MIPS_R2);
15869 gen_load_srsgpr(rs, rt);
15870 break;
15871 case WRPGPR:
15872 check_cp0_enabled(ctx);
15873 check_insn(ctx, ISA_MIPS_R2);
15874 gen_store_srsgpr(rs, rt);
15875 break;
15876 default:
15877 goto pool32axf_invalid;
15879 break;
15880 #ifndef CONFIG_USER_ONLY
15881 case 0x0d:
15882 switch (minor) {
15883 case TLBP:
15884 mips32_op = OPC_TLBP;
15885 goto do_cp0;
15886 case TLBR:
15887 mips32_op = OPC_TLBR;
15888 goto do_cp0;
15889 case TLBWI:
15890 mips32_op = OPC_TLBWI;
15891 goto do_cp0;
15892 case TLBWR:
15893 mips32_op = OPC_TLBWR;
15894 goto do_cp0;
15895 case TLBINV:
15896 mips32_op = OPC_TLBINV;
15897 goto do_cp0;
15898 case TLBINVF:
15899 mips32_op = OPC_TLBINVF;
15900 goto do_cp0;
15901 case WAIT:
15902 mips32_op = OPC_WAIT;
15903 goto do_cp0;
15904 case DERET:
15905 mips32_op = OPC_DERET;
15906 goto do_cp0;
15907 case ERET:
15908 mips32_op = OPC_ERET;
15909 do_cp0:
15910 gen_cp0(env, ctx, mips32_op, rt, rs);
15911 break;
15912 default:
15913 goto pool32axf_invalid;
15915 break;
15916 case 0x1d:
15917 switch (minor) {
15918 case DI:
15919 check_cp0_enabled(ctx);
15921 TCGv t0 = tcg_temp_new();
15923 save_cpu_state(ctx, 1);
15924 gen_helper_di(t0, cpu_env);
15925 gen_store_gpr(t0, rs);
15927 * Stop translation as we may have switched the execution
15928 * mode.
15930 ctx->base.is_jmp = DISAS_STOP;
15931 tcg_temp_free(t0);
15933 break;
15934 case EI:
15935 check_cp0_enabled(ctx);
15937 TCGv t0 = tcg_temp_new();
15939 save_cpu_state(ctx, 1);
15940 gen_helper_ei(t0, cpu_env);
15941 gen_store_gpr(t0, rs);
15943 * DISAS_STOP isn't sufficient, we need to ensure we break out
15944 * of translated code to check for pending interrupts.
15946 gen_save_pc(ctx->base.pc_next + 4);
15947 ctx->base.is_jmp = DISAS_EXIT;
15948 tcg_temp_free(t0);
15950 break;
15951 default:
15952 goto pool32axf_invalid;
15954 break;
15955 #endif
15956 case 0x2d:
15957 switch (minor) {
15958 case SYNC:
15959 gen_sync(extract32(ctx->opcode, 16, 5));
15960 break;
15961 case SYSCALL:
15962 generate_exception_end(ctx, EXCP_SYSCALL);
15963 break;
15964 case SDBBP:
15965 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
15966 gen_helper_do_semihosting(cpu_env);
15967 } else {
15968 check_insn(ctx, ISA_MIPS_R1);
15969 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15970 gen_reserved_instruction(ctx);
15971 } else {
15972 generate_exception_end(ctx, EXCP_DBp);
15975 break;
15976 default:
15977 goto pool32axf_invalid;
15979 break;
15980 case 0x01:
15981 switch (minor & 3) {
15982 case MFHI_ACC:
15983 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
15984 break;
15985 case MFLO_ACC:
15986 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
15987 break;
15988 case MTHI_ACC:
15989 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
15990 break;
15991 case MTLO_ACC:
15992 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
15993 break;
15994 default:
15995 goto pool32axf_invalid;
15997 break;
15998 case 0x35:
15999 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16000 switch (minor) {
16001 case MFHI32:
16002 gen_HILO(ctx, OPC_MFHI, 0, rs);
16003 break;
16004 case MFLO32:
16005 gen_HILO(ctx, OPC_MFLO, 0, rs);
16006 break;
16007 case MTHI32:
16008 gen_HILO(ctx, OPC_MTHI, 0, rs);
16009 break;
16010 case MTLO32:
16011 gen_HILO(ctx, OPC_MTLO, 0, rs);
16012 break;
16013 default:
16014 goto pool32axf_invalid;
16016 break;
16017 default:
16018 pool32axf_invalid:
16019 MIPS_INVAL("pool32axf");
16020 gen_reserved_instruction(ctx);
16021 break;
16026 * Values for microMIPS fmt field. Variable-width, depending on which
16027 * formats the instruction supports.
16029 enum {
16030 FMT_SD_S = 0,
16031 FMT_SD_D = 1,
16033 FMT_SDPS_S = 0,
16034 FMT_SDPS_D = 1,
16035 FMT_SDPS_PS = 2,
16037 FMT_SWL_S = 0,
16038 FMT_SWL_W = 1,
16039 FMT_SWL_L = 2,
16041 FMT_DWL_D = 0,
16042 FMT_DWL_W = 1,
16043 FMT_DWL_L = 2
16046 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
16048 int extension = (ctx->opcode >> 6) & 0x3ff;
16049 uint32_t mips32_op;
16051 #define FLOAT_1BIT_FMT(opc, fmt) ((fmt << 8) | opc)
16052 #define FLOAT_2BIT_FMT(opc, fmt) ((fmt << 7) | opc)
16053 #define COND_FLOAT_MOV(opc, cond) ((cond << 7) | opc)
16055 switch (extension) {
16056 case FLOAT_1BIT_FMT(CFC1, 0):
16057 mips32_op = OPC_CFC1;
16058 goto do_cp1;
16059 case FLOAT_1BIT_FMT(CTC1, 0):
16060 mips32_op = OPC_CTC1;
16061 goto do_cp1;
16062 case FLOAT_1BIT_FMT(MFC1, 0):
16063 mips32_op = OPC_MFC1;
16064 goto do_cp1;
16065 case FLOAT_1BIT_FMT(MTC1, 0):
16066 mips32_op = OPC_MTC1;
16067 goto do_cp1;
16068 case FLOAT_1BIT_FMT(MFHC1, 0):
16069 mips32_op = OPC_MFHC1;
16070 goto do_cp1;
16071 case FLOAT_1BIT_FMT(MTHC1, 0):
16072 mips32_op = OPC_MTHC1;
16073 do_cp1:
16074 gen_cp1(ctx, mips32_op, rt, rs);
16075 break;
16077 /* Reciprocal square root */
16078 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
16079 mips32_op = OPC_RSQRT_S;
16080 goto do_unaryfp;
16081 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
16082 mips32_op = OPC_RSQRT_D;
16083 goto do_unaryfp;
16085 /* Square root */
16086 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
16087 mips32_op = OPC_SQRT_S;
16088 goto do_unaryfp;
16089 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
16090 mips32_op = OPC_SQRT_D;
16091 goto do_unaryfp;
16093 /* Reciprocal */
16094 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
16095 mips32_op = OPC_RECIP_S;
16096 goto do_unaryfp;
16097 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
16098 mips32_op = OPC_RECIP_D;
16099 goto do_unaryfp;
16101 /* Floor */
16102 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
16103 mips32_op = OPC_FLOOR_L_S;
16104 goto do_unaryfp;
16105 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
16106 mips32_op = OPC_FLOOR_L_D;
16107 goto do_unaryfp;
16108 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
16109 mips32_op = OPC_FLOOR_W_S;
16110 goto do_unaryfp;
16111 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
16112 mips32_op = OPC_FLOOR_W_D;
16113 goto do_unaryfp;
16115 /* Ceiling */
16116 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
16117 mips32_op = OPC_CEIL_L_S;
16118 goto do_unaryfp;
16119 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
16120 mips32_op = OPC_CEIL_L_D;
16121 goto do_unaryfp;
16122 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
16123 mips32_op = OPC_CEIL_W_S;
16124 goto do_unaryfp;
16125 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
16126 mips32_op = OPC_CEIL_W_D;
16127 goto do_unaryfp;
16129 /* Truncation */
16130 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
16131 mips32_op = OPC_TRUNC_L_S;
16132 goto do_unaryfp;
16133 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
16134 mips32_op = OPC_TRUNC_L_D;
16135 goto do_unaryfp;
16136 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
16137 mips32_op = OPC_TRUNC_W_S;
16138 goto do_unaryfp;
16139 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
16140 mips32_op = OPC_TRUNC_W_D;
16141 goto do_unaryfp;
16143 /* Round */
16144 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
16145 mips32_op = OPC_ROUND_L_S;
16146 goto do_unaryfp;
16147 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
16148 mips32_op = OPC_ROUND_L_D;
16149 goto do_unaryfp;
16150 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
16151 mips32_op = OPC_ROUND_W_S;
16152 goto do_unaryfp;
16153 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
16154 mips32_op = OPC_ROUND_W_D;
16155 goto do_unaryfp;
16157 /* Integer to floating-point conversion */
16158 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
16159 mips32_op = OPC_CVT_L_S;
16160 goto do_unaryfp;
16161 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
16162 mips32_op = OPC_CVT_L_D;
16163 goto do_unaryfp;
16164 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
16165 mips32_op = OPC_CVT_W_S;
16166 goto do_unaryfp;
16167 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
16168 mips32_op = OPC_CVT_W_D;
16169 goto do_unaryfp;
16171 /* Paired-foo conversions */
16172 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
16173 mips32_op = OPC_CVT_S_PL;
16174 goto do_unaryfp;
16175 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
16176 mips32_op = OPC_CVT_S_PU;
16177 goto do_unaryfp;
16178 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
16179 mips32_op = OPC_CVT_PW_PS;
16180 goto do_unaryfp;
16181 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
16182 mips32_op = OPC_CVT_PS_PW;
16183 goto do_unaryfp;
16185 /* Floating-point moves */
16186 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
16187 mips32_op = OPC_MOV_S;
16188 goto do_unaryfp;
16189 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
16190 mips32_op = OPC_MOV_D;
16191 goto do_unaryfp;
16192 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
16193 mips32_op = OPC_MOV_PS;
16194 goto do_unaryfp;
16196 /* Absolute value */
16197 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
16198 mips32_op = OPC_ABS_S;
16199 goto do_unaryfp;
16200 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
16201 mips32_op = OPC_ABS_D;
16202 goto do_unaryfp;
16203 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
16204 mips32_op = OPC_ABS_PS;
16205 goto do_unaryfp;
16207 /* Negation */
16208 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
16209 mips32_op = OPC_NEG_S;
16210 goto do_unaryfp;
16211 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
16212 mips32_op = OPC_NEG_D;
16213 goto do_unaryfp;
16214 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
16215 mips32_op = OPC_NEG_PS;
16216 goto do_unaryfp;
16218 /* Reciprocal square root step */
16219 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
16220 mips32_op = OPC_RSQRT1_S;
16221 goto do_unaryfp;
16222 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
16223 mips32_op = OPC_RSQRT1_D;
16224 goto do_unaryfp;
16225 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
16226 mips32_op = OPC_RSQRT1_PS;
16227 goto do_unaryfp;
16229 /* Reciprocal step */
16230 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
16231 mips32_op = OPC_RECIP1_S;
16232 goto do_unaryfp;
16233 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
16234 mips32_op = OPC_RECIP1_S;
16235 goto do_unaryfp;
16236 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
16237 mips32_op = OPC_RECIP1_PS;
16238 goto do_unaryfp;
16240 /* Conversions from double */
16241 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
16242 mips32_op = OPC_CVT_D_S;
16243 goto do_unaryfp;
16244 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
16245 mips32_op = OPC_CVT_D_W;
16246 goto do_unaryfp;
16247 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
16248 mips32_op = OPC_CVT_D_L;
16249 goto do_unaryfp;
16251 /* Conversions from single */
16252 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
16253 mips32_op = OPC_CVT_S_D;
16254 goto do_unaryfp;
16255 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
16256 mips32_op = OPC_CVT_S_W;
16257 goto do_unaryfp;
16258 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
16259 mips32_op = OPC_CVT_S_L;
16260 do_unaryfp:
16261 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
16262 break;
16264 /* Conditional moves on floating-point codes */
16265 case COND_FLOAT_MOV(MOVT, 0):
16266 case COND_FLOAT_MOV(MOVT, 1):
16267 case COND_FLOAT_MOV(MOVT, 2):
16268 case COND_FLOAT_MOV(MOVT, 3):
16269 case COND_FLOAT_MOV(MOVT, 4):
16270 case COND_FLOAT_MOV(MOVT, 5):
16271 case COND_FLOAT_MOV(MOVT, 6):
16272 case COND_FLOAT_MOV(MOVT, 7):
16273 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16274 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
16275 break;
16276 case COND_FLOAT_MOV(MOVF, 0):
16277 case COND_FLOAT_MOV(MOVF, 1):
16278 case COND_FLOAT_MOV(MOVF, 2):
16279 case COND_FLOAT_MOV(MOVF, 3):
16280 case COND_FLOAT_MOV(MOVF, 4):
16281 case COND_FLOAT_MOV(MOVF, 5):
16282 case COND_FLOAT_MOV(MOVF, 6):
16283 case COND_FLOAT_MOV(MOVF, 7):
16284 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16285 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
16286 break;
16287 default:
16288 MIPS_INVAL("pool32fxf");
16289 gen_reserved_instruction(ctx);
16290 break;
16294 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
16296 int32_t offset;
16297 uint16_t insn;
16298 int rt, rs, rd, rr;
16299 int16_t imm;
16300 uint32_t op, minor, minor2, mips32_op;
16301 uint32_t cond, fmt, cc;
16303 insn = translator_lduw(env, ctx->base.pc_next + 2);
16304 ctx->opcode = (ctx->opcode << 16) | insn;
16306 rt = (ctx->opcode >> 21) & 0x1f;
16307 rs = (ctx->opcode >> 16) & 0x1f;
16308 rd = (ctx->opcode >> 11) & 0x1f;
16309 rr = (ctx->opcode >> 6) & 0x1f;
16310 imm = (int16_t) ctx->opcode;
16312 op = (ctx->opcode >> 26) & 0x3f;
16313 switch (op) {
16314 case POOL32A:
16315 minor = ctx->opcode & 0x3f;
16316 switch (minor) {
16317 case 0x00:
16318 minor = (ctx->opcode >> 6) & 0xf;
16319 switch (minor) {
16320 case SLL32:
16321 mips32_op = OPC_SLL;
16322 goto do_shifti;
16323 case SRA:
16324 mips32_op = OPC_SRA;
16325 goto do_shifti;
16326 case SRL32:
16327 mips32_op = OPC_SRL;
16328 goto do_shifti;
16329 case ROTR:
16330 mips32_op = OPC_ROTR;
16331 do_shifti:
16332 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
16333 break;
16334 case SELEQZ:
16335 check_insn(ctx, ISA_MIPS_R6);
16336 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
16337 break;
16338 case SELNEZ:
16339 check_insn(ctx, ISA_MIPS_R6);
16340 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
16341 break;
16342 case R6_RDHWR:
16343 check_insn(ctx, ISA_MIPS_R6);
16344 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
16345 break;
16346 default:
16347 goto pool32a_invalid;
16349 break;
16350 case 0x10:
16351 minor = (ctx->opcode >> 6) & 0xf;
16352 switch (minor) {
16353 /* Arithmetic */
16354 case ADD:
16355 mips32_op = OPC_ADD;
16356 goto do_arith;
16357 case ADDU32:
16358 mips32_op = OPC_ADDU;
16359 goto do_arith;
16360 case SUB:
16361 mips32_op = OPC_SUB;
16362 goto do_arith;
16363 case SUBU32:
16364 mips32_op = OPC_SUBU;
16365 goto do_arith;
16366 case MUL:
16367 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16368 mips32_op = OPC_MUL;
16369 do_arith:
16370 gen_arith(ctx, mips32_op, rd, rs, rt);
16371 break;
16372 /* Shifts */
16373 case SLLV:
16374 mips32_op = OPC_SLLV;
16375 goto do_shift;
16376 case SRLV:
16377 mips32_op = OPC_SRLV;
16378 goto do_shift;
16379 case SRAV:
16380 mips32_op = OPC_SRAV;
16381 goto do_shift;
16382 case ROTRV:
16383 mips32_op = OPC_ROTRV;
16384 do_shift:
16385 gen_shift(ctx, mips32_op, rd, rs, rt);
16386 break;
16387 /* Logical operations */
16388 case AND:
16389 mips32_op = OPC_AND;
16390 goto do_logic;
16391 case OR32:
16392 mips32_op = OPC_OR;
16393 goto do_logic;
16394 case NOR:
16395 mips32_op = OPC_NOR;
16396 goto do_logic;
16397 case XOR32:
16398 mips32_op = OPC_XOR;
16399 do_logic:
16400 gen_logic(ctx, mips32_op, rd, rs, rt);
16401 break;
16402 /* Set less than */
16403 case SLT:
16404 mips32_op = OPC_SLT;
16405 goto do_slt;
16406 case SLTU:
16407 mips32_op = OPC_SLTU;
16408 do_slt:
16409 gen_slt(ctx, mips32_op, rd, rs, rt);
16410 break;
16411 default:
16412 goto pool32a_invalid;
16414 break;
16415 case 0x18:
16416 minor = (ctx->opcode >> 6) & 0xf;
16417 switch (minor) {
16418 /* Conditional moves */
16419 case MOVN: /* MUL */
16420 if (ctx->insn_flags & ISA_MIPS_R6) {
16421 /* MUL */
16422 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
16423 } else {
16424 /* MOVN */
16425 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
16427 break;
16428 case MOVZ: /* MUH */
16429 if (ctx->insn_flags & ISA_MIPS_R6) {
16430 /* MUH */
16431 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
16432 } else {
16433 /* MOVZ */
16434 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
16436 break;
16437 case MULU:
16438 check_insn(ctx, ISA_MIPS_R6);
16439 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
16440 break;
16441 case MUHU:
16442 check_insn(ctx, ISA_MIPS_R6);
16443 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
16444 break;
16445 case LWXS: /* DIV */
16446 if (ctx->insn_flags & ISA_MIPS_R6) {
16447 /* DIV */
16448 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
16449 } else {
16450 /* LWXS */
16451 gen_ldxs(ctx, rs, rt, rd);
16453 break;
16454 case MOD:
16455 check_insn(ctx, ISA_MIPS_R6);
16456 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
16457 break;
16458 case R6_DIVU:
16459 check_insn(ctx, ISA_MIPS_R6);
16460 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
16461 break;
16462 case MODU:
16463 check_insn(ctx, ISA_MIPS_R6);
16464 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
16465 break;
16466 default:
16467 goto pool32a_invalid;
16469 break;
16470 case INS:
16471 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
16472 return;
16473 case LSA:
16474 check_insn(ctx, ISA_MIPS_R6);
16475 gen_lsa(ctx, rd, rt, rs, extract32(ctx->opcode, 9, 2));
16476 break;
16477 case ALIGN:
16478 check_insn(ctx, ISA_MIPS_R6);
16479 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
16480 break;
16481 case EXT:
16482 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
16483 return;
16484 case POOL32AXF:
16485 gen_pool32axf(env, ctx, rt, rs);
16486 break;
16487 case BREAK32:
16488 generate_exception_end(ctx, EXCP_BREAK);
16489 break;
16490 case SIGRIE:
16491 check_insn(ctx, ISA_MIPS_R6);
16492 gen_reserved_instruction(ctx);
16493 break;
16494 default:
16495 pool32a_invalid:
16496 MIPS_INVAL("pool32a");
16497 gen_reserved_instruction(ctx);
16498 break;
16500 break;
16501 case POOL32B:
16502 minor = (ctx->opcode >> 12) & 0xf;
16503 switch (minor) {
16504 case CACHE:
16505 check_cp0_enabled(ctx);
16506 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16507 gen_cache_operation(ctx, rt, rs, imm);
16509 break;
16510 case LWC2:
16511 case SWC2:
16512 /* COP2: Not implemented. */
16513 generate_exception_err(ctx, EXCP_CpU, 2);
16514 break;
16515 #ifdef TARGET_MIPS64
16516 case LDP:
16517 case SDP:
16518 check_insn(ctx, ISA_MIPS3);
16519 check_mips_64(ctx);
16520 #endif
16521 /* fall through */
16522 case LWP:
16523 case SWP:
16524 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16525 break;
16526 #ifdef TARGET_MIPS64
16527 case LDM:
16528 case SDM:
16529 check_insn(ctx, ISA_MIPS3);
16530 check_mips_64(ctx);
16531 #endif
16532 /* fall through */
16533 case LWM32:
16534 case SWM32:
16535 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16536 break;
16537 default:
16538 MIPS_INVAL("pool32b");
16539 gen_reserved_instruction(ctx);
16540 break;
16542 break;
16543 case POOL32F:
16544 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
16545 minor = ctx->opcode & 0x3f;
16546 check_cp1_enabled(ctx);
16547 switch (minor) {
16548 case ALNV_PS:
16549 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16550 mips32_op = OPC_ALNV_PS;
16551 goto do_madd;
16552 case MADD_S:
16553 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16554 mips32_op = OPC_MADD_S;
16555 goto do_madd;
16556 case MADD_D:
16557 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16558 mips32_op = OPC_MADD_D;
16559 goto do_madd;
16560 case MADD_PS:
16561 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16562 mips32_op = OPC_MADD_PS;
16563 goto do_madd;
16564 case MSUB_S:
16565 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16566 mips32_op = OPC_MSUB_S;
16567 goto do_madd;
16568 case MSUB_D:
16569 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16570 mips32_op = OPC_MSUB_D;
16571 goto do_madd;
16572 case MSUB_PS:
16573 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16574 mips32_op = OPC_MSUB_PS;
16575 goto do_madd;
16576 case NMADD_S:
16577 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16578 mips32_op = OPC_NMADD_S;
16579 goto do_madd;
16580 case NMADD_D:
16581 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16582 mips32_op = OPC_NMADD_D;
16583 goto do_madd;
16584 case NMADD_PS:
16585 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16586 mips32_op = OPC_NMADD_PS;
16587 goto do_madd;
16588 case NMSUB_S:
16589 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16590 mips32_op = OPC_NMSUB_S;
16591 goto do_madd;
16592 case NMSUB_D:
16593 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16594 mips32_op = OPC_NMSUB_D;
16595 goto do_madd;
16596 case NMSUB_PS:
16597 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16598 mips32_op = OPC_NMSUB_PS;
16599 do_madd:
16600 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
16601 break;
16602 case CABS_COND_FMT:
16603 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16604 cond = (ctx->opcode >> 6) & 0xf;
16605 cc = (ctx->opcode >> 13) & 0x7;
16606 fmt = (ctx->opcode >> 10) & 0x3;
16607 switch (fmt) {
16608 case 0x0:
16609 gen_cmpabs_s(ctx, cond, rt, rs, cc);
16610 break;
16611 case 0x1:
16612 gen_cmpabs_d(ctx, cond, rt, rs, cc);
16613 break;
16614 case 0x2:
16615 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
16616 break;
16617 default:
16618 goto pool32f_invalid;
16620 break;
16621 case C_COND_FMT:
16622 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16623 cond = (ctx->opcode >> 6) & 0xf;
16624 cc = (ctx->opcode >> 13) & 0x7;
16625 fmt = (ctx->opcode >> 10) & 0x3;
16626 switch (fmt) {
16627 case 0x0:
16628 gen_cmp_s(ctx, cond, rt, rs, cc);
16629 break;
16630 case 0x1:
16631 gen_cmp_d(ctx, cond, rt, rs, cc);
16632 break;
16633 case 0x2:
16634 gen_cmp_ps(ctx, cond, rt, rs, cc);
16635 break;
16636 default:
16637 goto pool32f_invalid;
16639 break;
16640 case CMP_CONDN_S:
16641 check_insn(ctx, ISA_MIPS_R6);
16642 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16643 break;
16644 case CMP_CONDN_D:
16645 check_insn(ctx, ISA_MIPS_R6);
16646 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16647 break;
16648 case POOL32FXF:
16649 gen_pool32fxf(ctx, rt, rs);
16650 break;
16651 case 0x00:
16652 /* PLL foo */
16653 switch ((ctx->opcode >> 6) & 0x7) {
16654 case PLL_PS:
16655 mips32_op = OPC_PLL_PS;
16656 goto do_ps;
16657 case PLU_PS:
16658 mips32_op = OPC_PLU_PS;
16659 goto do_ps;
16660 case PUL_PS:
16661 mips32_op = OPC_PUL_PS;
16662 goto do_ps;
16663 case PUU_PS:
16664 mips32_op = OPC_PUU_PS;
16665 goto do_ps;
16666 case CVT_PS_S:
16667 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16668 mips32_op = OPC_CVT_PS_S;
16669 do_ps:
16670 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16671 break;
16672 default:
16673 goto pool32f_invalid;
16675 break;
16676 case MIN_FMT:
16677 check_insn(ctx, ISA_MIPS_R6);
16678 switch ((ctx->opcode >> 9) & 0x3) {
16679 case FMT_SDPS_S:
16680 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
16681 break;
16682 case FMT_SDPS_D:
16683 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
16684 break;
16685 default:
16686 goto pool32f_invalid;
16688 break;
16689 case 0x08:
16690 /* [LS][WDU]XC1 */
16691 switch ((ctx->opcode >> 6) & 0x7) {
16692 case LWXC1:
16693 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16694 mips32_op = OPC_LWXC1;
16695 goto do_ldst_cp1;
16696 case SWXC1:
16697 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16698 mips32_op = OPC_SWXC1;
16699 goto do_ldst_cp1;
16700 case LDXC1:
16701 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16702 mips32_op = OPC_LDXC1;
16703 goto do_ldst_cp1;
16704 case SDXC1:
16705 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16706 mips32_op = OPC_SDXC1;
16707 goto do_ldst_cp1;
16708 case LUXC1:
16709 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16710 mips32_op = OPC_LUXC1;
16711 goto do_ldst_cp1;
16712 case SUXC1:
16713 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16714 mips32_op = OPC_SUXC1;
16715 do_ldst_cp1:
16716 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
16717 break;
16718 default:
16719 goto pool32f_invalid;
16721 break;
16722 case MAX_FMT:
16723 check_insn(ctx, ISA_MIPS_R6);
16724 switch ((ctx->opcode >> 9) & 0x3) {
16725 case FMT_SDPS_S:
16726 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
16727 break;
16728 case FMT_SDPS_D:
16729 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
16730 break;
16731 default:
16732 goto pool32f_invalid;
16734 break;
16735 case 0x18:
16736 /* 3D insns */
16737 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16738 fmt = (ctx->opcode >> 9) & 0x3;
16739 switch ((ctx->opcode >> 6) & 0x7) {
16740 case RSQRT2_FMT:
16741 switch (fmt) {
16742 case FMT_SDPS_S:
16743 mips32_op = OPC_RSQRT2_S;
16744 goto do_3d;
16745 case FMT_SDPS_D:
16746 mips32_op = OPC_RSQRT2_D;
16747 goto do_3d;
16748 case FMT_SDPS_PS:
16749 mips32_op = OPC_RSQRT2_PS;
16750 goto do_3d;
16751 default:
16752 goto pool32f_invalid;
16754 break;
16755 case RECIP2_FMT:
16756 switch (fmt) {
16757 case FMT_SDPS_S:
16758 mips32_op = OPC_RECIP2_S;
16759 goto do_3d;
16760 case FMT_SDPS_D:
16761 mips32_op = OPC_RECIP2_D;
16762 goto do_3d;
16763 case FMT_SDPS_PS:
16764 mips32_op = OPC_RECIP2_PS;
16765 goto do_3d;
16766 default:
16767 goto pool32f_invalid;
16769 break;
16770 case ADDR_PS:
16771 mips32_op = OPC_ADDR_PS;
16772 goto do_3d;
16773 case MULR_PS:
16774 mips32_op = OPC_MULR_PS;
16775 do_3d:
16776 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16777 break;
16778 default:
16779 goto pool32f_invalid;
16781 break;
16782 case 0x20:
16783 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
16784 cc = (ctx->opcode >> 13) & 0x7;
16785 fmt = (ctx->opcode >> 9) & 0x3;
16786 switch ((ctx->opcode >> 6) & 0x7) {
16787 case MOVF_FMT: /* RINT_FMT */
16788 if (ctx->insn_flags & ISA_MIPS_R6) {
16789 /* RINT_FMT */
16790 switch (fmt) {
16791 case FMT_SDPS_S:
16792 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
16793 break;
16794 case FMT_SDPS_D:
16795 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
16796 break;
16797 default:
16798 goto pool32f_invalid;
16800 } else {
16801 /* MOVF_FMT */
16802 switch (fmt) {
16803 case FMT_SDPS_S:
16804 gen_movcf_s(ctx, rs, rt, cc, 0);
16805 break;
16806 case FMT_SDPS_D:
16807 gen_movcf_d(ctx, rs, rt, cc, 0);
16808 break;
16809 case FMT_SDPS_PS:
16810 check_ps(ctx);
16811 gen_movcf_ps(ctx, rs, rt, cc, 0);
16812 break;
16813 default:
16814 goto pool32f_invalid;
16817 break;
16818 case MOVT_FMT: /* CLASS_FMT */
16819 if (ctx->insn_flags & ISA_MIPS_R6) {
16820 /* CLASS_FMT */
16821 switch (fmt) {
16822 case FMT_SDPS_S:
16823 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
16824 break;
16825 case FMT_SDPS_D:
16826 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
16827 break;
16828 default:
16829 goto pool32f_invalid;
16831 } else {
16832 /* MOVT_FMT */
16833 switch (fmt) {
16834 case FMT_SDPS_S:
16835 gen_movcf_s(ctx, rs, rt, cc, 1);
16836 break;
16837 case FMT_SDPS_D:
16838 gen_movcf_d(ctx, rs, rt, cc, 1);
16839 break;
16840 case FMT_SDPS_PS:
16841 check_ps(ctx);
16842 gen_movcf_ps(ctx, rs, rt, cc, 1);
16843 break;
16844 default:
16845 goto pool32f_invalid;
16848 break;
16849 case PREFX:
16850 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16851 break;
16852 default:
16853 goto pool32f_invalid;
16855 break;
16856 #define FINSN_3ARG_SDPS(prfx) \
16857 switch ((ctx->opcode >> 8) & 0x3) { \
16858 case FMT_SDPS_S: \
16859 mips32_op = OPC_##prfx##_S; \
16860 goto do_fpop; \
16861 case FMT_SDPS_D: \
16862 mips32_op = OPC_##prfx##_D; \
16863 goto do_fpop; \
16864 case FMT_SDPS_PS: \
16865 check_ps(ctx); \
16866 mips32_op = OPC_##prfx##_PS; \
16867 goto do_fpop; \
16868 default: \
16869 goto pool32f_invalid; \
16871 case MINA_FMT:
16872 check_insn(ctx, ISA_MIPS_R6);
16873 switch ((ctx->opcode >> 9) & 0x3) {
16874 case FMT_SDPS_S:
16875 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
16876 break;
16877 case FMT_SDPS_D:
16878 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
16879 break;
16880 default:
16881 goto pool32f_invalid;
16883 break;
16884 case MAXA_FMT:
16885 check_insn(ctx, ISA_MIPS_R6);
16886 switch ((ctx->opcode >> 9) & 0x3) {
16887 case FMT_SDPS_S:
16888 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
16889 break;
16890 case FMT_SDPS_D:
16891 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
16892 break;
16893 default:
16894 goto pool32f_invalid;
16896 break;
16897 case 0x30:
16898 /* regular FP ops */
16899 switch ((ctx->opcode >> 6) & 0x3) {
16900 case ADD_FMT:
16901 FINSN_3ARG_SDPS(ADD);
16902 break;
16903 case SUB_FMT:
16904 FINSN_3ARG_SDPS(SUB);
16905 break;
16906 case MUL_FMT:
16907 FINSN_3ARG_SDPS(MUL);
16908 break;
16909 case DIV_FMT:
16910 fmt = (ctx->opcode >> 8) & 0x3;
16911 if (fmt == 1) {
16912 mips32_op = OPC_DIV_D;
16913 } else if (fmt == 0) {
16914 mips32_op = OPC_DIV_S;
16915 } else {
16916 goto pool32f_invalid;
16918 goto do_fpop;
16919 default:
16920 goto pool32f_invalid;
16922 break;
16923 case 0x38:
16924 /* cmovs */
16925 switch ((ctx->opcode >> 6) & 0x7) {
16926 case MOVN_FMT: /* SELEQZ_FMT */
16927 if (ctx->insn_flags & ISA_MIPS_R6) {
16928 /* SELEQZ_FMT */
16929 switch ((ctx->opcode >> 9) & 0x3) {
16930 case FMT_SDPS_S:
16931 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
16932 break;
16933 case FMT_SDPS_D:
16934 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
16935 break;
16936 default:
16937 goto pool32f_invalid;
16939 } else {
16940 /* MOVN_FMT */
16941 FINSN_3ARG_SDPS(MOVN);
16943 break;
16944 case MOVN_FMT_04:
16945 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16946 FINSN_3ARG_SDPS(MOVN);
16947 break;
16948 case MOVZ_FMT: /* SELNEZ_FMT */
16949 if (ctx->insn_flags & ISA_MIPS_R6) {
16950 /* SELNEZ_FMT */
16951 switch ((ctx->opcode >> 9) & 0x3) {
16952 case FMT_SDPS_S:
16953 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
16954 break;
16955 case FMT_SDPS_D:
16956 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
16957 break;
16958 default:
16959 goto pool32f_invalid;
16961 } else {
16962 /* MOVZ_FMT */
16963 FINSN_3ARG_SDPS(MOVZ);
16965 break;
16966 case MOVZ_FMT_05:
16967 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16968 FINSN_3ARG_SDPS(MOVZ);
16969 break;
16970 case SEL_FMT:
16971 check_insn(ctx, ISA_MIPS_R6);
16972 switch ((ctx->opcode >> 9) & 0x3) {
16973 case FMT_SDPS_S:
16974 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
16975 break;
16976 case FMT_SDPS_D:
16977 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
16978 break;
16979 default:
16980 goto pool32f_invalid;
16982 break;
16983 case MADDF_FMT:
16984 check_insn(ctx, ISA_MIPS_R6);
16985 switch ((ctx->opcode >> 9) & 0x3) {
16986 case FMT_SDPS_S:
16987 mips32_op = OPC_MADDF_S;
16988 goto do_fpop;
16989 case FMT_SDPS_D:
16990 mips32_op = OPC_MADDF_D;
16991 goto do_fpop;
16992 default:
16993 goto pool32f_invalid;
16995 break;
16996 case MSUBF_FMT:
16997 check_insn(ctx, ISA_MIPS_R6);
16998 switch ((ctx->opcode >> 9) & 0x3) {
16999 case FMT_SDPS_S:
17000 mips32_op = OPC_MSUBF_S;
17001 goto do_fpop;
17002 case FMT_SDPS_D:
17003 mips32_op = OPC_MSUBF_D;
17004 goto do_fpop;
17005 default:
17006 goto pool32f_invalid;
17008 break;
17009 default:
17010 goto pool32f_invalid;
17012 break;
17013 do_fpop:
17014 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
17015 break;
17016 default:
17017 pool32f_invalid:
17018 MIPS_INVAL("pool32f");
17019 gen_reserved_instruction(ctx);
17020 break;
17022 } else {
17023 generate_exception_err(ctx, EXCP_CpU, 1);
17025 break;
17026 case POOL32I:
17027 minor = (ctx->opcode >> 21) & 0x1f;
17028 switch (minor) {
17029 case BLTZ:
17030 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17031 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
17032 break;
17033 case BLTZAL:
17034 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17035 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
17036 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17037 break;
17038 case BLTZALS:
17039 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17040 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
17041 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17042 break;
17043 case BGEZ:
17044 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17045 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
17046 break;
17047 case BGEZAL:
17048 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17049 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
17050 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17051 break;
17052 case BGEZALS:
17053 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17054 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
17055 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17056 break;
17057 case BLEZ:
17058 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17059 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
17060 break;
17061 case BGTZ:
17062 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17063 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
17064 break;
17066 /* Traps */
17067 case TLTI: /* BC1EQZC */
17068 if (ctx->insn_flags & ISA_MIPS_R6) {
17069 /* BC1EQZC */
17070 check_cp1_enabled(ctx);
17071 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
17072 } else {
17073 /* TLTI */
17074 mips32_op = OPC_TLTI;
17075 goto do_trapi;
17077 break;
17078 case TGEI: /* BC1NEZC */
17079 if (ctx->insn_flags & ISA_MIPS_R6) {
17080 /* BC1NEZC */
17081 check_cp1_enabled(ctx);
17082 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
17083 } else {
17084 /* TGEI */
17085 mips32_op = OPC_TGEI;
17086 goto do_trapi;
17088 break;
17089 case TLTIU:
17090 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17091 mips32_op = OPC_TLTIU;
17092 goto do_trapi;
17093 case TGEIU:
17094 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17095 mips32_op = OPC_TGEIU;
17096 goto do_trapi;
17097 case TNEI: /* SYNCI */
17098 if (ctx->insn_flags & ISA_MIPS_R6) {
17099 /* SYNCI */
17101 * Break the TB to be able to sync copied instructions
17102 * immediately.
17104 ctx->base.is_jmp = DISAS_STOP;
17105 } else {
17106 /* TNEI */
17107 mips32_op = OPC_TNEI;
17108 goto do_trapi;
17110 break;
17111 case TEQI:
17112 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17113 mips32_op = OPC_TEQI;
17114 do_trapi:
17115 gen_trap(ctx, mips32_op, rs, -1, imm);
17116 break;
17118 case BNEZC:
17119 case BEQZC:
17120 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17121 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
17122 4, rs, 0, imm << 1, 0);
17124 * Compact branches don't have a delay slot, so just let
17125 * the normal delay slot handling take us to the branch
17126 * target.
17128 break;
17129 case LUI:
17130 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17131 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
17132 break;
17133 case SYNCI:
17134 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17136 * Break the TB to be able to sync copied instructions
17137 * immediately.
17139 ctx->base.is_jmp = DISAS_STOP;
17140 break;
17141 case BC2F:
17142 case BC2T:
17143 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17144 /* COP2: Not implemented. */
17145 generate_exception_err(ctx, EXCP_CpU, 2);
17146 break;
17147 case BC1F:
17148 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17149 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
17150 goto do_cp1branch;
17151 case BC1T:
17152 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17153 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
17154 goto do_cp1branch;
17155 case BC1ANY4F:
17156 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17157 mips32_op = OPC_BC1FANY4;
17158 goto do_cp1mips3d;
17159 case BC1ANY4T:
17160 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17161 mips32_op = OPC_BC1TANY4;
17162 do_cp1mips3d:
17163 check_cop1x(ctx);
17164 check_insn(ctx, ASE_MIPS3D);
17165 /* Fall through */
17166 do_cp1branch:
17167 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
17168 check_cp1_enabled(ctx);
17169 gen_compute_branch1(ctx, mips32_op,
17170 (ctx->opcode >> 18) & 0x7, imm << 1);
17171 } else {
17172 generate_exception_err(ctx, EXCP_CpU, 1);
17174 break;
17175 case BPOSGE64:
17176 case BPOSGE32:
17177 /* MIPS DSP: not implemented */
17178 /* Fall through */
17179 default:
17180 MIPS_INVAL("pool32i");
17181 gen_reserved_instruction(ctx);
17182 break;
17184 break;
17185 case POOL32C:
17186 minor = (ctx->opcode >> 12) & 0xf;
17187 offset = sextract32(ctx->opcode, 0,
17188 (ctx->insn_flags & ISA_MIPS_R6) ? 9 : 12);
17189 switch (minor) {
17190 case LWL:
17191 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17192 mips32_op = OPC_LWL;
17193 goto do_ld_lr;
17194 case SWL:
17195 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17196 mips32_op = OPC_SWL;
17197 goto do_st_lr;
17198 case LWR:
17199 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17200 mips32_op = OPC_LWR;
17201 goto do_ld_lr;
17202 case SWR:
17203 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17204 mips32_op = OPC_SWR;
17205 goto do_st_lr;
17206 #if defined(TARGET_MIPS64)
17207 case LDL:
17208 check_insn(ctx, ISA_MIPS3);
17209 check_mips_64(ctx);
17210 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17211 mips32_op = OPC_LDL;
17212 goto do_ld_lr;
17213 case SDL:
17214 check_insn(ctx, ISA_MIPS3);
17215 check_mips_64(ctx);
17216 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17217 mips32_op = OPC_SDL;
17218 goto do_st_lr;
17219 case LDR:
17220 check_insn(ctx, ISA_MIPS3);
17221 check_mips_64(ctx);
17222 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17223 mips32_op = OPC_LDR;
17224 goto do_ld_lr;
17225 case SDR:
17226 check_insn(ctx, ISA_MIPS3);
17227 check_mips_64(ctx);
17228 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17229 mips32_op = OPC_SDR;
17230 goto do_st_lr;
17231 case LWU:
17232 check_insn(ctx, ISA_MIPS3);
17233 check_mips_64(ctx);
17234 mips32_op = OPC_LWU;
17235 goto do_ld_lr;
17236 case LLD:
17237 check_insn(ctx, ISA_MIPS3);
17238 check_mips_64(ctx);
17239 mips32_op = OPC_LLD;
17240 goto do_ld_lr;
17241 #endif
17242 case LL:
17243 mips32_op = OPC_LL;
17244 goto do_ld_lr;
17245 do_ld_lr:
17246 gen_ld(ctx, mips32_op, rt, rs, offset);
17247 break;
17248 do_st_lr:
17249 gen_st(ctx, mips32_op, rt, rs, offset);
17250 break;
17251 case SC:
17252 gen_st_cond(ctx, rt, rs, offset, MO_TESL, false);
17253 break;
17254 #if defined(TARGET_MIPS64)
17255 case SCD:
17256 check_insn(ctx, ISA_MIPS3);
17257 check_mips_64(ctx);
17258 gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false);
17259 break;
17260 #endif
17261 case LD_EVA:
17262 if (!ctx->eva) {
17263 MIPS_INVAL("pool32c ld-eva");
17264 gen_reserved_instruction(ctx);
17265 break;
17267 check_cp0_enabled(ctx);
17269 minor2 = (ctx->opcode >> 9) & 0x7;
17270 offset = sextract32(ctx->opcode, 0, 9);
17271 switch (minor2) {
17272 case LBUE:
17273 mips32_op = OPC_LBUE;
17274 goto do_ld_lr;
17275 case LHUE:
17276 mips32_op = OPC_LHUE;
17277 goto do_ld_lr;
17278 case LWLE:
17279 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17280 mips32_op = OPC_LWLE;
17281 goto do_ld_lr;
17282 case LWRE:
17283 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17284 mips32_op = OPC_LWRE;
17285 goto do_ld_lr;
17286 case LBE:
17287 mips32_op = OPC_LBE;
17288 goto do_ld_lr;
17289 case LHE:
17290 mips32_op = OPC_LHE;
17291 goto do_ld_lr;
17292 case LLE:
17293 mips32_op = OPC_LLE;
17294 goto do_ld_lr;
17295 case LWE:
17296 mips32_op = OPC_LWE;
17297 goto do_ld_lr;
17299 break;
17300 case ST_EVA:
17301 if (!ctx->eva) {
17302 MIPS_INVAL("pool32c st-eva");
17303 gen_reserved_instruction(ctx);
17304 break;
17306 check_cp0_enabled(ctx);
17308 minor2 = (ctx->opcode >> 9) & 0x7;
17309 offset = sextract32(ctx->opcode, 0, 9);
17310 switch (minor2) {
17311 case SWLE:
17312 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17313 mips32_op = OPC_SWLE;
17314 goto do_st_lr;
17315 case SWRE:
17316 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17317 mips32_op = OPC_SWRE;
17318 goto do_st_lr;
17319 case PREFE:
17320 /* Treat as no-op */
17321 if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >= 24)) {
17322 /* hint codes 24-31 are reserved and signal RI */
17323 generate_exception(ctx, EXCP_RI);
17325 break;
17326 case CACHEE:
17327 /* Treat as no-op */
17328 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
17329 gen_cache_operation(ctx, rt, rs, offset);
17331 break;
17332 case SBE:
17333 mips32_op = OPC_SBE;
17334 goto do_st_lr;
17335 case SHE:
17336 mips32_op = OPC_SHE;
17337 goto do_st_lr;
17338 case SCE:
17339 gen_st_cond(ctx, rt, rs, offset, MO_TESL, true);
17340 break;
17341 case SWE:
17342 mips32_op = OPC_SWE;
17343 goto do_st_lr;
17345 break;
17346 case PREF:
17347 /* Treat as no-op */
17348 if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >= 24)) {
17349 /* hint codes 24-31 are reserved and signal RI */
17350 generate_exception(ctx, EXCP_RI);
17352 break;
17353 default:
17354 MIPS_INVAL("pool32c");
17355 gen_reserved_instruction(ctx);
17356 break;
17358 break;
17359 case ADDI32: /* AUI, LUI */
17360 if (ctx->insn_flags & ISA_MIPS_R6) {
17361 /* AUI, LUI */
17362 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
17363 } else {
17364 /* ADDI32 */
17365 mips32_op = OPC_ADDI;
17366 goto do_addi;
17368 break;
17369 case ADDIU32:
17370 mips32_op = OPC_ADDIU;
17371 do_addi:
17372 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
17373 break;
17375 /* Logical operations */
17376 case ORI32:
17377 mips32_op = OPC_ORI;
17378 goto do_logici;
17379 case XORI32:
17380 mips32_op = OPC_XORI;
17381 goto do_logici;
17382 case ANDI32:
17383 mips32_op = OPC_ANDI;
17384 do_logici:
17385 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
17386 break;
17388 /* Set less than immediate */
17389 case SLTI32:
17390 mips32_op = OPC_SLTI;
17391 goto do_slti;
17392 case SLTIU32:
17393 mips32_op = OPC_SLTIU;
17394 do_slti:
17395 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
17396 break;
17397 case JALX32:
17398 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17399 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
17400 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
17401 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17402 break;
17403 case JALS32: /* BOVC, BEQC, BEQZALC */
17404 if (ctx->insn_flags & ISA_MIPS_R6) {
17405 if (rs >= rt) {
17406 /* BOVC */
17407 mips32_op = OPC_BOVC;
17408 } else if (rs < rt && rs == 0) {
17409 /* BEQZALC */
17410 mips32_op = OPC_BEQZALC;
17411 } else {
17412 /* BEQC */
17413 mips32_op = OPC_BEQC;
17415 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17416 } else {
17417 /* JALS32 */
17418 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
17419 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
17420 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17422 break;
17423 case BEQ32: /* BC */
17424 if (ctx->insn_flags & ISA_MIPS_R6) {
17425 /* BC */
17426 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
17427 sextract32(ctx->opcode << 1, 0, 27));
17428 } else {
17429 /* BEQ32 */
17430 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
17432 break;
17433 case BNE32: /* BALC */
17434 if (ctx->insn_flags & ISA_MIPS_R6) {
17435 /* BALC */
17436 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
17437 sextract32(ctx->opcode << 1, 0, 27));
17438 } else {
17439 /* BNE32 */
17440 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
17442 break;
17443 case J32: /* BGTZC, BLTZC, BLTC */
17444 if (ctx->insn_flags & ISA_MIPS_R6) {
17445 if (rs == 0 && rt != 0) {
17446 /* BGTZC */
17447 mips32_op = OPC_BGTZC;
17448 } else if (rs != 0 && rt != 0 && rs == rt) {
17449 /* BLTZC */
17450 mips32_op = OPC_BLTZC;
17451 } else {
17452 /* BLTC */
17453 mips32_op = OPC_BLTC;
17455 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17456 } else {
17457 /* J32 */
17458 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
17459 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17461 break;
17462 case JAL32: /* BLEZC, BGEZC, BGEC */
17463 if (ctx->insn_flags & ISA_MIPS_R6) {
17464 if (rs == 0 && rt != 0) {
17465 /* BLEZC */
17466 mips32_op = OPC_BLEZC;
17467 } else if (rs != 0 && rt != 0 && rs == rt) {
17468 /* BGEZC */
17469 mips32_op = OPC_BGEZC;
17470 } else {
17471 /* BGEC */
17472 mips32_op = OPC_BGEC;
17474 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17475 } else {
17476 /* JAL32 */
17477 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
17478 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17479 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17481 break;
17482 /* Floating point (COP1) */
17483 case LWC132:
17484 mips32_op = OPC_LWC1;
17485 goto do_cop1;
17486 case LDC132:
17487 mips32_op = OPC_LDC1;
17488 goto do_cop1;
17489 case SWC132:
17490 mips32_op = OPC_SWC1;
17491 goto do_cop1;
17492 case SDC132:
17493 mips32_op = OPC_SDC1;
17494 do_cop1:
17495 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
17496 break;
17497 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17498 if (ctx->insn_flags & ISA_MIPS_R6) {
17499 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17500 switch ((ctx->opcode >> 16) & 0x1f) {
17501 case ADDIUPC_00:
17502 case ADDIUPC_01:
17503 case ADDIUPC_02:
17504 case ADDIUPC_03:
17505 case ADDIUPC_04:
17506 case ADDIUPC_05:
17507 case ADDIUPC_06:
17508 case ADDIUPC_07:
17509 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
17510 break;
17511 case AUIPC:
17512 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
17513 break;
17514 case ALUIPC:
17515 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
17516 break;
17517 case LWPC_08:
17518 case LWPC_09:
17519 case LWPC_0A:
17520 case LWPC_0B:
17521 case LWPC_0C:
17522 case LWPC_0D:
17523 case LWPC_0E:
17524 case LWPC_0F:
17525 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
17526 break;
17527 default:
17528 generate_exception(ctx, EXCP_RI);
17529 break;
17531 } else {
17532 /* ADDIUPC */
17533 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
17534 offset = SIMM(ctx->opcode, 0, 23) << 2;
17536 gen_addiupc(ctx, reg, offset, 0, 0);
17538 break;
17539 case BNVC: /* BNEC, BNEZALC */
17540 check_insn(ctx, ISA_MIPS_R6);
17541 if (rs >= rt) {
17542 /* BNVC */
17543 mips32_op = OPC_BNVC;
17544 } else if (rs < rt && rs == 0) {
17545 /* BNEZALC */
17546 mips32_op = OPC_BNEZALC;
17547 } else {
17548 /* BNEC */
17549 mips32_op = OPC_BNEC;
17551 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17552 break;
17553 case R6_BNEZC: /* JIALC */
17554 check_insn(ctx, ISA_MIPS_R6);
17555 if (rt != 0) {
17556 /* BNEZC */
17557 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
17558 sextract32(ctx->opcode << 1, 0, 22));
17559 } else {
17560 /* JIALC */
17561 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
17563 break;
17564 case R6_BEQZC: /* JIC */
17565 check_insn(ctx, ISA_MIPS_R6);
17566 if (rt != 0) {
17567 /* BEQZC */
17568 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
17569 sextract32(ctx->opcode << 1, 0, 22));
17570 } else {
17571 /* JIC */
17572 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
17574 break;
17575 case BLEZALC: /* BGEZALC, BGEUC */
17576 check_insn(ctx, ISA_MIPS_R6);
17577 if (rs == 0 && rt != 0) {
17578 /* BLEZALC */
17579 mips32_op = OPC_BLEZALC;
17580 } else if (rs != 0 && rt != 0 && rs == rt) {
17581 /* BGEZALC */
17582 mips32_op = OPC_BGEZALC;
17583 } else {
17584 /* BGEUC */
17585 mips32_op = OPC_BGEUC;
17587 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17588 break;
17589 case BGTZALC: /* BLTZALC, BLTUC */
17590 check_insn(ctx, ISA_MIPS_R6);
17591 if (rs == 0 && rt != 0) {
17592 /* BGTZALC */
17593 mips32_op = OPC_BGTZALC;
17594 } else if (rs != 0 && rt != 0 && rs == rt) {
17595 /* BLTZALC */
17596 mips32_op = OPC_BLTZALC;
17597 } else {
17598 /* BLTUC */
17599 mips32_op = OPC_BLTUC;
17601 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17602 break;
17603 /* Loads and stores */
17604 case LB32:
17605 mips32_op = OPC_LB;
17606 goto do_ld;
17607 case LBU32:
17608 mips32_op = OPC_LBU;
17609 goto do_ld;
17610 case LH32:
17611 mips32_op = OPC_LH;
17612 goto do_ld;
17613 case LHU32:
17614 mips32_op = OPC_LHU;
17615 goto do_ld;
17616 case LW32:
17617 mips32_op = OPC_LW;
17618 goto do_ld;
17619 #ifdef TARGET_MIPS64
17620 case LD32:
17621 check_insn(ctx, ISA_MIPS3);
17622 check_mips_64(ctx);
17623 mips32_op = OPC_LD;
17624 goto do_ld;
17625 case SD32:
17626 check_insn(ctx, ISA_MIPS3);
17627 check_mips_64(ctx);
17628 mips32_op = OPC_SD;
17629 goto do_st;
17630 #endif
17631 case SB32:
17632 mips32_op = OPC_SB;
17633 goto do_st;
17634 case SH32:
17635 mips32_op = OPC_SH;
17636 goto do_st;
17637 case SW32:
17638 mips32_op = OPC_SW;
17639 goto do_st;
17640 do_ld:
17641 gen_ld(ctx, mips32_op, rt, rs, imm);
17642 break;
17643 do_st:
17644 gen_st(ctx, mips32_op, rt, rs, imm);
17645 break;
17646 default:
17647 gen_reserved_instruction(ctx);
17648 break;
17652 static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx)
17654 uint32_t op;
17656 /* make sure instructions are on a halfword boundary */
17657 if (ctx->base.pc_next & 0x1) {
17658 env->CP0_BadVAddr = ctx->base.pc_next;
17659 generate_exception_end(ctx, EXCP_AdEL);
17660 return 2;
17663 op = (ctx->opcode >> 10) & 0x3f;
17664 /* Enforce properly-sized instructions in a delay slot */
17665 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
17666 switch (op & 0x7) { /* MSB-3..MSB-5 */
17667 case 0:
17668 /* POOL32A, POOL32B, POOL32I, POOL32C */
17669 case 4:
17670 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
17671 case 5:
17672 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
17673 case 6:
17674 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
17675 case 7:
17676 /* LB32, LH32, LWC132, LDC132, LW32 */
17677 if (ctx->hflags & MIPS_HFLAG_BDS16) {
17678 gen_reserved_instruction(ctx);
17679 return 2;
17681 break;
17682 case 1:
17683 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
17684 case 2:
17685 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
17686 case 3:
17687 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
17688 if (ctx->hflags & MIPS_HFLAG_BDS32) {
17689 gen_reserved_instruction(ctx);
17690 return 2;
17692 break;
17696 switch (op) {
17697 case POOL16A:
17699 int rd = mmreg(uMIPS_RD(ctx->opcode));
17700 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
17701 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
17702 uint32_t opc = 0;
17704 switch (ctx->opcode & 0x1) {
17705 case ADDU16:
17706 opc = OPC_ADDU;
17707 break;
17708 case SUBU16:
17709 opc = OPC_SUBU;
17710 break;
17712 if (ctx->insn_flags & ISA_MIPS_R6) {
17714 * In the Release 6, the register number location in
17715 * the instruction encoding has changed.
17717 gen_arith(ctx, opc, rs1, rd, rs2);
17718 } else {
17719 gen_arith(ctx, opc, rd, rs1, rs2);
17722 break;
17723 case POOL16B:
17725 int rd = mmreg(uMIPS_RD(ctx->opcode));
17726 int rs = mmreg(uMIPS_RS(ctx->opcode));
17727 int amount = (ctx->opcode >> 1) & 0x7;
17728 uint32_t opc = 0;
17729 amount = amount == 0 ? 8 : amount;
17731 switch (ctx->opcode & 0x1) {
17732 case SLL16:
17733 opc = OPC_SLL;
17734 break;
17735 case SRL16:
17736 opc = OPC_SRL;
17737 break;
17740 gen_shift_imm(ctx, opc, rd, rs, amount);
17742 break;
17743 case POOL16C:
17744 if (ctx->insn_flags & ISA_MIPS_R6) {
17745 gen_pool16c_r6_insn(ctx);
17746 } else {
17747 gen_pool16c_insn(ctx);
17749 break;
17750 case LWGP16:
17752 int rd = mmreg(uMIPS_RD(ctx->opcode));
17753 int rb = 28; /* GP */
17754 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
17756 gen_ld(ctx, OPC_LW, rd, rb, offset);
17758 break;
17759 case POOL16F:
17760 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17761 if (ctx->opcode & 1) {
17762 gen_reserved_instruction(ctx);
17763 } else {
17764 /* MOVEP */
17765 int enc_dest = uMIPS_RD(ctx->opcode);
17766 int enc_rt = uMIPS_RS2(ctx->opcode);
17767 int enc_rs = uMIPS_RS1(ctx->opcode);
17768 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
17770 break;
17771 case LBU16:
17773 int rd = mmreg(uMIPS_RD(ctx->opcode));
17774 int rb = mmreg(uMIPS_RS(ctx->opcode));
17775 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17776 offset = (offset == 0xf ? -1 : offset);
17778 gen_ld(ctx, OPC_LBU, rd, rb, offset);
17780 break;
17781 case LHU16:
17783 int rd = mmreg(uMIPS_RD(ctx->opcode));
17784 int rb = mmreg(uMIPS_RS(ctx->opcode));
17785 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17787 gen_ld(ctx, OPC_LHU, rd, rb, offset);
17789 break;
17790 case LWSP16:
17792 int rd = (ctx->opcode >> 5) & 0x1f;
17793 int rb = 29; /* SP */
17794 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17796 gen_ld(ctx, OPC_LW, rd, rb, offset);
17798 break;
17799 case LW16:
17801 int rd = mmreg(uMIPS_RD(ctx->opcode));
17802 int rb = mmreg(uMIPS_RS(ctx->opcode));
17803 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17805 gen_ld(ctx, OPC_LW, rd, rb, offset);
17807 break;
17808 case SB16:
17810 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17811 int rb = mmreg(uMIPS_RS(ctx->opcode));
17812 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17814 gen_st(ctx, OPC_SB, rd, rb, offset);
17816 break;
17817 case SH16:
17819 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17820 int rb = mmreg(uMIPS_RS(ctx->opcode));
17821 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17823 gen_st(ctx, OPC_SH, rd, rb, offset);
17825 break;
17826 case SWSP16:
17828 int rd = (ctx->opcode >> 5) & 0x1f;
17829 int rb = 29; /* SP */
17830 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17832 gen_st(ctx, OPC_SW, rd, rb, offset);
17834 break;
17835 case SW16:
17837 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17838 int rb = mmreg(uMIPS_RS(ctx->opcode));
17839 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17841 gen_st(ctx, OPC_SW, rd, rb, offset);
17843 break;
17844 case MOVE16:
17846 int rd = uMIPS_RD5(ctx->opcode);
17847 int rs = uMIPS_RS5(ctx->opcode);
17849 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
17851 break;
17852 case ANDI16:
17853 gen_andi16(ctx);
17854 break;
17855 case POOL16D:
17856 switch (ctx->opcode & 0x1) {
17857 case ADDIUS5:
17858 gen_addius5(ctx);
17859 break;
17860 case ADDIUSP:
17861 gen_addiusp(ctx);
17862 break;
17864 break;
17865 case POOL16E:
17866 switch (ctx->opcode & 0x1) {
17867 case ADDIUR2:
17868 gen_addiur2(ctx);
17869 break;
17870 case ADDIUR1SP:
17871 gen_addiur1sp(ctx);
17872 break;
17874 break;
17875 case B16: /* BC16 */
17876 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
17877 sextract32(ctx->opcode, 0, 10) << 1,
17878 (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4);
17879 break;
17880 case BNEZ16: /* BNEZC16 */
17881 case BEQZ16: /* BEQZC16 */
17882 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
17883 mmreg(uMIPS_RD(ctx->opcode)),
17884 0, sextract32(ctx->opcode, 0, 7) << 1,
17885 (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4);
17887 break;
17888 case LI16:
17890 int reg = mmreg(uMIPS_RD(ctx->opcode));
17891 int imm = ZIMM(ctx->opcode, 0, 7);
17893 imm = (imm == 0x7f ? -1 : imm);
17894 tcg_gen_movi_tl(cpu_gpr[reg], imm);
17896 break;
17897 case RES_29:
17898 case RES_31:
17899 case RES_39:
17900 gen_reserved_instruction(ctx);
17901 break;
17902 default:
17903 decode_micromips32_opc(env, ctx);
17904 return 4;
17907 return 2;
17912 * nanoMIPS opcodes
17916 /* MAJOR, P16, and P32 pools opcodes */
17917 enum {
17918 NM_P_ADDIU = 0x00,
17919 NM_ADDIUPC = 0x01,
17920 NM_MOVE_BALC = 0x02,
17921 NM_P16_MV = 0x04,
17922 NM_LW16 = 0x05,
17923 NM_BC16 = 0x06,
17924 NM_P16_SR = 0x07,
17926 NM_POOL32A = 0x08,
17927 NM_P_BAL = 0x0a,
17928 NM_P16_SHIFT = 0x0c,
17929 NM_LWSP16 = 0x0d,
17930 NM_BALC16 = 0x0e,
17931 NM_P16_4X4 = 0x0f,
17933 NM_P_GP_W = 0x10,
17934 NM_P_GP_BH = 0x11,
17935 NM_P_J = 0x12,
17936 NM_P16C = 0x14,
17937 NM_LWGP16 = 0x15,
17938 NM_P16_LB = 0x17,
17940 NM_P48I = 0x18,
17941 NM_P16_A1 = 0x1c,
17942 NM_LW4X4 = 0x1d,
17943 NM_P16_LH = 0x1f,
17945 NM_P_U12 = 0x20,
17946 NM_P_LS_U12 = 0x21,
17947 NM_P_BR1 = 0x22,
17948 NM_P16_A2 = 0x24,
17949 NM_SW16 = 0x25,
17950 NM_BEQZC16 = 0x26,
17952 NM_POOL32F = 0x28,
17953 NM_P_LS_S9 = 0x29,
17954 NM_P_BR2 = 0x2a,
17956 NM_P16_ADDU = 0x2c,
17957 NM_SWSP16 = 0x2d,
17958 NM_BNEZC16 = 0x2e,
17959 NM_MOVEP = 0x2f,
17961 NM_POOL32S = 0x30,
17962 NM_P_BRI = 0x32,
17963 NM_LI16 = 0x34,
17964 NM_SWGP16 = 0x35,
17965 NM_P16_BR = 0x36,
17967 NM_P_LUI = 0x38,
17968 NM_ANDI16 = 0x3c,
17969 NM_SW4X4 = 0x3d,
17970 NM_MOVEPREV = 0x3f,
17973 /* POOL32A instruction pool */
17974 enum {
17975 NM_POOL32A0 = 0x00,
17976 NM_SPECIAL2 = 0x01,
17977 NM_COP2_1 = 0x02,
17978 NM_UDI = 0x03,
17979 NM_POOL32A5 = 0x05,
17980 NM_POOL32A7 = 0x07,
17983 /* P.GP.W instruction pool */
17984 enum {
17985 NM_ADDIUGP_W = 0x00,
17986 NM_LWGP = 0x02,
17987 NM_SWGP = 0x03,
17990 /* P48I instruction pool */
17991 enum {
17992 NM_LI48 = 0x00,
17993 NM_ADDIU48 = 0x01,
17994 NM_ADDIUGP48 = 0x02,
17995 NM_ADDIUPC48 = 0x03,
17996 NM_LWPC48 = 0x0b,
17997 NM_SWPC48 = 0x0f,
18000 /* P.U12 instruction pool */
18001 enum {
18002 NM_ORI = 0x00,
18003 NM_XORI = 0x01,
18004 NM_ANDI = 0x02,
18005 NM_P_SR = 0x03,
18006 NM_SLTI = 0x04,
18007 NM_SLTIU = 0x05,
18008 NM_SEQI = 0x06,
18009 NM_ADDIUNEG = 0x08,
18010 NM_P_SHIFT = 0x0c,
18011 NM_P_ROTX = 0x0d,
18012 NM_P_INS = 0x0e,
18013 NM_P_EXT = 0x0f,
18016 /* POOL32F instruction pool */
18017 enum {
18018 NM_POOL32F_0 = 0x00,
18019 NM_POOL32F_3 = 0x03,
18020 NM_POOL32F_5 = 0x05,
18023 /* POOL32S instruction pool */
18024 enum {
18025 NM_POOL32S_0 = 0x00,
18026 NM_POOL32S_4 = 0x04,
18029 /* P.LUI instruction pool */
18030 enum {
18031 NM_LUI = 0x00,
18032 NM_ALUIPC = 0x01,
18035 /* P.GP.BH instruction pool */
18036 enum {
18037 NM_LBGP = 0x00,
18038 NM_SBGP = 0x01,
18039 NM_LBUGP = 0x02,
18040 NM_ADDIUGP_B = 0x03,
18041 NM_P_GP_LH = 0x04,
18042 NM_P_GP_SH = 0x05,
18043 NM_P_GP_CP1 = 0x06,
18046 /* P.LS.U12 instruction pool */
18047 enum {
18048 NM_LB = 0x00,
18049 NM_SB = 0x01,
18050 NM_LBU = 0x02,
18051 NM_P_PREFU12 = 0x03,
18052 NM_LH = 0x04,
18053 NM_SH = 0x05,
18054 NM_LHU = 0x06,
18055 NM_LWU = 0x07,
18056 NM_LW = 0x08,
18057 NM_SW = 0x09,
18058 NM_LWC1 = 0x0a,
18059 NM_SWC1 = 0x0b,
18060 NM_LDC1 = 0x0e,
18061 NM_SDC1 = 0x0f,
18064 /* P.LS.S9 instruction pool */
18065 enum {
18066 NM_P_LS_S0 = 0x00,
18067 NM_P_LS_S1 = 0x01,
18068 NM_P_LS_E0 = 0x02,
18069 NM_P_LS_WM = 0x04,
18070 NM_P_LS_UAWM = 0x05,
18073 /* P.BAL instruction pool */
18074 enum {
18075 NM_BC = 0x00,
18076 NM_BALC = 0x01,
18079 /* P.J instruction pool */
18080 enum {
18081 NM_JALRC = 0x00,
18082 NM_JALRC_HB = 0x01,
18083 NM_P_BALRSC = 0x08,
18086 /* P.BR1 instruction pool */
18087 enum {
18088 NM_BEQC = 0x00,
18089 NM_P_BR3A = 0x01,
18090 NM_BGEC = 0x02,
18091 NM_BGEUC = 0x03,
18094 /* P.BR2 instruction pool */
18095 enum {
18096 NM_BNEC = 0x00,
18097 NM_BLTC = 0x02,
18098 NM_BLTUC = 0x03,
18101 /* P.BRI instruction pool */
18102 enum {
18103 NM_BEQIC = 0x00,
18104 NM_BBEQZC = 0x01,
18105 NM_BGEIC = 0x02,
18106 NM_BGEIUC = 0x03,
18107 NM_BNEIC = 0x04,
18108 NM_BBNEZC = 0x05,
18109 NM_BLTIC = 0x06,
18110 NM_BLTIUC = 0x07,
18113 /* P16.SHIFT instruction pool */
18114 enum {
18115 NM_SLL16 = 0x00,
18116 NM_SRL16 = 0x01,
18119 /* POOL16C instruction pool */
18120 enum {
18121 NM_POOL16C_0 = 0x00,
18122 NM_LWXS16 = 0x01,
18125 /* P16.A1 instruction pool */
18126 enum {
18127 NM_ADDIUR1SP = 0x01,
18130 /* P16.A2 instruction pool */
18131 enum {
18132 NM_ADDIUR2 = 0x00,
18133 NM_P_ADDIURS5 = 0x01,
18136 /* P16.ADDU instruction pool */
18137 enum {
18138 NM_ADDU16 = 0x00,
18139 NM_SUBU16 = 0x01,
18142 /* P16.SR instruction pool */
18143 enum {
18144 NM_SAVE16 = 0x00,
18145 NM_RESTORE_JRC16 = 0x01,
18148 /* P16.4X4 instruction pool */
18149 enum {
18150 NM_ADDU4X4 = 0x00,
18151 NM_MUL4X4 = 0x01,
18154 /* P16.LB instruction pool */
18155 enum {
18156 NM_LB16 = 0x00,
18157 NM_SB16 = 0x01,
18158 NM_LBU16 = 0x02,
18161 /* P16.LH instruction pool */
18162 enum {
18163 NM_LH16 = 0x00,
18164 NM_SH16 = 0x01,
18165 NM_LHU16 = 0x02,
18168 /* P.RI instruction pool */
18169 enum {
18170 NM_SIGRIE = 0x00,
18171 NM_P_SYSCALL = 0x01,
18172 NM_BREAK = 0x02,
18173 NM_SDBBP = 0x03,
18176 /* POOL32A0 instruction pool */
18177 enum {
18178 NM_P_TRAP = 0x00,
18179 NM_SEB = 0x01,
18180 NM_SLLV = 0x02,
18181 NM_MUL = 0x03,
18182 NM_MFC0 = 0x06,
18183 NM_MFHC0 = 0x07,
18184 NM_SEH = 0x09,
18185 NM_SRLV = 0x0a,
18186 NM_MUH = 0x0b,
18187 NM_MTC0 = 0x0e,
18188 NM_MTHC0 = 0x0f,
18189 NM_SRAV = 0x12,
18190 NM_MULU = 0x13,
18191 NM_ROTRV = 0x1a,
18192 NM_MUHU = 0x1b,
18193 NM_ADD = 0x22,
18194 NM_DIV = 0x23,
18195 NM_ADDU = 0x2a,
18196 NM_MOD = 0x2b,
18197 NM_SUB = 0x32,
18198 NM_DIVU = 0x33,
18199 NM_RDHWR = 0x38,
18200 NM_SUBU = 0x3a,
18201 NM_MODU = 0x3b,
18202 NM_P_CMOVE = 0x42,
18203 NM_FORK = 0x45,
18204 NM_MFTR = 0x46,
18205 NM_MFHTR = 0x47,
18206 NM_AND = 0x4a,
18207 NM_YIELD = 0x4d,
18208 NM_MTTR = 0x4e,
18209 NM_MTHTR = 0x4f,
18210 NM_OR = 0x52,
18211 NM_D_E_MT_VPE = 0x56,
18212 NM_NOR = 0x5a,
18213 NM_XOR = 0x62,
18214 NM_SLT = 0x6a,
18215 NM_P_SLTU = 0x72,
18216 NM_SOV = 0x7a,
18219 /* CRC32 instruction pool */
18220 enum {
18221 NM_CRC32B = 0x00,
18222 NM_CRC32H = 0x01,
18223 NM_CRC32W = 0x02,
18224 NM_CRC32CB = 0x04,
18225 NM_CRC32CH = 0x05,
18226 NM_CRC32CW = 0x06,
18229 /* POOL32A5 instruction pool */
18230 enum {
18231 NM_CMP_EQ_PH = 0x00,
18232 NM_CMP_LT_PH = 0x08,
18233 NM_CMP_LE_PH = 0x10,
18234 NM_CMPGU_EQ_QB = 0x18,
18235 NM_CMPGU_LT_QB = 0x20,
18236 NM_CMPGU_LE_QB = 0x28,
18237 NM_CMPGDU_EQ_QB = 0x30,
18238 NM_CMPGDU_LT_QB = 0x38,
18239 NM_CMPGDU_LE_QB = 0x40,
18240 NM_CMPU_EQ_QB = 0x48,
18241 NM_CMPU_LT_QB = 0x50,
18242 NM_CMPU_LE_QB = 0x58,
18243 NM_ADDQ_S_W = 0x60,
18244 NM_SUBQ_S_W = 0x68,
18245 NM_ADDSC = 0x70,
18246 NM_ADDWC = 0x78,
18248 NM_ADDQ_S_PH = 0x01,
18249 NM_ADDQH_R_PH = 0x09,
18250 NM_ADDQH_R_W = 0x11,
18251 NM_ADDU_S_QB = 0x19,
18252 NM_ADDU_S_PH = 0x21,
18253 NM_ADDUH_R_QB = 0x29,
18254 NM_SHRAV_R_PH = 0x31,
18255 NM_SHRAV_R_QB = 0x39,
18256 NM_SUBQ_S_PH = 0x41,
18257 NM_SUBQH_R_PH = 0x49,
18258 NM_SUBQH_R_W = 0x51,
18259 NM_SUBU_S_QB = 0x59,
18260 NM_SUBU_S_PH = 0x61,
18261 NM_SUBUH_R_QB = 0x69,
18262 NM_SHLLV_S_PH = 0x71,
18263 NM_PRECR_SRA_R_PH_W = 0x79,
18265 NM_MULEU_S_PH_QBL = 0x12,
18266 NM_MULEU_S_PH_QBR = 0x1a,
18267 NM_MULQ_RS_PH = 0x22,
18268 NM_MULQ_S_PH = 0x2a,
18269 NM_MULQ_RS_W = 0x32,
18270 NM_MULQ_S_W = 0x3a,
18271 NM_APPEND = 0x42,
18272 NM_MODSUB = 0x52,
18273 NM_SHRAV_R_W = 0x5a,
18274 NM_SHRLV_PH = 0x62,
18275 NM_SHRLV_QB = 0x6a,
18276 NM_SHLLV_QB = 0x72,
18277 NM_SHLLV_S_W = 0x7a,
18279 NM_SHILO = 0x03,
18281 NM_MULEQ_S_W_PHL = 0x04,
18282 NM_MULEQ_S_W_PHR = 0x0c,
18284 NM_MUL_S_PH = 0x05,
18285 NM_PRECR_QB_PH = 0x0d,
18286 NM_PRECRQ_QB_PH = 0x15,
18287 NM_PRECRQ_PH_W = 0x1d,
18288 NM_PRECRQ_RS_PH_W = 0x25,
18289 NM_PRECRQU_S_QB_PH = 0x2d,
18290 NM_PACKRL_PH = 0x35,
18291 NM_PICK_QB = 0x3d,
18292 NM_PICK_PH = 0x45,
18294 NM_SHRA_R_W = 0x5e,
18295 NM_SHRA_R_PH = 0x66,
18296 NM_SHLL_S_PH = 0x76,
18297 NM_SHLL_S_W = 0x7e,
18299 NM_REPL_PH = 0x07
18302 /* POOL32A7 instruction pool */
18303 enum {
18304 NM_P_LSX = 0x00,
18305 NM_LSA = 0x01,
18306 NM_EXTW = 0x03,
18307 NM_POOL32AXF = 0x07,
18310 /* P.SR instruction pool */
18311 enum {
18312 NM_PP_SR = 0x00,
18313 NM_P_SR_F = 0x01,
18316 /* P.SHIFT instruction pool */
18317 enum {
18318 NM_P_SLL = 0x00,
18319 NM_SRL = 0x02,
18320 NM_SRA = 0x04,
18321 NM_ROTR = 0x06,
18324 /* P.ROTX instruction pool */
18325 enum {
18326 NM_ROTX = 0x00,
18329 /* P.INS instruction pool */
18330 enum {
18331 NM_INS = 0x00,
18334 /* P.EXT instruction pool */
18335 enum {
18336 NM_EXT = 0x00,
18339 /* POOL32F_0 (fmt) instruction pool */
18340 enum {
18341 NM_RINT_S = 0x04,
18342 NM_RINT_D = 0x44,
18343 NM_ADD_S = 0x06,
18344 NM_SELEQZ_S = 0x07,
18345 NM_SELEQZ_D = 0x47,
18346 NM_CLASS_S = 0x0c,
18347 NM_CLASS_D = 0x4c,
18348 NM_SUB_S = 0x0e,
18349 NM_SELNEZ_S = 0x0f,
18350 NM_SELNEZ_D = 0x4f,
18351 NM_MUL_S = 0x16,
18352 NM_SEL_S = 0x17,
18353 NM_SEL_D = 0x57,
18354 NM_DIV_S = 0x1e,
18355 NM_ADD_D = 0x26,
18356 NM_SUB_D = 0x2e,
18357 NM_MUL_D = 0x36,
18358 NM_MADDF_S = 0x37,
18359 NM_MADDF_D = 0x77,
18360 NM_DIV_D = 0x3e,
18361 NM_MSUBF_S = 0x3f,
18362 NM_MSUBF_D = 0x7f,
18365 /* POOL32F_3 instruction pool */
18366 enum {
18367 NM_MIN_FMT = 0x00,
18368 NM_MAX_FMT = 0x01,
18369 NM_MINA_FMT = 0x04,
18370 NM_MAXA_FMT = 0x05,
18371 NM_POOL32FXF = 0x07,
18374 /* POOL32F_5 instruction pool */
18375 enum {
18376 NM_CMP_CONDN_S = 0x00,
18377 NM_CMP_CONDN_D = 0x02,
18380 /* P.GP.LH instruction pool */
18381 enum {
18382 NM_LHGP = 0x00,
18383 NM_LHUGP = 0x01,
18386 /* P.GP.SH instruction pool */
18387 enum {
18388 NM_SHGP = 0x00,
18391 /* P.GP.CP1 instruction pool */
18392 enum {
18393 NM_LWC1GP = 0x00,
18394 NM_SWC1GP = 0x01,
18395 NM_LDC1GP = 0x02,
18396 NM_SDC1GP = 0x03,
18399 /* P.LS.S0 instruction pool */
18400 enum {
18401 NM_LBS9 = 0x00,
18402 NM_LHS9 = 0x04,
18403 NM_LWS9 = 0x08,
18404 NM_LDS9 = 0x0c,
18406 NM_SBS9 = 0x01,
18407 NM_SHS9 = 0x05,
18408 NM_SWS9 = 0x09,
18409 NM_SDS9 = 0x0d,
18411 NM_LBUS9 = 0x02,
18412 NM_LHUS9 = 0x06,
18413 NM_LWC1S9 = 0x0a,
18414 NM_LDC1S9 = 0x0e,
18416 NM_P_PREFS9 = 0x03,
18417 NM_LWUS9 = 0x07,
18418 NM_SWC1S9 = 0x0b,
18419 NM_SDC1S9 = 0x0f,
18422 /* P.LS.S1 instruction pool */
18423 enum {
18424 NM_ASET_ACLR = 0x02,
18425 NM_UALH = 0x04,
18426 NM_UASH = 0x05,
18427 NM_CACHE = 0x07,
18428 NM_P_LL = 0x0a,
18429 NM_P_SC = 0x0b,
18432 /* P.LS.E0 instruction pool */
18433 enum {
18434 NM_LBE = 0x00,
18435 NM_SBE = 0x01,
18436 NM_LBUE = 0x02,
18437 NM_P_PREFE = 0x03,
18438 NM_LHE = 0x04,
18439 NM_SHE = 0x05,
18440 NM_LHUE = 0x06,
18441 NM_CACHEE = 0x07,
18442 NM_LWE = 0x08,
18443 NM_SWE = 0x09,
18444 NM_P_LLE = 0x0a,
18445 NM_P_SCE = 0x0b,
18448 /* P.PREFE instruction pool */
18449 enum {
18450 NM_SYNCIE = 0x00,
18451 NM_PREFE = 0x01,
18454 /* P.LLE instruction pool */
18455 enum {
18456 NM_LLE = 0x00,
18457 NM_LLWPE = 0x01,
18460 /* P.SCE instruction pool */
18461 enum {
18462 NM_SCE = 0x00,
18463 NM_SCWPE = 0x01,
18466 /* P.LS.WM instruction pool */
18467 enum {
18468 NM_LWM = 0x00,
18469 NM_SWM = 0x01,
18472 /* P.LS.UAWM instruction pool */
18473 enum {
18474 NM_UALWM = 0x00,
18475 NM_UASWM = 0x01,
18478 /* P.BR3A instruction pool */
18479 enum {
18480 NM_BC1EQZC = 0x00,
18481 NM_BC1NEZC = 0x01,
18482 NM_BC2EQZC = 0x02,
18483 NM_BC2NEZC = 0x03,
18484 NM_BPOSGE32C = 0x04,
18487 /* P16.RI instruction pool */
18488 enum {
18489 NM_P16_SYSCALL = 0x01,
18490 NM_BREAK16 = 0x02,
18491 NM_SDBBP16 = 0x03,
18494 /* POOL16C_0 instruction pool */
18495 enum {
18496 NM_POOL16C_00 = 0x00,
18499 /* P16.JRC instruction pool */
18500 enum {
18501 NM_JRC = 0x00,
18502 NM_JALRC16 = 0x01,
18505 /* P.SYSCALL instruction pool */
18506 enum {
18507 NM_SYSCALL = 0x00,
18508 NM_HYPCALL = 0x01,
18511 /* P.TRAP instruction pool */
18512 enum {
18513 NM_TEQ = 0x00,
18514 NM_TNE = 0x01,
18517 /* P.CMOVE instruction pool */
18518 enum {
18519 NM_MOVZ = 0x00,
18520 NM_MOVN = 0x01,
18523 /* POOL32Axf instruction pool */
18524 enum {
18525 NM_POOL32AXF_1 = 0x01,
18526 NM_POOL32AXF_2 = 0x02,
18527 NM_POOL32AXF_4 = 0x04,
18528 NM_POOL32AXF_5 = 0x05,
18529 NM_POOL32AXF_7 = 0x07,
18532 /* POOL32Axf_1 instruction pool */
18533 enum {
18534 NM_POOL32AXF_1_0 = 0x00,
18535 NM_POOL32AXF_1_1 = 0x01,
18536 NM_POOL32AXF_1_3 = 0x03,
18537 NM_POOL32AXF_1_4 = 0x04,
18538 NM_POOL32AXF_1_5 = 0x05,
18539 NM_POOL32AXF_1_7 = 0x07,
18542 /* POOL32Axf_2 instruction pool */
18543 enum {
18544 NM_POOL32AXF_2_0_7 = 0x00,
18545 NM_POOL32AXF_2_8_15 = 0x01,
18546 NM_POOL32AXF_2_16_23 = 0x02,
18547 NM_POOL32AXF_2_24_31 = 0x03,
18550 /* POOL32Axf_7 instruction pool */
18551 enum {
18552 NM_SHRA_R_QB = 0x0,
18553 NM_SHRL_PH = 0x1,
18554 NM_REPL_QB = 0x2,
18557 /* POOL32Axf_1_0 instruction pool */
18558 enum {
18559 NM_MFHI = 0x0,
18560 NM_MFLO = 0x1,
18561 NM_MTHI = 0x2,
18562 NM_MTLO = 0x3,
18565 /* POOL32Axf_1_1 instruction pool */
18566 enum {
18567 NM_MTHLIP = 0x0,
18568 NM_SHILOV = 0x1,
18571 /* POOL32Axf_1_3 instruction pool */
18572 enum {
18573 NM_RDDSP = 0x0,
18574 NM_WRDSP = 0x1,
18575 NM_EXTP = 0x2,
18576 NM_EXTPDP = 0x3,
18579 /* POOL32Axf_1_4 instruction pool */
18580 enum {
18581 NM_SHLL_QB = 0x0,
18582 NM_SHRL_QB = 0x1,
18585 /* POOL32Axf_1_5 instruction pool */
18586 enum {
18587 NM_MAQ_S_W_PHR = 0x0,
18588 NM_MAQ_S_W_PHL = 0x1,
18589 NM_MAQ_SA_W_PHR = 0x2,
18590 NM_MAQ_SA_W_PHL = 0x3,
18593 /* POOL32Axf_1_7 instruction pool */
18594 enum {
18595 NM_EXTR_W = 0x0,
18596 NM_EXTR_R_W = 0x1,
18597 NM_EXTR_RS_W = 0x2,
18598 NM_EXTR_S_H = 0x3,
18601 /* POOL32Axf_2_0_7 instruction pool */
18602 enum {
18603 NM_DPA_W_PH = 0x0,
18604 NM_DPAQ_S_W_PH = 0x1,
18605 NM_DPS_W_PH = 0x2,
18606 NM_DPSQ_S_W_PH = 0x3,
18607 NM_BALIGN = 0x4,
18608 NM_MADD = 0x5,
18609 NM_MULT = 0x6,
18610 NM_EXTRV_W = 0x7,
18613 /* POOL32Axf_2_8_15 instruction pool */
18614 enum {
18615 NM_DPAX_W_PH = 0x0,
18616 NM_DPAQ_SA_L_W = 0x1,
18617 NM_DPSX_W_PH = 0x2,
18618 NM_DPSQ_SA_L_W = 0x3,
18619 NM_MADDU = 0x5,
18620 NM_MULTU = 0x6,
18621 NM_EXTRV_R_W = 0x7,
18624 /* POOL32Axf_2_16_23 instruction pool */
18625 enum {
18626 NM_DPAU_H_QBL = 0x0,
18627 NM_DPAQX_S_W_PH = 0x1,
18628 NM_DPSU_H_QBL = 0x2,
18629 NM_DPSQX_S_W_PH = 0x3,
18630 NM_EXTPV = 0x4,
18631 NM_MSUB = 0x5,
18632 NM_MULSA_W_PH = 0x6,
18633 NM_EXTRV_RS_W = 0x7,
18636 /* POOL32Axf_2_24_31 instruction pool */
18637 enum {
18638 NM_DPAU_H_QBR = 0x0,
18639 NM_DPAQX_SA_W_PH = 0x1,
18640 NM_DPSU_H_QBR = 0x2,
18641 NM_DPSQX_SA_W_PH = 0x3,
18642 NM_EXTPDPV = 0x4,
18643 NM_MSUBU = 0x5,
18644 NM_MULSAQ_S_W_PH = 0x6,
18645 NM_EXTRV_S_H = 0x7,
18648 /* POOL32Axf_{4, 5} instruction pool */
18649 enum {
18650 NM_CLO = 0x25,
18651 NM_CLZ = 0x2d,
18653 NM_TLBP = 0x01,
18654 NM_TLBR = 0x09,
18655 NM_TLBWI = 0x11,
18656 NM_TLBWR = 0x19,
18657 NM_TLBINV = 0x03,
18658 NM_TLBINVF = 0x0b,
18659 NM_DI = 0x23,
18660 NM_EI = 0x2b,
18661 NM_RDPGPR = 0x70,
18662 NM_WRPGPR = 0x78,
18663 NM_WAIT = 0x61,
18664 NM_DERET = 0x71,
18665 NM_ERETX = 0x79,
18667 /* nanoMIPS DSP instructions */
18668 NM_ABSQ_S_QB = 0x00,
18669 NM_ABSQ_S_PH = 0x08,
18670 NM_ABSQ_S_W = 0x10,
18671 NM_PRECEQ_W_PHL = 0x28,
18672 NM_PRECEQ_W_PHR = 0x30,
18673 NM_PRECEQU_PH_QBL = 0x38,
18674 NM_PRECEQU_PH_QBR = 0x48,
18675 NM_PRECEU_PH_QBL = 0x58,
18676 NM_PRECEU_PH_QBR = 0x68,
18677 NM_PRECEQU_PH_QBLA = 0x39,
18678 NM_PRECEQU_PH_QBRA = 0x49,
18679 NM_PRECEU_PH_QBLA = 0x59,
18680 NM_PRECEU_PH_QBRA = 0x69,
18681 NM_REPLV_PH = 0x01,
18682 NM_REPLV_QB = 0x09,
18683 NM_BITREV = 0x18,
18684 NM_INSV = 0x20,
18685 NM_RADDU_W_QB = 0x78,
18687 NM_BITSWAP = 0x05,
18688 NM_WSBH = 0x3d,
18691 /* PP.SR instruction pool */
18692 enum {
18693 NM_SAVE = 0x00,
18694 NM_RESTORE = 0x02,
18695 NM_RESTORE_JRC = 0x03,
18698 /* P.SR.F instruction pool */
18699 enum {
18700 NM_SAVEF = 0x00,
18701 NM_RESTOREF = 0x01,
18704 /* P16.SYSCALL instruction pool */
18705 enum {
18706 NM_SYSCALL16 = 0x00,
18707 NM_HYPCALL16 = 0x01,
18710 /* POOL16C_00 instruction pool */
18711 enum {
18712 NM_NOT16 = 0x00,
18713 NM_XOR16 = 0x01,
18714 NM_AND16 = 0x02,
18715 NM_OR16 = 0x03,
18718 /* PP.LSX and PP.LSXS instruction pool */
18719 enum {
18720 NM_LBX = 0x00,
18721 NM_LHX = 0x04,
18722 NM_LWX = 0x08,
18723 NM_LDX = 0x0c,
18725 NM_SBX = 0x01,
18726 NM_SHX = 0x05,
18727 NM_SWX = 0x09,
18728 NM_SDX = 0x0d,
18730 NM_LBUX = 0x02,
18731 NM_LHUX = 0x06,
18732 NM_LWC1X = 0x0a,
18733 NM_LDC1X = 0x0e,
18735 NM_LWUX = 0x07,
18736 NM_SWC1X = 0x0b,
18737 NM_SDC1X = 0x0f,
18739 NM_LHXS = 0x04,
18740 NM_LWXS = 0x08,
18741 NM_LDXS = 0x0c,
18743 NM_SHXS = 0x05,
18744 NM_SWXS = 0x09,
18745 NM_SDXS = 0x0d,
18747 NM_LHUXS = 0x06,
18748 NM_LWC1XS = 0x0a,
18749 NM_LDC1XS = 0x0e,
18751 NM_LWUXS = 0x07,
18752 NM_SWC1XS = 0x0b,
18753 NM_SDC1XS = 0x0f,
18756 /* ERETx instruction pool */
18757 enum {
18758 NM_ERET = 0x00,
18759 NM_ERETNC = 0x01,
18762 /* POOL32FxF_{0, 1} insturction pool */
18763 enum {
18764 NM_CFC1 = 0x40,
18765 NM_CTC1 = 0x60,
18766 NM_MFC1 = 0x80,
18767 NM_MTC1 = 0xa0,
18768 NM_MFHC1 = 0xc0,
18769 NM_MTHC1 = 0xe0,
18771 NM_CVT_S_PL = 0x84,
18772 NM_CVT_S_PU = 0xa4,
18774 NM_CVT_L_S = 0x004,
18775 NM_CVT_L_D = 0x104,
18776 NM_CVT_W_S = 0x024,
18777 NM_CVT_W_D = 0x124,
18779 NM_RSQRT_S = 0x008,
18780 NM_RSQRT_D = 0x108,
18782 NM_SQRT_S = 0x028,
18783 NM_SQRT_D = 0x128,
18785 NM_RECIP_S = 0x048,
18786 NM_RECIP_D = 0x148,
18788 NM_FLOOR_L_S = 0x00c,
18789 NM_FLOOR_L_D = 0x10c,
18791 NM_FLOOR_W_S = 0x02c,
18792 NM_FLOOR_W_D = 0x12c,
18794 NM_CEIL_L_S = 0x04c,
18795 NM_CEIL_L_D = 0x14c,
18796 NM_CEIL_W_S = 0x06c,
18797 NM_CEIL_W_D = 0x16c,
18798 NM_TRUNC_L_S = 0x08c,
18799 NM_TRUNC_L_D = 0x18c,
18800 NM_TRUNC_W_S = 0x0ac,
18801 NM_TRUNC_W_D = 0x1ac,
18802 NM_ROUND_L_S = 0x0cc,
18803 NM_ROUND_L_D = 0x1cc,
18804 NM_ROUND_W_S = 0x0ec,
18805 NM_ROUND_W_D = 0x1ec,
18807 NM_MOV_S = 0x01,
18808 NM_MOV_D = 0x81,
18809 NM_ABS_S = 0x0d,
18810 NM_ABS_D = 0x8d,
18811 NM_NEG_S = 0x2d,
18812 NM_NEG_D = 0xad,
18813 NM_CVT_D_S = 0x04d,
18814 NM_CVT_D_W = 0x0cd,
18815 NM_CVT_D_L = 0x14d,
18816 NM_CVT_S_D = 0x06d,
18817 NM_CVT_S_W = 0x0ed,
18818 NM_CVT_S_L = 0x16d,
18821 /* P.LL instruction pool */
18822 enum {
18823 NM_LL = 0x00,
18824 NM_LLWP = 0x01,
18827 /* P.SC instruction pool */
18828 enum {
18829 NM_SC = 0x00,
18830 NM_SCWP = 0x01,
18833 /* P.DVP instruction pool */
18834 enum {
18835 NM_DVP = 0x00,
18836 NM_EVP = 0x01,
18842 * nanoMIPS decoding engine
18847 /* extraction utilities */
18849 #define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7)
18850 #define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7)
18851 #define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7)
18852 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18853 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18855 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
18856 static inline int decode_gpr_gpr3(int r)
18858 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
18860 return map[r & 0x7];
18863 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
18864 static inline int decode_gpr_gpr3_src_store(int r)
18866 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
18868 return map[r & 0x7];
18871 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
18872 static inline int decode_gpr_gpr4(int r)
18874 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
18875 16, 17, 18, 19, 20, 21, 22, 23 };
18877 return map[r & 0xf];
18880 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
18881 static inline int decode_gpr_gpr4_zero(int r)
18883 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
18884 16, 17, 18, 19, 20, 21, 22, 23 };
18886 return map[r & 0xf];
18890 static void gen_adjust_sp(DisasContext *ctx, int u)
18892 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
18895 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
18896 uint8_t gp, uint16_t u)
18898 int counter = 0;
18899 TCGv va = tcg_temp_new();
18900 TCGv t0 = tcg_temp_new();
18902 while (counter != count) {
18903 bool use_gp = gp && (counter == count - 1);
18904 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18905 int this_offset = -((counter + 1) << 2);
18906 gen_base_offset_addr(ctx, va, 29, this_offset);
18907 gen_load_gpr(t0, this_rt);
18908 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
18909 (MO_TEUL | ctx->default_tcg_memop_mask));
18910 counter++;
18913 /* adjust stack pointer */
18914 gen_adjust_sp(ctx, -u);
18916 tcg_temp_free(t0);
18917 tcg_temp_free(va);
18920 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
18921 uint8_t gp, uint16_t u)
18923 int counter = 0;
18924 TCGv va = tcg_temp_new();
18925 TCGv t0 = tcg_temp_new();
18927 while (counter != count) {
18928 bool use_gp = gp && (counter == count - 1);
18929 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18930 int this_offset = u - ((counter + 1) << 2);
18931 gen_base_offset_addr(ctx, va, 29, this_offset);
18932 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
18933 ctx->default_tcg_memop_mask);
18934 tcg_gen_ext32s_tl(t0, t0);
18935 gen_store_gpr(t0, this_rt);
18936 counter++;
18939 /* adjust stack pointer */
18940 gen_adjust_sp(ctx, u);
18942 tcg_temp_free(t0);
18943 tcg_temp_free(va);
18946 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
18948 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
18949 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
18951 switch (extract32(ctx->opcode, 2, 2)) {
18952 case NM_NOT16:
18953 gen_logic(ctx, OPC_NOR, rt, rs, 0);
18954 break;
18955 case NM_AND16:
18956 gen_logic(ctx, OPC_AND, rt, rt, rs);
18957 break;
18958 case NM_XOR16:
18959 gen_logic(ctx, OPC_XOR, rt, rt, rs);
18960 break;
18961 case NM_OR16:
18962 gen_logic(ctx, OPC_OR, rt, rt, rs);
18963 break;
18967 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18969 int rt = extract32(ctx->opcode, 21, 5);
18970 int rs = extract32(ctx->opcode, 16, 5);
18971 int rd = extract32(ctx->opcode, 11, 5);
18973 switch (extract32(ctx->opcode, 3, 7)) {
18974 case NM_P_TRAP:
18975 switch (extract32(ctx->opcode, 10, 1)) {
18976 case NM_TEQ:
18977 check_nms(ctx);
18978 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
18979 break;
18980 case NM_TNE:
18981 check_nms(ctx);
18982 gen_trap(ctx, OPC_TNE, rs, rt, -1);
18983 break;
18985 break;
18986 case NM_RDHWR:
18987 check_nms(ctx);
18988 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
18989 break;
18990 case NM_SEB:
18991 check_nms(ctx);
18992 gen_bshfl(ctx, OPC_SEB, rs, rt);
18993 break;
18994 case NM_SEH:
18995 gen_bshfl(ctx, OPC_SEH, rs, rt);
18996 break;
18997 case NM_SLLV:
18998 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
18999 break;
19000 case NM_SRLV:
19001 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
19002 break;
19003 case NM_SRAV:
19004 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
19005 break;
19006 case NM_ROTRV:
19007 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
19008 break;
19009 case NM_ADD:
19010 gen_arith(ctx, OPC_ADD, rd, rs, rt);
19011 break;
19012 case NM_ADDU:
19013 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
19014 break;
19015 case NM_SUB:
19016 check_nms(ctx);
19017 gen_arith(ctx, OPC_SUB, rd, rs, rt);
19018 break;
19019 case NM_SUBU:
19020 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
19021 break;
19022 case NM_P_CMOVE:
19023 switch (extract32(ctx->opcode, 10, 1)) {
19024 case NM_MOVZ:
19025 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
19026 break;
19027 case NM_MOVN:
19028 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
19029 break;
19031 break;
19032 case NM_AND:
19033 gen_logic(ctx, OPC_AND, rd, rs, rt);
19034 break;
19035 case NM_OR:
19036 gen_logic(ctx, OPC_OR, rd, rs, rt);
19037 break;
19038 case NM_NOR:
19039 gen_logic(ctx, OPC_NOR, rd, rs, rt);
19040 break;
19041 case NM_XOR:
19042 gen_logic(ctx, OPC_XOR, rd, rs, rt);
19043 break;
19044 case NM_SLT:
19045 gen_slt(ctx, OPC_SLT, rd, rs, rt);
19046 break;
19047 case NM_P_SLTU:
19048 if (rd == 0) {
19049 /* P_DVP */
19050 #ifndef CONFIG_USER_ONLY
19051 TCGv t0 = tcg_temp_new();
19052 switch (extract32(ctx->opcode, 10, 1)) {
19053 case NM_DVP:
19054 if (ctx->vp) {
19055 check_cp0_enabled(ctx);
19056 gen_helper_dvp(t0, cpu_env);
19057 gen_store_gpr(t0, rt);
19059 break;
19060 case NM_EVP:
19061 if (ctx->vp) {
19062 check_cp0_enabled(ctx);
19063 gen_helper_evp(t0, cpu_env);
19064 gen_store_gpr(t0, rt);
19066 break;
19068 tcg_temp_free(t0);
19069 #endif
19070 } else {
19071 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
19073 break;
19074 case NM_SOV:
19076 TCGv t0 = tcg_temp_new();
19077 TCGv t1 = tcg_temp_new();
19078 TCGv t2 = tcg_temp_new();
19080 gen_load_gpr(t1, rs);
19081 gen_load_gpr(t2, rt);
19082 tcg_gen_add_tl(t0, t1, t2);
19083 tcg_gen_ext32s_tl(t0, t0);
19084 tcg_gen_xor_tl(t1, t1, t2);
19085 tcg_gen_xor_tl(t2, t0, t2);
19086 tcg_gen_andc_tl(t1, t2, t1);
19088 /* operands of same sign, result different sign */
19089 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
19090 gen_store_gpr(t0, rd);
19092 tcg_temp_free(t0);
19093 tcg_temp_free(t1);
19094 tcg_temp_free(t2);
19096 break;
19097 case NM_MUL:
19098 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
19099 break;
19100 case NM_MUH:
19101 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
19102 break;
19103 case NM_MULU:
19104 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
19105 break;
19106 case NM_MUHU:
19107 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
19108 break;
19109 case NM_DIV:
19110 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
19111 break;
19112 case NM_MOD:
19113 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
19114 break;
19115 case NM_DIVU:
19116 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
19117 break;
19118 case NM_MODU:
19119 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
19120 break;
19121 #ifndef CONFIG_USER_ONLY
19122 case NM_MFC0:
19123 check_cp0_enabled(ctx);
19124 if (rt == 0) {
19125 /* Treat as NOP. */
19126 break;
19128 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
19129 break;
19130 case NM_MTC0:
19131 check_cp0_enabled(ctx);
19133 TCGv t0 = tcg_temp_new();
19135 gen_load_gpr(t0, rt);
19136 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
19137 tcg_temp_free(t0);
19139 break;
19140 case NM_D_E_MT_VPE:
19142 uint8_t sc = extract32(ctx->opcode, 10, 1);
19143 TCGv t0 = tcg_temp_new();
19145 switch (sc) {
19146 case 0:
19147 if (rs == 1) {
19148 /* DMT */
19149 check_cp0_mt(ctx);
19150 gen_helper_dmt(t0);
19151 gen_store_gpr(t0, rt);
19152 } else if (rs == 0) {
19153 /* DVPE */
19154 check_cp0_mt(ctx);
19155 gen_helper_dvpe(t0, cpu_env);
19156 gen_store_gpr(t0, rt);
19157 } else {
19158 gen_reserved_instruction(ctx);
19160 break;
19161 case 1:
19162 if (rs == 1) {
19163 /* EMT */
19164 check_cp0_mt(ctx);
19165 gen_helper_emt(t0);
19166 gen_store_gpr(t0, rt);
19167 } else if (rs == 0) {
19168 /* EVPE */
19169 check_cp0_mt(ctx);
19170 gen_helper_evpe(t0, cpu_env);
19171 gen_store_gpr(t0, rt);
19172 } else {
19173 gen_reserved_instruction(ctx);
19175 break;
19178 tcg_temp_free(t0);
19180 break;
19181 case NM_FORK:
19182 check_mt(ctx);
19184 TCGv t0 = tcg_temp_new();
19185 TCGv t1 = tcg_temp_new();
19187 gen_load_gpr(t0, rt);
19188 gen_load_gpr(t1, rs);
19189 gen_helper_fork(t0, t1);
19190 tcg_temp_free(t0);
19191 tcg_temp_free(t1);
19193 break;
19194 case NM_MFTR:
19195 case NM_MFHTR:
19196 check_cp0_enabled(ctx);
19197 if (rd == 0) {
19198 /* Treat as NOP. */
19199 return;
19201 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
19202 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
19203 break;
19204 case NM_MTTR:
19205 case NM_MTHTR:
19206 check_cp0_enabled(ctx);
19207 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
19208 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
19209 break;
19210 case NM_YIELD:
19211 check_mt(ctx);
19213 TCGv t0 = tcg_temp_new();
19215 gen_load_gpr(t0, rs);
19216 gen_helper_yield(t0, cpu_env, t0);
19217 gen_store_gpr(t0, rt);
19218 tcg_temp_free(t0);
19220 break;
19221 #endif
19222 default:
19223 gen_reserved_instruction(ctx);
19224 break;
19228 /* dsp */
19229 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
19230 int ret, int v1, int v2)
19232 TCGv_i32 t0;
19233 TCGv v0_t;
19234 TCGv v1_t;
19236 t0 = tcg_temp_new_i32();
19238 v0_t = tcg_temp_new();
19239 v1_t = tcg_temp_new();
19241 tcg_gen_movi_i32(t0, v2 >> 3);
19243 gen_load_gpr(v0_t, ret);
19244 gen_load_gpr(v1_t, v1);
19246 switch (opc) {
19247 case NM_MAQ_S_W_PHR:
19248 check_dsp(ctx);
19249 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
19250 break;
19251 case NM_MAQ_S_W_PHL:
19252 check_dsp(ctx);
19253 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
19254 break;
19255 case NM_MAQ_SA_W_PHR:
19256 check_dsp(ctx);
19257 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
19258 break;
19259 case NM_MAQ_SA_W_PHL:
19260 check_dsp(ctx);
19261 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
19262 break;
19263 default:
19264 gen_reserved_instruction(ctx);
19265 break;
19268 tcg_temp_free_i32(t0);
19270 tcg_temp_free(v0_t);
19271 tcg_temp_free(v1_t);
19275 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
19276 int ret, int v1, int v2)
19278 int16_t imm;
19279 TCGv t0 = tcg_temp_new();
19280 TCGv t1 = tcg_temp_new();
19281 TCGv v0_t = tcg_temp_new();
19283 gen_load_gpr(v0_t, v1);
19285 switch (opc) {
19286 case NM_POOL32AXF_1_0:
19287 check_dsp(ctx);
19288 switch (extract32(ctx->opcode, 12, 2)) {
19289 case NM_MFHI:
19290 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
19291 break;
19292 case NM_MFLO:
19293 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
19294 break;
19295 case NM_MTHI:
19296 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
19297 break;
19298 case NM_MTLO:
19299 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
19300 break;
19302 break;
19303 case NM_POOL32AXF_1_1:
19304 check_dsp(ctx);
19305 switch (extract32(ctx->opcode, 12, 2)) {
19306 case NM_MTHLIP:
19307 tcg_gen_movi_tl(t0, v2);
19308 gen_helper_mthlip(t0, v0_t, cpu_env);
19309 break;
19310 case NM_SHILOV:
19311 tcg_gen_movi_tl(t0, v2 >> 3);
19312 gen_helper_shilo(t0, v0_t, cpu_env);
19313 break;
19314 default:
19315 gen_reserved_instruction(ctx);
19316 break;
19318 break;
19319 case NM_POOL32AXF_1_3:
19320 check_dsp(ctx);
19321 imm = extract32(ctx->opcode, 14, 7);
19322 switch (extract32(ctx->opcode, 12, 2)) {
19323 case NM_RDDSP:
19324 tcg_gen_movi_tl(t0, imm);
19325 gen_helper_rddsp(t0, t0, cpu_env);
19326 gen_store_gpr(t0, ret);
19327 break;
19328 case NM_WRDSP:
19329 gen_load_gpr(t0, ret);
19330 tcg_gen_movi_tl(t1, imm);
19331 gen_helper_wrdsp(t0, t1, cpu_env);
19332 break;
19333 case NM_EXTP:
19334 tcg_gen_movi_tl(t0, v2 >> 3);
19335 tcg_gen_movi_tl(t1, v1);
19336 gen_helper_extp(t0, t0, t1, cpu_env);
19337 gen_store_gpr(t0, ret);
19338 break;
19339 case NM_EXTPDP:
19340 tcg_gen_movi_tl(t0, v2 >> 3);
19341 tcg_gen_movi_tl(t1, v1);
19342 gen_helper_extpdp(t0, t0, t1, cpu_env);
19343 gen_store_gpr(t0, ret);
19344 break;
19346 break;
19347 case NM_POOL32AXF_1_4:
19348 check_dsp(ctx);
19349 tcg_gen_movi_tl(t0, v2 >> 2);
19350 switch (extract32(ctx->opcode, 12, 1)) {
19351 case NM_SHLL_QB:
19352 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
19353 gen_store_gpr(t0, ret);
19354 break;
19355 case NM_SHRL_QB:
19356 gen_helper_shrl_qb(t0, t0, v0_t);
19357 gen_store_gpr(t0, ret);
19358 break;
19360 break;
19361 case NM_POOL32AXF_1_5:
19362 opc = extract32(ctx->opcode, 12, 2);
19363 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
19364 break;
19365 case NM_POOL32AXF_1_7:
19366 check_dsp(ctx);
19367 tcg_gen_movi_tl(t0, v2 >> 3);
19368 tcg_gen_movi_tl(t1, v1);
19369 switch (extract32(ctx->opcode, 12, 2)) {
19370 case NM_EXTR_W:
19371 gen_helper_extr_w(t0, t0, t1, cpu_env);
19372 gen_store_gpr(t0, ret);
19373 break;
19374 case NM_EXTR_R_W:
19375 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
19376 gen_store_gpr(t0, ret);
19377 break;
19378 case NM_EXTR_RS_W:
19379 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
19380 gen_store_gpr(t0, ret);
19381 break;
19382 case NM_EXTR_S_H:
19383 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
19384 gen_store_gpr(t0, ret);
19385 break;
19387 break;
19388 default:
19389 gen_reserved_instruction(ctx);
19390 break;
19393 tcg_temp_free(t0);
19394 tcg_temp_free(t1);
19395 tcg_temp_free(v0_t);
19398 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
19399 TCGv v0, TCGv v1, int rd)
19401 TCGv_i32 t0;
19403 t0 = tcg_temp_new_i32();
19405 tcg_gen_movi_i32(t0, rd >> 3);
19407 switch (opc) {
19408 case NM_POOL32AXF_2_0_7:
19409 switch (extract32(ctx->opcode, 9, 3)) {
19410 case NM_DPA_W_PH:
19411 check_dsp_r2(ctx);
19412 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
19413 break;
19414 case NM_DPAQ_S_W_PH:
19415 check_dsp(ctx);
19416 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
19417 break;
19418 case NM_DPS_W_PH:
19419 check_dsp_r2(ctx);
19420 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
19421 break;
19422 case NM_DPSQ_S_W_PH:
19423 check_dsp(ctx);
19424 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
19425 break;
19426 default:
19427 gen_reserved_instruction(ctx);
19428 break;
19430 break;
19431 case NM_POOL32AXF_2_8_15:
19432 switch (extract32(ctx->opcode, 9, 3)) {
19433 case NM_DPAX_W_PH:
19434 check_dsp_r2(ctx);
19435 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
19436 break;
19437 case NM_DPAQ_SA_L_W:
19438 check_dsp(ctx);
19439 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
19440 break;
19441 case NM_DPSX_W_PH:
19442 check_dsp_r2(ctx);
19443 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
19444 break;
19445 case NM_DPSQ_SA_L_W:
19446 check_dsp(ctx);
19447 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
19448 break;
19449 default:
19450 gen_reserved_instruction(ctx);
19451 break;
19453 break;
19454 case NM_POOL32AXF_2_16_23:
19455 switch (extract32(ctx->opcode, 9, 3)) {
19456 case NM_DPAU_H_QBL:
19457 check_dsp(ctx);
19458 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
19459 break;
19460 case NM_DPAQX_S_W_PH:
19461 check_dsp_r2(ctx);
19462 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
19463 break;
19464 case NM_DPSU_H_QBL:
19465 check_dsp(ctx);
19466 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
19467 break;
19468 case NM_DPSQX_S_W_PH:
19469 check_dsp_r2(ctx);
19470 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
19471 break;
19472 case NM_MULSA_W_PH:
19473 check_dsp_r2(ctx);
19474 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
19475 break;
19476 default:
19477 gen_reserved_instruction(ctx);
19478 break;
19480 break;
19481 case NM_POOL32AXF_2_24_31:
19482 switch (extract32(ctx->opcode, 9, 3)) {
19483 case NM_DPAU_H_QBR:
19484 check_dsp(ctx);
19485 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
19486 break;
19487 case NM_DPAQX_SA_W_PH:
19488 check_dsp_r2(ctx);
19489 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
19490 break;
19491 case NM_DPSU_H_QBR:
19492 check_dsp(ctx);
19493 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
19494 break;
19495 case NM_DPSQX_SA_W_PH:
19496 check_dsp_r2(ctx);
19497 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
19498 break;
19499 case NM_MULSAQ_S_W_PH:
19500 check_dsp(ctx);
19501 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
19502 break;
19503 default:
19504 gen_reserved_instruction(ctx);
19505 break;
19507 break;
19508 default:
19509 gen_reserved_instruction(ctx);
19510 break;
19513 tcg_temp_free_i32(t0);
19516 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
19517 int rt, int rs, int rd)
19519 int ret = rt;
19520 TCGv t0 = tcg_temp_new();
19521 TCGv t1 = tcg_temp_new();
19522 TCGv v0_t = tcg_temp_new();
19523 TCGv v1_t = tcg_temp_new();
19525 gen_load_gpr(v0_t, rt);
19526 gen_load_gpr(v1_t, rs);
19528 switch (opc) {
19529 case NM_POOL32AXF_2_0_7:
19530 switch (extract32(ctx->opcode, 9, 3)) {
19531 case NM_DPA_W_PH:
19532 case NM_DPAQ_S_W_PH:
19533 case NM_DPS_W_PH:
19534 case NM_DPSQ_S_W_PH:
19535 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19536 break;
19537 case NM_BALIGN:
19538 check_dsp_r2(ctx);
19539 if (rt != 0) {
19540 gen_load_gpr(t0, rs);
19541 rd &= 3;
19542 if (rd != 0 && rd != 2) {
19543 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
19544 tcg_gen_ext32u_tl(t0, t0);
19545 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
19546 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19548 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
19550 break;
19551 case NM_MADD:
19552 check_dsp(ctx);
19554 int acc = extract32(ctx->opcode, 14, 2);
19555 TCGv_i64 t2 = tcg_temp_new_i64();
19556 TCGv_i64 t3 = tcg_temp_new_i64();
19558 gen_load_gpr(t0, rt);
19559 gen_load_gpr(t1, rs);
19560 tcg_gen_ext_tl_i64(t2, t0);
19561 tcg_gen_ext_tl_i64(t3, t1);
19562 tcg_gen_mul_i64(t2, t2, t3);
19563 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19564 tcg_gen_add_i64(t2, t2, t3);
19565 tcg_temp_free_i64(t3);
19566 gen_move_low32(cpu_LO[acc], t2);
19567 gen_move_high32(cpu_HI[acc], t2);
19568 tcg_temp_free_i64(t2);
19570 break;
19571 case NM_MULT:
19572 check_dsp(ctx);
19574 int acc = extract32(ctx->opcode, 14, 2);
19575 TCGv_i32 t2 = tcg_temp_new_i32();
19576 TCGv_i32 t3 = tcg_temp_new_i32();
19578 gen_load_gpr(t0, rs);
19579 gen_load_gpr(t1, rt);
19580 tcg_gen_trunc_tl_i32(t2, t0);
19581 tcg_gen_trunc_tl_i32(t3, t1);
19582 tcg_gen_muls2_i32(t2, t3, t2, t3);
19583 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19584 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19585 tcg_temp_free_i32(t2);
19586 tcg_temp_free_i32(t3);
19588 break;
19589 case NM_EXTRV_W:
19590 check_dsp(ctx);
19591 gen_load_gpr(v1_t, rs);
19592 tcg_gen_movi_tl(t0, rd >> 3);
19593 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
19594 gen_store_gpr(t0, ret);
19595 break;
19597 break;
19598 case NM_POOL32AXF_2_8_15:
19599 switch (extract32(ctx->opcode, 9, 3)) {
19600 case NM_DPAX_W_PH:
19601 case NM_DPAQ_SA_L_W:
19602 case NM_DPSX_W_PH:
19603 case NM_DPSQ_SA_L_W:
19604 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19605 break;
19606 case NM_MADDU:
19607 check_dsp(ctx);
19609 int acc = extract32(ctx->opcode, 14, 2);
19610 TCGv_i64 t2 = tcg_temp_new_i64();
19611 TCGv_i64 t3 = tcg_temp_new_i64();
19613 gen_load_gpr(t0, rs);
19614 gen_load_gpr(t1, rt);
19615 tcg_gen_ext32u_tl(t0, t0);
19616 tcg_gen_ext32u_tl(t1, t1);
19617 tcg_gen_extu_tl_i64(t2, t0);
19618 tcg_gen_extu_tl_i64(t3, t1);
19619 tcg_gen_mul_i64(t2, t2, t3);
19620 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19621 tcg_gen_add_i64(t2, t2, t3);
19622 tcg_temp_free_i64(t3);
19623 gen_move_low32(cpu_LO[acc], t2);
19624 gen_move_high32(cpu_HI[acc], t2);
19625 tcg_temp_free_i64(t2);
19627 break;
19628 case NM_MULTU:
19629 check_dsp(ctx);
19631 int acc = extract32(ctx->opcode, 14, 2);
19632 TCGv_i32 t2 = tcg_temp_new_i32();
19633 TCGv_i32 t3 = tcg_temp_new_i32();
19635 gen_load_gpr(t0, rs);
19636 gen_load_gpr(t1, rt);
19637 tcg_gen_trunc_tl_i32(t2, t0);
19638 tcg_gen_trunc_tl_i32(t3, t1);
19639 tcg_gen_mulu2_i32(t2, t3, t2, t3);
19640 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19641 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19642 tcg_temp_free_i32(t2);
19643 tcg_temp_free_i32(t3);
19645 break;
19646 case NM_EXTRV_R_W:
19647 check_dsp(ctx);
19648 tcg_gen_movi_tl(t0, rd >> 3);
19649 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
19650 gen_store_gpr(t0, ret);
19651 break;
19652 default:
19653 gen_reserved_instruction(ctx);
19654 break;
19656 break;
19657 case NM_POOL32AXF_2_16_23:
19658 switch (extract32(ctx->opcode, 9, 3)) {
19659 case NM_DPAU_H_QBL:
19660 case NM_DPAQX_S_W_PH:
19661 case NM_DPSU_H_QBL:
19662 case NM_DPSQX_S_W_PH:
19663 case NM_MULSA_W_PH:
19664 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19665 break;
19666 case NM_EXTPV:
19667 check_dsp(ctx);
19668 tcg_gen_movi_tl(t0, rd >> 3);
19669 gen_helper_extp(t0, t0, v1_t, cpu_env);
19670 gen_store_gpr(t0, ret);
19671 break;
19672 case NM_MSUB:
19673 check_dsp(ctx);
19675 int acc = extract32(ctx->opcode, 14, 2);
19676 TCGv_i64 t2 = tcg_temp_new_i64();
19677 TCGv_i64 t3 = tcg_temp_new_i64();
19679 gen_load_gpr(t0, rs);
19680 gen_load_gpr(t1, rt);
19681 tcg_gen_ext_tl_i64(t2, t0);
19682 tcg_gen_ext_tl_i64(t3, t1);
19683 tcg_gen_mul_i64(t2, t2, t3);
19684 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19685 tcg_gen_sub_i64(t2, t3, t2);
19686 tcg_temp_free_i64(t3);
19687 gen_move_low32(cpu_LO[acc], t2);
19688 gen_move_high32(cpu_HI[acc], t2);
19689 tcg_temp_free_i64(t2);
19691 break;
19692 case NM_EXTRV_RS_W:
19693 check_dsp(ctx);
19694 tcg_gen_movi_tl(t0, rd >> 3);
19695 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
19696 gen_store_gpr(t0, ret);
19697 break;
19699 break;
19700 case NM_POOL32AXF_2_24_31:
19701 switch (extract32(ctx->opcode, 9, 3)) {
19702 case NM_DPAU_H_QBR:
19703 case NM_DPAQX_SA_W_PH:
19704 case NM_DPSU_H_QBR:
19705 case NM_DPSQX_SA_W_PH:
19706 case NM_MULSAQ_S_W_PH:
19707 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19708 break;
19709 case NM_EXTPDPV:
19710 check_dsp(ctx);
19711 tcg_gen_movi_tl(t0, rd >> 3);
19712 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
19713 gen_store_gpr(t0, ret);
19714 break;
19715 case NM_MSUBU:
19716 check_dsp(ctx);
19718 int acc = extract32(ctx->opcode, 14, 2);
19719 TCGv_i64 t2 = tcg_temp_new_i64();
19720 TCGv_i64 t3 = tcg_temp_new_i64();
19722 gen_load_gpr(t0, rs);
19723 gen_load_gpr(t1, rt);
19724 tcg_gen_ext32u_tl(t0, t0);
19725 tcg_gen_ext32u_tl(t1, t1);
19726 tcg_gen_extu_tl_i64(t2, t0);
19727 tcg_gen_extu_tl_i64(t3, t1);
19728 tcg_gen_mul_i64(t2, t2, t3);
19729 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19730 tcg_gen_sub_i64(t2, t3, t2);
19731 tcg_temp_free_i64(t3);
19732 gen_move_low32(cpu_LO[acc], t2);
19733 gen_move_high32(cpu_HI[acc], t2);
19734 tcg_temp_free_i64(t2);
19736 break;
19737 case NM_EXTRV_S_H:
19738 check_dsp(ctx);
19739 tcg_gen_movi_tl(t0, rd >> 3);
19740 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
19741 gen_store_gpr(t0, ret);
19742 break;
19744 break;
19745 default:
19746 gen_reserved_instruction(ctx);
19747 break;
19750 tcg_temp_free(t0);
19751 tcg_temp_free(t1);
19753 tcg_temp_free(v0_t);
19754 tcg_temp_free(v1_t);
19757 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
19758 int rt, int rs)
19760 int ret = rt;
19761 TCGv t0 = tcg_temp_new();
19762 TCGv v0_t = tcg_temp_new();
19764 gen_load_gpr(v0_t, rs);
19766 switch (opc) {
19767 case NM_ABSQ_S_QB:
19768 check_dsp_r2(ctx);
19769 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
19770 gen_store_gpr(v0_t, ret);
19771 break;
19772 case NM_ABSQ_S_PH:
19773 check_dsp(ctx);
19774 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
19775 gen_store_gpr(v0_t, ret);
19776 break;
19777 case NM_ABSQ_S_W:
19778 check_dsp(ctx);
19779 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
19780 gen_store_gpr(v0_t, ret);
19781 break;
19782 case NM_PRECEQ_W_PHL:
19783 check_dsp(ctx);
19784 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
19785 tcg_gen_ext32s_tl(v0_t, v0_t);
19786 gen_store_gpr(v0_t, ret);
19787 break;
19788 case NM_PRECEQ_W_PHR:
19789 check_dsp(ctx);
19790 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
19791 tcg_gen_shli_tl(v0_t, v0_t, 16);
19792 tcg_gen_ext32s_tl(v0_t, v0_t);
19793 gen_store_gpr(v0_t, ret);
19794 break;
19795 case NM_PRECEQU_PH_QBL:
19796 check_dsp(ctx);
19797 gen_helper_precequ_ph_qbl(v0_t, v0_t);
19798 gen_store_gpr(v0_t, ret);
19799 break;
19800 case NM_PRECEQU_PH_QBR:
19801 check_dsp(ctx);
19802 gen_helper_precequ_ph_qbr(v0_t, v0_t);
19803 gen_store_gpr(v0_t, ret);
19804 break;
19805 case NM_PRECEQU_PH_QBLA:
19806 check_dsp(ctx);
19807 gen_helper_precequ_ph_qbla(v0_t, v0_t);
19808 gen_store_gpr(v0_t, ret);
19809 break;
19810 case NM_PRECEQU_PH_QBRA:
19811 check_dsp(ctx);
19812 gen_helper_precequ_ph_qbra(v0_t, v0_t);
19813 gen_store_gpr(v0_t, ret);
19814 break;
19815 case NM_PRECEU_PH_QBL:
19816 check_dsp(ctx);
19817 gen_helper_preceu_ph_qbl(v0_t, v0_t);
19818 gen_store_gpr(v0_t, ret);
19819 break;
19820 case NM_PRECEU_PH_QBR:
19821 check_dsp(ctx);
19822 gen_helper_preceu_ph_qbr(v0_t, v0_t);
19823 gen_store_gpr(v0_t, ret);
19824 break;
19825 case NM_PRECEU_PH_QBLA:
19826 check_dsp(ctx);
19827 gen_helper_preceu_ph_qbla(v0_t, v0_t);
19828 gen_store_gpr(v0_t, ret);
19829 break;
19830 case NM_PRECEU_PH_QBRA:
19831 check_dsp(ctx);
19832 gen_helper_preceu_ph_qbra(v0_t, v0_t);
19833 gen_store_gpr(v0_t, ret);
19834 break;
19835 case NM_REPLV_PH:
19836 check_dsp(ctx);
19837 tcg_gen_ext16u_tl(v0_t, v0_t);
19838 tcg_gen_shli_tl(t0, v0_t, 16);
19839 tcg_gen_or_tl(v0_t, v0_t, t0);
19840 tcg_gen_ext32s_tl(v0_t, v0_t);
19841 gen_store_gpr(v0_t, ret);
19842 break;
19843 case NM_REPLV_QB:
19844 check_dsp(ctx);
19845 tcg_gen_ext8u_tl(v0_t, v0_t);
19846 tcg_gen_shli_tl(t0, v0_t, 8);
19847 tcg_gen_or_tl(v0_t, v0_t, t0);
19848 tcg_gen_shli_tl(t0, v0_t, 16);
19849 tcg_gen_or_tl(v0_t, v0_t, t0);
19850 tcg_gen_ext32s_tl(v0_t, v0_t);
19851 gen_store_gpr(v0_t, ret);
19852 break;
19853 case NM_BITREV:
19854 check_dsp(ctx);
19855 gen_helper_bitrev(v0_t, v0_t);
19856 gen_store_gpr(v0_t, ret);
19857 break;
19858 case NM_INSV:
19859 check_dsp(ctx);
19861 TCGv tv0 = tcg_temp_new();
19863 gen_load_gpr(tv0, rt);
19864 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
19865 gen_store_gpr(v0_t, ret);
19866 tcg_temp_free(tv0);
19868 break;
19869 case NM_RADDU_W_QB:
19870 check_dsp(ctx);
19871 gen_helper_raddu_w_qb(v0_t, v0_t);
19872 gen_store_gpr(v0_t, ret);
19873 break;
19874 case NM_BITSWAP:
19875 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
19876 break;
19877 case NM_CLO:
19878 check_nms(ctx);
19879 gen_cl(ctx, OPC_CLO, ret, rs);
19880 break;
19881 case NM_CLZ:
19882 check_nms(ctx);
19883 gen_cl(ctx, OPC_CLZ, ret, rs);
19884 break;
19885 case NM_WSBH:
19886 gen_bshfl(ctx, OPC_WSBH, ret, rs);
19887 break;
19888 default:
19889 gen_reserved_instruction(ctx);
19890 break;
19893 tcg_temp_free(v0_t);
19894 tcg_temp_free(t0);
19897 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
19898 int rt, int rs, int rd)
19900 TCGv t0 = tcg_temp_new();
19901 TCGv rs_t = tcg_temp_new();
19903 gen_load_gpr(rs_t, rs);
19905 switch (opc) {
19906 case NM_SHRA_R_QB:
19907 check_dsp_r2(ctx);
19908 tcg_gen_movi_tl(t0, rd >> 2);
19909 switch (extract32(ctx->opcode, 12, 1)) {
19910 case 0:
19911 /* NM_SHRA_QB */
19912 gen_helper_shra_qb(t0, t0, rs_t);
19913 gen_store_gpr(t0, rt);
19914 break;
19915 case 1:
19916 /* NM_SHRA_R_QB */
19917 gen_helper_shra_r_qb(t0, t0, rs_t);
19918 gen_store_gpr(t0, rt);
19919 break;
19921 break;
19922 case NM_SHRL_PH:
19923 check_dsp_r2(ctx);
19924 tcg_gen_movi_tl(t0, rd >> 1);
19925 gen_helper_shrl_ph(t0, t0, rs_t);
19926 gen_store_gpr(t0, rt);
19927 break;
19928 case NM_REPL_QB:
19929 check_dsp(ctx);
19931 int16_t imm;
19932 target_long result;
19933 imm = extract32(ctx->opcode, 13, 8);
19934 result = (uint32_t)imm << 24 |
19935 (uint32_t)imm << 16 |
19936 (uint32_t)imm << 8 |
19937 (uint32_t)imm;
19938 result = (int32_t)result;
19939 tcg_gen_movi_tl(t0, result);
19940 gen_store_gpr(t0, rt);
19942 break;
19943 default:
19944 gen_reserved_instruction(ctx);
19945 break;
19947 tcg_temp_free(t0);
19948 tcg_temp_free(rs_t);
19952 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19954 int rt = extract32(ctx->opcode, 21, 5);
19955 int rs = extract32(ctx->opcode, 16, 5);
19956 int rd = extract32(ctx->opcode, 11, 5);
19958 switch (extract32(ctx->opcode, 6, 3)) {
19959 case NM_POOL32AXF_1:
19961 int32_t op1 = extract32(ctx->opcode, 9, 3);
19962 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
19964 break;
19965 case NM_POOL32AXF_2:
19967 int32_t op1 = extract32(ctx->opcode, 12, 2);
19968 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
19970 break;
19971 case NM_POOL32AXF_4:
19973 int32_t op1 = extract32(ctx->opcode, 9, 7);
19974 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
19976 break;
19977 case NM_POOL32AXF_5:
19978 switch (extract32(ctx->opcode, 9, 7)) {
19979 #ifndef CONFIG_USER_ONLY
19980 case NM_TLBP:
19981 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
19982 break;
19983 case NM_TLBR:
19984 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
19985 break;
19986 case NM_TLBWI:
19987 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
19988 break;
19989 case NM_TLBWR:
19990 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
19991 break;
19992 case NM_TLBINV:
19993 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
19994 break;
19995 case NM_TLBINVF:
19996 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
19997 break;
19998 case NM_DI:
19999 check_cp0_enabled(ctx);
20001 TCGv t0 = tcg_temp_new();
20003 save_cpu_state(ctx, 1);
20004 gen_helper_di(t0, cpu_env);
20005 gen_store_gpr(t0, rt);
20006 /* Stop translation as we may have switched the execution mode */
20007 ctx->base.is_jmp = DISAS_STOP;
20008 tcg_temp_free(t0);
20010 break;
20011 case NM_EI:
20012 check_cp0_enabled(ctx);
20014 TCGv t0 = tcg_temp_new();
20016 save_cpu_state(ctx, 1);
20017 gen_helper_ei(t0, cpu_env);
20018 gen_store_gpr(t0, rt);
20019 /* Stop translation as we may have switched the execution mode */
20020 ctx->base.is_jmp = DISAS_STOP;
20021 tcg_temp_free(t0);
20023 break;
20024 case NM_RDPGPR:
20025 gen_load_srsgpr(rs, rt);
20026 break;
20027 case NM_WRPGPR:
20028 gen_store_srsgpr(rs, rt);
20029 break;
20030 case NM_WAIT:
20031 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
20032 break;
20033 case NM_DERET:
20034 gen_cp0(env, ctx, OPC_DERET, 0, 0);
20035 break;
20036 case NM_ERETX:
20037 gen_cp0(env, ctx, OPC_ERET, 0, 0);
20038 break;
20039 #endif
20040 default:
20041 gen_reserved_instruction(ctx);
20042 break;
20044 break;
20045 case NM_POOL32AXF_7:
20047 int32_t op1 = extract32(ctx->opcode, 9, 3);
20048 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
20050 break;
20051 default:
20052 gen_reserved_instruction(ctx);
20053 break;
20057 /* Immediate Value Compact Branches */
20058 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
20059 int rt, int32_t imm, int32_t offset)
20061 TCGCond cond = TCG_COND_ALWAYS;
20062 TCGv t0 = tcg_temp_new();
20063 TCGv t1 = tcg_temp_new();
20065 gen_load_gpr(t0, rt);
20066 tcg_gen_movi_tl(t1, imm);
20067 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20069 /* Load needed operands and calculate btarget */
20070 switch (opc) {
20071 case NM_BEQIC:
20072 if (rt == 0 && imm == 0) {
20073 /* Unconditional branch */
20074 } else if (rt == 0 && imm != 0) {
20075 /* Treat as NOP */
20076 goto out;
20077 } else {
20078 cond = TCG_COND_EQ;
20080 break;
20081 case NM_BBEQZC:
20082 case NM_BBNEZC:
20083 check_nms(ctx);
20084 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
20085 gen_reserved_instruction(ctx);
20086 goto out;
20087 } else if (rt == 0 && opc == NM_BBEQZC) {
20088 /* Unconditional branch */
20089 } else if (rt == 0 && opc == NM_BBNEZC) {
20090 /* Treat as NOP */
20091 goto out;
20092 } else {
20093 tcg_gen_shri_tl(t0, t0, imm);
20094 tcg_gen_andi_tl(t0, t0, 1);
20095 tcg_gen_movi_tl(t1, 0);
20096 if (opc == NM_BBEQZC) {
20097 cond = TCG_COND_EQ;
20098 } else {
20099 cond = TCG_COND_NE;
20102 break;
20103 case NM_BNEIC:
20104 if (rt == 0 && imm == 0) {
20105 /* Treat as NOP */
20106 goto out;
20107 } else if (rt == 0 && imm != 0) {
20108 /* Unconditional branch */
20109 } else {
20110 cond = TCG_COND_NE;
20112 break;
20113 case NM_BGEIC:
20114 if (rt == 0 && imm == 0) {
20115 /* Unconditional branch */
20116 } else {
20117 cond = TCG_COND_GE;
20119 break;
20120 case NM_BLTIC:
20121 cond = TCG_COND_LT;
20122 break;
20123 case NM_BGEIUC:
20124 if (rt == 0 && imm == 0) {
20125 /* Unconditional branch */
20126 } else {
20127 cond = TCG_COND_GEU;
20129 break;
20130 case NM_BLTIUC:
20131 cond = TCG_COND_LTU;
20132 break;
20133 default:
20134 MIPS_INVAL("Immediate Value Compact branch");
20135 gen_reserved_instruction(ctx);
20136 goto out;
20139 /* branch completion */
20140 clear_branch_hflags(ctx);
20141 ctx->base.is_jmp = DISAS_NORETURN;
20143 if (cond == TCG_COND_ALWAYS) {
20144 /* Uncoditional compact branch */
20145 gen_goto_tb(ctx, 0, ctx->btarget);
20146 } else {
20147 /* Conditional compact branch */
20148 TCGLabel *fs = gen_new_label();
20150 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
20152 gen_goto_tb(ctx, 1, ctx->btarget);
20153 gen_set_label(fs);
20155 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20158 out:
20159 tcg_temp_free(t0);
20160 tcg_temp_free(t1);
20163 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
20164 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
20165 int rt)
20167 TCGv t0 = tcg_temp_new();
20168 TCGv t1 = tcg_temp_new();
20170 /* load rs */
20171 gen_load_gpr(t0, rs);
20173 /* link */
20174 if (rt != 0) {
20175 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
20178 /* calculate btarget */
20179 tcg_gen_shli_tl(t0, t0, 1);
20180 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
20181 gen_op_addr_add(ctx, btarget, t1, t0);
20183 /* branch completion */
20184 clear_branch_hflags(ctx);
20185 ctx->base.is_jmp = DISAS_NORETURN;
20187 /* unconditional branch to register */
20188 tcg_gen_mov_tl(cpu_PC, btarget);
20189 tcg_gen_lookup_and_goto_ptr();
20191 tcg_temp_free(t0);
20192 tcg_temp_free(t1);
20195 /* nanoMIPS Branches */
20196 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
20197 int rs, int rt, int32_t offset)
20199 int bcond_compute = 0;
20200 TCGv t0 = tcg_temp_new();
20201 TCGv t1 = tcg_temp_new();
20203 /* Load needed operands and calculate btarget */
20204 switch (opc) {
20205 /* compact branch */
20206 case OPC_BGEC:
20207 case OPC_BLTC:
20208 gen_load_gpr(t0, rs);
20209 gen_load_gpr(t1, rt);
20210 bcond_compute = 1;
20211 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20212 break;
20213 case OPC_BGEUC:
20214 case OPC_BLTUC:
20215 if (rs == 0 || rs == rt) {
20216 /* OPC_BLEZALC, OPC_BGEZALC */
20217 /* OPC_BGTZALC, OPC_BLTZALC */
20218 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
20220 gen_load_gpr(t0, rs);
20221 gen_load_gpr(t1, rt);
20222 bcond_compute = 1;
20223 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20224 break;
20225 case OPC_BC:
20226 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20227 break;
20228 case OPC_BEQZC:
20229 if (rs != 0) {
20230 /* OPC_BEQZC, OPC_BNEZC */
20231 gen_load_gpr(t0, rs);
20232 bcond_compute = 1;
20233 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20234 } else {
20235 /* OPC_JIC, OPC_JIALC */
20236 TCGv tbase = tcg_temp_new();
20237 TCGv toffset = tcg_temp_new();
20239 gen_load_gpr(tbase, rt);
20240 tcg_gen_movi_tl(toffset, offset);
20241 gen_op_addr_add(ctx, btarget, tbase, toffset);
20242 tcg_temp_free(tbase);
20243 tcg_temp_free(toffset);
20245 break;
20246 default:
20247 MIPS_INVAL("Compact branch/jump");
20248 gen_reserved_instruction(ctx);
20249 goto out;
20252 if (bcond_compute == 0) {
20253 /* Uncoditional compact branch */
20254 switch (opc) {
20255 case OPC_BC:
20256 gen_goto_tb(ctx, 0, ctx->btarget);
20257 break;
20258 default:
20259 MIPS_INVAL("Compact branch/jump");
20260 gen_reserved_instruction(ctx);
20261 goto out;
20263 } else {
20264 /* Conditional compact branch */
20265 TCGLabel *fs = gen_new_label();
20267 switch (opc) {
20268 case OPC_BGEUC:
20269 if (rs == 0 && rt != 0) {
20270 /* OPC_BLEZALC */
20271 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20272 } else if (rs != 0 && rt != 0 && rs == rt) {
20273 /* OPC_BGEZALC */
20274 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20275 } else {
20276 /* OPC_BGEUC */
20277 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
20279 break;
20280 case OPC_BLTUC:
20281 if (rs == 0 && rt != 0) {
20282 /* OPC_BGTZALC */
20283 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20284 } else if (rs != 0 && rt != 0 && rs == rt) {
20285 /* OPC_BLTZALC */
20286 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20287 } else {
20288 /* OPC_BLTUC */
20289 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
20291 break;
20292 case OPC_BGEC:
20293 if (rs == 0 && rt != 0) {
20294 /* OPC_BLEZC */
20295 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20296 } else if (rs != 0 && rt != 0 && rs == rt) {
20297 /* OPC_BGEZC */
20298 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20299 } else {
20300 /* OPC_BGEC */
20301 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
20303 break;
20304 case OPC_BLTC:
20305 if (rs == 0 && rt != 0) {
20306 /* OPC_BGTZC */
20307 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20308 } else if (rs != 0 && rt != 0 && rs == rt) {
20309 /* OPC_BLTZC */
20310 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20311 } else {
20312 /* OPC_BLTC */
20313 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
20315 break;
20316 case OPC_BEQZC:
20317 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
20318 break;
20319 default:
20320 MIPS_INVAL("Compact conditional branch/jump");
20321 gen_reserved_instruction(ctx);
20322 goto out;
20325 /* branch completion */
20326 clear_branch_hflags(ctx);
20327 ctx->base.is_jmp = DISAS_NORETURN;
20329 /* Generating branch here as compact branches don't have delay slot */
20330 gen_goto_tb(ctx, 1, ctx->btarget);
20331 gen_set_label(fs);
20333 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20336 out:
20337 tcg_temp_free(t0);
20338 tcg_temp_free(t1);
20342 /* nanoMIPS CP1 Branches */
20343 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
20344 int32_t ft, int32_t offset)
20346 target_ulong btarget;
20347 TCGv_i64 t0 = tcg_temp_new_i64();
20349 gen_load_fpr64(ctx, t0, ft);
20350 tcg_gen_andi_i64(t0, t0, 1);
20352 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20354 switch (op) {
20355 case NM_BC1EQZC:
20356 tcg_gen_xori_i64(t0, t0, 1);
20357 ctx->hflags |= MIPS_HFLAG_BC;
20358 break;
20359 case NM_BC1NEZC:
20360 /* t0 already set */
20361 ctx->hflags |= MIPS_HFLAG_BC;
20362 break;
20363 default:
20364 MIPS_INVAL("cp1 cond branch");
20365 gen_reserved_instruction(ctx);
20366 goto out;
20369 tcg_gen_trunc_i64_tl(bcond, t0);
20371 ctx->btarget = btarget;
20373 out:
20374 tcg_temp_free_i64(t0);
20378 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
20380 TCGv t0, t1;
20381 t0 = tcg_temp_new();
20382 t1 = tcg_temp_new();
20384 gen_load_gpr(t0, rs);
20385 gen_load_gpr(t1, rt);
20387 if ((extract32(ctx->opcode, 6, 1)) == 1) {
20388 /* PP.LSXS instructions require shifting */
20389 switch (extract32(ctx->opcode, 7, 4)) {
20390 case NM_SHXS:
20391 check_nms(ctx);
20392 /* fall through */
20393 case NM_LHXS:
20394 case NM_LHUXS:
20395 tcg_gen_shli_tl(t0, t0, 1);
20396 break;
20397 case NM_SWXS:
20398 check_nms(ctx);
20399 /* fall through */
20400 case NM_LWXS:
20401 case NM_LWC1XS:
20402 case NM_SWC1XS:
20403 tcg_gen_shli_tl(t0, t0, 2);
20404 break;
20405 case NM_LDC1XS:
20406 case NM_SDC1XS:
20407 tcg_gen_shli_tl(t0, t0, 3);
20408 break;
20411 gen_op_addr_add(ctx, t0, t0, t1);
20413 switch (extract32(ctx->opcode, 7, 4)) {
20414 case NM_LBX:
20415 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20416 MO_SB);
20417 gen_store_gpr(t0, rd);
20418 break;
20419 case NM_LHX:
20420 /*case NM_LHXS:*/
20421 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20422 MO_TESW);
20423 gen_store_gpr(t0, rd);
20424 break;
20425 case NM_LWX:
20426 /*case NM_LWXS:*/
20427 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20428 MO_TESL);
20429 gen_store_gpr(t0, rd);
20430 break;
20431 case NM_LBUX:
20432 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20433 MO_UB);
20434 gen_store_gpr(t0, rd);
20435 break;
20436 case NM_LHUX:
20437 /*case NM_LHUXS:*/
20438 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20439 MO_TEUW);
20440 gen_store_gpr(t0, rd);
20441 break;
20442 case NM_SBX:
20443 check_nms(ctx);
20444 gen_load_gpr(t1, rd);
20445 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20446 MO_8);
20447 break;
20448 case NM_SHX:
20449 /*case NM_SHXS:*/
20450 check_nms(ctx);
20451 gen_load_gpr(t1, rd);
20452 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20453 MO_TEUW);
20454 break;
20455 case NM_SWX:
20456 /*case NM_SWXS:*/
20457 check_nms(ctx);
20458 gen_load_gpr(t1, rd);
20459 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20460 MO_TEUL);
20461 break;
20462 case NM_LWC1X:
20463 /*case NM_LWC1XS:*/
20464 case NM_LDC1X:
20465 /*case NM_LDC1XS:*/
20466 case NM_SWC1X:
20467 /*case NM_SWC1XS:*/
20468 case NM_SDC1X:
20469 /*case NM_SDC1XS:*/
20470 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
20471 check_cp1_enabled(ctx);
20472 switch (extract32(ctx->opcode, 7, 4)) {
20473 case NM_LWC1X:
20474 /*case NM_LWC1XS:*/
20475 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
20476 break;
20477 case NM_LDC1X:
20478 /*case NM_LDC1XS:*/
20479 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
20480 break;
20481 case NM_SWC1X:
20482 /*case NM_SWC1XS:*/
20483 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
20484 break;
20485 case NM_SDC1X:
20486 /*case NM_SDC1XS:*/
20487 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
20488 break;
20490 } else {
20491 generate_exception_err(ctx, EXCP_CpU, 1);
20493 break;
20494 default:
20495 gen_reserved_instruction(ctx);
20496 break;
20499 tcg_temp_free(t0);
20500 tcg_temp_free(t1);
20503 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
20505 int rt, rs, rd;
20507 rt = extract32(ctx->opcode, 21, 5);
20508 rs = extract32(ctx->opcode, 16, 5);
20509 rd = extract32(ctx->opcode, 11, 5);
20511 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
20512 gen_reserved_instruction(ctx);
20513 return;
20515 check_cp1_enabled(ctx);
20516 switch (extract32(ctx->opcode, 0, 3)) {
20517 case NM_POOL32F_0:
20518 switch (extract32(ctx->opcode, 3, 7)) {
20519 case NM_RINT_S:
20520 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
20521 break;
20522 case NM_RINT_D:
20523 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
20524 break;
20525 case NM_CLASS_S:
20526 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
20527 break;
20528 case NM_CLASS_D:
20529 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
20530 break;
20531 case NM_ADD_S:
20532 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
20533 break;
20534 case NM_ADD_D:
20535 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
20536 break;
20537 case NM_SUB_S:
20538 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
20539 break;
20540 case NM_SUB_D:
20541 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
20542 break;
20543 case NM_MUL_S:
20544 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
20545 break;
20546 case NM_MUL_D:
20547 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
20548 break;
20549 case NM_DIV_S:
20550 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
20551 break;
20552 case NM_DIV_D:
20553 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
20554 break;
20555 case NM_SELEQZ_S:
20556 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
20557 break;
20558 case NM_SELEQZ_D:
20559 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
20560 break;
20561 case NM_SELNEZ_S:
20562 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
20563 break;
20564 case NM_SELNEZ_D:
20565 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
20566 break;
20567 case NM_SEL_S:
20568 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
20569 break;
20570 case NM_SEL_D:
20571 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
20572 break;
20573 case NM_MADDF_S:
20574 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
20575 break;
20576 case NM_MADDF_D:
20577 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
20578 break;
20579 case NM_MSUBF_S:
20580 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
20581 break;
20582 case NM_MSUBF_D:
20583 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
20584 break;
20585 default:
20586 gen_reserved_instruction(ctx);
20587 break;
20589 break;
20590 case NM_POOL32F_3:
20591 switch (extract32(ctx->opcode, 3, 3)) {
20592 case NM_MIN_FMT:
20593 switch (extract32(ctx->opcode, 9, 1)) {
20594 case FMT_SDPS_S:
20595 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
20596 break;
20597 case FMT_SDPS_D:
20598 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
20599 break;
20601 break;
20602 case NM_MAX_FMT:
20603 switch (extract32(ctx->opcode, 9, 1)) {
20604 case FMT_SDPS_S:
20605 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
20606 break;
20607 case FMT_SDPS_D:
20608 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
20609 break;
20611 break;
20612 case NM_MINA_FMT:
20613 switch (extract32(ctx->opcode, 9, 1)) {
20614 case FMT_SDPS_S:
20615 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
20616 break;
20617 case FMT_SDPS_D:
20618 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
20619 break;
20621 break;
20622 case NM_MAXA_FMT:
20623 switch (extract32(ctx->opcode, 9, 1)) {
20624 case FMT_SDPS_S:
20625 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
20626 break;
20627 case FMT_SDPS_D:
20628 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
20629 break;
20631 break;
20632 case NM_POOL32FXF:
20633 switch (extract32(ctx->opcode, 6, 8)) {
20634 case NM_CFC1:
20635 gen_cp1(ctx, OPC_CFC1, rt, rs);
20636 break;
20637 case NM_CTC1:
20638 gen_cp1(ctx, OPC_CTC1, rt, rs);
20639 break;
20640 case NM_MFC1:
20641 gen_cp1(ctx, OPC_MFC1, rt, rs);
20642 break;
20643 case NM_MTC1:
20644 gen_cp1(ctx, OPC_MTC1, rt, rs);
20645 break;
20646 case NM_MFHC1:
20647 gen_cp1(ctx, OPC_MFHC1, rt, rs);
20648 break;
20649 case NM_MTHC1:
20650 gen_cp1(ctx, OPC_MTHC1, rt, rs);
20651 break;
20652 case NM_CVT_S_PL:
20653 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
20654 break;
20655 case NM_CVT_S_PU:
20656 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
20657 break;
20658 default:
20659 switch (extract32(ctx->opcode, 6, 9)) {
20660 case NM_CVT_L_S:
20661 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
20662 break;
20663 case NM_CVT_L_D:
20664 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
20665 break;
20666 case NM_CVT_W_S:
20667 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
20668 break;
20669 case NM_CVT_W_D:
20670 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
20671 break;
20672 case NM_RSQRT_S:
20673 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
20674 break;
20675 case NM_RSQRT_D:
20676 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
20677 break;
20678 case NM_SQRT_S:
20679 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
20680 break;
20681 case NM_SQRT_D:
20682 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
20683 break;
20684 case NM_RECIP_S:
20685 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
20686 break;
20687 case NM_RECIP_D:
20688 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
20689 break;
20690 case NM_FLOOR_L_S:
20691 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
20692 break;
20693 case NM_FLOOR_L_D:
20694 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
20695 break;
20696 case NM_FLOOR_W_S:
20697 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
20698 break;
20699 case NM_FLOOR_W_D:
20700 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
20701 break;
20702 case NM_CEIL_L_S:
20703 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
20704 break;
20705 case NM_CEIL_L_D:
20706 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
20707 break;
20708 case NM_CEIL_W_S:
20709 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
20710 break;
20711 case NM_CEIL_W_D:
20712 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
20713 break;
20714 case NM_TRUNC_L_S:
20715 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
20716 break;
20717 case NM_TRUNC_L_D:
20718 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
20719 break;
20720 case NM_TRUNC_W_S:
20721 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
20722 break;
20723 case NM_TRUNC_W_D:
20724 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
20725 break;
20726 case NM_ROUND_L_S:
20727 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
20728 break;
20729 case NM_ROUND_L_D:
20730 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
20731 break;
20732 case NM_ROUND_W_S:
20733 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
20734 break;
20735 case NM_ROUND_W_D:
20736 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
20737 break;
20738 case NM_MOV_S:
20739 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
20740 break;
20741 case NM_MOV_D:
20742 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
20743 break;
20744 case NM_ABS_S:
20745 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
20746 break;
20747 case NM_ABS_D:
20748 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
20749 break;
20750 case NM_NEG_S:
20751 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
20752 break;
20753 case NM_NEG_D:
20754 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
20755 break;
20756 case NM_CVT_D_S:
20757 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
20758 break;
20759 case NM_CVT_D_W:
20760 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
20761 break;
20762 case NM_CVT_D_L:
20763 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
20764 break;
20765 case NM_CVT_S_D:
20766 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
20767 break;
20768 case NM_CVT_S_W:
20769 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
20770 break;
20771 case NM_CVT_S_L:
20772 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
20773 break;
20774 default:
20775 gen_reserved_instruction(ctx);
20776 break;
20778 break;
20780 break;
20782 break;
20783 case NM_POOL32F_5:
20784 switch (extract32(ctx->opcode, 3, 3)) {
20785 case NM_CMP_CONDN_S:
20786 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20787 break;
20788 case NM_CMP_CONDN_D:
20789 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20790 break;
20791 default:
20792 gen_reserved_instruction(ctx);
20793 break;
20795 break;
20796 default:
20797 gen_reserved_instruction(ctx);
20798 break;
20802 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
20803 int rd, int rs, int rt)
20805 int ret = rd;
20806 TCGv t0 = tcg_temp_new();
20807 TCGv v1_t = tcg_temp_new();
20808 TCGv v2_t = tcg_temp_new();
20810 gen_load_gpr(v1_t, rs);
20811 gen_load_gpr(v2_t, rt);
20813 switch (opc) {
20814 case NM_CMP_EQ_PH:
20815 check_dsp(ctx);
20816 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
20817 break;
20818 case NM_CMP_LT_PH:
20819 check_dsp(ctx);
20820 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
20821 break;
20822 case NM_CMP_LE_PH:
20823 check_dsp(ctx);
20824 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
20825 break;
20826 case NM_CMPU_EQ_QB:
20827 check_dsp(ctx);
20828 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
20829 break;
20830 case NM_CMPU_LT_QB:
20831 check_dsp(ctx);
20832 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
20833 break;
20834 case NM_CMPU_LE_QB:
20835 check_dsp(ctx);
20836 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
20837 break;
20838 case NM_CMPGU_EQ_QB:
20839 check_dsp(ctx);
20840 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20841 gen_store_gpr(v1_t, ret);
20842 break;
20843 case NM_CMPGU_LT_QB:
20844 check_dsp(ctx);
20845 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20846 gen_store_gpr(v1_t, ret);
20847 break;
20848 case NM_CMPGU_LE_QB:
20849 check_dsp(ctx);
20850 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20851 gen_store_gpr(v1_t, ret);
20852 break;
20853 case NM_CMPGDU_EQ_QB:
20854 check_dsp_r2(ctx);
20855 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20856 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20857 gen_store_gpr(v1_t, ret);
20858 break;
20859 case NM_CMPGDU_LT_QB:
20860 check_dsp_r2(ctx);
20861 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20862 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20863 gen_store_gpr(v1_t, ret);
20864 break;
20865 case NM_CMPGDU_LE_QB:
20866 check_dsp_r2(ctx);
20867 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20868 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20869 gen_store_gpr(v1_t, ret);
20870 break;
20871 case NM_PACKRL_PH:
20872 check_dsp(ctx);
20873 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
20874 gen_store_gpr(v1_t, ret);
20875 break;
20876 case NM_PICK_QB:
20877 check_dsp(ctx);
20878 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
20879 gen_store_gpr(v1_t, ret);
20880 break;
20881 case NM_PICK_PH:
20882 check_dsp(ctx);
20883 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
20884 gen_store_gpr(v1_t, ret);
20885 break;
20886 case NM_ADDQ_S_W:
20887 check_dsp(ctx);
20888 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
20889 gen_store_gpr(v1_t, ret);
20890 break;
20891 case NM_SUBQ_S_W:
20892 check_dsp(ctx);
20893 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
20894 gen_store_gpr(v1_t, ret);
20895 break;
20896 case NM_ADDSC:
20897 check_dsp(ctx);
20898 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
20899 gen_store_gpr(v1_t, ret);
20900 break;
20901 case NM_ADDWC:
20902 check_dsp(ctx);
20903 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
20904 gen_store_gpr(v1_t, ret);
20905 break;
20906 case NM_ADDQ_S_PH:
20907 check_dsp(ctx);
20908 switch (extract32(ctx->opcode, 10, 1)) {
20909 case 0:
20910 /* ADDQ_PH */
20911 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
20912 gen_store_gpr(v1_t, ret);
20913 break;
20914 case 1:
20915 /* ADDQ_S_PH */
20916 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20917 gen_store_gpr(v1_t, ret);
20918 break;
20920 break;
20921 case NM_ADDQH_R_PH:
20922 check_dsp_r2(ctx);
20923 switch (extract32(ctx->opcode, 10, 1)) {
20924 case 0:
20925 /* ADDQH_PH */
20926 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
20927 gen_store_gpr(v1_t, ret);
20928 break;
20929 case 1:
20930 /* ADDQH_R_PH */
20931 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
20932 gen_store_gpr(v1_t, ret);
20933 break;
20935 break;
20936 case NM_ADDQH_R_W:
20937 check_dsp_r2(ctx);
20938 switch (extract32(ctx->opcode, 10, 1)) {
20939 case 0:
20940 /* ADDQH_W */
20941 gen_helper_addqh_w(v1_t, v1_t, v2_t);
20942 gen_store_gpr(v1_t, ret);
20943 break;
20944 case 1:
20945 /* ADDQH_R_W */
20946 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
20947 gen_store_gpr(v1_t, ret);
20948 break;
20950 break;
20951 case NM_ADDU_S_QB:
20952 check_dsp(ctx);
20953 switch (extract32(ctx->opcode, 10, 1)) {
20954 case 0:
20955 /* ADDU_QB */
20956 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
20957 gen_store_gpr(v1_t, ret);
20958 break;
20959 case 1:
20960 /* ADDU_S_QB */
20961 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20962 gen_store_gpr(v1_t, ret);
20963 break;
20965 break;
20966 case NM_ADDU_S_PH:
20967 check_dsp_r2(ctx);
20968 switch (extract32(ctx->opcode, 10, 1)) {
20969 case 0:
20970 /* ADDU_PH */
20971 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
20972 gen_store_gpr(v1_t, ret);
20973 break;
20974 case 1:
20975 /* ADDU_S_PH */
20976 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20977 gen_store_gpr(v1_t, ret);
20978 break;
20980 break;
20981 case NM_ADDUH_R_QB:
20982 check_dsp_r2(ctx);
20983 switch (extract32(ctx->opcode, 10, 1)) {
20984 case 0:
20985 /* ADDUH_QB */
20986 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
20987 gen_store_gpr(v1_t, ret);
20988 break;
20989 case 1:
20990 /* ADDUH_R_QB */
20991 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
20992 gen_store_gpr(v1_t, ret);
20993 break;
20995 break;
20996 case NM_SHRAV_R_PH:
20997 check_dsp(ctx);
20998 switch (extract32(ctx->opcode, 10, 1)) {
20999 case 0:
21000 /* SHRAV_PH */
21001 gen_helper_shra_ph(v1_t, v1_t, v2_t);
21002 gen_store_gpr(v1_t, ret);
21003 break;
21004 case 1:
21005 /* SHRAV_R_PH */
21006 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
21007 gen_store_gpr(v1_t, ret);
21008 break;
21010 break;
21011 case NM_SHRAV_R_QB:
21012 check_dsp_r2(ctx);
21013 switch (extract32(ctx->opcode, 10, 1)) {
21014 case 0:
21015 /* SHRAV_QB */
21016 gen_helper_shra_qb(v1_t, v1_t, v2_t);
21017 gen_store_gpr(v1_t, ret);
21018 break;
21019 case 1:
21020 /* SHRAV_R_QB */
21021 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
21022 gen_store_gpr(v1_t, ret);
21023 break;
21025 break;
21026 case NM_SUBQ_S_PH:
21027 check_dsp(ctx);
21028 switch (extract32(ctx->opcode, 10, 1)) {
21029 case 0:
21030 /* SUBQ_PH */
21031 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
21032 gen_store_gpr(v1_t, ret);
21033 break;
21034 case 1:
21035 /* SUBQ_S_PH */
21036 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
21037 gen_store_gpr(v1_t, ret);
21038 break;
21040 break;
21041 case NM_SUBQH_R_PH:
21042 check_dsp_r2(ctx);
21043 switch (extract32(ctx->opcode, 10, 1)) {
21044 case 0:
21045 /* SUBQH_PH */
21046 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
21047 gen_store_gpr(v1_t, ret);
21048 break;
21049 case 1:
21050 /* SUBQH_R_PH */
21051 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
21052 gen_store_gpr(v1_t, ret);
21053 break;
21055 break;
21056 case NM_SUBQH_R_W:
21057 check_dsp_r2(ctx);
21058 switch (extract32(ctx->opcode, 10, 1)) {
21059 case 0:
21060 /* SUBQH_W */
21061 gen_helper_subqh_w(v1_t, v1_t, v2_t);
21062 gen_store_gpr(v1_t, ret);
21063 break;
21064 case 1:
21065 /* SUBQH_R_W */
21066 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
21067 gen_store_gpr(v1_t, ret);
21068 break;
21070 break;
21071 case NM_SUBU_S_QB:
21072 check_dsp(ctx);
21073 switch (extract32(ctx->opcode, 10, 1)) {
21074 case 0:
21075 /* SUBU_QB */
21076 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
21077 gen_store_gpr(v1_t, ret);
21078 break;
21079 case 1:
21080 /* SUBU_S_QB */
21081 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
21082 gen_store_gpr(v1_t, ret);
21083 break;
21085 break;
21086 case NM_SUBU_S_PH:
21087 check_dsp_r2(ctx);
21088 switch (extract32(ctx->opcode, 10, 1)) {
21089 case 0:
21090 /* SUBU_PH */
21091 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
21092 gen_store_gpr(v1_t, ret);
21093 break;
21094 case 1:
21095 /* SUBU_S_PH */
21096 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
21097 gen_store_gpr(v1_t, ret);
21098 break;
21100 break;
21101 case NM_SUBUH_R_QB:
21102 check_dsp_r2(ctx);
21103 switch (extract32(ctx->opcode, 10, 1)) {
21104 case 0:
21105 /* SUBUH_QB */
21106 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
21107 gen_store_gpr(v1_t, ret);
21108 break;
21109 case 1:
21110 /* SUBUH_R_QB */
21111 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
21112 gen_store_gpr(v1_t, ret);
21113 break;
21115 break;
21116 case NM_SHLLV_S_PH:
21117 check_dsp(ctx);
21118 switch (extract32(ctx->opcode, 10, 1)) {
21119 case 0:
21120 /* SHLLV_PH */
21121 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
21122 gen_store_gpr(v1_t, ret);
21123 break;
21124 case 1:
21125 /* SHLLV_S_PH */
21126 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
21127 gen_store_gpr(v1_t, ret);
21128 break;
21130 break;
21131 case NM_PRECR_SRA_R_PH_W:
21132 check_dsp_r2(ctx);
21133 switch (extract32(ctx->opcode, 10, 1)) {
21134 case 0:
21135 /* PRECR_SRA_PH_W */
21137 TCGv_i32 sa_t = tcg_const_i32(rd);
21138 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
21139 cpu_gpr[rt]);
21140 gen_store_gpr(v1_t, rt);
21141 tcg_temp_free_i32(sa_t);
21143 break;
21144 case 1:
21145 /* PRECR_SRA_R_PH_W */
21147 TCGv_i32 sa_t = tcg_const_i32(rd);
21148 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
21149 cpu_gpr[rt]);
21150 gen_store_gpr(v1_t, rt);
21151 tcg_temp_free_i32(sa_t);
21153 break;
21155 break;
21156 case NM_MULEU_S_PH_QBL:
21157 check_dsp(ctx);
21158 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
21159 gen_store_gpr(v1_t, ret);
21160 break;
21161 case NM_MULEU_S_PH_QBR:
21162 check_dsp(ctx);
21163 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
21164 gen_store_gpr(v1_t, ret);
21165 break;
21166 case NM_MULQ_RS_PH:
21167 check_dsp(ctx);
21168 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
21169 gen_store_gpr(v1_t, ret);
21170 break;
21171 case NM_MULQ_S_PH:
21172 check_dsp_r2(ctx);
21173 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
21174 gen_store_gpr(v1_t, ret);
21175 break;
21176 case NM_MULQ_RS_W:
21177 check_dsp_r2(ctx);
21178 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
21179 gen_store_gpr(v1_t, ret);
21180 break;
21181 case NM_MULQ_S_W:
21182 check_dsp_r2(ctx);
21183 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
21184 gen_store_gpr(v1_t, ret);
21185 break;
21186 case NM_APPEND:
21187 check_dsp_r2(ctx);
21188 gen_load_gpr(t0, rs);
21189 if (rd != 0) {
21190 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
21192 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21193 break;
21194 case NM_MODSUB:
21195 check_dsp(ctx);
21196 gen_helper_modsub(v1_t, v1_t, v2_t);
21197 gen_store_gpr(v1_t, ret);
21198 break;
21199 case NM_SHRAV_R_W:
21200 check_dsp(ctx);
21201 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
21202 gen_store_gpr(v1_t, ret);
21203 break;
21204 case NM_SHRLV_PH:
21205 check_dsp_r2(ctx);
21206 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
21207 gen_store_gpr(v1_t, ret);
21208 break;
21209 case NM_SHRLV_QB:
21210 check_dsp(ctx);
21211 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
21212 gen_store_gpr(v1_t, ret);
21213 break;
21214 case NM_SHLLV_QB:
21215 check_dsp(ctx);
21216 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
21217 gen_store_gpr(v1_t, ret);
21218 break;
21219 case NM_SHLLV_S_W:
21220 check_dsp(ctx);
21221 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
21222 gen_store_gpr(v1_t, ret);
21223 break;
21224 case NM_SHILO:
21225 check_dsp(ctx);
21227 TCGv tv0 = tcg_temp_new();
21228 TCGv tv1 = tcg_temp_new();
21229 int16_t imm = extract32(ctx->opcode, 16, 7);
21231 tcg_gen_movi_tl(tv0, rd >> 3);
21232 tcg_gen_movi_tl(tv1, imm);
21233 gen_helper_shilo(tv0, tv1, cpu_env);
21235 break;
21236 case NM_MULEQ_S_W_PHL:
21237 check_dsp(ctx);
21238 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
21239 gen_store_gpr(v1_t, ret);
21240 break;
21241 case NM_MULEQ_S_W_PHR:
21242 check_dsp(ctx);
21243 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
21244 gen_store_gpr(v1_t, ret);
21245 break;
21246 case NM_MUL_S_PH:
21247 check_dsp_r2(ctx);
21248 switch (extract32(ctx->opcode, 10, 1)) {
21249 case 0:
21250 /* MUL_PH */
21251 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
21252 gen_store_gpr(v1_t, ret);
21253 break;
21254 case 1:
21255 /* MUL_S_PH */
21256 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
21257 gen_store_gpr(v1_t, ret);
21258 break;
21260 break;
21261 case NM_PRECR_QB_PH:
21262 check_dsp_r2(ctx);
21263 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
21264 gen_store_gpr(v1_t, ret);
21265 break;
21266 case NM_PRECRQ_QB_PH:
21267 check_dsp(ctx);
21268 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
21269 gen_store_gpr(v1_t, ret);
21270 break;
21271 case NM_PRECRQ_PH_W:
21272 check_dsp(ctx);
21273 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
21274 gen_store_gpr(v1_t, ret);
21275 break;
21276 case NM_PRECRQ_RS_PH_W:
21277 check_dsp(ctx);
21278 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
21279 gen_store_gpr(v1_t, ret);
21280 break;
21281 case NM_PRECRQU_S_QB_PH:
21282 check_dsp(ctx);
21283 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
21284 gen_store_gpr(v1_t, ret);
21285 break;
21286 case NM_SHRA_R_W:
21287 check_dsp(ctx);
21288 tcg_gen_movi_tl(t0, rd);
21289 gen_helper_shra_r_w(v1_t, t0, v1_t);
21290 gen_store_gpr(v1_t, rt);
21291 break;
21292 case NM_SHRA_R_PH:
21293 check_dsp(ctx);
21294 tcg_gen_movi_tl(t0, rd >> 1);
21295 switch (extract32(ctx->opcode, 10, 1)) {
21296 case 0:
21297 /* SHRA_PH */
21298 gen_helper_shra_ph(v1_t, t0, v1_t);
21299 gen_store_gpr(v1_t, rt);
21300 break;
21301 case 1:
21302 /* SHRA_R_PH */
21303 gen_helper_shra_r_ph(v1_t, t0, v1_t);
21304 gen_store_gpr(v1_t, rt);
21305 break;
21307 break;
21308 case NM_SHLL_S_PH:
21309 check_dsp(ctx);
21310 tcg_gen_movi_tl(t0, rd >> 1);
21311 switch (extract32(ctx->opcode, 10, 2)) {
21312 case 0:
21313 /* SHLL_PH */
21314 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
21315 gen_store_gpr(v1_t, rt);
21316 break;
21317 case 2:
21318 /* SHLL_S_PH */
21319 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
21320 gen_store_gpr(v1_t, rt);
21321 break;
21322 default:
21323 gen_reserved_instruction(ctx);
21324 break;
21326 break;
21327 case NM_SHLL_S_W:
21328 check_dsp(ctx);
21329 tcg_gen_movi_tl(t0, rd);
21330 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
21331 gen_store_gpr(v1_t, rt);
21332 break;
21333 case NM_REPL_PH:
21334 check_dsp(ctx);
21336 int16_t imm;
21337 imm = sextract32(ctx->opcode, 11, 11);
21338 imm = (int16_t)(imm << 6) >> 6;
21339 if (rt != 0) {
21340 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
21343 break;
21344 default:
21345 gen_reserved_instruction(ctx);
21346 break;
21350 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
21352 uint16_t insn;
21353 uint32_t op;
21354 int rt, rs, rd;
21355 int offset;
21356 int imm;
21358 insn = translator_lduw(env, ctx->base.pc_next + 2);
21359 ctx->opcode = (ctx->opcode << 16) | insn;
21361 rt = extract32(ctx->opcode, 21, 5);
21362 rs = extract32(ctx->opcode, 16, 5);
21363 rd = extract32(ctx->opcode, 11, 5);
21365 op = extract32(ctx->opcode, 26, 6);
21366 switch (op) {
21367 case NM_P_ADDIU:
21368 if (rt == 0) {
21369 /* P.RI */
21370 switch (extract32(ctx->opcode, 19, 2)) {
21371 case NM_SIGRIE:
21372 default:
21373 gen_reserved_instruction(ctx);
21374 break;
21375 case NM_P_SYSCALL:
21376 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
21377 generate_exception_end(ctx, EXCP_SYSCALL);
21378 } else {
21379 gen_reserved_instruction(ctx);
21381 break;
21382 case NM_BREAK:
21383 generate_exception_end(ctx, EXCP_BREAK);
21384 break;
21385 case NM_SDBBP:
21386 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
21387 gen_helper_do_semihosting(cpu_env);
21388 } else {
21389 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21390 gen_reserved_instruction(ctx);
21391 } else {
21392 generate_exception_end(ctx, EXCP_DBp);
21395 break;
21397 } else {
21398 /* NM_ADDIU */
21399 imm = extract32(ctx->opcode, 0, 16);
21400 if (rs != 0) {
21401 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
21402 } else {
21403 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21405 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21407 break;
21408 case NM_ADDIUPC:
21409 if (rt != 0) {
21410 offset = sextract32(ctx->opcode, 0, 1) << 21 |
21411 extract32(ctx->opcode, 1, 20) << 1;
21412 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
21413 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21415 break;
21416 case NM_POOL32A:
21417 switch (ctx->opcode & 0x07) {
21418 case NM_POOL32A0:
21419 gen_pool32a0_nanomips_insn(env, ctx);
21420 break;
21421 case NM_POOL32A5:
21423 int32_t op1 = extract32(ctx->opcode, 3, 7);
21424 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
21426 break;
21427 case NM_POOL32A7:
21428 switch (extract32(ctx->opcode, 3, 3)) {
21429 case NM_P_LSX:
21430 gen_p_lsx(ctx, rd, rs, rt);
21431 break;
21432 case NM_LSA:
21434 * In nanoMIPS, the shift field directly encodes the shift
21435 * amount, meaning that the supported shift values are in
21436 * the range 0 to 3 (instead of 1 to 4 in MIPSR6).
21438 gen_lsa(ctx, rd, rt, rs, extract32(ctx->opcode, 9, 2) - 1);
21439 break;
21440 case NM_EXTW:
21441 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
21442 break;
21443 case NM_POOL32AXF:
21444 gen_pool32axf_nanomips_insn(env, ctx);
21445 break;
21446 default:
21447 gen_reserved_instruction(ctx);
21448 break;
21450 break;
21451 default:
21452 gen_reserved_instruction(ctx);
21453 break;
21455 break;
21456 case NM_P_GP_W:
21457 switch (ctx->opcode & 0x03) {
21458 case NM_ADDIUGP_W:
21459 if (rt != 0) {
21460 offset = extract32(ctx->opcode, 0, 21);
21461 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
21463 break;
21464 case NM_LWGP:
21465 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21466 break;
21467 case NM_SWGP:
21468 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21469 break;
21470 default:
21471 gen_reserved_instruction(ctx);
21472 break;
21474 break;
21475 case NM_P48I:
21477 insn = translator_lduw(env, ctx->base.pc_next + 4);
21478 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
21479 switch (extract32(ctx->opcode, 16, 5)) {
21480 case NM_LI48:
21481 check_nms(ctx);
21482 if (rt != 0) {
21483 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
21485 break;
21486 case NM_ADDIU48:
21487 check_nms(ctx);
21488 if (rt != 0) {
21489 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
21490 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21492 break;
21493 case NM_ADDIUGP48:
21494 check_nms(ctx);
21495 if (rt != 0) {
21496 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
21498 break;
21499 case NM_ADDIUPC48:
21500 check_nms(ctx);
21501 if (rt != 0) {
21502 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21503 addr_off);
21505 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21507 break;
21508 case NM_LWPC48:
21509 check_nms(ctx);
21510 if (rt != 0) {
21511 TCGv t0;
21512 t0 = tcg_temp_new();
21514 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21515 addr_off);
21517 tcg_gen_movi_tl(t0, addr);
21518 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
21519 tcg_temp_free(t0);
21521 break;
21522 case NM_SWPC48:
21523 check_nms(ctx);
21525 TCGv t0, t1;
21526 t0 = tcg_temp_new();
21527 t1 = tcg_temp_new();
21529 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21530 addr_off);
21532 tcg_gen_movi_tl(t0, addr);
21533 gen_load_gpr(t1, rt);
21535 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
21537 tcg_temp_free(t0);
21538 tcg_temp_free(t1);
21540 break;
21541 default:
21542 gen_reserved_instruction(ctx);
21543 break;
21545 return 6;
21547 case NM_P_U12:
21548 switch (extract32(ctx->opcode, 12, 4)) {
21549 case NM_ORI:
21550 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
21551 break;
21552 case NM_XORI:
21553 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
21554 break;
21555 case NM_ANDI:
21556 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
21557 break;
21558 case NM_P_SR:
21559 switch (extract32(ctx->opcode, 20, 1)) {
21560 case NM_PP_SR:
21561 switch (ctx->opcode & 3) {
21562 case NM_SAVE:
21563 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
21564 extract32(ctx->opcode, 2, 1),
21565 extract32(ctx->opcode, 3, 9) << 3);
21566 break;
21567 case NM_RESTORE:
21568 case NM_RESTORE_JRC:
21569 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
21570 extract32(ctx->opcode, 2, 1),
21571 extract32(ctx->opcode, 3, 9) << 3);
21572 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
21573 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21575 break;
21576 default:
21577 gen_reserved_instruction(ctx);
21578 break;
21580 break;
21581 case NM_P_SR_F:
21582 gen_reserved_instruction(ctx);
21583 break;
21585 break;
21586 case NM_SLTI:
21587 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
21588 break;
21589 case NM_SLTIU:
21590 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
21591 break;
21592 case NM_SEQI:
21594 TCGv t0 = tcg_temp_new();
21596 imm = extract32(ctx->opcode, 0, 12);
21597 gen_load_gpr(t0, rs);
21598 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
21599 gen_store_gpr(t0, rt);
21601 tcg_temp_free(t0);
21603 break;
21604 case NM_ADDIUNEG:
21605 imm = (int16_t) extract32(ctx->opcode, 0, 12);
21606 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
21607 break;
21608 case NM_P_SHIFT:
21610 int shift = extract32(ctx->opcode, 0, 5);
21611 switch (extract32(ctx->opcode, 5, 4)) {
21612 case NM_P_SLL:
21613 if (rt == 0 && shift == 0) {
21614 /* NOP */
21615 } else if (rt == 0 && shift == 3) {
21616 /* EHB - treat as NOP */
21617 } else if (rt == 0 && shift == 5) {
21618 /* PAUSE - treat as NOP */
21619 } else if (rt == 0 && shift == 6) {
21620 /* SYNC */
21621 gen_sync(extract32(ctx->opcode, 16, 5));
21622 } else {
21623 /* SLL */
21624 gen_shift_imm(ctx, OPC_SLL, rt, rs,
21625 extract32(ctx->opcode, 0, 5));
21627 break;
21628 case NM_SRL:
21629 gen_shift_imm(ctx, OPC_SRL, rt, rs,
21630 extract32(ctx->opcode, 0, 5));
21631 break;
21632 case NM_SRA:
21633 gen_shift_imm(ctx, OPC_SRA, rt, rs,
21634 extract32(ctx->opcode, 0, 5));
21635 break;
21636 case NM_ROTR:
21637 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
21638 extract32(ctx->opcode, 0, 5));
21639 break;
21642 break;
21643 case NM_P_ROTX:
21644 check_nms(ctx);
21645 if (rt != 0) {
21646 TCGv t0 = tcg_temp_new();
21647 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
21648 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
21649 << 1);
21650 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
21652 gen_load_gpr(t0, rs);
21653 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
21654 tcg_temp_free(t0);
21656 tcg_temp_free_i32(shift);
21657 tcg_temp_free_i32(shiftx);
21658 tcg_temp_free_i32(stripe);
21660 break;
21661 case NM_P_INS:
21662 switch (((ctx->opcode >> 10) & 2) |
21663 (extract32(ctx->opcode, 5, 1))) {
21664 case NM_INS:
21665 check_nms(ctx);
21666 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
21667 extract32(ctx->opcode, 6, 5));
21668 break;
21669 default:
21670 gen_reserved_instruction(ctx);
21671 break;
21673 break;
21674 case NM_P_EXT:
21675 switch (((ctx->opcode >> 10) & 2) |
21676 (extract32(ctx->opcode, 5, 1))) {
21677 case NM_EXT:
21678 check_nms(ctx);
21679 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
21680 extract32(ctx->opcode, 6, 5));
21681 break;
21682 default:
21683 gen_reserved_instruction(ctx);
21684 break;
21686 break;
21687 default:
21688 gen_reserved_instruction(ctx);
21689 break;
21691 break;
21692 case NM_POOL32F:
21693 gen_pool32f_nanomips_insn(ctx);
21694 break;
21695 case NM_POOL32S:
21696 break;
21697 case NM_P_LUI:
21698 switch (extract32(ctx->opcode, 1, 1)) {
21699 case NM_LUI:
21700 if (rt != 0) {
21701 tcg_gen_movi_tl(cpu_gpr[rt],
21702 sextract32(ctx->opcode, 0, 1) << 31 |
21703 extract32(ctx->opcode, 2, 10) << 21 |
21704 extract32(ctx->opcode, 12, 9) << 12);
21706 break;
21707 case NM_ALUIPC:
21708 if (rt != 0) {
21709 offset = sextract32(ctx->opcode, 0, 1) << 31 |
21710 extract32(ctx->opcode, 2, 10) << 21 |
21711 extract32(ctx->opcode, 12, 9) << 12;
21712 target_long addr;
21713 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
21714 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21716 break;
21718 break;
21719 case NM_P_GP_BH:
21721 uint32_t u = extract32(ctx->opcode, 0, 18);
21723 switch (extract32(ctx->opcode, 18, 3)) {
21724 case NM_LBGP:
21725 gen_ld(ctx, OPC_LB, rt, 28, u);
21726 break;
21727 case NM_SBGP:
21728 gen_st(ctx, OPC_SB, rt, 28, u);
21729 break;
21730 case NM_LBUGP:
21731 gen_ld(ctx, OPC_LBU, rt, 28, u);
21732 break;
21733 case NM_ADDIUGP_B:
21734 if (rt != 0) {
21735 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
21737 break;
21738 case NM_P_GP_LH:
21739 u &= ~1;
21740 switch (ctx->opcode & 1) {
21741 case NM_LHGP:
21742 gen_ld(ctx, OPC_LH, rt, 28, u);
21743 break;
21744 case NM_LHUGP:
21745 gen_ld(ctx, OPC_LHU, rt, 28, u);
21746 break;
21748 break;
21749 case NM_P_GP_SH:
21750 u &= ~1;
21751 switch (ctx->opcode & 1) {
21752 case NM_SHGP:
21753 gen_st(ctx, OPC_SH, rt, 28, u);
21754 break;
21755 default:
21756 gen_reserved_instruction(ctx);
21757 break;
21759 break;
21760 case NM_P_GP_CP1:
21761 u &= ~0x3;
21762 switch (ctx->opcode & 0x3) {
21763 case NM_LWC1GP:
21764 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
21765 break;
21766 case NM_LDC1GP:
21767 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
21768 break;
21769 case NM_SWC1GP:
21770 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
21771 break;
21772 case NM_SDC1GP:
21773 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
21774 break;
21776 break;
21777 default:
21778 gen_reserved_instruction(ctx);
21779 break;
21782 break;
21783 case NM_P_LS_U12:
21785 uint32_t u = extract32(ctx->opcode, 0, 12);
21787 switch (extract32(ctx->opcode, 12, 4)) {
21788 case NM_P_PREFU12:
21789 if (rt == 31) {
21790 /* SYNCI */
21792 * Break the TB to be able to sync copied instructions
21793 * immediately.
21795 ctx->base.is_jmp = DISAS_STOP;
21796 } else {
21797 /* PREF */
21798 /* Treat as NOP. */
21800 break;
21801 case NM_LB:
21802 gen_ld(ctx, OPC_LB, rt, rs, u);
21803 break;
21804 case NM_LH:
21805 gen_ld(ctx, OPC_LH, rt, rs, u);
21806 break;
21807 case NM_LW:
21808 gen_ld(ctx, OPC_LW, rt, rs, u);
21809 break;
21810 case NM_LBU:
21811 gen_ld(ctx, OPC_LBU, rt, rs, u);
21812 break;
21813 case NM_LHU:
21814 gen_ld(ctx, OPC_LHU, rt, rs, u);
21815 break;
21816 case NM_SB:
21817 gen_st(ctx, OPC_SB, rt, rs, u);
21818 break;
21819 case NM_SH:
21820 gen_st(ctx, OPC_SH, rt, rs, u);
21821 break;
21822 case NM_SW:
21823 gen_st(ctx, OPC_SW, rt, rs, u);
21824 break;
21825 case NM_LWC1:
21826 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
21827 break;
21828 case NM_LDC1:
21829 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
21830 break;
21831 case NM_SWC1:
21832 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
21833 break;
21834 case NM_SDC1:
21835 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
21836 break;
21837 default:
21838 gen_reserved_instruction(ctx);
21839 break;
21842 break;
21843 case NM_P_LS_S9:
21845 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
21846 extract32(ctx->opcode, 0, 8);
21848 switch (extract32(ctx->opcode, 8, 3)) {
21849 case NM_P_LS_S0:
21850 switch (extract32(ctx->opcode, 11, 4)) {
21851 case NM_LBS9:
21852 gen_ld(ctx, OPC_LB, rt, rs, s);
21853 break;
21854 case NM_LHS9:
21855 gen_ld(ctx, OPC_LH, rt, rs, s);
21856 break;
21857 case NM_LWS9:
21858 gen_ld(ctx, OPC_LW, rt, rs, s);
21859 break;
21860 case NM_LBUS9:
21861 gen_ld(ctx, OPC_LBU, rt, rs, s);
21862 break;
21863 case NM_LHUS9:
21864 gen_ld(ctx, OPC_LHU, rt, rs, s);
21865 break;
21866 case NM_SBS9:
21867 gen_st(ctx, OPC_SB, rt, rs, s);
21868 break;
21869 case NM_SHS9:
21870 gen_st(ctx, OPC_SH, rt, rs, s);
21871 break;
21872 case NM_SWS9:
21873 gen_st(ctx, OPC_SW, rt, rs, s);
21874 break;
21875 case NM_LWC1S9:
21876 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
21877 break;
21878 case NM_LDC1S9:
21879 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
21880 break;
21881 case NM_SWC1S9:
21882 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
21883 break;
21884 case NM_SDC1S9:
21885 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
21886 break;
21887 case NM_P_PREFS9:
21888 if (rt == 31) {
21889 /* SYNCI */
21891 * Break the TB to be able to sync copied instructions
21892 * immediately.
21894 ctx->base.is_jmp = DISAS_STOP;
21895 } else {
21896 /* PREF */
21897 /* Treat as NOP. */
21899 break;
21900 default:
21901 gen_reserved_instruction(ctx);
21902 break;
21904 break;
21905 case NM_P_LS_S1:
21906 switch (extract32(ctx->opcode, 11, 4)) {
21907 case NM_UALH:
21908 case NM_UASH:
21909 check_nms(ctx);
21911 TCGv t0 = tcg_temp_new();
21912 TCGv t1 = tcg_temp_new();
21914 gen_base_offset_addr(ctx, t0, rs, s);
21916 switch (extract32(ctx->opcode, 11, 4)) {
21917 case NM_UALH:
21918 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
21919 MO_UNALN);
21920 gen_store_gpr(t0, rt);
21921 break;
21922 case NM_UASH:
21923 gen_load_gpr(t1, rt);
21924 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
21925 MO_UNALN);
21926 break;
21928 tcg_temp_free(t0);
21929 tcg_temp_free(t1);
21931 break;
21932 case NM_P_LL:
21933 switch (ctx->opcode & 0x03) {
21934 case NM_LL:
21935 gen_ld(ctx, OPC_LL, rt, rs, s);
21936 break;
21937 case NM_LLWP:
21938 check_xnp(ctx);
21939 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21940 break;
21942 break;
21943 case NM_P_SC:
21944 switch (ctx->opcode & 0x03) {
21945 case NM_SC:
21946 gen_st_cond(ctx, rt, rs, s, MO_TESL, false);
21947 break;
21948 case NM_SCWP:
21949 check_xnp(ctx);
21950 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21951 false);
21952 break;
21954 break;
21955 case NM_CACHE:
21956 check_cp0_enabled(ctx);
21957 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
21958 gen_cache_operation(ctx, rt, rs, s);
21960 break;
21962 break;
21963 case NM_P_LS_E0:
21964 switch (extract32(ctx->opcode, 11, 4)) {
21965 case NM_LBE:
21966 check_eva(ctx);
21967 check_cp0_enabled(ctx);
21968 gen_ld(ctx, OPC_LBE, rt, rs, s);
21969 break;
21970 case NM_SBE:
21971 check_eva(ctx);
21972 check_cp0_enabled(ctx);
21973 gen_st(ctx, OPC_SBE, rt, rs, s);
21974 break;
21975 case NM_LBUE:
21976 check_eva(ctx);
21977 check_cp0_enabled(ctx);
21978 gen_ld(ctx, OPC_LBUE, rt, rs, s);
21979 break;
21980 case NM_P_PREFE:
21981 if (rt == 31) {
21982 /* case NM_SYNCIE */
21983 check_eva(ctx);
21984 check_cp0_enabled(ctx);
21986 * Break the TB to be able to sync copied instructions
21987 * immediately.
21989 ctx->base.is_jmp = DISAS_STOP;
21990 } else {
21991 /* case NM_PREFE */
21992 check_eva(ctx);
21993 check_cp0_enabled(ctx);
21994 /* Treat as NOP. */
21996 break;
21997 case NM_LHE:
21998 check_eva(ctx);
21999 check_cp0_enabled(ctx);
22000 gen_ld(ctx, OPC_LHE, rt, rs, s);
22001 break;
22002 case NM_SHE:
22003 check_eva(ctx);
22004 check_cp0_enabled(ctx);
22005 gen_st(ctx, OPC_SHE, rt, rs, s);
22006 break;
22007 case NM_LHUE:
22008 check_eva(ctx);
22009 check_cp0_enabled(ctx);
22010 gen_ld(ctx, OPC_LHUE, rt, rs, s);
22011 break;
22012 case NM_CACHEE:
22013 check_nms_dl_il_sl_tl_l2c(ctx);
22014 gen_cache_operation(ctx, rt, rs, s);
22015 break;
22016 case NM_LWE:
22017 check_eva(ctx);
22018 check_cp0_enabled(ctx);
22019 gen_ld(ctx, OPC_LWE, rt, rs, s);
22020 break;
22021 case NM_SWE:
22022 check_eva(ctx);
22023 check_cp0_enabled(ctx);
22024 gen_st(ctx, OPC_SWE, rt, rs, s);
22025 break;
22026 case NM_P_LLE:
22027 switch (extract32(ctx->opcode, 2, 2)) {
22028 case NM_LLE:
22029 check_xnp(ctx);
22030 check_eva(ctx);
22031 check_cp0_enabled(ctx);
22032 gen_ld(ctx, OPC_LLE, rt, rs, s);
22033 break;
22034 case NM_LLWPE:
22035 check_xnp(ctx);
22036 check_eva(ctx);
22037 check_cp0_enabled(ctx);
22038 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
22039 break;
22040 default:
22041 gen_reserved_instruction(ctx);
22042 break;
22044 break;
22045 case NM_P_SCE:
22046 switch (extract32(ctx->opcode, 2, 2)) {
22047 case NM_SCE:
22048 check_xnp(ctx);
22049 check_eva(ctx);
22050 check_cp0_enabled(ctx);
22051 gen_st_cond(ctx, rt, rs, s, MO_TESL, true);
22052 break;
22053 case NM_SCWPE:
22054 check_xnp(ctx);
22055 check_eva(ctx);
22056 check_cp0_enabled(ctx);
22057 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
22058 true);
22059 break;
22060 default:
22061 gen_reserved_instruction(ctx);
22062 break;
22064 break;
22066 break;
22067 case NM_P_LS_WM:
22068 case NM_P_LS_UAWM:
22069 check_nms(ctx);
22071 int count = extract32(ctx->opcode, 12, 3);
22072 int counter = 0;
22074 offset = sextract32(ctx->opcode, 15, 1) << 8 |
22075 extract32(ctx->opcode, 0, 8);
22076 TCGv va = tcg_temp_new();
22077 TCGv t1 = tcg_temp_new();
22078 MemOp memop = (extract32(ctx->opcode, 8, 3)) ==
22079 NM_P_LS_UAWM ? MO_UNALN : 0;
22081 count = (count == 0) ? 8 : count;
22082 while (counter != count) {
22083 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
22084 int this_offset = offset + (counter << 2);
22086 gen_base_offset_addr(ctx, va, rs, this_offset);
22088 switch (extract32(ctx->opcode, 11, 1)) {
22089 case NM_LWM:
22090 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
22091 memop | MO_TESL);
22092 gen_store_gpr(t1, this_rt);
22093 if ((this_rt == rs) &&
22094 (counter != (count - 1))) {
22095 /* UNPREDICTABLE */
22097 break;
22098 case NM_SWM:
22099 this_rt = (rt == 0) ? 0 : this_rt;
22100 gen_load_gpr(t1, this_rt);
22101 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
22102 memop | MO_TEUL);
22103 break;
22105 counter++;
22107 tcg_temp_free(va);
22108 tcg_temp_free(t1);
22110 break;
22111 default:
22112 gen_reserved_instruction(ctx);
22113 break;
22116 break;
22117 case NM_MOVE_BALC:
22118 check_nms(ctx);
22120 TCGv t0 = tcg_temp_new();
22121 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
22122 extract32(ctx->opcode, 1, 20) << 1;
22123 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
22124 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
22125 extract32(ctx->opcode, 21, 3));
22126 gen_load_gpr(t0, rt);
22127 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22128 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
22129 tcg_temp_free(t0);
22131 break;
22132 case NM_P_BAL:
22134 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
22135 extract32(ctx->opcode, 1, 24) << 1;
22137 if ((extract32(ctx->opcode, 25, 1)) == 0) {
22138 /* BC */
22139 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
22140 } else {
22141 /* BALC */
22142 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
22145 break;
22146 case NM_P_J:
22147 switch (extract32(ctx->opcode, 12, 4)) {
22148 case NM_JALRC:
22149 case NM_JALRC_HB:
22150 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
22151 break;
22152 case NM_P_BALRSC:
22153 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
22154 break;
22155 default:
22156 gen_reserved_instruction(ctx);
22157 break;
22159 break;
22160 case NM_P_BR1:
22162 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
22163 extract32(ctx->opcode, 1, 13) << 1;
22164 switch (extract32(ctx->opcode, 14, 2)) {
22165 case NM_BEQC:
22166 check_nms(ctx);
22167 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
22168 break;
22169 case NM_P_BR3A:
22170 s = sextract32(ctx->opcode, 0, 1) << 14 |
22171 extract32(ctx->opcode, 1, 13) << 1;
22172 check_cp1_enabled(ctx);
22173 switch (extract32(ctx->opcode, 16, 5)) {
22174 case NM_BC1EQZC:
22175 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
22176 break;
22177 case NM_BC1NEZC:
22178 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
22179 break;
22180 case NM_BPOSGE32C:
22181 check_dsp_r3(ctx);
22183 int32_t imm = extract32(ctx->opcode, 1, 13) |
22184 extract32(ctx->opcode, 0, 1) << 13;
22186 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
22187 imm);
22189 break;
22190 default:
22191 gen_reserved_instruction(ctx);
22192 break;
22194 break;
22195 case NM_BGEC:
22196 if (rs == rt) {
22197 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
22198 } else {
22199 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
22201 break;
22202 case NM_BGEUC:
22203 if (rs == rt || rt == 0) {
22204 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
22205 } else if (rs == 0) {
22206 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
22207 } else {
22208 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
22210 break;
22213 break;
22214 case NM_P_BR2:
22216 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
22217 extract32(ctx->opcode, 1, 13) << 1;
22218 switch (extract32(ctx->opcode, 14, 2)) {
22219 case NM_BNEC:
22220 check_nms(ctx);
22221 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
22222 break;
22223 case NM_BLTC:
22224 if (rs != 0 && rt != 0 && rs == rt) {
22225 /* NOP */
22226 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22227 } else {
22228 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
22230 break;
22231 case NM_BLTUC:
22232 if (rs == 0 || rs == rt) {
22233 /* NOP */
22234 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22235 } else {
22236 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
22238 break;
22239 default:
22240 gen_reserved_instruction(ctx);
22241 break;
22244 break;
22245 case NM_P_BRI:
22247 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
22248 extract32(ctx->opcode, 1, 10) << 1;
22249 uint32_t u = extract32(ctx->opcode, 11, 7);
22251 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
22252 rt, u, s);
22254 break;
22255 default:
22256 gen_reserved_instruction(ctx);
22257 break;
22259 return 4;
22262 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
22264 uint32_t op;
22265 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
22266 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22267 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode));
22268 int offset;
22269 int imm;
22271 /* make sure instructions are on a halfword boundary */
22272 if (ctx->base.pc_next & 0x1) {
22273 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
22274 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
22275 tcg_temp_free(tmp);
22276 generate_exception_end(ctx, EXCP_AdEL);
22277 return 2;
22280 op = extract32(ctx->opcode, 10, 6);
22281 switch (op) {
22282 case NM_P16_MV:
22283 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22284 if (rt != 0) {
22285 /* MOVE */
22286 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
22287 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
22288 } else {
22289 /* P16.RI */
22290 switch (extract32(ctx->opcode, 3, 2)) {
22291 case NM_P16_SYSCALL:
22292 if (extract32(ctx->opcode, 2, 1) == 0) {
22293 generate_exception_end(ctx, EXCP_SYSCALL);
22294 } else {
22295 gen_reserved_instruction(ctx);
22297 break;
22298 case NM_BREAK16:
22299 generate_exception_end(ctx, EXCP_BREAK);
22300 break;
22301 case NM_SDBBP16:
22302 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
22303 gen_helper_do_semihosting(cpu_env);
22304 } else {
22305 if (ctx->hflags & MIPS_HFLAG_SBRI) {
22306 gen_reserved_instruction(ctx);
22307 } else {
22308 generate_exception_end(ctx, EXCP_DBp);
22311 break;
22312 default:
22313 gen_reserved_instruction(ctx);
22314 break;
22317 break;
22318 case NM_P16_SHIFT:
22320 int shift = extract32(ctx->opcode, 0, 3);
22321 uint32_t opc = 0;
22322 shift = (shift == 0) ? 8 : shift;
22324 switch (extract32(ctx->opcode, 3, 1)) {
22325 case NM_SLL16:
22326 opc = OPC_SLL;
22327 break;
22328 case NM_SRL16:
22329 opc = OPC_SRL;
22330 break;
22332 gen_shift_imm(ctx, opc, rt, rs, shift);
22334 break;
22335 case NM_P16C:
22336 switch (ctx->opcode & 1) {
22337 case NM_POOL16C_0:
22338 gen_pool16c_nanomips_insn(ctx);
22339 break;
22340 case NM_LWXS16:
22341 gen_ldxs(ctx, rt, rs, rd);
22342 break;
22344 break;
22345 case NM_P16_A1:
22346 switch (extract32(ctx->opcode, 6, 1)) {
22347 case NM_ADDIUR1SP:
22348 imm = extract32(ctx->opcode, 0, 6) << 2;
22349 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
22350 break;
22351 default:
22352 gen_reserved_instruction(ctx);
22353 break;
22355 break;
22356 case NM_P16_A2:
22357 switch (extract32(ctx->opcode, 3, 1)) {
22358 case NM_ADDIUR2:
22359 imm = extract32(ctx->opcode, 0, 3) << 2;
22360 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
22361 break;
22362 case NM_P_ADDIURS5:
22363 rt = extract32(ctx->opcode, 5, 5);
22364 if (rt != 0) {
22365 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
22366 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
22367 (extract32(ctx->opcode, 0, 3));
22368 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
22370 break;
22372 break;
22373 case NM_P16_ADDU:
22374 switch (ctx->opcode & 0x1) {
22375 case NM_ADDU16:
22376 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
22377 break;
22378 case NM_SUBU16:
22379 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
22380 break;
22382 break;
22383 case NM_P16_4X4:
22384 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22385 extract32(ctx->opcode, 5, 3);
22386 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22387 extract32(ctx->opcode, 0, 3);
22388 rt = decode_gpr_gpr4(rt);
22389 rs = decode_gpr_gpr4(rs);
22390 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
22391 (extract32(ctx->opcode, 3, 1))) {
22392 case NM_ADDU4X4:
22393 check_nms(ctx);
22394 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
22395 break;
22396 case NM_MUL4X4:
22397 check_nms(ctx);
22398 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
22399 break;
22400 default:
22401 gen_reserved_instruction(ctx);
22402 break;
22404 break;
22405 case NM_LI16:
22407 int imm = extract32(ctx->opcode, 0, 7);
22408 imm = (imm == 0x7f ? -1 : imm);
22409 if (rt != 0) {
22410 tcg_gen_movi_tl(cpu_gpr[rt], imm);
22413 break;
22414 case NM_ANDI16:
22416 uint32_t u = extract32(ctx->opcode, 0, 4);
22417 u = (u == 12) ? 0xff :
22418 (u == 13) ? 0xffff : u;
22419 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
22421 break;
22422 case NM_P16_LB:
22423 offset = extract32(ctx->opcode, 0, 2);
22424 switch (extract32(ctx->opcode, 2, 2)) {
22425 case NM_LB16:
22426 gen_ld(ctx, OPC_LB, rt, rs, offset);
22427 break;
22428 case NM_SB16:
22429 rt = decode_gpr_gpr3_src_store(
22430 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22431 gen_st(ctx, OPC_SB, rt, rs, offset);
22432 break;
22433 case NM_LBU16:
22434 gen_ld(ctx, OPC_LBU, rt, rs, offset);
22435 break;
22436 default:
22437 gen_reserved_instruction(ctx);
22438 break;
22440 break;
22441 case NM_P16_LH:
22442 offset = extract32(ctx->opcode, 1, 2) << 1;
22443 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
22444 case NM_LH16:
22445 gen_ld(ctx, OPC_LH, rt, rs, offset);
22446 break;
22447 case NM_SH16:
22448 rt = decode_gpr_gpr3_src_store(
22449 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22450 gen_st(ctx, OPC_SH, rt, rs, offset);
22451 break;
22452 case NM_LHU16:
22453 gen_ld(ctx, OPC_LHU, rt, rs, offset);
22454 break;
22455 default:
22456 gen_reserved_instruction(ctx);
22457 break;
22459 break;
22460 case NM_LW16:
22461 offset = extract32(ctx->opcode, 0, 4) << 2;
22462 gen_ld(ctx, OPC_LW, rt, rs, offset);
22463 break;
22464 case NM_LWSP16:
22465 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22466 offset = extract32(ctx->opcode, 0, 5) << 2;
22467 gen_ld(ctx, OPC_LW, rt, 29, offset);
22468 break;
22469 case NM_LW4X4:
22470 check_nms(ctx);
22471 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22472 extract32(ctx->opcode, 5, 3);
22473 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22474 extract32(ctx->opcode, 0, 3);
22475 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22476 (extract32(ctx->opcode, 8, 1) << 2);
22477 rt = decode_gpr_gpr4(rt);
22478 rs = decode_gpr_gpr4(rs);
22479 gen_ld(ctx, OPC_LW, rt, rs, offset);
22480 break;
22481 case NM_SW4X4:
22482 check_nms(ctx);
22483 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22484 extract32(ctx->opcode, 5, 3);
22485 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22486 extract32(ctx->opcode, 0, 3);
22487 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22488 (extract32(ctx->opcode, 8, 1) << 2);
22489 rt = decode_gpr_gpr4_zero(rt);
22490 rs = decode_gpr_gpr4(rs);
22491 gen_st(ctx, OPC_SW, rt, rs, offset);
22492 break;
22493 case NM_LWGP16:
22494 offset = extract32(ctx->opcode, 0, 7) << 2;
22495 gen_ld(ctx, OPC_LW, rt, 28, offset);
22496 break;
22497 case NM_SWSP16:
22498 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22499 offset = extract32(ctx->opcode, 0, 5) << 2;
22500 gen_st(ctx, OPC_SW, rt, 29, offset);
22501 break;
22502 case NM_SW16:
22503 rt = decode_gpr_gpr3_src_store(
22504 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22505 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22506 offset = extract32(ctx->opcode, 0, 4) << 2;
22507 gen_st(ctx, OPC_SW, rt, rs, offset);
22508 break;
22509 case NM_SWGP16:
22510 rt = decode_gpr_gpr3_src_store(
22511 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22512 offset = extract32(ctx->opcode, 0, 7) << 2;
22513 gen_st(ctx, OPC_SW, rt, 28, offset);
22514 break;
22515 case NM_BC16:
22516 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
22517 (sextract32(ctx->opcode, 0, 1) << 10) |
22518 (extract32(ctx->opcode, 1, 9) << 1));
22519 break;
22520 case NM_BALC16:
22521 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
22522 (sextract32(ctx->opcode, 0, 1) << 10) |
22523 (extract32(ctx->opcode, 1, 9) << 1));
22524 break;
22525 case NM_BEQZC16:
22526 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
22527 (sextract32(ctx->opcode, 0, 1) << 7) |
22528 (extract32(ctx->opcode, 1, 6) << 1));
22529 break;
22530 case NM_BNEZC16:
22531 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
22532 (sextract32(ctx->opcode, 0, 1) << 7) |
22533 (extract32(ctx->opcode, 1, 6) << 1));
22534 break;
22535 case NM_P16_BR:
22536 switch (ctx->opcode & 0xf) {
22537 case 0:
22538 /* P16.JRC */
22539 switch (extract32(ctx->opcode, 4, 1)) {
22540 case NM_JRC:
22541 gen_compute_branch_nm(ctx, OPC_JR, 2,
22542 extract32(ctx->opcode, 5, 5), 0, 0);
22543 break;
22544 case NM_JALRC16:
22545 gen_compute_branch_nm(ctx, OPC_JALR, 2,
22546 extract32(ctx->opcode, 5, 5), 31, 0);
22547 break;
22549 break;
22550 default:
22552 /* P16.BRI */
22553 uint32_t opc = extract32(ctx->opcode, 4, 3) <
22554 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
22555 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
22556 extract32(ctx->opcode, 0, 4) << 1);
22558 break;
22560 break;
22561 case NM_P16_SR:
22563 int count = extract32(ctx->opcode, 0, 4);
22564 int u = extract32(ctx->opcode, 4, 4) << 4;
22566 rt = 30 + extract32(ctx->opcode, 9, 1);
22567 switch (extract32(ctx->opcode, 8, 1)) {
22568 case NM_SAVE16:
22569 gen_save(ctx, rt, count, 0, u);
22570 break;
22571 case NM_RESTORE_JRC16:
22572 gen_restore(ctx, rt, count, 0, u);
22573 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
22574 break;
22577 break;
22578 case NM_MOVEP:
22579 case NM_MOVEPREV:
22580 check_nms(ctx);
22582 static const int gpr2reg1[] = {4, 5, 6, 7};
22583 static const int gpr2reg2[] = {5, 6, 7, 8};
22584 int re;
22585 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
22586 extract32(ctx->opcode, 8, 1);
22587 int r1 = gpr2reg1[rd2];
22588 int r2 = gpr2reg2[rd2];
22589 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
22590 extract32(ctx->opcode, 0, 3);
22591 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
22592 extract32(ctx->opcode, 5, 3);
22593 TCGv t0 = tcg_temp_new();
22594 TCGv t1 = tcg_temp_new();
22595 if (op == NM_MOVEP) {
22596 rd = r1;
22597 re = r2;
22598 rs = decode_gpr_gpr4_zero(r3);
22599 rt = decode_gpr_gpr4_zero(r4);
22600 } else {
22601 rd = decode_gpr_gpr4(r3);
22602 re = decode_gpr_gpr4(r4);
22603 rs = r1;
22604 rt = r2;
22606 gen_load_gpr(t0, rs);
22607 gen_load_gpr(t1, rt);
22608 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22609 tcg_gen_mov_tl(cpu_gpr[re], t1);
22610 tcg_temp_free(t0);
22611 tcg_temp_free(t1);
22613 break;
22614 default:
22615 return decode_nanomips_32_48_opc(env, ctx);
22618 return 2;
22622 /* SmartMIPS extension to MIPS32 */
22624 #if defined(TARGET_MIPS64)
22626 /* MDMX extension to MIPS64 */
22628 #endif
22630 /* MIPSDSP functions. */
22631 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
22632 int rd, int base, int offset)
22634 TCGv t0;
22636 check_dsp(ctx);
22637 t0 = tcg_temp_new();
22639 if (base == 0) {
22640 gen_load_gpr(t0, offset);
22641 } else if (offset == 0) {
22642 gen_load_gpr(t0, base);
22643 } else {
22644 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
22647 switch (opc) {
22648 case OPC_LBUX:
22649 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
22650 gen_store_gpr(t0, rd);
22651 break;
22652 case OPC_LHX:
22653 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
22654 gen_store_gpr(t0, rd);
22655 break;
22656 case OPC_LWX:
22657 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
22658 gen_store_gpr(t0, rd);
22659 break;
22660 #if defined(TARGET_MIPS64)
22661 case OPC_LDX:
22662 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
22663 gen_store_gpr(t0, rd);
22664 break;
22665 #endif
22667 tcg_temp_free(t0);
22670 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
22671 int ret, int v1, int v2)
22673 TCGv v1_t;
22674 TCGv v2_t;
22676 if (ret == 0) {
22677 /* Treat as NOP. */
22678 return;
22681 v1_t = tcg_temp_new();
22682 v2_t = tcg_temp_new();
22684 gen_load_gpr(v1_t, v1);
22685 gen_load_gpr(v2_t, v2);
22687 switch (op1) {
22688 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
22689 case OPC_MULT_G_2E:
22690 check_dsp_r2(ctx);
22691 switch (op2) {
22692 case OPC_ADDUH_QB:
22693 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
22694 break;
22695 case OPC_ADDUH_R_QB:
22696 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22697 break;
22698 case OPC_ADDQH_PH:
22699 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
22700 break;
22701 case OPC_ADDQH_R_PH:
22702 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22703 break;
22704 case OPC_ADDQH_W:
22705 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
22706 break;
22707 case OPC_ADDQH_R_W:
22708 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22709 break;
22710 case OPC_SUBUH_QB:
22711 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
22712 break;
22713 case OPC_SUBUH_R_QB:
22714 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22715 break;
22716 case OPC_SUBQH_PH:
22717 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
22718 break;
22719 case OPC_SUBQH_R_PH:
22720 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22721 break;
22722 case OPC_SUBQH_W:
22723 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
22724 break;
22725 case OPC_SUBQH_R_W:
22726 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22727 break;
22729 break;
22730 case OPC_ABSQ_S_PH_DSP:
22731 switch (op2) {
22732 case OPC_ABSQ_S_QB:
22733 check_dsp_r2(ctx);
22734 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
22735 break;
22736 case OPC_ABSQ_S_PH:
22737 check_dsp(ctx);
22738 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
22739 break;
22740 case OPC_ABSQ_S_W:
22741 check_dsp(ctx);
22742 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
22743 break;
22744 case OPC_PRECEQ_W_PHL:
22745 check_dsp(ctx);
22746 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
22747 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22748 break;
22749 case OPC_PRECEQ_W_PHR:
22750 check_dsp(ctx);
22751 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
22752 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
22753 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22754 break;
22755 case OPC_PRECEQU_PH_QBL:
22756 check_dsp(ctx);
22757 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
22758 break;
22759 case OPC_PRECEQU_PH_QBR:
22760 check_dsp(ctx);
22761 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
22762 break;
22763 case OPC_PRECEQU_PH_QBLA:
22764 check_dsp(ctx);
22765 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
22766 break;
22767 case OPC_PRECEQU_PH_QBRA:
22768 check_dsp(ctx);
22769 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
22770 break;
22771 case OPC_PRECEU_PH_QBL:
22772 check_dsp(ctx);
22773 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
22774 break;
22775 case OPC_PRECEU_PH_QBR:
22776 check_dsp(ctx);
22777 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
22778 break;
22779 case OPC_PRECEU_PH_QBLA:
22780 check_dsp(ctx);
22781 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
22782 break;
22783 case OPC_PRECEU_PH_QBRA:
22784 check_dsp(ctx);
22785 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
22786 break;
22788 break;
22789 case OPC_ADDU_QB_DSP:
22790 switch (op2) {
22791 case OPC_ADDQ_PH:
22792 check_dsp(ctx);
22793 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22794 break;
22795 case OPC_ADDQ_S_PH:
22796 check_dsp(ctx);
22797 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22798 break;
22799 case OPC_ADDQ_S_W:
22800 check_dsp(ctx);
22801 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22802 break;
22803 case OPC_ADDU_QB:
22804 check_dsp(ctx);
22805 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22806 break;
22807 case OPC_ADDU_S_QB:
22808 check_dsp(ctx);
22809 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22810 break;
22811 case OPC_ADDU_PH:
22812 check_dsp_r2(ctx);
22813 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22814 break;
22815 case OPC_ADDU_S_PH:
22816 check_dsp_r2(ctx);
22817 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22818 break;
22819 case OPC_SUBQ_PH:
22820 check_dsp(ctx);
22821 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22822 break;
22823 case OPC_SUBQ_S_PH:
22824 check_dsp(ctx);
22825 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22826 break;
22827 case OPC_SUBQ_S_W:
22828 check_dsp(ctx);
22829 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22830 break;
22831 case OPC_SUBU_QB:
22832 check_dsp(ctx);
22833 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22834 break;
22835 case OPC_SUBU_S_QB:
22836 check_dsp(ctx);
22837 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22838 break;
22839 case OPC_SUBU_PH:
22840 check_dsp_r2(ctx);
22841 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22842 break;
22843 case OPC_SUBU_S_PH:
22844 check_dsp_r2(ctx);
22845 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22846 break;
22847 case OPC_ADDSC:
22848 check_dsp(ctx);
22849 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22850 break;
22851 case OPC_ADDWC:
22852 check_dsp(ctx);
22853 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22854 break;
22855 case OPC_MODSUB:
22856 check_dsp(ctx);
22857 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
22858 break;
22859 case OPC_RADDU_W_QB:
22860 check_dsp(ctx);
22861 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
22862 break;
22864 break;
22865 case OPC_CMPU_EQ_QB_DSP:
22866 switch (op2) {
22867 case OPC_PRECR_QB_PH:
22868 check_dsp_r2(ctx);
22869 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22870 break;
22871 case OPC_PRECRQ_QB_PH:
22872 check_dsp(ctx);
22873 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22874 break;
22875 case OPC_PRECR_SRA_PH_W:
22876 check_dsp_r2(ctx);
22878 TCGv_i32 sa_t = tcg_const_i32(v2);
22879 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
22880 cpu_gpr[ret]);
22881 tcg_temp_free_i32(sa_t);
22882 break;
22884 case OPC_PRECR_SRA_R_PH_W:
22885 check_dsp_r2(ctx);
22887 TCGv_i32 sa_t = tcg_const_i32(v2);
22888 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
22889 cpu_gpr[ret]);
22890 tcg_temp_free_i32(sa_t);
22891 break;
22893 case OPC_PRECRQ_PH_W:
22894 check_dsp(ctx);
22895 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
22896 break;
22897 case OPC_PRECRQ_RS_PH_W:
22898 check_dsp(ctx);
22899 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22900 break;
22901 case OPC_PRECRQU_S_QB_PH:
22902 check_dsp(ctx);
22903 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22904 break;
22906 break;
22907 #ifdef TARGET_MIPS64
22908 case OPC_ABSQ_S_QH_DSP:
22909 switch (op2) {
22910 case OPC_PRECEQ_L_PWL:
22911 check_dsp(ctx);
22912 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
22913 break;
22914 case OPC_PRECEQ_L_PWR:
22915 check_dsp(ctx);
22916 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
22917 break;
22918 case OPC_PRECEQ_PW_QHL:
22919 check_dsp(ctx);
22920 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
22921 break;
22922 case OPC_PRECEQ_PW_QHR:
22923 check_dsp(ctx);
22924 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
22925 break;
22926 case OPC_PRECEQ_PW_QHLA:
22927 check_dsp(ctx);
22928 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
22929 break;
22930 case OPC_PRECEQ_PW_QHRA:
22931 check_dsp(ctx);
22932 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
22933 break;
22934 case OPC_PRECEQU_QH_OBL:
22935 check_dsp(ctx);
22936 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
22937 break;
22938 case OPC_PRECEQU_QH_OBR:
22939 check_dsp(ctx);
22940 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
22941 break;
22942 case OPC_PRECEQU_QH_OBLA:
22943 check_dsp(ctx);
22944 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
22945 break;
22946 case OPC_PRECEQU_QH_OBRA:
22947 check_dsp(ctx);
22948 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
22949 break;
22950 case OPC_PRECEU_QH_OBL:
22951 check_dsp(ctx);
22952 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
22953 break;
22954 case OPC_PRECEU_QH_OBR:
22955 check_dsp(ctx);
22956 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
22957 break;
22958 case OPC_PRECEU_QH_OBLA:
22959 check_dsp(ctx);
22960 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
22961 break;
22962 case OPC_PRECEU_QH_OBRA:
22963 check_dsp(ctx);
22964 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
22965 break;
22966 case OPC_ABSQ_S_OB:
22967 check_dsp_r2(ctx);
22968 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
22969 break;
22970 case OPC_ABSQ_S_PW:
22971 check_dsp(ctx);
22972 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
22973 break;
22974 case OPC_ABSQ_S_QH:
22975 check_dsp(ctx);
22976 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
22977 break;
22979 break;
22980 case OPC_ADDU_OB_DSP:
22981 switch (op2) {
22982 case OPC_RADDU_L_OB:
22983 check_dsp(ctx);
22984 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
22985 break;
22986 case OPC_SUBQ_PW:
22987 check_dsp(ctx);
22988 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22989 break;
22990 case OPC_SUBQ_S_PW:
22991 check_dsp(ctx);
22992 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22993 break;
22994 case OPC_SUBQ_QH:
22995 check_dsp(ctx);
22996 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22997 break;
22998 case OPC_SUBQ_S_QH:
22999 check_dsp(ctx);
23000 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23001 break;
23002 case OPC_SUBU_OB:
23003 check_dsp(ctx);
23004 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23005 break;
23006 case OPC_SUBU_S_OB:
23007 check_dsp(ctx);
23008 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23009 break;
23010 case OPC_SUBU_QH:
23011 check_dsp_r2(ctx);
23012 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23013 break;
23014 case OPC_SUBU_S_QH:
23015 check_dsp_r2(ctx);
23016 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23017 break;
23018 case OPC_SUBUH_OB:
23019 check_dsp_r2(ctx);
23020 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
23021 break;
23022 case OPC_SUBUH_R_OB:
23023 check_dsp_r2(ctx);
23024 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
23025 break;
23026 case OPC_ADDQ_PW:
23027 check_dsp(ctx);
23028 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23029 break;
23030 case OPC_ADDQ_S_PW:
23031 check_dsp(ctx);
23032 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23033 break;
23034 case OPC_ADDQ_QH:
23035 check_dsp(ctx);
23036 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23037 break;
23038 case OPC_ADDQ_S_QH:
23039 check_dsp(ctx);
23040 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23041 break;
23042 case OPC_ADDU_OB:
23043 check_dsp(ctx);
23044 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23045 break;
23046 case OPC_ADDU_S_OB:
23047 check_dsp(ctx);
23048 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23049 break;
23050 case OPC_ADDU_QH:
23051 check_dsp_r2(ctx);
23052 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23053 break;
23054 case OPC_ADDU_S_QH:
23055 check_dsp_r2(ctx);
23056 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23057 break;
23058 case OPC_ADDUH_OB:
23059 check_dsp_r2(ctx);
23060 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
23061 break;
23062 case OPC_ADDUH_R_OB:
23063 check_dsp_r2(ctx);
23064 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
23065 break;
23067 break;
23068 case OPC_CMPU_EQ_OB_DSP:
23069 switch (op2) {
23070 case OPC_PRECR_OB_QH:
23071 check_dsp_r2(ctx);
23072 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
23073 break;
23074 case OPC_PRECR_SRA_QH_PW:
23075 check_dsp_r2(ctx);
23077 TCGv_i32 ret_t = tcg_const_i32(ret);
23078 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
23079 tcg_temp_free_i32(ret_t);
23080 break;
23082 case OPC_PRECR_SRA_R_QH_PW:
23083 check_dsp_r2(ctx);
23085 TCGv_i32 sa_v = tcg_const_i32(ret);
23086 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
23087 tcg_temp_free_i32(sa_v);
23088 break;
23090 case OPC_PRECRQ_OB_QH:
23091 check_dsp(ctx);
23092 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
23093 break;
23094 case OPC_PRECRQ_PW_L:
23095 check_dsp(ctx);
23096 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
23097 break;
23098 case OPC_PRECRQ_QH_PW:
23099 check_dsp(ctx);
23100 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
23101 break;
23102 case OPC_PRECRQ_RS_QH_PW:
23103 check_dsp(ctx);
23104 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23105 break;
23106 case OPC_PRECRQU_S_OB_QH:
23107 check_dsp(ctx);
23108 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23109 break;
23111 break;
23112 #endif
23115 tcg_temp_free(v1_t);
23116 tcg_temp_free(v2_t);
23119 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
23120 int ret, int v1, int v2)
23122 uint32_t op2;
23123 TCGv t0;
23124 TCGv v1_t;
23125 TCGv v2_t;
23127 if (ret == 0) {
23128 /* Treat as NOP. */
23129 return;
23132 t0 = tcg_temp_new();
23133 v1_t = tcg_temp_new();
23134 v2_t = tcg_temp_new();
23136 tcg_gen_movi_tl(t0, v1);
23137 gen_load_gpr(v1_t, v1);
23138 gen_load_gpr(v2_t, v2);
23140 switch (opc) {
23141 case OPC_SHLL_QB_DSP:
23143 op2 = MASK_SHLL_QB(ctx->opcode);
23144 switch (op2) {
23145 case OPC_SHLL_QB:
23146 check_dsp(ctx);
23147 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
23148 break;
23149 case OPC_SHLLV_QB:
23150 check_dsp(ctx);
23151 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23152 break;
23153 case OPC_SHLL_PH:
23154 check_dsp(ctx);
23155 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
23156 break;
23157 case OPC_SHLLV_PH:
23158 check_dsp(ctx);
23159 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23160 break;
23161 case OPC_SHLL_S_PH:
23162 check_dsp(ctx);
23163 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
23164 break;
23165 case OPC_SHLLV_S_PH:
23166 check_dsp(ctx);
23167 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23168 break;
23169 case OPC_SHLL_S_W:
23170 check_dsp(ctx);
23171 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
23172 break;
23173 case OPC_SHLLV_S_W:
23174 check_dsp(ctx);
23175 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23176 break;
23177 case OPC_SHRL_QB:
23178 check_dsp(ctx);
23179 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
23180 break;
23181 case OPC_SHRLV_QB:
23182 check_dsp(ctx);
23183 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
23184 break;
23185 case OPC_SHRL_PH:
23186 check_dsp_r2(ctx);
23187 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
23188 break;
23189 case OPC_SHRLV_PH:
23190 check_dsp_r2(ctx);
23191 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
23192 break;
23193 case OPC_SHRA_QB:
23194 check_dsp_r2(ctx);
23195 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
23196 break;
23197 case OPC_SHRA_R_QB:
23198 check_dsp_r2(ctx);
23199 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
23200 break;
23201 case OPC_SHRAV_QB:
23202 check_dsp_r2(ctx);
23203 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
23204 break;
23205 case OPC_SHRAV_R_QB:
23206 check_dsp_r2(ctx);
23207 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
23208 break;
23209 case OPC_SHRA_PH:
23210 check_dsp(ctx);
23211 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
23212 break;
23213 case OPC_SHRA_R_PH:
23214 check_dsp(ctx);
23215 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
23216 break;
23217 case OPC_SHRAV_PH:
23218 check_dsp(ctx);
23219 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
23220 break;
23221 case OPC_SHRAV_R_PH:
23222 check_dsp(ctx);
23223 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
23224 break;
23225 case OPC_SHRA_R_W:
23226 check_dsp(ctx);
23227 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
23228 break;
23229 case OPC_SHRAV_R_W:
23230 check_dsp(ctx);
23231 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
23232 break;
23233 default: /* Invalid */
23234 MIPS_INVAL("MASK SHLL.QB");
23235 gen_reserved_instruction(ctx);
23236 break;
23238 break;
23240 #ifdef TARGET_MIPS64
23241 case OPC_SHLL_OB_DSP:
23242 op2 = MASK_SHLL_OB(ctx->opcode);
23243 switch (op2) {
23244 case OPC_SHLL_PW:
23245 check_dsp(ctx);
23246 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23247 break;
23248 case OPC_SHLLV_PW:
23249 check_dsp(ctx);
23250 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23251 break;
23252 case OPC_SHLL_S_PW:
23253 check_dsp(ctx);
23254 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23255 break;
23256 case OPC_SHLLV_S_PW:
23257 check_dsp(ctx);
23258 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23259 break;
23260 case OPC_SHLL_OB:
23261 check_dsp(ctx);
23262 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
23263 break;
23264 case OPC_SHLLV_OB:
23265 check_dsp(ctx);
23266 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23267 break;
23268 case OPC_SHLL_QH:
23269 check_dsp(ctx);
23270 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23271 break;
23272 case OPC_SHLLV_QH:
23273 check_dsp(ctx);
23274 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23275 break;
23276 case OPC_SHLL_S_QH:
23277 check_dsp(ctx);
23278 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23279 break;
23280 case OPC_SHLLV_S_QH:
23281 check_dsp(ctx);
23282 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23283 break;
23284 case OPC_SHRA_OB:
23285 check_dsp_r2(ctx);
23286 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
23287 break;
23288 case OPC_SHRAV_OB:
23289 check_dsp_r2(ctx);
23290 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
23291 break;
23292 case OPC_SHRA_R_OB:
23293 check_dsp_r2(ctx);
23294 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
23295 break;
23296 case OPC_SHRAV_R_OB:
23297 check_dsp_r2(ctx);
23298 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
23299 break;
23300 case OPC_SHRA_PW:
23301 check_dsp(ctx);
23302 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
23303 break;
23304 case OPC_SHRAV_PW:
23305 check_dsp(ctx);
23306 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
23307 break;
23308 case OPC_SHRA_R_PW:
23309 check_dsp(ctx);
23310 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
23311 break;
23312 case OPC_SHRAV_R_PW:
23313 check_dsp(ctx);
23314 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
23315 break;
23316 case OPC_SHRA_QH:
23317 check_dsp(ctx);
23318 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
23319 break;
23320 case OPC_SHRAV_QH:
23321 check_dsp(ctx);
23322 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
23323 break;
23324 case OPC_SHRA_R_QH:
23325 check_dsp(ctx);
23326 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
23327 break;
23328 case OPC_SHRAV_R_QH:
23329 check_dsp(ctx);
23330 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
23331 break;
23332 case OPC_SHRL_OB:
23333 check_dsp(ctx);
23334 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
23335 break;
23336 case OPC_SHRLV_OB:
23337 check_dsp(ctx);
23338 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
23339 break;
23340 case OPC_SHRL_QH:
23341 check_dsp_r2(ctx);
23342 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
23343 break;
23344 case OPC_SHRLV_QH:
23345 check_dsp_r2(ctx);
23346 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
23347 break;
23348 default: /* Invalid */
23349 MIPS_INVAL("MASK SHLL.OB");
23350 gen_reserved_instruction(ctx);
23351 break;
23353 break;
23354 #endif
23357 tcg_temp_free(t0);
23358 tcg_temp_free(v1_t);
23359 tcg_temp_free(v2_t);
23362 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
23363 int ret, int v1, int v2, int check_ret)
23365 TCGv_i32 t0;
23366 TCGv v1_t;
23367 TCGv v2_t;
23369 if ((ret == 0) && (check_ret == 1)) {
23370 /* Treat as NOP. */
23371 return;
23374 t0 = tcg_temp_new_i32();
23375 v1_t = tcg_temp_new();
23376 v2_t = tcg_temp_new();
23378 tcg_gen_movi_i32(t0, ret);
23379 gen_load_gpr(v1_t, v1);
23380 gen_load_gpr(v2_t, v2);
23382 switch (op1) {
23384 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
23385 * the same mask and op1.
23387 case OPC_MULT_G_2E:
23388 check_dsp_r2(ctx);
23389 switch (op2) {
23390 case OPC_MUL_PH:
23391 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23392 break;
23393 case OPC_MUL_S_PH:
23394 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23395 break;
23396 case OPC_MULQ_S_W:
23397 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23398 break;
23399 case OPC_MULQ_RS_W:
23400 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23401 break;
23403 break;
23404 case OPC_DPA_W_PH_DSP:
23405 switch (op2) {
23406 case OPC_DPAU_H_QBL:
23407 check_dsp(ctx);
23408 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
23409 break;
23410 case OPC_DPAU_H_QBR:
23411 check_dsp(ctx);
23412 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
23413 break;
23414 case OPC_DPSU_H_QBL:
23415 check_dsp(ctx);
23416 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
23417 break;
23418 case OPC_DPSU_H_QBR:
23419 check_dsp(ctx);
23420 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
23421 break;
23422 case OPC_DPA_W_PH:
23423 check_dsp_r2(ctx);
23424 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
23425 break;
23426 case OPC_DPAX_W_PH:
23427 check_dsp_r2(ctx);
23428 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
23429 break;
23430 case OPC_DPAQ_S_W_PH:
23431 check_dsp(ctx);
23432 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23433 break;
23434 case OPC_DPAQX_S_W_PH:
23435 check_dsp_r2(ctx);
23436 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23437 break;
23438 case OPC_DPAQX_SA_W_PH:
23439 check_dsp_r2(ctx);
23440 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23441 break;
23442 case OPC_DPS_W_PH:
23443 check_dsp_r2(ctx);
23444 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
23445 break;
23446 case OPC_DPSX_W_PH:
23447 check_dsp_r2(ctx);
23448 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
23449 break;
23450 case OPC_DPSQ_S_W_PH:
23451 check_dsp(ctx);
23452 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23453 break;
23454 case OPC_DPSQX_S_W_PH:
23455 check_dsp_r2(ctx);
23456 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23457 break;
23458 case OPC_DPSQX_SA_W_PH:
23459 check_dsp_r2(ctx);
23460 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23461 break;
23462 case OPC_MULSAQ_S_W_PH:
23463 check_dsp(ctx);
23464 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23465 break;
23466 case OPC_DPAQ_SA_L_W:
23467 check_dsp(ctx);
23468 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23469 break;
23470 case OPC_DPSQ_SA_L_W:
23471 check_dsp(ctx);
23472 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23473 break;
23474 case OPC_MAQ_S_W_PHL:
23475 check_dsp(ctx);
23476 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
23477 break;
23478 case OPC_MAQ_S_W_PHR:
23479 check_dsp(ctx);
23480 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
23481 break;
23482 case OPC_MAQ_SA_W_PHL:
23483 check_dsp(ctx);
23484 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
23485 break;
23486 case OPC_MAQ_SA_W_PHR:
23487 check_dsp(ctx);
23488 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
23489 break;
23490 case OPC_MULSA_W_PH:
23491 check_dsp_r2(ctx);
23492 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
23493 break;
23495 break;
23496 #ifdef TARGET_MIPS64
23497 case OPC_DPAQ_W_QH_DSP:
23499 int ac = ret & 0x03;
23500 tcg_gen_movi_i32(t0, ac);
23502 switch (op2) {
23503 case OPC_DMADD:
23504 check_dsp(ctx);
23505 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
23506 break;
23507 case OPC_DMADDU:
23508 check_dsp(ctx);
23509 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
23510 break;
23511 case OPC_DMSUB:
23512 check_dsp(ctx);
23513 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
23514 break;
23515 case OPC_DMSUBU:
23516 check_dsp(ctx);
23517 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
23518 break;
23519 case OPC_DPA_W_QH:
23520 check_dsp_r2(ctx);
23521 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
23522 break;
23523 case OPC_DPAQ_S_W_QH:
23524 check_dsp(ctx);
23525 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23526 break;
23527 case OPC_DPAQ_SA_L_PW:
23528 check_dsp(ctx);
23529 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23530 break;
23531 case OPC_DPAU_H_OBL:
23532 check_dsp(ctx);
23533 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
23534 break;
23535 case OPC_DPAU_H_OBR:
23536 check_dsp(ctx);
23537 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
23538 break;
23539 case OPC_DPS_W_QH:
23540 check_dsp_r2(ctx);
23541 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
23542 break;
23543 case OPC_DPSQ_S_W_QH:
23544 check_dsp(ctx);
23545 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23546 break;
23547 case OPC_DPSQ_SA_L_PW:
23548 check_dsp(ctx);
23549 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23550 break;
23551 case OPC_DPSU_H_OBL:
23552 check_dsp(ctx);
23553 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
23554 break;
23555 case OPC_DPSU_H_OBR:
23556 check_dsp(ctx);
23557 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
23558 break;
23559 case OPC_MAQ_S_L_PWL:
23560 check_dsp(ctx);
23561 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
23562 break;
23563 case OPC_MAQ_S_L_PWR:
23564 check_dsp(ctx);
23565 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
23566 break;
23567 case OPC_MAQ_S_W_QHLL:
23568 check_dsp(ctx);
23569 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
23570 break;
23571 case OPC_MAQ_SA_W_QHLL:
23572 check_dsp(ctx);
23573 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
23574 break;
23575 case OPC_MAQ_S_W_QHLR:
23576 check_dsp(ctx);
23577 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
23578 break;
23579 case OPC_MAQ_SA_W_QHLR:
23580 check_dsp(ctx);
23581 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
23582 break;
23583 case OPC_MAQ_S_W_QHRL:
23584 check_dsp(ctx);
23585 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
23586 break;
23587 case OPC_MAQ_SA_W_QHRL:
23588 check_dsp(ctx);
23589 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
23590 break;
23591 case OPC_MAQ_S_W_QHRR:
23592 check_dsp(ctx);
23593 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
23594 break;
23595 case OPC_MAQ_SA_W_QHRR:
23596 check_dsp(ctx);
23597 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
23598 break;
23599 case OPC_MULSAQ_S_L_PW:
23600 check_dsp(ctx);
23601 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
23602 break;
23603 case OPC_MULSAQ_S_W_QH:
23604 check_dsp(ctx);
23605 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23606 break;
23609 break;
23610 #endif
23611 case OPC_ADDU_QB_DSP:
23612 switch (op2) {
23613 case OPC_MULEU_S_PH_QBL:
23614 check_dsp(ctx);
23615 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23616 break;
23617 case OPC_MULEU_S_PH_QBR:
23618 check_dsp(ctx);
23619 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23620 break;
23621 case OPC_MULQ_RS_PH:
23622 check_dsp(ctx);
23623 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23624 break;
23625 case OPC_MULEQ_S_W_PHL:
23626 check_dsp(ctx);
23627 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23628 break;
23629 case OPC_MULEQ_S_W_PHR:
23630 check_dsp(ctx);
23631 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23632 break;
23633 case OPC_MULQ_S_PH:
23634 check_dsp_r2(ctx);
23635 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23636 break;
23638 break;
23639 #ifdef TARGET_MIPS64
23640 case OPC_ADDU_OB_DSP:
23641 switch (op2) {
23642 case OPC_MULEQ_S_PW_QHL:
23643 check_dsp(ctx);
23644 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23645 break;
23646 case OPC_MULEQ_S_PW_QHR:
23647 check_dsp(ctx);
23648 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23649 break;
23650 case OPC_MULEU_S_QH_OBL:
23651 check_dsp(ctx);
23652 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23653 break;
23654 case OPC_MULEU_S_QH_OBR:
23655 check_dsp(ctx);
23656 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23657 break;
23658 case OPC_MULQ_RS_QH:
23659 check_dsp(ctx);
23660 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23661 break;
23663 break;
23664 #endif
23667 tcg_temp_free_i32(t0);
23668 tcg_temp_free(v1_t);
23669 tcg_temp_free(v2_t);
23672 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23673 int ret, int val)
23675 int16_t imm;
23676 TCGv t0;
23677 TCGv val_t;
23679 if (ret == 0) {
23680 /* Treat as NOP. */
23681 return;
23684 t0 = tcg_temp_new();
23685 val_t = tcg_temp_new();
23686 gen_load_gpr(val_t, val);
23688 switch (op1) {
23689 case OPC_ABSQ_S_PH_DSP:
23690 switch (op2) {
23691 case OPC_BITREV:
23692 check_dsp(ctx);
23693 gen_helper_bitrev(cpu_gpr[ret], val_t);
23694 break;
23695 case OPC_REPL_QB:
23696 check_dsp(ctx);
23698 target_long result;
23699 imm = (ctx->opcode >> 16) & 0xFF;
23700 result = (uint32_t)imm << 24 |
23701 (uint32_t)imm << 16 |
23702 (uint32_t)imm << 8 |
23703 (uint32_t)imm;
23704 result = (int32_t)result;
23705 tcg_gen_movi_tl(cpu_gpr[ret], result);
23707 break;
23708 case OPC_REPLV_QB:
23709 check_dsp(ctx);
23710 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23711 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23712 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23713 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23714 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23715 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23716 break;
23717 case OPC_REPL_PH:
23718 check_dsp(ctx);
23720 imm = (ctx->opcode >> 16) & 0x03FF;
23721 imm = (int16_t)(imm << 6) >> 6;
23722 tcg_gen_movi_tl(cpu_gpr[ret], \
23723 (target_long)((int32_t)imm << 16 | \
23724 (uint16_t)imm));
23726 break;
23727 case OPC_REPLV_PH:
23728 check_dsp(ctx);
23729 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23730 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23731 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23732 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23733 break;
23735 break;
23736 #ifdef TARGET_MIPS64
23737 case OPC_ABSQ_S_QH_DSP:
23738 switch (op2) {
23739 case OPC_REPL_OB:
23740 check_dsp(ctx);
23742 target_long temp;
23744 imm = (ctx->opcode >> 16) & 0xFF;
23745 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
23746 temp = (temp << 16) | temp;
23747 temp = (temp << 32) | temp;
23748 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23749 break;
23751 case OPC_REPL_PW:
23752 check_dsp(ctx);
23754 target_long temp;
23756 imm = (ctx->opcode >> 16) & 0x03FF;
23757 imm = (int16_t)(imm << 6) >> 6;
23758 temp = ((target_long)imm << 32) \
23759 | ((target_long)imm & 0xFFFFFFFF);
23760 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23761 break;
23763 case OPC_REPL_QH:
23764 check_dsp(ctx);
23766 target_long temp;
23768 imm = (ctx->opcode >> 16) & 0x03FF;
23769 imm = (int16_t)(imm << 6) >> 6;
23771 temp = ((uint64_t)(uint16_t)imm << 48) |
23772 ((uint64_t)(uint16_t)imm << 32) |
23773 ((uint64_t)(uint16_t)imm << 16) |
23774 (uint64_t)(uint16_t)imm;
23775 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23776 break;
23778 case OPC_REPLV_OB:
23779 check_dsp(ctx);
23780 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23781 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23782 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23783 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23784 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23785 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23786 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23787 break;
23788 case OPC_REPLV_PW:
23789 check_dsp(ctx);
23790 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
23791 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23792 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23793 break;
23794 case OPC_REPLV_QH:
23795 check_dsp(ctx);
23796 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23797 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23798 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23799 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23800 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23801 break;
23803 break;
23804 #endif
23806 tcg_temp_free(t0);
23807 tcg_temp_free(val_t);
23810 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
23811 uint32_t op1, uint32_t op2,
23812 int ret, int v1, int v2, int check_ret)
23814 TCGv t1;
23815 TCGv v1_t;
23816 TCGv v2_t;
23818 if ((ret == 0) && (check_ret == 1)) {
23819 /* Treat as NOP. */
23820 return;
23823 t1 = tcg_temp_new();
23824 v1_t = tcg_temp_new();
23825 v2_t = tcg_temp_new();
23827 gen_load_gpr(v1_t, v1);
23828 gen_load_gpr(v2_t, v2);
23830 switch (op1) {
23831 case OPC_CMPU_EQ_QB_DSP:
23832 switch (op2) {
23833 case OPC_CMPU_EQ_QB:
23834 check_dsp(ctx);
23835 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
23836 break;
23837 case OPC_CMPU_LT_QB:
23838 check_dsp(ctx);
23839 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
23840 break;
23841 case OPC_CMPU_LE_QB:
23842 check_dsp(ctx);
23843 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
23844 break;
23845 case OPC_CMPGU_EQ_QB:
23846 check_dsp(ctx);
23847 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
23848 break;
23849 case OPC_CMPGU_LT_QB:
23850 check_dsp(ctx);
23851 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
23852 break;
23853 case OPC_CMPGU_LE_QB:
23854 check_dsp(ctx);
23855 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
23856 break;
23857 case OPC_CMPGDU_EQ_QB:
23858 check_dsp_r2(ctx);
23859 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
23860 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23861 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23862 tcg_gen_shli_tl(t1, t1, 24);
23863 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23864 break;
23865 case OPC_CMPGDU_LT_QB:
23866 check_dsp_r2(ctx);
23867 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
23868 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23869 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23870 tcg_gen_shli_tl(t1, t1, 24);
23871 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23872 break;
23873 case OPC_CMPGDU_LE_QB:
23874 check_dsp_r2(ctx);
23875 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
23876 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23877 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23878 tcg_gen_shli_tl(t1, t1, 24);
23879 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23880 break;
23881 case OPC_CMP_EQ_PH:
23882 check_dsp(ctx);
23883 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
23884 break;
23885 case OPC_CMP_LT_PH:
23886 check_dsp(ctx);
23887 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
23888 break;
23889 case OPC_CMP_LE_PH:
23890 check_dsp(ctx);
23891 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
23892 break;
23893 case OPC_PICK_QB:
23894 check_dsp(ctx);
23895 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23896 break;
23897 case OPC_PICK_PH:
23898 check_dsp(ctx);
23899 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23900 break;
23901 case OPC_PACKRL_PH:
23902 check_dsp(ctx);
23903 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
23904 break;
23906 break;
23907 #ifdef TARGET_MIPS64
23908 case OPC_CMPU_EQ_OB_DSP:
23909 switch (op2) {
23910 case OPC_CMP_EQ_PW:
23911 check_dsp(ctx);
23912 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
23913 break;
23914 case OPC_CMP_LT_PW:
23915 check_dsp(ctx);
23916 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
23917 break;
23918 case OPC_CMP_LE_PW:
23919 check_dsp(ctx);
23920 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
23921 break;
23922 case OPC_CMP_EQ_QH:
23923 check_dsp(ctx);
23924 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
23925 break;
23926 case OPC_CMP_LT_QH:
23927 check_dsp(ctx);
23928 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
23929 break;
23930 case OPC_CMP_LE_QH:
23931 check_dsp(ctx);
23932 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
23933 break;
23934 case OPC_CMPGDU_EQ_OB:
23935 check_dsp_r2(ctx);
23936 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23937 break;
23938 case OPC_CMPGDU_LT_OB:
23939 check_dsp_r2(ctx);
23940 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23941 break;
23942 case OPC_CMPGDU_LE_OB:
23943 check_dsp_r2(ctx);
23944 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23945 break;
23946 case OPC_CMPGU_EQ_OB:
23947 check_dsp(ctx);
23948 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
23949 break;
23950 case OPC_CMPGU_LT_OB:
23951 check_dsp(ctx);
23952 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
23953 break;
23954 case OPC_CMPGU_LE_OB:
23955 check_dsp(ctx);
23956 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
23957 break;
23958 case OPC_CMPU_EQ_OB:
23959 check_dsp(ctx);
23960 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
23961 break;
23962 case OPC_CMPU_LT_OB:
23963 check_dsp(ctx);
23964 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
23965 break;
23966 case OPC_CMPU_LE_OB:
23967 check_dsp(ctx);
23968 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
23969 break;
23970 case OPC_PACKRL_PW:
23971 check_dsp(ctx);
23972 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
23973 break;
23974 case OPC_PICK_OB:
23975 check_dsp(ctx);
23976 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23977 break;
23978 case OPC_PICK_PW:
23979 check_dsp(ctx);
23980 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23981 break;
23982 case OPC_PICK_QH:
23983 check_dsp(ctx);
23984 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23985 break;
23987 break;
23988 #endif
23991 tcg_temp_free(t1);
23992 tcg_temp_free(v1_t);
23993 tcg_temp_free(v2_t);
23996 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
23997 uint32_t op1, int rt, int rs, int sa)
23999 TCGv t0;
24001 check_dsp_r2(ctx);
24003 if (rt == 0) {
24004 /* Treat as NOP. */
24005 return;
24008 t0 = tcg_temp_new();
24009 gen_load_gpr(t0, rs);
24011 switch (op1) {
24012 case OPC_APPEND_DSP:
24013 switch (MASK_APPEND(ctx->opcode)) {
24014 case OPC_APPEND:
24015 if (sa != 0) {
24016 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
24018 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
24019 break;
24020 case OPC_PREPEND:
24021 if (sa != 0) {
24022 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
24023 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
24024 tcg_gen_shli_tl(t0, t0, 32 - sa);
24025 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24027 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
24028 break;
24029 case OPC_BALIGN:
24030 sa &= 3;
24031 if (sa != 0 && sa != 2) {
24032 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
24033 tcg_gen_ext32u_tl(t0, t0);
24034 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
24035 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24037 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
24038 break;
24039 default: /* Invalid */
24040 MIPS_INVAL("MASK APPEND");
24041 gen_reserved_instruction(ctx);
24042 break;
24044 break;
24045 #ifdef TARGET_MIPS64
24046 case OPC_DAPPEND_DSP:
24047 switch (MASK_DAPPEND(ctx->opcode)) {
24048 case OPC_DAPPEND:
24049 if (sa != 0) {
24050 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
24052 break;
24053 case OPC_PREPENDD:
24054 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
24055 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
24056 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
24057 break;
24058 case OPC_PREPENDW:
24059 if (sa != 0) {
24060 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
24061 tcg_gen_shli_tl(t0, t0, 64 - sa);
24062 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24064 break;
24065 case OPC_DBALIGN:
24066 sa &= 7;
24067 if (sa != 0 && sa != 2 && sa != 4) {
24068 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
24069 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
24070 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24072 break;
24073 default: /* Invalid */
24074 MIPS_INVAL("MASK DAPPEND");
24075 gen_reserved_instruction(ctx);
24076 break;
24078 break;
24079 #endif
24081 tcg_temp_free(t0);
24084 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
24085 int ret, int v1, int v2, int check_ret)
24088 TCGv t0;
24089 TCGv t1;
24090 TCGv v1_t;
24091 TCGv v2_t;
24092 int16_t imm;
24094 if ((ret == 0) && (check_ret == 1)) {
24095 /* Treat as NOP. */
24096 return;
24099 t0 = tcg_temp_new();
24100 t1 = tcg_temp_new();
24101 v1_t = tcg_temp_new();
24102 v2_t = tcg_temp_new();
24104 gen_load_gpr(v1_t, v1);
24105 gen_load_gpr(v2_t, v2);
24107 switch (op1) {
24108 case OPC_EXTR_W_DSP:
24109 check_dsp(ctx);
24110 switch (op2) {
24111 case OPC_EXTR_W:
24112 tcg_gen_movi_tl(t0, v2);
24113 tcg_gen_movi_tl(t1, v1);
24114 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
24115 break;
24116 case OPC_EXTR_R_W:
24117 tcg_gen_movi_tl(t0, v2);
24118 tcg_gen_movi_tl(t1, v1);
24119 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24120 break;
24121 case OPC_EXTR_RS_W:
24122 tcg_gen_movi_tl(t0, v2);
24123 tcg_gen_movi_tl(t1, v1);
24124 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24125 break;
24126 case OPC_EXTR_S_H:
24127 tcg_gen_movi_tl(t0, v2);
24128 tcg_gen_movi_tl(t1, v1);
24129 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24130 break;
24131 case OPC_EXTRV_S_H:
24132 tcg_gen_movi_tl(t0, v2);
24133 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
24134 break;
24135 case OPC_EXTRV_W:
24136 tcg_gen_movi_tl(t0, v2);
24137 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24138 break;
24139 case OPC_EXTRV_R_W:
24140 tcg_gen_movi_tl(t0, v2);
24141 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24142 break;
24143 case OPC_EXTRV_RS_W:
24144 tcg_gen_movi_tl(t0, v2);
24145 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24146 break;
24147 case OPC_EXTP:
24148 tcg_gen_movi_tl(t0, v2);
24149 tcg_gen_movi_tl(t1, v1);
24150 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
24151 break;
24152 case OPC_EXTPV:
24153 tcg_gen_movi_tl(t0, v2);
24154 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
24155 break;
24156 case OPC_EXTPDP:
24157 tcg_gen_movi_tl(t0, v2);
24158 tcg_gen_movi_tl(t1, v1);
24159 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
24160 break;
24161 case OPC_EXTPDPV:
24162 tcg_gen_movi_tl(t0, v2);
24163 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
24164 break;
24165 case OPC_SHILO:
24166 imm = (ctx->opcode >> 20) & 0x3F;
24167 tcg_gen_movi_tl(t0, ret);
24168 tcg_gen_movi_tl(t1, imm);
24169 gen_helper_shilo(t0, t1, cpu_env);
24170 break;
24171 case OPC_SHILOV:
24172 tcg_gen_movi_tl(t0, ret);
24173 gen_helper_shilo(t0, v1_t, cpu_env);
24174 break;
24175 case OPC_MTHLIP:
24176 tcg_gen_movi_tl(t0, ret);
24177 gen_helper_mthlip(t0, v1_t, cpu_env);
24178 break;
24179 case OPC_WRDSP:
24180 imm = (ctx->opcode >> 11) & 0x3FF;
24181 tcg_gen_movi_tl(t0, imm);
24182 gen_helper_wrdsp(v1_t, t0, cpu_env);
24183 break;
24184 case OPC_RDDSP:
24185 imm = (ctx->opcode >> 16) & 0x03FF;
24186 tcg_gen_movi_tl(t0, imm);
24187 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
24188 break;
24190 break;
24191 #ifdef TARGET_MIPS64
24192 case OPC_DEXTR_W_DSP:
24193 check_dsp(ctx);
24194 switch (op2) {
24195 case OPC_DMTHLIP:
24196 tcg_gen_movi_tl(t0, ret);
24197 gen_helper_dmthlip(v1_t, t0, cpu_env);
24198 break;
24199 case OPC_DSHILO:
24201 int shift = (ctx->opcode >> 19) & 0x7F;
24202 int ac = (ctx->opcode >> 11) & 0x03;
24203 tcg_gen_movi_tl(t0, shift);
24204 tcg_gen_movi_tl(t1, ac);
24205 gen_helper_dshilo(t0, t1, cpu_env);
24206 break;
24208 case OPC_DSHILOV:
24210 int ac = (ctx->opcode >> 11) & 0x03;
24211 tcg_gen_movi_tl(t0, ac);
24212 gen_helper_dshilo(v1_t, t0, cpu_env);
24213 break;
24215 case OPC_DEXTP:
24216 tcg_gen_movi_tl(t0, v2);
24217 tcg_gen_movi_tl(t1, v1);
24219 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
24220 break;
24221 case OPC_DEXTPV:
24222 tcg_gen_movi_tl(t0, v2);
24223 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
24224 break;
24225 case OPC_DEXTPDP:
24226 tcg_gen_movi_tl(t0, v2);
24227 tcg_gen_movi_tl(t1, v1);
24228 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
24229 break;
24230 case OPC_DEXTPDPV:
24231 tcg_gen_movi_tl(t0, v2);
24232 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
24233 break;
24234 case OPC_DEXTR_L:
24235 tcg_gen_movi_tl(t0, v2);
24236 tcg_gen_movi_tl(t1, v1);
24237 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
24238 break;
24239 case OPC_DEXTR_R_L:
24240 tcg_gen_movi_tl(t0, v2);
24241 tcg_gen_movi_tl(t1, v1);
24242 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
24243 break;
24244 case OPC_DEXTR_RS_L:
24245 tcg_gen_movi_tl(t0, v2);
24246 tcg_gen_movi_tl(t1, v1);
24247 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
24248 break;
24249 case OPC_DEXTR_W:
24250 tcg_gen_movi_tl(t0, v2);
24251 tcg_gen_movi_tl(t1, v1);
24252 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
24253 break;
24254 case OPC_DEXTR_R_W:
24255 tcg_gen_movi_tl(t0, v2);
24256 tcg_gen_movi_tl(t1, v1);
24257 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24258 break;
24259 case OPC_DEXTR_RS_W:
24260 tcg_gen_movi_tl(t0, v2);
24261 tcg_gen_movi_tl(t1, v1);
24262 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24263 break;
24264 case OPC_DEXTR_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_S_H:
24270 tcg_gen_movi_tl(t0, v2);
24271 tcg_gen_movi_tl(t1, v1);
24272 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24273 break;
24274 case OPC_DEXTRV_L:
24275 tcg_gen_movi_tl(t0, v2);
24276 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24277 break;
24278 case OPC_DEXTRV_R_L:
24279 tcg_gen_movi_tl(t0, v2);
24280 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24281 break;
24282 case OPC_DEXTRV_RS_L:
24283 tcg_gen_movi_tl(t0, v2);
24284 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24285 break;
24286 case OPC_DEXTRV_W:
24287 tcg_gen_movi_tl(t0, v2);
24288 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24289 break;
24290 case OPC_DEXTRV_R_W:
24291 tcg_gen_movi_tl(t0, v2);
24292 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24293 break;
24294 case OPC_DEXTRV_RS_W:
24295 tcg_gen_movi_tl(t0, v2);
24296 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24297 break;
24299 break;
24300 #endif
24303 tcg_temp_free(t0);
24304 tcg_temp_free(t1);
24305 tcg_temp_free(v1_t);
24306 tcg_temp_free(v2_t);
24309 /* End MIPSDSP functions. */
24311 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
24313 int rs, rt, rd, sa;
24314 uint32_t op1, op2;
24316 rs = (ctx->opcode >> 21) & 0x1f;
24317 rt = (ctx->opcode >> 16) & 0x1f;
24318 rd = (ctx->opcode >> 11) & 0x1f;
24319 sa = (ctx->opcode >> 6) & 0x1f;
24321 op1 = MASK_SPECIAL(ctx->opcode);
24322 switch (op1) {
24323 case OPC_MULT:
24324 case OPC_MULTU:
24325 case OPC_DIV:
24326 case OPC_DIVU:
24327 op2 = MASK_R6_MULDIV(ctx->opcode);
24328 switch (op2) {
24329 case R6_OPC_MUL:
24330 case R6_OPC_MUH:
24331 case R6_OPC_MULU:
24332 case R6_OPC_MUHU:
24333 case R6_OPC_DIV:
24334 case R6_OPC_MOD:
24335 case R6_OPC_DIVU:
24336 case R6_OPC_MODU:
24337 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24338 break;
24339 default:
24340 MIPS_INVAL("special_r6 muldiv");
24341 gen_reserved_instruction(ctx);
24342 break;
24344 break;
24345 case OPC_SELEQZ:
24346 case OPC_SELNEZ:
24347 gen_cond_move(ctx, op1, rd, rs, rt);
24348 break;
24349 case R6_OPC_CLO:
24350 case R6_OPC_CLZ:
24351 if (rt == 0 && sa == 1) {
24353 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24354 * We need additionally to check other fields.
24356 gen_cl(ctx, op1, rd, rs);
24357 } else {
24358 gen_reserved_instruction(ctx);
24360 break;
24361 case R6_OPC_SDBBP:
24362 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
24363 gen_helper_do_semihosting(cpu_env);
24364 } else {
24365 if (ctx->hflags & MIPS_HFLAG_SBRI) {
24366 gen_reserved_instruction(ctx);
24367 } else {
24368 generate_exception_end(ctx, EXCP_DBp);
24371 break;
24372 #if defined(TARGET_MIPS64)
24373 case R6_OPC_DCLO:
24374 case R6_OPC_DCLZ:
24375 if (rt == 0 && sa == 1) {
24377 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24378 * We need additionally to check other fields.
24380 check_mips_64(ctx);
24381 gen_cl(ctx, op1, rd, rs);
24382 } else {
24383 gen_reserved_instruction(ctx);
24385 break;
24386 case OPC_DMULT:
24387 case OPC_DMULTU:
24388 case OPC_DDIV:
24389 case OPC_DDIVU:
24391 op2 = MASK_R6_MULDIV(ctx->opcode);
24392 switch (op2) {
24393 case R6_OPC_DMUL:
24394 case R6_OPC_DMUH:
24395 case R6_OPC_DMULU:
24396 case R6_OPC_DMUHU:
24397 case R6_OPC_DDIV:
24398 case R6_OPC_DMOD:
24399 case R6_OPC_DDIVU:
24400 case R6_OPC_DMODU:
24401 check_mips_64(ctx);
24402 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24403 break;
24404 default:
24405 MIPS_INVAL("special_r6 muldiv");
24406 gen_reserved_instruction(ctx);
24407 break;
24409 break;
24410 #endif
24411 default: /* Invalid */
24412 MIPS_INVAL("special_r6");
24413 gen_reserved_instruction(ctx);
24414 break;
24418 static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
24420 int rs = extract32(ctx->opcode, 21, 5);
24421 int rt = extract32(ctx->opcode, 16, 5);
24422 int rd = extract32(ctx->opcode, 11, 5);
24423 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
24425 switch (op1) {
24426 case OPC_MOVN: /* Conditional move */
24427 case OPC_MOVZ:
24428 gen_cond_move(ctx, op1, rd, rs, rt);
24429 break;
24430 case OPC_MFHI: /* Move from HI/LO */
24431 case OPC_MFLO:
24432 gen_HILO(ctx, op1, 0, rd);
24433 break;
24434 case OPC_MTHI:
24435 case OPC_MTLO: /* Move to HI/LO */
24436 gen_HILO(ctx, op1, 0, rs);
24437 break;
24438 case OPC_MULT:
24439 case OPC_MULTU:
24440 gen_mul_txx9(ctx, op1, rd, rs, rt);
24441 break;
24442 case OPC_DIV:
24443 case OPC_DIVU:
24444 gen_muldiv(ctx, op1, 0, rs, rt);
24445 break;
24446 #if defined(TARGET_MIPS64)
24447 case OPC_DMULT:
24448 case OPC_DMULTU:
24449 case OPC_DDIV:
24450 case OPC_DDIVU:
24451 check_insn_opc_user_only(ctx, INSN_R5900);
24452 gen_muldiv(ctx, op1, 0, rs, rt);
24453 break;
24454 #endif
24455 case OPC_JR:
24456 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
24457 break;
24458 default: /* Invalid */
24459 MIPS_INVAL("special_tx79");
24460 gen_reserved_instruction(ctx);
24461 break;
24465 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
24467 int rs, rt, rd, sa;
24468 uint32_t op1;
24470 rs = (ctx->opcode >> 21) & 0x1f;
24471 rt = (ctx->opcode >> 16) & 0x1f;
24472 rd = (ctx->opcode >> 11) & 0x1f;
24473 sa = (ctx->opcode >> 6) & 0x1f;
24475 op1 = MASK_SPECIAL(ctx->opcode);
24476 switch (op1) {
24477 case OPC_MOVN: /* Conditional move */
24478 case OPC_MOVZ:
24479 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1 |
24480 INSN_LOONGSON2E | INSN_LOONGSON2F);
24481 gen_cond_move(ctx, op1, rd, rs, rt);
24482 break;
24483 case OPC_MFHI: /* Move from HI/LO */
24484 case OPC_MFLO:
24485 gen_HILO(ctx, op1, rs & 3, rd);
24486 break;
24487 case OPC_MTHI:
24488 case OPC_MTLO: /* Move to HI/LO */
24489 gen_HILO(ctx, op1, rd & 3, rs);
24490 break;
24491 case OPC_MOVCI:
24492 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
24493 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
24494 check_cp1_enabled(ctx);
24495 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
24496 (ctx->opcode >> 16) & 1);
24497 } else {
24498 generate_exception_err(ctx, EXCP_CpU, 1);
24500 break;
24501 case OPC_MULT:
24502 case OPC_MULTU:
24503 if (sa) {
24504 check_insn(ctx, INSN_VR54XX);
24505 op1 = MASK_MUL_VR54XX(ctx->opcode);
24506 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
24507 } else {
24508 gen_muldiv(ctx, op1, rd & 3, rs, rt);
24510 break;
24511 case OPC_DIV:
24512 case OPC_DIVU:
24513 gen_muldiv(ctx, op1, 0, rs, rt);
24514 break;
24515 #if defined(TARGET_MIPS64)
24516 case OPC_DMULT:
24517 case OPC_DMULTU:
24518 case OPC_DDIV:
24519 case OPC_DDIVU:
24520 check_insn(ctx, ISA_MIPS3);
24521 check_mips_64(ctx);
24522 gen_muldiv(ctx, op1, 0, rs, rt);
24523 break;
24524 #endif
24525 case OPC_JR:
24526 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24527 break;
24528 case OPC_SPIM:
24529 #ifdef MIPS_STRICT_STANDARD
24530 MIPS_INVAL("SPIM");
24531 gen_reserved_instruction(ctx);
24532 #else
24533 /* Implemented as RI exception for now. */
24534 MIPS_INVAL("spim (unofficial)");
24535 gen_reserved_instruction(ctx);
24536 #endif
24537 break;
24538 default: /* Invalid */
24539 MIPS_INVAL("special_legacy");
24540 gen_reserved_instruction(ctx);
24541 break;
24545 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
24547 int rs, rt, rd, sa;
24548 uint32_t op1;
24550 rs = (ctx->opcode >> 21) & 0x1f;
24551 rt = (ctx->opcode >> 16) & 0x1f;
24552 rd = (ctx->opcode >> 11) & 0x1f;
24553 sa = (ctx->opcode >> 6) & 0x1f;
24555 op1 = MASK_SPECIAL(ctx->opcode);
24556 switch (op1) {
24557 case OPC_SLL: /* Shift with immediate */
24558 if (sa == 5 && rd == 0 &&
24559 rs == 0 && rt == 0) { /* PAUSE */
24560 if ((ctx->insn_flags & ISA_MIPS_R6) &&
24561 (ctx->hflags & MIPS_HFLAG_BMASK)) {
24562 gen_reserved_instruction(ctx);
24563 break;
24566 /* Fallthrough */
24567 case OPC_SRA:
24568 gen_shift_imm(ctx, op1, rd, rt, sa);
24569 break;
24570 case OPC_SRL:
24571 switch ((ctx->opcode >> 21) & 0x1f) {
24572 case 1:
24573 /* rotr is decoded as srl on non-R2 CPUs */
24574 if (ctx->insn_flags & ISA_MIPS_R2) {
24575 op1 = OPC_ROTR;
24577 /* Fallthrough */
24578 case 0:
24579 gen_shift_imm(ctx, op1, rd, rt, sa);
24580 break;
24581 default:
24582 gen_reserved_instruction(ctx);
24583 break;
24585 break;
24586 case OPC_ADD:
24587 case OPC_ADDU:
24588 case OPC_SUB:
24589 case OPC_SUBU:
24590 gen_arith(ctx, op1, rd, rs, rt);
24591 break;
24592 case OPC_SLLV: /* Shifts */
24593 case OPC_SRAV:
24594 gen_shift(ctx, op1, rd, rs, rt);
24595 break;
24596 case OPC_SRLV:
24597 switch ((ctx->opcode >> 6) & 0x1f) {
24598 case 1:
24599 /* rotrv is decoded as srlv on non-R2 CPUs */
24600 if (ctx->insn_flags & ISA_MIPS_R2) {
24601 op1 = OPC_ROTRV;
24603 /* Fallthrough */
24604 case 0:
24605 gen_shift(ctx, op1, rd, rs, rt);
24606 break;
24607 default:
24608 gen_reserved_instruction(ctx);
24609 break;
24611 break;
24612 case OPC_SLT: /* Set on less than */
24613 case OPC_SLTU:
24614 gen_slt(ctx, op1, rd, rs, rt);
24615 break;
24616 case OPC_AND: /* Logic*/
24617 case OPC_OR:
24618 case OPC_NOR:
24619 case OPC_XOR:
24620 gen_logic(ctx, op1, rd, rs, rt);
24621 break;
24622 case OPC_JALR:
24623 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24624 break;
24625 case OPC_TGE: /* Traps */
24626 case OPC_TGEU:
24627 case OPC_TLT:
24628 case OPC_TLTU:
24629 case OPC_TEQ:
24630 case OPC_TNE:
24631 check_insn(ctx, ISA_MIPS2);
24632 gen_trap(ctx, op1, rs, rt, -1);
24633 break;
24634 case OPC_PMON:
24635 /* Pmon entry point, also R4010 selsl */
24636 #ifdef MIPS_STRICT_STANDARD
24637 MIPS_INVAL("PMON / selsl");
24638 gen_reserved_instruction(ctx);
24639 #else
24640 gen_helper_0e0i(pmon, sa);
24641 #endif
24642 break;
24643 case OPC_SYSCALL:
24644 generate_exception_end(ctx, EXCP_SYSCALL);
24645 break;
24646 case OPC_BREAK:
24647 generate_exception_end(ctx, EXCP_BREAK);
24648 break;
24649 case OPC_SYNC:
24650 check_insn(ctx, ISA_MIPS2);
24651 gen_sync(extract32(ctx->opcode, 6, 5));
24652 break;
24654 #if defined(TARGET_MIPS64)
24655 /* MIPS64 specific opcodes */
24656 case OPC_DSLL:
24657 case OPC_DSRA:
24658 case OPC_DSLL32:
24659 case OPC_DSRA32:
24660 check_insn(ctx, ISA_MIPS3);
24661 check_mips_64(ctx);
24662 gen_shift_imm(ctx, op1, rd, rt, sa);
24663 break;
24664 case OPC_DSRL:
24665 switch ((ctx->opcode >> 21) & 0x1f) {
24666 case 1:
24667 /* drotr is decoded as dsrl on non-R2 CPUs */
24668 if (ctx->insn_flags & ISA_MIPS_R2) {
24669 op1 = OPC_DROTR;
24671 /* Fallthrough */
24672 case 0:
24673 check_insn(ctx, ISA_MIPS3);
24674 check_mips_64(ctx);
24675 gen_shift_imm(ctx, op1, rd, rt, sa);
24676 break;
24677 default:
24678 gen_reserved_instruction(ctx);
24679 break;
24681 break;
24682 case OPC_DSRL32:
24683 switch ((ctx->opcode >> 21) & 0x1f) {
24684 case 1:
24685 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
24686 if (ctx->insn_flags & ISA_MIPS_R2) {
24687 op1 = OPC_DROTR32;
24689 /* Fallthrough */
24690 case 0:
24691 check_insn(ctx, ISA_MIPS3);
24692 check_mips_64(ctx);
24693 gen_shift_imm(ctx, op1, rd, rt, sa);
24694 break;
24695 default:
24696 gen_reserved_instruction(ctx);
24697 break;
24699 break;
24700 case OPC_DADD:
24701 case OPC_DADDU:
24702 case OPC_DSUB:
24703 case OPC_DSUBU:
24704 check_insn(ctx, ISA_MIPS3);
24705 check_mips_64(ctx);
24706 gen_arith(ctx, op1, rd, rs, rt);
24707 break;
24708 case OPC_DSLLV:
24709 case OPC_DSRAV:
24710 check_insn(ctx, ISA_MIPS3);
24711 check_mips_64(ctx);
24712 gen_shift(ctx, op1, rd, rs, rt);
24713 break;
24714 case OPC_DSRLV:
24715 switch ((ctx->opcode >> 6) & 0x1f) {
24716 case 1:
24717 /* drotrv is decoded as dsrlv on non-R2 CPUs */
24718 if (ctx->insn_flags & ISA_MIPS_R2) {
24719 op1 = OPC_DROTRV;
24721 /* Fallthrough */
24722 case 0:
24723 check_insn(ctx, ISA_MIPS3);
24724 check_mips_64(ctx);
24725 gen_shift(ctx, op1, rd, rs, rt);
24726 break;
24727 default:
24728 gen_reserved_instruction(ctx);
24729 break;
24731 break;
24732 #endif
24733 default:
24734 if (ctx->insn_flags & ISA_MIPS_R6) {
24735 decode_opc_special_r6(env, ctx);
24736 } else if (ctx->insn_flags & INSN_R5900) {
24737 decode_opc_special_tx79(env, ctx);
24738 } else {
24739 decode_opc_special_legacy(env, ctx);
24745 #if defined(TARGET_MIPS64)
24749 * MMI (MultiMedia Interface) ASE instructions
24750 * ===========================================
24754 * MMI instructions category: data communication
24755 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24757 * PCPYH PEXCH PEXTLB PINTH PPACB PEXT5 PREVH
24758 * PCPYLD PEXCW PEXTLH PINTEH PPACH PPAC5 PROT3W
24759 * PCPYUD PEXEH PEXTLW PPACW
24760 * PEXEW PEXTUB
24761 * PEXTUH
24762 * PEXTUW
24766 * PCPYH rd, rt
24768 * Parallel Copy Halfword
24770 * 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
24771 * +-----------+---------+---------+---------+---------+-----------+
24772 * | MMI |0 0 0 0 0| rt | rd | PCPYH | MMI3 |
24773 * +-----------+---------+---------+---------+---------+-----------+
24775 static void gen_mmi_pcpyh(DisasContext *ctx)
24777 uint32_t pd, rt, rd;
24778 uint32_t opcode;
24780 opcode = ctx->opcode;
24782 pd = extract32(opcode, 21, 5);
24783 rt = extract32(opcode, 16, 5);
24784 rd = extract32(opcode, 11, 5);
24786 if (unlikely(pd != 0)) {
24787 gen_reserved_instruction(ctx);
24788 } else if (rd == 0) {
24789 /* nop */
24790 } else if (rt == 0) {
24791 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24792 tcg_gen_movi_i64(cpu_gpr_hi[rd], 0);
24793 } else {
24794 TCGv_i64 t0 = tcg_temp_new();
24795 TCGv_i64 t1 = tcg_temp_new();
24796 uint64_t mask = (1ULL << 16) - 1;
24798 tcg_gen_andi_i64(t0, cpu_gpr[rt], mask);
24799 tcg_gen_movi_i64(t1, 0);
24800 tcg_gen_or_i64(t1, t0, t1);
24801 tcg_gen_shli_i64(t0, t0, 16);
24802 tcg_gen_or_i64(t1, t0, t1);
24803 tcg_gen_shli_i64(t0, t0, 16);
24804 tcg_gen_or_i64(t1, t0, t1);
24805 tcg_gen_shli_i64(t0, t0, 16);
24806 tcg_gen_or_i64(t1, t0, t1);
24808 tcg_gen_mov_i64(cpu_gpr[rd], t1);
24810 tcg_gen_andi_i64(t0, cpu_gpr_hi[rt], mask);
24811 tcg_gen_movi_i64(t1, 0);
24812 tcg_gen_or_i64(t1, t0, t1);
24813 tcg_gen_shli_i64(t0, t0, 16);
24814 tcg_gen_or_i64(t1, t0, t1);
24815 tcg_gen_shli_i64(t0, t0, 16);
24816 tcg_gen_or_i64(t1, t0, t1);
24817 tcg_gen_shli_i64(t0, t0, 16);
24818 tcg_gen_or_i64(t1, t0, t1);
24820 tcg_gen_mov_i64(cpu_gpr_hi[rd], t1);
24822 tcg_temp_free(t0);
24823 tcg_temp_free(t1);
24828 * PCPYLD rd, rs, rt
24830 * Parallel Copy Lower Doubleword
24832 * 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
24833 * +-----------+---------+---------+---------+---------+-----------+
24834 * | MMI | rs | rt | rd | PCPYLD | MMI2 |
24835 * +-----------+---------+---------+---------+---------+-----------+
24837 static void gen_mmi_pcpyld(DisasContext *ctx)
24839 uint32_t rs, rt, rd;
24840 uint32_t opcode;
24842 opcode = ctx->opcode;
24844 rs = extract32(opcode, 21, 5);
24845 rt = extract32(opcode, 16, 5);
24846 rd = extract32(opcode, 11, 5);
24848 if (rd == 0) {
24849 /* nop */
24850 } else {
24851 if (rs == 0) {
24852 tcg_gen_movi_i64(cpu_gpr_hi[rd], 0);
24853 } else {
24854 tcg_gen_mov_i64(cpu_gpr_hi[rd], cpu_gpr[rs]);
24856 if (rt == 0) {
24857 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24858 } else {
24859 if (rd != rt) {
24860 tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr[rt]);
24867 * PCPYUD rd, rs, rt
24869 * Parallel Copy Upper Doubleword
24871 * 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
24872 * +-----------+---------+---------+---------+---------+-----------+
24873 * | MMI | rs | rt | rd | PCPYUD | MMI3 |
24874 * +-----------+---------+---------+---------+---------+-----------+
24876 static void gen_mmi_pcpyud(DisasContext *ctx)
24878 uint32_t rs, rt, rd;
24879 uint32_t opcode;
24881 opcode = ctx->opcode;
24883 rs = extract32(opcode, 21, 5);
24884 rt = extract32(opcode, 16, 5);
24885 rd = extract32(opcode, 11, 5);
24887 if (rd == 0) {
24888 /* nop */
24889 } else {
24890 if (rs == 0) {
24891 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24892 } else {
24893 tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr_hi[rs]);
24895 if (rt == 0) {
24896 tcg_gen_movi_i64(cpu_gpr_hi[rd], 0);
24897 } else {
24898 if (rd != rt) {
24899 tcg_gen_mov_i64(cpu_gpr_hi[rd], cpu_gpr_hi[rt]);
24905 #endif
24908 #if !defined(TARGET_MIPS64)
24910 /* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
24911 #define MXU_APTN1_A 0
24912 #define MXU_APTN1_S 1
24914 /* MXU accumulate add/subtract 2-bit pattern 'aptn2' */
24915 #define MXU_APTN2_AA 0
24916 #define MXU_APTN2_AS 1
24917 #define MXU_APTN2_SA 2
24918 #define MXU_APTN2_SS 3
24920 /* MXU execute add/subtract 2-bit pattern 'eptn2' */
24921 #define MXU_EPTN2_AA 0
24922 #define MXU_EPTN2_AS 1
24923 #define MXU_EPTN2_SA 2
24924 #define MXU_EPTN2_SS 3
24926 /* MXU operand getting pattern 'optn2' */
24927 #define MXU_OPTN2_PTN0 0
24928 #define MXU_OPTN2_PTN1 1
24929 #define MXU_OPTN2_PTN2 2
24930 #define MXU_OPTN2_PTN3 3
24931 /* alternative naming scheme for 'optn2' */
24932 #define MXU_OPTN2_WW 0
24933 #define MXU_OPTN2_LW 1
24934 #define MXU_OPTN2_HW 2
24935 #define MXU_OPTN2_XW 3
24937 /* MXU operand getting pattern 'optn3' */
24938 #define MXU_OPTN3_PTN0 0
24939 #define MXU_OPTN3_PTN1 1
24940 #define MXU_OPTN3_PTN2 2
24941 #define MXU_OPTN3_PTN3 3
24942 #define MXU_OPTN3_PTN4 4
24943 #define MXU_OPTN3_PTN5 5
24944 #define MXU_OPTN3_PTN6 6
24945 #define MXU_OPTN3_PTN7 7
24949 * S32I2M XRa, rb - Register move from GRF to XRF
24951 static void gen_mxu_s32i2m(DisasContext *ctx)
24953 TCGv t0;
24954 uint32_t XRa, Rb;
24956 t0 = tcg_temp_new();
24958 XRa = extract32(ctx->opcode, 6, 5);
24959 Rb = extract32(ctx->opcode, 16, 5);
24961 gen_load_gpr(t0, Rb);
24962 if (XRa <= 15) {
24963 gen_store_mxu_gpr(t0, XRa);
24964 } else if (XRa == 16) {
24965 gen_store_mxu_cr(t0);
24968 tcg_temp_free(t0);
24972 * S32M2I XRa, rb - Register move from XRF to GRF
24974 static void gen_mxu_s32m2i(DisasContext *ctx)
24976 TCGv t0;
24977 uint32_t XRa, Rb;
24979 t0 = tcg_temp_new();
24981 XRa = extract32(ctx->opcode, 6, 5);
24982 Rb = extract32(ctx->opcode, 16, 5);
24984 if (XRa <= 15) {
24985 gen_load_mxu_gpr(t0, XRa);
24986 } else if (XRa == 16) {
24987 gen_load_mxu_cr(t0);
24990 gen_store_gpr(t0, Rb);
24992 tcg_temp_free(t0);
24996 * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF
24998 static void gen_mxu_s8ldd(DisasContext *ctx)
25000 TCGv t0, t1;
25001 uint32_t XRa, Rb, s8, optn3;
25003 t0 = tcg_temp_new();
25004 t1 = tcg_temp_new();
25006 XRa = extract32(ctx->opcode, 6, 4);
25007 s8 = extract32(ctx->opcode, 10, 8);
25008 optn3 = extract32(ctx->opcode, 18, 3);
25009 Rb = extract32(ctx->opcode, 21, 5);
25011 gen_load_gpr(t0, Rb);
25012 tcg_gen_addi_tl(t0, t0, (int8_t)s8);
25014 switch (optn3) {
25015 /* XRa[7:0] = tmp8 */
25016 case MXU_OPTN3_PTN0:
25017 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25018 gen_load_mxu_gpr(t0, XRa);
25019 tcg_gen_deposit_tl(t0, t0, t1, 0, 8);
25020 break;
25021 /* XRa[15:8] = tmp8 */
25022 case MXU_OPTN3_PTN1:
25023 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25024 gen_load_mxu_gpr(t0, XRa);
25025 tcg_gen_deposit_tl(t0, t0, t1, 8, 8);
25026 break;
25027 /* XRa[23:16] = tmp8 */
25028 case MXU_OPTN3_PTN2:
25029 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25030 gen_load_mxu_gpr(t0, XRa);
25031 tcg_gen_deposit_tl(t0, t0, t1, 16, 8);
25032 break;
25033 /* XRa[31:24] = tmp8 */
25034 case MXU_OPTN3_PTN3:
25035 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25036 gen_load_mxu_gpr(t0, XRa);
25037 tcg_gen_deposit_tl(t0, t0, t1, 24, 8);
25038 break;
25039 /* XRa = {8'b0, tmp8, 8'b0, tmp8} */
25040 case MXU_OPTN3_PTN4:
25041 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25042 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25043 break;
25044 /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */
25045 case MXU_OPTN3_PTN5:
25046 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25047 tcg_gen_shli_tl(t1, t1, 8);
25048 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25049 break;
25050 /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */
25051 case MXU_OPTN3_PTN6:
25052 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB);
25053 tcg_gen_mov_tl(t0, t1);
25054 tcg_gen_andi_tl(t0, t0, 0xFF00FFFF);
25055 tcg_gen_shli_tl(t1, t1, 16);
25056 tcg_gen_or_tl(t0, t0, t1);
25057 break;
25058 /* XRa = {tmp8, tmp8, tmp8, tmp8} */
25059 case MXU_OPTN3_PTN7:
25060 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25061 tcg_gen_deposit_tl(t1, t1, t1, 8, 8);
25062 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25063 break;
25066 gen_store_mxu_gpr(t0, XRa);
25068 tcg_temp_free(t0);
25069 tcg_temp_free(t1);
25073 * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication
25075 static void gen_mxu_d16mul(DisasContext *ctx)
25077 TCGv t0, t1, t2, t3;
25078 uint32_t XRa, XRb, XRc, XRd, optn2;
25080 t0 = tcg_temp_new();
25081 t1 = tcg_temp_new();
25082 t2 = tcg_temp_new();
25083 t3 = tcg_temp_new();
25085 XRa = extract32(ctx->opcode, 6, 4);
25086 XRb = extract32(ctx->opcode, 10, 4);
25087 XRc = extract32(ctx->opcode, 14, 4);
25088 XRd = extract32(ctx->opcode, 18, 4);
25089 optn2 = extract32(ctx->opcode, 22, 2);
25091 gen_load_mxu_gpr(t1, XRb);
25092 tcg_gen_sextract_tl(t0, t1, 0, 16);
25093 tcg_gen_sextract_tl(t1, t1, 16, 16);
25094 gen_load_mxu_gpr(t3, XRc);
25095 tcg_gen_sextract_tl(t2, t3, 0, 16);
25096 tcg_gen_sextract_tl(t3, t3, 16, 16);
25098 switch (optn2) {
25099 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
25100 tcg_gen_mul_tl(t3, t1, t3);
25101 tcg_gen_mul_tl(t2, t0, t2);
25102 break;
25103 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
25104 tcg_gen_mul_tl(t3, t0, t3);
25105 tcg_gen_mul_tl(t2, t0, t2);
25106 break;
25107 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
25108 tcg_gen_mul_tl(t3, t1, t3);
25109 tcg_gen_mul_tl(t2, t1, t2);
25110 break;
25111 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
25112 tcg_gen_mul_tl(t3, t0, t3);
25113 tcg_gen_mul_tl(t2, t1, t2);
25114 break;
25116 gen_store_mxu_gpr(t3, XRa);
25117 gen_store_mxu_gpr(t2, XRd);
25119 tcg_temp_free(t0);
25120 tcg_temp_free(t1);
25121 tcg_temp_free(t2);
25122 tcg_temp_free(t3);
25126 * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply
25127 * and accumulate
25129 static void gen_mxu_d16mac(DisasContext *ctx)
25131 TCGv t0, t1, t2, t3;
25132 uint32_t XRa, XRb, XRc, XRd, optn2, aptn2;
25134 t0 = tcg_temp_new();
25135 t1 = tcg_temp_new();
25136 t2 = tcg_temp_new();
25137 t3 = tcg_temp_new();
25139 XRa = extract32(ctx->opcode, 6, 4);
25140 XRb = extract32(ctx->opcode, 10, 4);
25141 XRc = extract32(ctx->opcode, 14, 4);
25142 XRd = extract32(ctx->opcode, 18, 4);
25143 optn2 = extract32(ctx->opcode, 22, 2);
25144 aptn2 = extract32(ctx->opcode, 24, 2);
25146 gen_load_mxu_gpr(t1, XRb);
25147 tcg_gen_sextract_tl(t0, t1, 0, 16);
25148 tcg_gen_sextract_tl(t1, t1, 16, 16);
25150 gen_load_mxu_gpr(t3, XRc);
25151 tcg_gen_sextract_tl(t2, t3, 0, 16);
25152 tcg_gen_sextract_tl(t3, t3, 16, 16);
25154 switch (optn2) {
25155 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
25156 tcg_gen_mul_tl(t3, t1, t3);
25157 tcg_gen_mul_tl(t2, t0, t2);
25158 break;
25159 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
25160 tcg_gen_mul_tl(t3, t0, t3);
25161 tcg_gen_mul_tl(t2, t0, t2);
25162 break;
25163 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
25164 tcg_gen_mul_tl(t3, t1, t3);
25165 tcg_gen_mul_tl(t2, t1, t2);
25166 break;
25167 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
25168 tcg_gen_mul_tl(t3, t0, t3);
25169 tcg_gen_mul_tl(t2, t1, t2);
25170 break;
25172 gen_load_mxu_gpr(t0, XRa);
25173 gen_load_mxu_gpr(t1, XRd);
25175 switch (aptn2) {
25176 case MXU_APTN2_AA:
25177 tcg_gen_add_tl(t3, t0, t3);
25178 tcg_gen_add_tl(t2, t1, t2);
25179 break;
25180 case MXU_APTN2_AS:
25181 tcg_gen_add_tl(t3, t0, t3);
25182 tcg_gen_sub_tl(t2, t1, t2);
25183 break;
25184 case MXU_APTN2_SA:
25185 tcg_gen_sub_tl(t3, t0, t3);
25186 tcg_gen_add_tl(t2, t1, t2);
25187 break;
25188 case MXU_APTN2_SS:
25189 tcg_gen_sub_tl(t3, t0, t3);
25190 tcg_gen_sub_tl(t2, t1, t2);
25191 break;
25193 gen_store_mxu_gpr(t3, XRa);
25194 gen_store_mxu_gpr(t2, XRd);
25196 tcg_temp_free(t0);
25197 tcg_temp_free(t1);
25198 tcg_temp_free(t2);
25199 tcg_temp_free(t3);
25203 * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply
25204 * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply
25206 static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx)
25208 TCGv t0, t1, t2, t3, t4, t5, t6, t7;
25209 uint32_t XRa, XRb, XRc, XRd, sel;
25211 t0 = tcg_temp_new();
25212 t1 = tcg_temp_new();
25213 t2 = tcg_temp_new();
25214 t3 = tcg_temp_new();
25215 t4 = tcg_temp_new();
25216 t5 = tcg_temp_new();
25217 t6 = tcg_temp_new();
25218 t7 = tcg_temp_new();
25220 XRa = extract32(ctx->opcode, 6, 4);
25221 XRb = extract32(ctx->opcode, 10, 4);
25222 XRc = extract32(ctx->opcode, 14, 4);
25223 XRd = extract32(ctx->opcode, 18, 4);
25224 sel = extract32(ctx->opcode, 22, 2);
25226 gen_load_mxu_gpr(t3, XRb);
25227 gen_load_mxu_gpr(t7, XRc);
25229 if (sel == 0x2) {
25230 /* Q8MULSU */
25231 tcg_gen_ext8s_tl(t0, t3);
25232 tcg_gen_shri_tl(t3, t3, 8);
25233 tcg_gen_ext8s_tl(t1, t3);
25234 tcg_gen_shri_tl(t3, t3, 8);
25235 tcg_gen_ext8s_tl(t2, t3);
25236 tcg_gen_shri_tl(t3, t3, 8);
25237 tcg_gen_ext8s_tl(t3, t3);
25238 } else {
25239 /* Q8MUL */
25240 tcg_gen_ext8u_tl(t0, t3);
25241 tcg_gen_shri_tl(t3, t3, 8);
25242 tcg_gen_ext8u_tl(t1, t3);
25243 tcg_gen_shri_tl(t3, t3, 8);
25244 tcg_gen_ext8u_tl(t2, t3);
25245 tcg_gen_shri_tl(t3, t3, 8);
25246 tcg_gen_ext8u_tl(t3, t3);
25249 tcg_gen_ext8u_tl(t4, t7);
25250 tcg_gen_shri_tl(t7, t7, 8);
25251 tcg_gen_ext8u_tl(t5, t7);
25252 tcg_gen_shri_tl(t7, t7, 8);
25253 tcg_gen_ext8u_tl(t6, t7);
25254 tcg_gen_shri_tl(t7, t7, 8);
25255 tcg_gen_ext8u_tl(t7, t7);
25257 tcg_gen_mul_tl(t0, t0, t4);
25258 tcg_gen_mul_tl(t1, t1, t5);
25259 tcg_gen_mul_tl(t2, t2, t6);
25260 tcg_gen_mul_tl(t3, t3, t7);
25262 tcg_gen_andi_tl(t0, t0, 0xFFFF);
25263 tcg_gen_andi_tl(t1, t1, 0xFFFF);
25264 tcg_gen_andi_tl(t2, t2, 0xFFFF);
25265 tcg_gen_andi_tl(t3, t3, 0xFFFF);
25267 tcg_gen_shli_tl(t1, t1, 16);
25268 tcg_gen_shli_tl(t3, t3, 16);
25270 tcg_gen_or_tl(t0, t0, t1);
25271 tcg_gen_or_tl(t1, t2, t3);
25273 gen_store_mxu_gpr(t0, XRd);
25274 gen_store_mxu_gpr(t1, XRa);
25276 tcg_temp_free(t0);
25277 tcg_temp_free(t1);
25278 tcg_temp_free(t2);
25279 tcg_temp_free(t3);
25280 tcg_temp_free(t4);
25281 tcg_temp_free(t5);
25282 tcg_temp_free(t6);
25283 tcg_temp_free(t7);
25287 * S32LDD XRa, Rb, S12 - Load a word from memory to XRF
25288 * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte seq.
25290 static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx)
25292 TCGv t0, t1;
25293 uint32_t XRa, Rb, s12, sel;
25295 t0 = tcg_temp_new();
25296 t1 = tcg_temp_new();
25298 XRa = extract32(ctx->opcode, 6, 4);
25299 s12 = extract32(ctx->opcode, 10, 10);
25300 sel = extract32(ctx->opcode, 20, 1);
25301 Rb = extract32(ctx->opcode, 21, 5);
25303 gen_load_gpr(t0, Rb);
25305 tcg_gen_movi_tl(t1, s12);
25306 tcg_gen_shli_tl(t1, t1, 2);
25307 if (s12 & 0x200) {
25308 tcg_gen_ori_tl(t1, t1, 0xFFFFF000);
25310 tcg_gen_add_tl(t1, t0, t1);
25311 tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL);
25313 if (sel == 1) {
25314 /* S32LDDR */
25315 tcg_gen_bswap32_tl(t1, t1);
25317 gen_store_mxu_gpr(t1, XRa);
25319 tcg_temp_free(t0);
25320 tcg_temp_free(t1);
25325 * MXU instruction category: logic
25326 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25328 * S32NOR S32AND S32OR S32XOR
25332 * S32NOR XRa, XRb, XRc
25333 * Update XRa with the result of logical bitwise 'nor' operation
25334 * applied to the content of XRb and XRc.
25336 * 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
25337 * +-----------+---------+-----+-------+-------+-------+-----------+
25338 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25339 * +-----------+---------+-----+-------+-------+-------+-----------+
25341 static void gen_mxu_S32NOR(DisasContext *ctx)
25343 uint32_t pad, XRc, XRb, XRa;
25345 pad = extract32(ctx->opcode, 21, 5);
25346 XRc = extract32(ctx->opcode, 14, 4);
25347 XRb = extract32(ctx->opcode, 10, 4);
25348 XRa = extract32(ctx->opcode, 6, 4);
25350 if (unlikely(pad != 0)) {
25351 /* opcode padding incorrect -> do nothing */
25352 } else if (unlikely(XRa == 0)) {
25353 /* destination is zero register -> do nothing */
25354 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25355 /* both operands zero registers -> just set destination to all 1s */
25356 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF);
25357 } else if (unlikely(XRb == 0)) {
25358 /* XRb zero register -> just set destination to the negation of XRc */
25359 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25360 } else if (unlikely(XRc == 0)) {
25361 /* XRa zero register -> just set destination to the negation of XRb */
25362 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25363 } else if (unlikely(XRb == XRc)) {
25364 /* both operands same -> just set destination to the negation of XRb */
25365 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25366 } else {
25367 /* the most general case */
25368 tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25373 * S32AND XRa, XRb, XRc
25374 * Update XRa with the result of logical bitwise 'and' operation
25375 * applied to the content of XRb and XRc.
25377 * 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
25378 * +-----------+---------+-----+-------+-------+-------+-----------+
25379 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25380 * +-----------+---------+-----+-------+-------+-------+-----------+
25382 static void gen_mxu_S32AND(DisasContext *ctx)
25384 uint32_t pad, XRc, XRb, XRa;
25386 pad = extract32(ctx->opcode, 21, 5);
25387 XRc = extract32(ctx->opcode, 14, 4);
25388 XRb = extract32(ctx->opcode, 10, 4);
25389 XRa = extract32(ctx->opcode, 6, 4);
25391 if (unlikely(pad != 0)) {
25392 /* opcode padding incorrect -> do nothing */
25393 } else if (unlikely(XRa == 0)) {
25394 /* destination is zero register -> do nothing */
25395 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25396 /* one of operands zero register -> just set destination to all 0s */
25397 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25398 } else if (unlikely(XRb == XRc)) {
25399 /* both operands same -> just set destination to one of them */
25400 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25401 } else {
25402 /* the most general case */
25403 tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25408 * S32OR XRa, XRb, XRc
25409 * Update XRa with the result of logical bitwise 'or' operation
25410 * applied to the content of XRb and XRc.
25412 * 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
25413 * +-----------+---------+-----+-------+-------+-------+-----------+
25414 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25415 * +-----------+---------+-----+-------+-------+-------+-----------+
25417 static void gen_mxu_S32OR(DisasContext *ctx)
25419 uint32_t pad, XRc, XRb, XRa;
25421 pad = extract32(ctx->opcode, 21, 5);
25422 XRc = extract32(ctx->opcode, 14, 4);
25423 XRb = extract32(ctx->opcode, 10, 4);
25424 XRa = extract32(ctx->opcode, 6, 4);
25426 if (unlikely(pad != 0)) {
25427 /* opcode padding incorrect -> do nothing */
25428 } else if (unlikely(XRa == 0)) {
25429 /* destination is zero register -> do nothing */
25430 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25431 /* both operands zero registers -> just set destination to all 0s */
25432 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25433 } else if (unlikely(XRb == 0)) {
25434 /* XRb zero register -> just set destination to the content of XRc */
25435 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25436 } else if (unlikely(XRc == 0)) {
25437 /* XRc zero register -> just set destination to the content of XRb */
25438 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25439 } else if (unlikely(XRb == XRc)) {
25440 /* both operands same -> just set destination to one of them */
25441 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25442 } else {
25443 /* the most general case */
25444 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25449 * S32XOR XRa, XRb, XRc
25450 * Update XRa with the result of logical bitwise 'xor' operation
25451 * applied to the content of XRb and XRc.
25453 * 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
25454 * +-----------+---------+-----+-------+-------+-------+-----------+
25455 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25456 * +-----------+---------+-----+-------+-------+-------+-----------+
25458 static void gen_mxu_S32XOR(DisasContext *ctx)
25460 uint32_t pad, XRc, XRb, XRa;
25462 pad = extract32(ctx->opcode, 21, 5);
25463 XRc = extract32(ctx->opcode, 14, 4);
25464 XRb = extract32(ctx->opcode, 10, 4);
25465 XRa = extract32(ctx->opcode, 6, 4);
25467 if (unlikely(pad != 0)) {
25468 /* opcode padding incorrect -> do nothing */
25469 } else if (unlikely(XRa == 0)) {
25470 /* destination is zero register -> do nothing */
25471 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25472 /* both operands zero registers -> just set destination to all 0s */
25473 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25474 } else if (unlikely(XRb == 0)) {
25475 /* XRb zero register -> just set destination to the content of XRc */
25476 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25477 } else if (unlikely(XRc == 0)) {
25478 /* XRc zero register -> just set destination to the content of XRb */
25479 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25480 } else if (unlikely(XRb == XRc)) {
25481 /* both operands same -> just set destination to all 0s */
25482 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25483 } else {
25484 /* the most general case */
25485 tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25491 * MXU instruction category max/min
25492 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25494 * S32MAX D16MAX Q8MAX
25495 * S32MIN D16MIN Q8MIN
25499 * S32MAX XRa, XRb, XRc
25500 * Update XRa with the maximum of signed 32-bit integers contained
25501 * in XRb and XRc.
25503 * S32MIN XRa, XRb, XRc
25504 * Update XRa with the minimum of signed 32-bit integers contained
25505 * in XRb and XRc.
25507 * 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
25508 * +-----------+---------+-----+-------+-------+-------+-----------+
25509 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25510 * +-----------+---------+-----+-------+-------+-------+-----------+
25512 static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx)
25514 uint32_t pad, opc, XRc, XRb, XRa;
25516 pad = extract32(ctx->opcode, 21, 5);
25517 opc = extract32(ctx->opcode, 18, 3);
25518 XRc = extract32(ctx->opcode, 14, 4);
25519 XRb = extract32(ctx->opcode, 10, 4);
25520 XRa = extract32(ctx->opcode, 6, 4);
25522 if (unlikely(pad != 0)) {
25523 /* opcode padding incorrect -> do nothing */
25524 } else if (unlikely(XRa == 0)) {
25525 /* destination is zero register -> do nothing */
25526 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25527 /* both operands zero registers -> just set destination to zero */
25528 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25529 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25530 /* exactly one operand is zero register - find which one is not...*/
25531 uint32_t XRx = XRb ? XRb : XRc;
25532 /* ...and do max/min operation with one operand 0 */
25533 if (opc == OPC_MXU_S32MAX) {
25534 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25535 } else {
25536 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25538 } else if (unlikely(XRb == XRc)) {
25539 /* both operands same -> just set destination to one of them */
25540 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25541 } else {
25542 /* the most general case */
25543 if (opc == OPC_MXU_S32MAX) {
25544 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25545 mxu_gpr[XRc - 1]);
25546 } else {
25547 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25548 mxu_gpr[XRc - 1]);
25554 * D16MAX
25555 * Update XRa with the 16-bit-wise maximums of signed integers
25556 * contained in XRb and XRc.
25558 * D16MIN
25559 * Update XRa with the 16-bit-wise minimums of signed integers
25560 * contained in XRb and XRc.
25562 * 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
25563 * +-----------+---------+-----+-------+-------+-------+-----------+
25564 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25565 * +-----------+---------+-----+-------+-------+-------+-----------+
25567 static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx)
25569 uint32_t pad, opc, XRc, XRb, XRa;
25571 pad = extract32(ctx->opcode, 21, 5);
25572 opc = extract32(ctx->opcode, 18, 3);
25573 XRc = extract32(ctx->opcode, 14, 4);
25574 XRb = extract32(ctx->opcode, 10, 4);
25575 XRa = extract32(ctx->opcode, 6, 4);
25577 if (unlikely(pad != 0)) {
25578 /* opcode padding incorrect -> do nothing */
25579 } else if (unlikely(XRc == 0)) {
25580 /* destination is zero register -> do nothing */
25581 } else if (unlikely((XRb == 0) && (XRa == 0))) {
25582 /* both operands zero registers -> just set destination to zero */
25583 tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0);
25584 } else if (unlikely((XRb == 0) || (XRa == 0))) {
25585 /* exactly one operand is zero register - find which one is not...*/
25586 uint32_t XRx = XRb ? XRb : XRc;
25587 /* ...and do half-word-wise max/min with one operand 0 */
25588 TCGv_i32 t0 = tcg_temp_new();
25589 TCGv_i32 t1 = tcg_const_i32(0);
25591 /* the left half-word first */
25592 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000);
25593 if (opc == OPC_MXU_D16MAX) {
25594 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25595 } else {
25596 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25599 /* the right half-word */
25600 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF);
25601 /* move half-words to the leftmost position */
25602 tcg_gen_shli_i32(t0, t0, 16);
25603 /* t0 will be max/min of t0 and t1 */
25604 if (opc == OPC_MXU_D16MAX) {
25605 tcg_gen_smax_i32(t0, t0, t1);
25606 } else {
25607 tcg_gen_smin_i32(t0, t0, t1);
25609 /* return resulting half-words to its original position */
25610 tcg_gen_shri_i32(t0, t0, 16);
25611 /* finally update the destination */
25612 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25614 tcg_temp_free(t1);
25615 tcg_temp_free(t0);
25616 } else if (unlikely(XRb == XRc)) {
25617 /* both operands same -> just set destination to one of them */
25618 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25619 } else {
25620 /* the most general case */
25621 TCGv_i32 t0 = tcg_temp_new();
25622 TCGv_i32 t1 = tcg_temp_new();
25624 /* the left half-word first */
25625 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000);
25626 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25627 if (opc == OPC_MXU_D16MAX) {
25628 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25629 } else {
25630 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25633 /* the right half-word */
25634 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25635 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF);
25636 /* move half-words to the leftmost position */
25637 tcg_gen_shli_i32(t0, t0, 16);
25638 tcg_gen_shli_i32(t1, t1, 16);
25639 /* t0 will be max/min of t0 and t1 */
25640 if (opc == OPC_MXU_D16MAX) {
25641 tcg_gen_smax_i32(t0, t0, t1);
25642 } else {
25643 tcg_gen_smin_i32(t0, t0, t1);
25645 /* return resulting half-words to its original position */
25646 tcg_gen_shri_i32(t0, t0, 16);
25647 /* finally update the destination */
25648 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25650 tcg_temp_free(t1);
25651 tcg_temp_free(t0);
25656 * Q8MAX
25657 * Update XRa with the 8-bit-wise maximums of signed integers
25658 * contained in XRb and XRc.
25660 * Q8MIN
25661 * Update XRa with the 8-bit-wise minimums of signed integers
25662 * contained in XRb and XRc.
25664 * 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
25665 * +-----------+---------+-----+-------+-------+-------+-----------+
25666 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25667 * +-----------+---------+-----+-------+-------+-------+-----------+
25669 static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx)
25671 uint32_t pad, opc, XRc, XRb, XRa;
25673 pad = extract32(ctx->opcode, 21, 5);
25674 opc = extract32(ctx->opcode, 18, 3);
25675 XRc = extract32(ctx->opcode, 14, 4);
25676 XRb = extract32(ctx->opcode, 10, 4);
25677 XRa = extract32(ctx->opcode, 6, 4);
25679 if (unlikely(pad != 0)) {
25680 /* opcode padding incorrect -> do nothing */
25681 } else if (unlikely(XRa == 0)) {
25682 /* destination is zero register -> do nothing */
25683 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25684 /* both operands zero registers -> just set destination to zero */
25685 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25686 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25687 /* exactly one operand is zero register - make it be the first...*/
25688 uint32_t XRx = XRb ? XRb : XRc;
25689 /* ...and do byte-wise max/min with one operand 0 */
25690 TCGv_i32 t0 = tcg_temp_new();
25691 TCGv_i32 t1 = tcg_const_i32(0);
25692 int32_t i;
25694 /* the leftmost byte (byte 3) first */
25695 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000);
25696 if (opc == OPC_MXU_Q8MAX) {
25697 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25698 } else {
25699 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25702 /* bytes 2, 1, 0 */
25703 for (i = 2; i >= 0; i--) {
25704 /* extract the byte */
25705 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i));
25706 /* move the byte to the leftmost position */
25707 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25708 /* t0 will be max/min of t0 and t1 */
25709 if (opc == OPC_MXU_Q8MAX) {
25710 tcg_gen_smax_i32(t0, t0, t1);
25711 } else {
25712 tcg_gen_smin_i32(t0, t0, t1);
25714 /* return resulting byte to its original position */
25715 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25716 /* finally update the destination */
25717 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25720 tcg_temp_free(t1);
25721 tcg_temp_free(t0);
25722 } else if (unlikely(XRb == XRc)) {
25723 /* both operands same -> just set destination to one of them */
25724 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25725 } else {
25726 /* the most general case */
25727 TCGv_i32 t0 = tcg_temp_new();
25728 TCGv_i32 t1 = tcg_temp_new();
25729 int32_t i;
25731 /* the leftmost bytes (bytes 3) first */
25732 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000);
25733 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25734 if (opc == OPC_MXU_Q8MAX) {
25735 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25736 } else {
25737 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25740 /* bytes 2, 1, 0 */
25741 for (i = 2; i >= 0; i--) {
25742 /* extract corresponding bytes */
25743 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i));
25744 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i));
25745 /* move the bytes to the leftmost position */
25746 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25747 tcg_gen_shli_i32(t1, t1, 8 * (3 - i));
25748 /* t0 will be max/min of t0 and t1 */
25749 if (opc == OPC_MXU_Q8MAX) {
25750 tcg_gen_smax_i32(t0, t0, t1);
25751 } else {
25752 tcg_gen_smin_i32(t0, t0, t1);
25754 /* return resulting byte to its original position */
25755 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25756 /* finally update the destination */
25757 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25760 tcg_temp_free(t1);
25761 tcg_temp_free(t0);
25767 * MXU instruction category: align
25768 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25770 * S32ALN S32ALNI
25774 * S32ALNI XRc, XRb, XRa, optn3
25775 * Arrange bytes from XRb and XRc according to one of five sets of
25776 * rules determined by optn3, and place the result in XRa.
25778 * 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
25779 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25780 * | SPECIAL2 |optn3|0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
25781 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25784 static void gen_mxu_S32ALNI(DisasContext *ctx)
25786 uint32_t optn3, pad, XRc, XRb, XRa;
25788 optn3 = extract32(ctx->opcode, 23, 3);
25789 pad = extract32(ctx->opcode, 21, 2);
25790 XRc = extract32(ctx->opcode, 14, 4);
25791 XRb = extract32(ctx->opcode, 10, 4);
25792 XRa = extract32(ctx->opcode, 6, 4);
25794 if (unlikely(pad != 0)) {
25795 /* opcode padding incorrect -> do nothing */
25796 } else if (unlikely(XRa == 0)) {
25797 /* destination is zero register -> do nothing */
25798 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25799 /* both operands zero registers -> just set destination to all 0s */
25800 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25801 } else if (unlikely(XRb == 0)) {
25802 /* XRb zero register -> just appropriatelly shift XRc into XRa */
25803 switch (optn3) {
25804 case MXU_OPTN3_PTN0:
25805 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25806 break;
25807 case MXU_OPTN3_PTN1:
25808 case MXU_OPTN3_PTN2:
25809 case MXU_OPTN3_PTN3:
25810 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1],
25811 8 * (4 - optn3));
25812 break;
25813 case MXU_OPTN3_PTN4:
25814 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25815 break;
25817 } else if (unlikely(XRc == 0)) {
25818 /* XRc zero register -> just appropriatelly shift XRb into XRa */
25819 switch (optn3) {
25820 case MXU_OPTN3_PTN0:
25821 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25822 break;
25823 case MXU_OPTN3_PTN1:
25824 case MXU_OPTN3_PTN2:
25825 case MXU_OPTN3_PTN3:
25826 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25827 break;
25828 case MXU_OPTN3_PTN4:
25829 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25830 break;
25832 } else if (unlikely(XRb == XRc)) {
25833 /* both operands same -> just rotation or moving from any of them */
25834 switch (optn3) {
25835 case MXU_OPTN3_PTN0:
25836 case MXU_OPTN3_PTN4:
25837 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25838 break;
25839 case MXU_OPTN3_PTN1:
25840 case MXU_OPTN3_PTN2:
25841 case MXU_OPTN3_PTN3:
25842 tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25843 break;
25845 } else {
25846 /* the most general case */
25847 switch (optn3) {
25848 case MXU_OPTN3_PTN0:
25850 /* */
25851 /* XRb XRc */
25852 /* +---------------+ */
25853 /* | A B C D | E F G H */
25854 /* +-------+-------+ */
25855 /* | */
25856 /* XRa */
25857 /* */
25859 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25861 break;
25862 case MXU_OPTN3_PTN1:
25864 /* */
25865 /* XRb XRc */
25866 /* +-------------------+ */
25867 /* A | B C D E | F G H */
25868 /* +---------+---------+ */
25869 /* | */
25870 /* XRa */
25871 /* */
25873 TCGv_i32 t0 = tcg_temp_new();
25874 TCGv_i32 t1 = tcg_temp_new();
25876 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF);
25877 tcg_gen_shli_i32(t0, t0, 8);
25879 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25880 tcg_gen_shri_i32(t1, t1, 24);
25882 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25884 tcg_temp_free(t1);
25885 tcg_temp_free(t0);
25887 break;
25888 case MXU_OPTN3_PTN2:
25890 /* */
25891 /* XRb XRc */
25892 /* +-------------------+ */
25893 /* A B | C D E F | G H */
25894 /* +---------+---------+ */
25895 /* | */
25896 /* XRa */
25897 /* */
25899 TCGv_i32 t0 = tcg_temp_new();
25900 TCGv_i32 t1 = tcg_temp_new();
25902 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25903 tcg_gen_shli_i32(t0, t0, 16);
25905 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25906 tcg_gen_shri_i32(t1, t1, 16);
25908 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25910 tcg_temp_free(t1);
25911 tcg_temp_free(t0);
25913 break;
25914 case MXU_OPTN3_PTN3:
25916 /* */
25917 /* XRb XRc */
25918 /* +-------------------+ */
25919 /* A B C | D E F G | H */
25920 /* +---------+---------+ */
25921 /* | */
25922 /* XRa */
25923 /* */
25925 TCGv_i32 t0 = tcg_temp_new();
25926 TCGv_i32 t1 = tcg_temp_new();
25928 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF);
25929 tcg_gen_shli_i32(t0, t0, 24);
25931 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00);
25932 tcg_gen_shri_i32(t1, t1, 8);
25934 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25936 tcg_temp_free(t1);
25937 tcg_temp_free(t0);
25939 break;
25940 case MXU_OPTN3_PTN4:
25942 /* */
25943 /* XRb XRc */
25944 /* +---------------+ */
25945 /* A B C D | E F G H | */
25946 /* +-------+-------+ */
25947 /* | */
25948 /* XRa */
25949 /* */
25951 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25953 break;
25960 * Decoding engine for MXU
25961 * =======================
25966 * Decode MXU pool00
25968 * 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
25969 * +-----------+---------+-----+-------+-------+-------+-----------+
25970 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL00|
25971 * +-----------+---------+-----+-------+-------+-------+-----------+
25974 static void decode_opc_mxu__pool00(CPUMIPSState *env, DisasContext *ctx)
25976 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25978 switch (opcode) {
25979 case OPC_MXU_S32MAX:
25980 case OPC_MXU_S32MIN:
25981 gen_mxu_S32MAX_S32MIN(ctx);
25982 break;
25983 case OPC_MXU_D16MAX:
25984 case OPC_MXU_D16MIN:
25985 gen_mxu_D16MAX_D16MIN(ctx);
25986 break;
25987 case OPC_MXU_Q8MAX:
25988 case OPC_MXU_Q8MIN:
25989 gen_mxu_Q8MAX_Q8MIN(ctx);
25990 break;
25991 case OPC_MXU_Q8SLT:
25992 /* TODO: Implement emulation of Q8SLT instruction. */
25993 MIPS_INVAL("OPC_MXU_Q8SLT");
25994 gen_reserved_instruction(ctx);
25995 break;
25996 case OPC_MXU_Q8SLTU:
25997 /* TODO: Implement emulation of Q8SLTU instruction. */
25998 MIPS_INVAL("OPC_MXU_Q8SLTU");
25999 gen_reserved_instruction(ctx);
26000 break;
26001 default:
26002 MIPS_INVAL("decode_opc_mxu");
26003 gen_reserved_instruction(ctx);
26004 break;
26010 * Decode MXU pool01
26012 * S32SLT, D16SLT, D16AVG, D16AVGR, Q8AVG, Q8AVGR:
26013 * 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
26014 * +-----------+---------+-----+-------+-------+-------+-----------+
26015 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
26016 * +-----------+---------+-----+-------+-------+-------+-----------+
26018 * Q8ADD:
26019 * 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
26020 * +-----------+---+-----+-----+-------+-------+-------+-----------+
26021 * | SPECIAL2 |en2|0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
26022 * +-----------+---+-----+-----+-------+-------+-------+-----------+
26025 static void decode_opc_mxu__pool01(CPUMIPSState *env, DisasContext *ctx)
26027 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26029 switch (opcode) {
26030 case OPC_MXU_S32SLT:
26031 /* TODO: Implement emulation of S32SLT instruction. */
26032 MIPS_INVAL("OPC_MXU_S32SLT");
26033 gen_reserved_instruction(ctx);
26034 break;
26035 case OPC_MXU_D16SLT:
26036 /* TODO: Implement emulation of D16SLT instruction. */
26037 MIPS_INVAL("OPC_MXU_D16SLT");
26038 gen_reserved_instruction(ctx);
26039 break;
26040 case OPC_MXU_D16AVG:
26041 /* TODO: Implement emulation of D16AVG instruction. */
26042 MIPS_INVAL("OPC_MXU_D16AVG");
26043 gen_reserved_instruction(ctx);
26044 break;
26045 case OPC_MXU_D16AVGR:
26046 /* TODO: Implement emulation of D16AVGR instruction. */
26047 MIPS_INVAL("OPC_MXU_D16AVGR");
26048 gen_reserved_instruction(ctx);
26049 break;
26050 case OPC_MXU_Q8AVG:
26051 /* TODO: Implement emulation of Q8AVG instruction. */
26052 MIPS_INVAL("OPC_MXU_Q8AVG");
26053 gen_reserved_instruction(ctx);
26054 break;
26055 case OPC_MXU_Q8AVGR:
26056 /* TODO: Implement emulation of Q8AVGR instruction. */
26057 MIPS_INVAL("OPC_MXU_Q8AVGR");
26058 gen_reserved_instruction(ctx);
26059 break;
26060 case OPC_MXU_Q8ADD:
26061 /* TODO: Implement emulation of Q8ADD instruction. */
26062 MIPS_INVAL("OPC_MXU_Q8ADD");
26063 gen_reserved_instruction(ctx);
26064 break;
26065 default:
26066 MIPS_INVAL("decode_opc_mxu");
26067 gen_reserved_instruction(ctx);
26068 break;
26074 * Decode MXU pool02
26076 * 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
26077 * +-----------+---------+-----+-------+-------+-------+-----------+
26078 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL02|
26079 * +-----------+---------+-----+-------+-------+-------+-----------+
26082 static void decode_opc_mxu__pool02(CPUMIPSState *env, DisasContext *ctx)
26084 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26086 switch (opcode) {
26087 case OPC_MXU_S32CPS:
26088 /* TODO: Implement emulation of S32CPS instruction. */
26089 MIPS_INVAL("OPC_MXU_S32CPS");
26090 gen_reserved_instruction(ctx);
26091 break;
26092 case OPC_MXU_D16CPS:
26093 /* TODO: Implement emulation of D16CPS instruction. */
26094 MIPS_INVAL("OPC_MXU_D16CPS");
26095 gen_reserved_instruction(ctx);
26096 break;
26097 case OPC_MXU_Q8ABD:
26098 /* TODO: Implement emulation of Q8ABD instruction. */
26099 MIPS_INVAL("OPC_MXU_Q8ABD");
26100 gen_reserved_instruction(ctx);
26101 break;
26102 case OPC_MXU_Q16SAT:
26103 /* TODO: Implement emulation of Q16SAT instruction. */
26104 MIPS_INVAL("OPC_MXU_Q16SAT");
26105 gen_reserved_instruction(ctx);
26106 break;
26107 default:
26108 MIPS_INVAL("decode_opc_mxu");
26109 gen_reserved_instruction(ctx);
26110 break;
26116 * Decode MXU pool03
26118 * D16MULF:
26119 * 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
26120 * +-----------+---+---+-------+-------+-------+-------+-----------+
26121 * | SPECIAL2 |x x|on2|0 0 0 0| XRc | XRb | XRa |MXU__POOL03|
26122 * +-----------+---+---+-------+-------+-------+-------+-----------+
26124 * D16MULE:
26125 * 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
26126 * +-----------+---+---+-------+-------+-------+-------+-----------+
26127 * | SPECIAL2 |x x|on2| Xd | XRc | XRb | XRa |MXU__POOL03|
26128 * +-----------+---+---+-------+-------+-------+-------+-----------+
26131 static void decode_opc_mxu__pool03(CPUMIPSState *env, DisasContext *ctx)
26133 uint32_t opcode = extract32(ctx->opcode, 24, 2);
26135 switch (opcode) {
26136 case OPC_MXU_D16MULF:
26137 /* TODO: Implement emulation of D16MULF instruction. */
26138 MIPS_INVAL("OPC_MXU_D16MULF");
26139 gen_reserved_instruction(ctx);
26140 break;
26141 case OPC_MXU_D16MULE:
26142 /* TODO: Implement emulation of D16MULE instruction. */
26143 MIPS_INVAL("OPC_MXU_D16MULE");
26144 gen_reserved_instruction(ctx);
26145 break;
26146 default:
26147 MIPS_INVAL("decode_opc_mxu");
26148 gen_reserved_instruction(ctx);
26149 break;
26155 * Decode MXU pool04
26157 * 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
26158 * +-----------+---------+-+-------------------+-------+-----------+
26159 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL04|
26160 * +-----------+---------+-+-------------------+-------+-----------+
26163 static void decode_opc_mxu__pool04(CPUMIPSState *env, DisasContext *ctx)
26165 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26167 switch (opcode) {
26168 case OPC_MXU_S32LDD:
26169 case OPC_MXU_S32LDDR:
26170 gen_mxu_s32ldd_s32lddr(ctx);
26171 break;
26172 default:
26173 MIPS_INVAL("decode_opc_mxu");
26174 gen_reserved_instruction(ctx);
26175 break;
26181 * Decode MXU pool05
26183 * 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
26184 * +-----------+---------+-+-------------------+-------+-----------+
26185 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL05|
26186 * +-----------+---------+-+-------------------+-------+-----------+
26189 static void decode_opc_mxu__pool05(CPUMIPSState *env, DisasContext *ctx)
26191 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26193 switch (opcode) {
26194 case OPC_MXU_S32STD:
26195 /* TODO: Implement emulation of S32STD instruction. */
26196 MIPS_INVAL("OPC_MXU_S32STD");
26197 gen_reserved_instruction(ctx);
26198 break;
26199 case OPC_MXU_S32STDR:
26200 /* TODO: Implement emulation of S32STDR instruction. */
26201 MIPS_INVAL("OPC_MXU_S32STDR");
26202 gen_reserved_instruction(ctx);
26203 break;
26204 default:
26205 MIPS_INVAL("decode_opc_mxu");
26206 gen_reserved_instruction(ctx);
26207 break;
26213 * Decode MXU pool06
26215 * 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
26216 * +-----------+---------+---------+---+-------+-------+-----------+
26217 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL06|
26218 * +-----------+---------+---------+---+-------+-------+-----------+
26221 static void decode_opc_mxu__pool06(CPUMIPSState *env, DisasContext *ctx)
26223 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26225 switch (opcode) {
26226 case OPC_MXU_S32LDDV:
26227 /* TODO: Implement emulation of S32LDDV instruction. */
26228 MIPS_INVAL("OPC_MXU_S32LDDV");
26229 gen_reserved_instruction(ctx);
26230 break;
26231 case OPC_MXU_S32LDDVR:
26232 /* TODO: Implement emulation of S32LDDVR instruction. */
26233 MIPS_INVAL("OPC_MXU_S32LDDVR");
26234 gen_reserved_instruction(ctx);
26235 break;
26236 default:
26237 MIPS_INVAL("decode_opc_mxu");
26238 gen_reserved_instruction(ctx);
26239 break;
26245 * Decode MXU pool07
26247 * 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
26248 * +-----------+---------+---------+---+-------+-------+-----------+
26249 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL07|
26250 * +-----------+---------+---------+---+-------+-------+-----------+
26253 static void decode_opc_mxu__pool07(CPUMIPSState *env, DisasContext *ctx)
26255 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26257 switch (opcode) {
26258 case OPC_MXU_S32STDV:
26259 /* TODO: Implement emulation of S32TDV instruction. */
26260 MIPS_INVAL("OPC_MXU_S32TDV");
26261 gen_reserved_instruction(ctx);
26262 break;
26263 case OPC_MXU_S32STDVR:
26264 /* TODO: Implement emulation of S32TDVR instruction. */
26265 MIPS_INVAL("OPC_MXU_S32TDVR");
26266 gen_reserved_instruction(ctx);
26267 break;
26268 default:
26269 MIPS_INVAL("decode_opc_mxu");
26270 gen_reserved_instruction(ctx);
26271 break;
26277 * Decode MXU pool08
26279 * 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
26280 * +-----------+---------+-+-------------------+-------+-----------+
26281 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL08|
26282 * +-----------+---------+-+-------------------+-------+-----------+
26285 static void decode_opc_mxu__pool08(CPUMIPSState *env, DisasContext *ctx)
26287 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26289 switch (opcode) {
26290 case OPC_MXU_S32LDI:
26291 /* TODO: Implement emulation of S32LDI instruction. */
26292 MIPS_INVAL("OPC_MXU_S32LDI");
26293 gen_reserved_instruction(ctx);
26294 break;
26295 case OPC_MXU_S32LDIR:
26296 /* TODO: Implement emulation of S32LDIR instruction. */
26297 MIPS_INVAL("OPC_MXU_S32LDIR");
26298 gen_reserved_instruction(ctx);
26299 break;
26300 default:
26301 MIPS_INVAL("decode_opc_mxu");
26302 gen_reserved_instruction(ctx);
26303 break;
26309 * Decode MXU pool09
26311 * 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
26312 * +-----------+---------+-+-------------------+-------+-----------+
26313 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL09|
26314 * +-----------+---------+-+-------------------+-------+-----------+
26317 static void decode_opc_mxu__pool09(CPUMIPSState *env, DisasContext *ctx)
26319 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26321 switch (opcode) {
26322 case OPC_MXU_S32SDI:
26323 /* TODO: Implement emulation of S32SDI instruction. */
26324 MIPS_INVAL("OPC_MXU_S32SDI");
26325 gen_reserved_instruction(ctx);
26326 break;
26327 case OPC_MXU_S32SDIR:
26328 /* TODO: Implement emulation of S32SDIR instruction. */
26329 MIPS_INVAL("OPC_MXU_S32SDIR");
26330 gen_reserved_instruction(ctx);
26331 break;
26332 default:
26333 MIPS_INVAL("decode_opc_mxu");
26334 gen_reserved_instruction(ctx);
26335 break;
26341 * Decode MXU pool10
26343 * 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
26344 * +-----------+---------+---------+---+-------+-------+-----------+
26345 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL10|
26346 * +-----------+---------+---------+---+-------+-------+-----------+
26349 static void decode_opc_mxu__pool10(CPUMIPSState *env, DisasContext *ctx)
26351 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26353 switch (opcode) {
26354 case OPC_MXU_S32LDIV:
26355 /* TODO: Implement emulation of S32LDIV instruction. */
26356 MIPS_INVAL("OPC_MXU_S32LDIV");
26357 gen_reserved_instruction(ctx);
26358 break;
26359 case OPC_MXU_S32LDIVR:
26360 /* TODO: Implement emulation of S32LDIVR instruction. */
26361 MIPS_INVAL("OPC_MXU_S32LDIVR");
26362 gen_reserved_instruction(ctx);
26363 break;
26364 default:
26365 MIPS_INVAL("decode_opc_mxu");
26366 gen_reserved_instruction(ctx);
26367 break;
26373 * Decode MXU pool11
26375 * 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
26376 * +-----------+---------+---------+---+-------+-------+-----------+
26377 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL11|
26378 * +-----------+---------+---------+---+-------+-------+-----------+
26381 static void decode_opc_mxu__pool11(CPUMIPSState *env, DisasContext *ctx)
26383 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26385 switch (opcode) {
26386 case OPC_MXU_S32SDIV:
26387 /* TODO: Implement emulation of S32SDIV instruction. */
26388 MIPS_INVAL("OPC_MXU_S32SDIV");
26389 gen_reserved_instruction(ctx);
26390 break;
26391 case OPC_MXU_S32SDIVR:
26392 /* TODO: Implement emulation of S32SDIVR instruction. */
26393 MIPS_INVAL("OPC_MXU_S32SDIVR");
26394 gen_reserved_instruction(ctx);
26395 break;
26396 default:
26397 MIPS_INVAL("decode_opc_mxu");
26398 gen_reserved_instruction(ctx);
26399 break;
26405 * Decode MXU pool12
26407 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26408 * +-----------+---+---+-------+-------+-------+-------+-----------+
26409 * | SPECIAL2 |an2|x x| Xd | XRc | XRb | XRa |MXU__POOL12|
26410 * +-----------+---+---+-------+-------+-------+-------+-----------+
26413 static void decode_opc_mxu__pool12(CPUMIPSState *env, DisasContext *ctx)
26415 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26417 switch (opcode) {
26418 case OPC_MXU_D32ACC:
26419 /* TODO: Implement emulation of D32ACC instruction. */
26420 MIPS_INVAL("OPC_MXU_D32ACC");
26421 gen_reserved_instruction(ctx);
26422 break;
26423 case OPC_MXU_D32ACCM:
26424 /* TODO: Implement emulation of D32ACCM instruction. */
26425 MIPS_INVAL("OPC_MXU_D32ACCM");
26426 gen_reserved_instruction(ctx);
26427 break;
26428 case OPC_MXU_D32ASUM:
26429 /* TODO: Implement emulation of D32ASUM instruction. */
26430 MIPS_INVAL("OPC_MXU_D32ASUM");
26431 gen_reserved_instruction(ctx);
26432 break;
26433 default:
26434 MIPS_INVAL("decode_opc_mxu");
26435 gen_reserved_instruction(ctx);
26436 break;
26442 * Decode MXU pool13
26444 * 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
26445 * +-----------+---+---+-------+-------+-------+-------+-----------+
26446 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL13|
26447 * +-----------+---+---+-------+-------+-------+-------+-----------+
26450 static void decode_opc_mxu__pool13(CPUMIPSState *env, DisasContext *ctx)
26452 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26454 switch (opcode) {
26455 case OPC_MXU_Q16ACC:
26456 /* TODO: Implement emulation of Q16ACC instruction. */
26457 MIPS_INVAL("OPC_MXU_Q16ACC");
26458 gen_reserved_instruction(ctx);
26459 break;
26460 case OPC_MXU_Q16ACCM:
26461 /* TODO: Implement emulation of Q16ACCM instruction. */
26462 MIPS_INVAL("OPC_MXU_Q16ACCM");
26463 gen_reserved_instruction(ctx);
26464 break;
26465 case OPC_MXU_Q16ASUM:
26466 /* TODO: Implement emulation of Q16ASUM instruction. */
26467 MIPS_INVAL("OPC_MXU_Q16ASUM");
26468 gen_reserved_instruction(ctx);
26469 break;
26470 default:
26471 MIPS_INVAL("decode_opc_mxu");
26472 gen_reserved_instruction(ctx);
26473 break;
26479 * Decode MXU pool14
26481 * Q8ADDE, Q8ACCE:
26482 * 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
26483 * +-----------+---+---+-------+-------+-------+-------+-----------+
26484 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL14|
26485 * +-----------+---+---+-------+-------+-------+-------+-----------+
26487 * D8SUM, D8SUMC:
26488 * 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
26489 * +-----------+---+---+-------+-------+-------+-------+-----------+
26490 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL14|
26491 * +-----------+---+---+-------+-------+-------+-------+-----------+
26494 static void decode_opc_mxu__pool14(CPUMIPSState *env, DisasContext *ctx)
26496 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26498 switch (opcode) {
26499 case OPC_MXU_Q8ADDE:
26500 /* TODO: Implement emulation of Q8ADDE instruction. */
26501 MIPS_INVAL("OPC_MXU_Q8ADDE");
26502 gen_reserved_instruction(ctx);
26503 break;
26504 case OPC_MXU_D8SUM:
26505 /* TODO: Implement emulation of D8SUM instruction. */
26506 MIPS_INVAL("OPC_MXU_D8SUM");
26507 gen_reserved_instruction(ctx);
26508 break;
26509 case OPC_MXU_D8SUMC:
26510 /* TODO: Implement emulation of D8SUMC instruction. */
26511 MIPS_INVAL("OPC_MXU_D8SUMC");
26512 gen_reserved_instruction(ctx);
26513 break;
26514 default:
26515 MIPS_INVAL("decode_opc_mxu");
26516 gen_reserved_instruction(ctx);
26517 break;
26523 * Decode MXU pool15
26525 * S32MUL, S32MULU, S32EXTRV:
26526 * 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
26527 * +-----------+---------+---------+---+-------+-------+-----------+
26528 * | SPECIAL2 | rs | rt |x x| XRd | XRa |MXU__POOL15|
26529 * +-----------+---------+---------+---+-------+-------+-----------+
26531 * S32EXTR:
26532 * 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
26533 * +-----------+---------+---------+---+-------+-------+-----------+
26534 * | SPECIAL2 | rb | sft5 |x x| XRd | XRa |MXU__POOL15|
26535 * +-----------+---------+---------+---+-------+-------+-----------+
26538 static void decode_opc_mxu__pool15(CPUMIPSState *env, DisasContext *ctx)
26540 uint32_t opcode = extract32(ctx->opcode, 14, 2);
26542 switch (opcode) {
26543 case OPC_MXU_S32MUL:
26544 /* TODO: Implement emulation of S32MUL instruction. */
26545 MIPS_INVAL("OPC_MXU_S32MUL");
26546 gen_reserved_instruction(ctx);
26547 break;
26548 case OPC_MXU_S32MULU:
26549 /* TODO: Implement emulation of S32MULU instruction. */
26550 MIPS_INVAL("OPC_MXU_S32MULU");
26551 gen_reserved_instruction(ctx);
26552 break;
26553 case OPC_MXU_S32EXTR:
26554 /* TODO: Implement emulation of S32EXTR instruction. */
26555 MIPS_INVAL("OPC_MXU_S32EXTR");
26556 gen_reserved_instruction(ctx);
26557 break;
26558 case OPC_MXU_S32EXTRV:
26559 /* TODO: Implement emulation of S32EXTRV instruction. */
26560 MIPS_INVAL("OPC_MXU_S32EXTRV");
26561 gen_reserved_instruction(ctx);
26562 break;
26563 default:
26564 MIPS_INVAL("decode_opc_mxu");
26565 gen_reserved_instruction(ctx);
26566 break;
26572 * Decode MXU pool16
26574 * D32SARW:
26575 * 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
26576 * +-----------+---------+-----+-------+-------+-------+-----------+
26577 * | SPECIAL2 | rb |x x x| XRc | XRb | XRa |MXU__POOL16|
26578 * +-----------+---------+-----+-------+-------+-------+-----------+
26580 * S32ALN:
26581 * 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
26582 * +-----------+---------+-----+-------+-------+-------+-----------+
26583 * | SPECIAL2 | rs |x x x| XRc | XRb | XRa |MXU__POOL16|
26584 * +-----------+---------+-----+-------+-------+-------+-----------+
26586 * S32ALNI:
26587 * 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
26588 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26589 * | SPECIAL2 | s3 |0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26590 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26592 * S32LUI:
26593 * 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
26594 * +-----------+-----+---+-----+-------+---------------+-----------+
26595 * | SPECIAL2 |optn3|0 0|x x x| XRc | s8 |MXU__POOL16|
26596 * +-----------+-----+---+-----+-------+---------------+-----------+
26598 * S32NOR, S32AND, S32OR, S32XOR:
26599 * 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
26600 * +-----------+---------+-----+-------+-------+-------+-----------+
26601 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26602 * +-----------+---------+-----+-------+-------+-------+-----------+
26605 static void decode_opc_mxu__pool16(CPUMIPSState *env, DisasContext *ctx)
26607 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26609 switch (opcode) {
26610 case OPC_MXU_D32SARW:
26611 /* TODO: Implement emulation of D32SARW instruction. */
26612 MIPS_INVAL("OPC_MXU_D32SARW");
26613 gen_reserved_instruction(ctx);
26614 break;
26615 case OPC_MXU_S32ALN:
26616 /* TODO: Implement emulation of S32ALN instruction. */
26617 MIPS_INVAL("OPC_MXU_S32ALN");
26618 gen_reserved_instruction(ctx);
26619 break;
26620 case OPC_MXU_S32ALNI:
26621 gen_mxu_S32ALNI(ctx);
26622 break;
26623 case OPC_MXU_S32LUI:
26624 /* TODO: Implement emulation of S32LUI instruction. */
26625 MIPS_INVAL("OPC_MXU_S32LUI");
26626 gen_reserved_instruction(ctx);
26627 break;
26628 case OPC_MXU_S32NOR:
26629 gen_mxu_S32NOR(ctx);
26630 break;
26631 case OPC_MXU_S32AND:
26632 gen_mxu_S32AND(ctx);
26633 break;
26634 case OPC_MXU_S32OR:
26635 gen_mxu_S32OR(ctx);
26636 break;
26637 case OPC_MXU_S32XOR:
26638 gen_mxu_S32XOR(ctx);
26639 break;
26640 default:
26641 MIPS_INVAL("decode_opc_mxu");
26642 gen_reserved_instruction(ctx);
26643 break;
26649 * Decode MXU pool17
26651 * 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
26652 * +-----------+---------+---------+---+---------+-----+-----------+
26653 * | SPECIAL2 | rs | rt |0 0| rd |x x x|MXU__POOL15|
26654 * +-----------+---------+---------+---+---------+-----+-----------+
26657 static void decode_opc_mxu__pool17(CPUMIPSState *env, DisasContext *ctx)
26659 uint32_t opcode = extract32(ctx->opcode, 6, 2);
26661 switch (opcode) {
26662 case OPC_MXU_LXW:
26663 /* TODO: Implement emulation of LXW instruction. */
26664 MIPS_INVAL("OPC_MXU_LXW");
26665 gen_reserved_instruction(ctx);
26666 break;
26667 case OPC_MXU_LXH:
26668 /* TODO: Implement emulation of LXH instruction. */
26669 MIPS_INVAL("OPC_MXU_LXH");
26670 gen_reserved_instruction(ctx);
26671 break;
26672 case OPC_MXU_LXHU:
26673 /* TODO: Implement emulation of LXHU instruction. */
26674 MIPS_INVAL("OPC_MXU_LXHU");
26675 gen_reserved_instruction(ctx);
26676 break;
26677 case OPC_MXU_LXB:
26678 /* TODO: Implement emulation of LXB instruction. */
26679 MIPS_INVAL("OPC_MXU_LXB");
26680 gen_reserved_instruction(ctx);
26681 break;
26682 case OPC_MXU_LXBU:
26683 /* TODO: Implement emulation of LXBU instruction. */
26684 MIPS_INVAL("OPC_MXU_LXBU");
26685 gen_reserved_instruction(ctx);
26686 break;
26687 default:
26688 MIPS_INVAL("decode_opc_mxu");
26689 gen_reserved_instruction(ctx);
26690 break;
26695 * Decode MXU pool18
26697 * 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
26698 * +-----------+---------+-----+-------+-------+-------+-----------+
26699 * | SPECIAL2 | rb |x x x| XRd | XRa |0 0 0 0|MXU__POOL18|
26700 * +-----------+---------+-----+-------+-------+-------+-----------+
26703 static void decode_opc_mxu__pool18(CPUMIPSState *env, DisasContext *ctx)
26705 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26707 switch (opcode) {
26708 case OPC_MXU_D32SLLV:
26709 /* TODO: Implement emulation of D32SLLV instruction. */
26710 MIPS_INVAL("OPC_MXU_D32SLLV");
26711 gen_reserved_instruction(ctx);
26712 break;
26713 case OPC_MXU_D32SLRV:
26714 /* TODO: Implement emulation of D32SLRV instruction. */
26715 MIPS_INVAL("OPC_MXU_D32SLRV");
26716 gen_reserved_instruction(ctx);
26717 break;
26718 case OPC_MXU_D32SARV:
26719 /* TODO: Implement emulation of D32SARV instruction. */
26720 MIPS_INVAL("OPC_MXU_D32SARV");
26721 gen_reserved_instruction(ctx);
26722 break;
26723 case OPC_MXU_Q16SLLV:
26724 /* TODO: Implement emulation of Q16SLLV instruction. */
26725 MIPS_INVAL("OPC_MXU_Q16SLLV");
26726 gen_reserved_instruction(ctx);
26727 break;
26728 case OPC_MXU_Q16SLRV:
26729 /* TODO: Implement emulation of Q16SLRV instruction. */
26730 MIPS_INVAL("OPC_MXU_Q16SLRV");
26731 gen_reserved_instruction(ctx);
26732 break;
26733 case OPC_MXU_Q16SARV:
26734 /* TODO: Implement emulation of Q16SARV instruction. */
26735 MIPS_INVAL("OPC_MXU_Q16SARV");
26736 gen_reserved_instruction(ctx);
26737 break;
26738 default:
26739 MIPS_INVAL("decode_opc_mxu");
26740 gen_reserved_instruction(ctx);
26741 break;
26747 * Decode MXU pool19
26749 * 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
26750 * +-----------+---+---+-------+-------+-------+-------+-----------+
26751 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL19|
26752 * +-----------+---+---+-------+-------+-------+-------+-----------+
26755 static void decode_opc_mxu__pool19(CPUMIPSState *env, DisasContext *ctx)
26757 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26759 switch (opcode) {
26760 case OPC_MXU_Q8MUL:
26761 case OPC_MXU_Q8MULSU:
26762 gen_mxu_q8mul_q8mulsu(ctx);
26763 break;
26764 default:
26765 MIPS_INVAL("decode_opc_mxu");
26766 gen_reserved_instruction(ctx);
26767 break;
26773 * Decode MXU pool20
26775 * 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
26776 * +-----------+---------+-----+-------+-------+-------+-----------+
26777 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL20|
26778 * +-----------+---------+-----+-------+-------+-------+-----------+
26781 static void decode_opc_mxu__pool20(CPUMIPSState *env, DisasContext *ctx)
26783 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26785 switch (opcode) {
26786 case OPC_MXU_Q8MOVZ:
26787 /* TODO: Implement emulation of Q8MOVZ instruction. */
26788 MIPS_INVAL("OPC_MXU_Q8MOVZ");
26789 gen_reserved_instruction(ctx);
26790 break;
26791 case OPC_MXU_Q8MOVN:
26792 /* TODO: Implement emulation of Q8MOVN instruction. */
26793 MIPS_INVAL("OPC_MXU_Q8MOVN");
26794 gen_reserved_instruction(ctx);
26795 break;
26796 case OPC_MXU_D16MOVZ:
26797 /* TODO: Implement emulation of D16MOVZ instruction. */
26798 MIPS_INVAL("OPC_MXU_D16MOVZ");
26799 gen_reserved_instruction(ctx);
26800 break;
26801 case OPC_MXU_D16MOVN:
26802 /* TODO: Implement emulation of D16MOVN instruction. */
26803 MIPS_INVAL("OPC_MXU_D16MOVN");
26804 gen_reserved_instruction(ctx);
26805 break;
26806 case OPC_MXU_S32MOVZ:
26807 /* TODO: Implement emulation of S32MOVZ instruction. */
26808 MIPS_INVAL("OPC_MXU_S32MOVZ");
26809 gen_reserved_instruction(ctx);
26810 break;
26811 case OPC_MXU_S32MOVN:
26812 /* TODO: Implement emulation of S32MOVN instruction. */
26813 MIPS_INVAL("OPC_MXU_S32MOVN");
26814 gen_reserved_instruction(ctx);
26815 break;
26816 default:
26817 MIPS_INVAL("decode_opc_mxu");
26818 gen_reserved_instruction(ctx);
26819 break;
26825 * Decode MXU pool21
26827 * 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
26828 * +-----------+---+---+-------+-------+-------+-------+-----------+
26829 * | SPECIAL2 |an2|x x| XRd | XRc | XRb | XRa |MXU__POOL21|
26830 * +-----------+---+---+-------+-------+-------+-------+-----------+
26833 static void decode_opc_mxu__pool21(CPUMIPSState *env, DisasContext *ctx)
26835 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26837 switch (opcode) {
26838 case OPC_MXU_Q8MAC:
26839 /* TODO: Implement emulation of Q8MAC instruction. */
26840 MIPS_INVAL("OPC_MXU_Q8MAC");
26841 gen_reserved_instruction(ctx);
26842 break;
26843 case OPC_MXU_Q8MACSU:
26844 /* TODO: Implement emulation of Q8MACSU instruction. */
26845 MIPS_INVAL("OPC_MXU_Q8MACSU");
26846 gen_reserved_instruction(ctx);
26847 break;
26848 default:
26849 MIPS_INVAL("decode_opc_mxu");
26850 gen_reserved_instruction(ctx);
26851 break;
26857 * Main MXU decoding function
26859 * 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
26860 * +-----------+---------------------------------------+-----------+
26861 * | SPECIAL2 | |x x x x x x|
26862 * +-----------+---------------------------------------+-----------+
26865 static void decode_opc_mxu(CPUMIPSState *env, DisasContext *ctx)
26868 * TODO: Investigate necessity of including handling of
26869 * CLZ, CLO, SDBB in this function, as they belong to
26870 * SPECIAL2 opcode space for regular pre-R6 MIPS ISAs.
26872 uint32_t opcode = extract32(ctx->opcode, 0, 6);
26874 if (opcode == OPC__MXU_MUL) {
26875 uint32_t rs, rt, rd, op1;
26877 rs = extract32(ctx->opcode, 21, 5);
26878 rt = extract32(ctx->opcode, 16, 5);
26879 rd = extract32(ctx->opcode, 11, 5);
26880 op1 = MASK_SPECIAL2(ctx->opcode);
26882 gen_arith(ctx, op1, rd, rs, rt);
26884 return;
26887 if (opcode == OPC_MXU_S32M2I) {
26888 gen_mxu_s32m2i(ctx);
26889 return;
26892 if (opcode == OPC_MXU_S32I2M) {
26893 gen_mxu_s32i2m(ctx);
26894 return;
26898 TCGv t_mxu_cr = tcg_temp_new();
26899 TCGLabel *l_exit = gen_new_label();
26901 gen_load_mxu_cr(t_mxu_cr);
26902 tcg_gen_andi_tl(t_mxu_cr, t_mxu_cr, MXU_CR_MXU_EN);
26903 tcg_gen_brcondi_tl(TCG_COND_NE, t_mxu_cr, MXU_CR_MXU_EN, l_exit);
26905 switch (opcode) {
26906 case OPC_MXU_S32MADD:
26907 /* TODO: Implement emulation of S32MADD instruction. */
26908 MIPS_INVAL("OPC_MXU_S32MADD");
26909 gen_reserved_instruction(ctx);
26910 break;
26911 case OPC_MXU_S32MADDU:
26912 /* TODO: Implement emulation of S32MADDU instruction. */
26913 MIPS_INVAL("OPC_MXU_S32MADDU");
26914 gen_reserved_instruction(ctx);
26915 break;
26916 case OPC_MXU__POOL00:
26917 decode_opc_mxu__pool00(env, ctx);
26918 break;
26919 case OPC_MXU_S32MSUB:
26920 /* TODO: Implement emulation of S32MSUB instruction. */
26921 MIPS_INVAL("OPC_MXU_S32MSUB");
26922 gen_reserved_instruction(ctx);
26923 break;
26924 case OPC_MXU_S32MSUBU:
26925 /* TODO: Implement emulation of S32MSUBU instruction. */
26926 MIPS_INVAL("OPC_MXU_S32MSUBU");
26927 gen_reserved_instruction(ctx);
26928 break;
26929 case OPC_MXU__POOL01:
26930 decode_opc_mxu__pool01(env, ctx);
26931 break;
26932 case OPC_MXU__POOL02:
26933 decode_opc_mxu__pool02(env, ctx);
26934 break;
26935 case OPC_MXU_D16MUL:
26936 gen_mxu_d16mul(ctx);
26937 break;
26938 case OPC_MXU__POOL03:
26939 decode_opc_mxu__pool03(env, ctx);
26940 break;
26941 case OPC_MXU_D16MAC:
26942 gen_mxu_d16mac(ctx);
26943 break;
26944 case OPC_MXU_D16MACF:
26945 /* TODO: Implement emulation of D16MACF instruction. */
26946 MIPS_INVAL("OPC_MXU_D16MACF");
26947 gen_reserved_instruction(ctx);
26948 break;
26949 case OPC_MXU_D16MADL:
26950 /* TODO: Implement emulation of D16MADL instruction. */
26951 MIPS_INVAL("OPC_MXU_D16MADL");
26952 gen_reserved_instruction(ctx);
26953 break;
26954 case OPC_MXU_S16MAD:
26955 /* TODO: Implement emulation of S16MAD instruction. */
26956 MIPS_INVAL("OPC_MXU_S16MAD");
26957 gen_reserved_instruction(ctx);
26958 break;
26959 case OPC_MXU_Q16ADD:
26960 /* TODO: Implement emulation of Q16ADD instruction. */
26961 MIPS_INVAL("OPC_MXU_Q16ADD");
26962 gen_reserved_instruction(ctx);
26963 break;
26964 case OPC_MXU_D16MACE:
26965 /* TODO: Implement emulation of D16MACE instruction. */
26966 MIPS_INVAL("OPC_MXU_D16MACE");
26967 gen_reserved_instruction(ctx);
26968 break;
26969 case OPC_MXU__POOL04:
26970 decode_opc_mxu__pool04(env, ctx);
26971 break;
26972 case OPC_MXU__POOL05:
26973 decode_opc_mxu__pool05(env, ctx);
26974 break;
26975 case OPC_MXU__POOL06:
26976 decode_opc_mxu__pool06(env, ctx);
26977 break;
26978 case OPC_MXU__POOL07:
26979 decode_opc_mxu__pool07(env, ctx);
26980 break;
26981 case OPC_MXU__POOL08:
26982 decode_opc_mxu__pool08(env, ctx);
26983 break;
26984 case OPC_MXU__POOL09:
26985 decode_opc_mxu__pool09(env, ctx);
26986 break;
26987 case OPC_MXU__POOL10:
26988 decode_opc_mxu__pool10(env, ctx);
26989 break;
26990 case OPC_MXU__POOL11:
26991 decode_opc_mxu__pool11(env, ctx);
26992 break;
26993 case OPC_MXU_D32ADD:
26994 /* TODO: Implement emulation of D32ADD instruction. */
26995 MIPS_INVAL("OPC_MXU_D32ADD");
26996 gen_reserved_instruction(ctx);
26997 break;
26998 case OPC_MXU__POOL12:
26999 decode_opc_mxu__pool12(env, ctx);
27000 break;
27001 case OPC_MXU__POOL13:
27002 decode_opc_mxu__pool13(env, ctx);
27003 break;
27004 case OPC_MXU__POOL14:
27005 decode_opc_mxu__pool14(env, ctx);
27006 break;
27007 case OPC_MXU_Q8ACCE:
27008 /* TODO: Implement emulation of Q8ACCE instruction. */
27009 MIPS_INVAL("OPC_MXU_Q8ACCE");
27010 gen_reserved_instruction(ctx);
27011 break;
27012 case OPC_MXU_S8LDD:
27013 gen_mxu_s8ldd(ctx);
27014 break;
27015 case OPC_MXU_S8STD:
27016 /* TODO: Implement emulation of S8STD instruction. */
27017 MIPS_INVAL("OPC_MXU_S8STD");
27018 gen_reserved_instruction(ctx);
27019 break;
27020 case OPC_MXU_S8LDI:
27021 /* TODO: Implement emulation of S8LDI instruction. */
27022 MIPS_INVAL("OPC_MXU_S8LDI");
27023 gen_reserved_instruction(ctx);
27024 break;
27025 case OPC_MXU_S8SDI:
27026 /* TODO: Implement emulation of S8SDI instruction. */
27027 MIPS_INVAL("OPC_MXU_S8SDI");
27028 gen_reserved_instruction(ctx);
27029 break;
27030 case OPC_MXU__POOL15:
27031 decode_opc_mxu__pool15(env, ctx);
27032 break;
27033 case OPC_MXU__POOL16:
27034 decode_opc_mxu__pool16(env, ctx);
27035 break;
27036 case OPC_MXU__POOL17:
27037 decode_opc_mxu__pool17(env, ctx);
27038 break;
27039 case OPC_MXU_S16LDD:
27040 /* TODO: Implement emulation of S16LDD instruction. */
27041 MIPS_INVAL("OPC_MXU_S16LDD");
27042 gen_reserved_instruction(ctx);
27043 break;
27044 case OPC_MXU_S16STD:
27045 /* TODO: Implement emulation of S16STD instruction. */
27046 MIPS_INVAL("OPC_MXU_S16STD");
27047 gen_reserved_instruction(ctx);
27048 break;
27049 case OPC_MXU_S16LDI:
27050 /* TODO: Implement emulation of S16LDI instruction. */
27051 MIPS_INVAL("OPC_MXU_S16LDI");
27052 gen_reserved_instruction(ctx);
27053 break;
27054 case OPC_MXU_S16SDI:
27055 /* TODO: Implement emulation of S16SDI instruction. */
27056 MIPS_INVAL("OPC_MXU_S16SDI");
27057 gen_reserved_instruction(ctx);
27058 break;
27059 case OPC_MXU_D32SLL:
27060 /* TODO: Implement emulation of D32SLL instruction. */
27061 MIPS_INVAL("OPC_MXU_D32SLL");
27062 gen_reserved_instruction(ctx);
27063 break;
27064 case OPC_MXU_D32SLR:
27065 /* TODO: Implement emulation of D32SLR instruction. */
27066 MIPS_INVAL("OPC_MXU_D32SLR");
27067 gen_reserved_instruction(ctx);
27068 break;
27069 case OPC_MXU_D32SARL:
27070 /* TODO: Implement emulation of D32SARL instruction. */
27071 MIPS_INVAL("OPC_MXU_D32SARL");
27072 gen_reserved_instruction(ctx);
27073 break;
27074 case OPC_MXU_D32SAR:
27075 /* TODO: Implement emulation of D32SAR instruction. */
27076 MIPS_INVAL("OPC_MXU_D32SAR");
27077 gen_reserved_instruction(ctx);
27078 break;
27079 case OPC_MXU_Q16SLL:
27080 /* TODO: Implement emulation of Q16SLL instruction. */
27081 MIPS_INVAL("OPC_MXU_Q16SLL");
27082 gen_reserved_instruction(ctx);
27083 break;
27084 case OPC_MXU_Q16SLR:
27085 /* TODO: Implement emulation of Q16SLR instruction. */
27086 MIPS_INVAL("OPC_MXU_Q16SLR");
27087 gen_reserved_instruction(ctx);
27088 break;
27089 case OPC_MXU__POOL18:
27090 decode_opc_mxu__pool18(env, ctx);
27091 break;
27092 case OPC_MXU_Q16SAR:
27093 /* TODO: Implement emulation of Q16SAR instruction. */
27094 MIPS_INVAL("OPC_MXU_Q16SAR");
27095 gen_reserved_instruction(ctx);
27096 break;
27097 case OPC_MXU__POOL19:
27098 decode_opc_mxu__pool19(env, ctx);
27099 break;
27100 case OPC_MXU__POOL20:
27101 decode_opc_mxu__pool20(env, ctx);
27102 break;
27103 case OPC_MXU__POOL21:
27104 decode_opc_mxu__pool21(env, ctx);
27105 break;
27106 case OPC_MXU_Q16SCOP:
27107 /* TODO: Implement emulation of Q16SCOP instruction. */
27108 MIPS_INVAL("OPC_MXU_Q16SCOP");
27109 gen_reserved_instruction(ctx);
27110 break;
27111 case OPC_MXU_Q8MADL:
27112 /* TODO: Implement emulation of Q8MADL instruction. */
27113 MIPS_INVAL("OPC_MXU_Q8MADL");
27114 gen_reserved_instruction(ctx);
27115 break;
27116 case OPC_MXU_S32SFL:
27117 /* TODO: Implement emulation of S32SFL instruction. */
27118 MIPS_INVAL("OPC_MXU_S32SFL");
27119 gen_reserved_instruction(ctx);
27120 break;
27121 case OPC_MXU_Q8SAD:
27122 /* TODO: Implement emulation of Q8SAD instruction. */
27123 MIPS_INVAL("OPC_MXU_Q8SAD");
27124 gen_reserved_instruction(ctx);
27125 break;
27126 default:
27127 MIPS_INVAL("decode_opc_mxu");
27128 gen_reserved_instruction(ctx);
27131 gen_set_label(l_exit);
27132 tcg_temp_free(t_mxu_cr);
27136 #endif /* !defined(TARGET_MIPS64) */
27139 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
27141 int rs, rt, rd;
27142 uint32_t op1;
27144 rs = (ctx->opcode >> 21) & 0x1f;
27145 rt = (ctx->opcode >> 16) & 0x1f;
27146 rd = (ctx->opcode >> 11) & 0x1f;
27148 op1 = MASK_SPECIAL2(ctx->opcode);
27149 switch (op1) {
27150 case OPC_MADD: /* Multiply and add/sub */
27151 case OPC_MADDU:
27152 case OPC_MSUB:
27153 case OPC_MSUBU:
27154 check_insn(ctx, ISA_MIPS_R1);
27155 gen_muldiv(ctx, op1, rd & 3, rs, rt);
27156 break;
27157 case OPC_MUL:
27158 gen_arith(ctx, op1, rd, rs, rt);
27159 break;
27160 case OPC_DIV_G_2F:
27161 case OPC_DIVU_G_2F:
27162 case OPC_MULT_G_2F:
27163 case OPC_MULTU_G_2F:
27164 case OPC_MOD_G_2F:
27165 case OPC_MODU_G_2F:
27166 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
27167 gen_loongson_integer(ctx, op1, rd, rs, rt);
27168 break;
27169 case OPC_CLO:
27170 case OPC_CLZ:
27171 check_insn(ctx, ISA_MIPS_R1);
27172 gen_cl(ctx, op1, rd, rs);
27173 break;
27174 case OPC_SDBBP:
27175 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
27176 gen_helper_do_semihosting(cpu_env);
27177 } else {
27179 * XXX: not clear which exception should be raised
27180 * when in debug mode...
27182 check_insn(ctx, ISA_MIPS_R1);
27183 generate_exception_end(ctx, EXCP_DBp);
27185 break;
27186 #if defined(TARGET_MIPS64)
27187 case OPC_DCLO:
27188 case OPC_DCLZ:
27189 check_insn(ctx, ISA_MIPS_R1);
27190 check_mips_64(ctx);
27191 gen_cl(ctx, op1, rd, rs);
27192 break;
27193 case OPC_DMULT_G_2F:
27194 case OPC_DMULTU_G_2F:
27195 case OPC_DDIV_G_2F:
27196 case OPC_DDIVU_G_2F:
27197 case OPC_DMOD_G_2F:
27198 case OPC_DMODU_G_2F:
27199 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
27200 gen_loongson_integer(ctx, op1, rd, rs, rt);
27201 break;
27202 #endif
27203 default: /* Invalid */
27204 MIPS_INVAL("special2_legacy");
27205 gen_reserved_instruction(ctx);
27206 break;
27210 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
27212 int rs, rt, rd, sa;
27213 uint32_t op1, op2;
27214 int16_t imm;
27216 rs = (ctx->opcode >> 21) & 0x1f;
27217 rt = (ctx->opcode >> 16) & 0x1f;
27218 rd = (ctx->opcode >> 11) & 0x1f;
27219 sa = (ctx->opcode >> 6) & 0x1f;
27220 imm = (int16_t)ctx->opcode >> 7;
27222 op1 = MASK_SPECIAL3(ctx->opcode);
27223 switch (op1) {
27224 case R6_OPC_PREF:
27225 if (rt >= 24) {
27226 /* hint codes 24-31 are reserved and signal RI */
27227 gen_reserved_instruction(ctx);
27229 /* Treat as NOP. */
27230 break;
27231 case R6_OPC_CACHE:
27232 check_cp0_enabled(ctx);
27233 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
27234 gen_cache_operation(ctx, rt, rs, imm);
27236 break;
27237 case R6_OPC_SC:
27238 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
27239 break;
27240 case R6_OPC_LL:
27241 gen_ld(ctx, op1, rt, rs, imm);
27242 break;
27243 case OPC_BSHFL:
27245 if (rd == 0) {
27246 /* Treat as NOP. */
27247 break;
27249 op2 = MASK_BSHFL(ctx->opcode);
27250 switch (op2) {
27251 case OPC_ALIGN:
27252 case OPC_ALIGN_1:
27253 case OPC_ALIGN_2:
27254 case OPC_ALIGN_3:
27255 gen_align(ctx, 32, rd, rs, rt, sa & 3);
27256 break;
27257 case OPC_BITSWAP:
27258 gen_bitswap(ctx, op2, rd, rt);
27259 break;
27262 break;
27263 #ifndef CONFIG_USER_ONLY
27264 case OPC_GINV:
27265 if (unlikely(ctx->gi <= 1)) {
27266 gen_reserved_instruction(ctx);
27268 check_cp0_enabled(ctx);
27269 switch ((ctx->opcode >> 6) & 3) {
27270 case 0: /* GINVI */
27271 /* Treat as NOP. */
27272 break;
27273 case 2: /* GINVT */
27274 gen_helper_0e1i(ginvt, cpu_gpr[rs], extract32(ctx->opcode, 8, 2));
27275 break;
27276 default:
27277 gen_reserved_instruction(ctx);
27278 break;
27280 break;
27281 #endif
27282 #if defined(TARGET_MIPS64)
27283 case R6_OPC_SCD:
27284 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
27285 break;
27286 case R6_OPC_LLD:
27287 gen_ld(ctx, op1, rt, rs, imm);
27288 break;
27289 case OPC_DBSHFL:
27290 check_mips_64(ctx);
27292 if (rd == 0) {
27293 /* Treat as NOP. */
27294 break;
27296 op2 = MASK_DBSHFL(ctx->opcode);
27297 switch (op2) {
27298 case OPC_DALIGN:
27299 case OPC_DALIGN_1:
27300 case OPC_DALIGN_2:
27301 case OPC_DALIGN_3:
27302 case OPC_DALIGN_4:
27303 case OPC_DALIGN_5:
27304 case OPC_DALIGN_6:
27305 case OPC_DALIGN_7:
27306 gen_align(ctx, 64, rd, rs, rt, sa & 7);
27307 break;
27308 case OPC_DBITSWAP:
27309 gen_bitswap(ctx, op2, rd, rt);
27310 break;
27314 break;
27315 #endif
27316 default: /* Invalid */
27317 MIPS_INVAL("special3_r6");
27318 gen_reserved_instruction(ctx);
27319 break;
27323 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
27325 int rs, rt, rd;
27326 uint32_t op1, op2;
27328 rs = (ctx->opcode >> 21) & 0x1f;
27329 rt = (ctx->opcode >> 16) & 0x1f;
27330 rd = (ctx->opcode >> 11) & 0x1f;
27332 op1 = MASK_SPECIAL3(ctx->opcode);
27333 switch (op1) {
27334 case OPC_DIV_G_2E:
27335 case OPC_DIVU_G_2E:
27336 case OPC_MOD_G_2E:
27337 case OPC_MODU_G_2E:
27338 case OPC_MULT_G_2E:
27339 case OPC_MULTU_G_2E:
27341 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
27342 * the same mask and op1.
27344 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
27345 op2 = MASK_ADDUH_QB(ctx->opcode);
27346 switch (op2) {
27347 case OPC_ADDUH_QB:
27348 case OPC_ADDUH_R_QB:
27349 case OPC_ADDQH_PH:
27350 case OPC_ADDQH_R_PH:
27351 case OPC_ADDQH_W:
27352 case OPC_ADDQH_R_W:
27353 case OPC_SUBUH_QB:
27354 case OPC_SUBUH_R_QB:
27355 case OPC_SUBQH_PH:
27356 case OPC_SUBQH_R_PH:
27357 case OPC_SUBQH_W:
27358 case OPC_SUBQH_R_W:
27359 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27360 break;
27361 case OPC_MUL_PH:
27362 case OPC_MUL_S_PH:
27363 case OPC_MULQ_S_W:
27364 case OPC_MULQ_RS_W:
27365 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27366 break;
27367 default:
27368 MIPS_INVAL("MASK ADDUH.QB");
27369 gen_reserved_instruction(ctx);
27370 break;
27372 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
27373 gen_loongson_integer(ctx, op1, rd, rs, rt);
27374 } else {
27375 gen_reserved_instruction(ctx);
27377 break;
27378 case OPC_LX_DSP:
27379 op2 = MASK_LX(ctx->opcode);
27380 switch (op2) {
27381 #if defined(TARGET_MIPS64)
27382 case OPC_LDX:
27383 #endif
27384 case OPC_LBUX:
27385 case OPC_LHX:
27386 case OPC_LWX:
27387 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
27388 break;
27389 default: /* Invalid */
27390 MIPS_INVAL("MASK LX");
27391 gen_reserved_instruction(ctx);
27392 break;
27394 break;
27395 case OPC_ABSQ_S_PH_DSP:
27396 op2 = MASK_ABSQ_S_PH(ctx->opcode);
27397 switch (op2) {
27398 case OPC_ABSQ_S_QB:
27399 case OPC_ABSQ_S_PH:
27400 case OPC_ABSQ_S_W:
27401 case OPC_PRECEQ_W_PHL:
27402 case OPC_PRECEQ_W_PHR:
27403 case OPC_PRECEQU_PH_QBL:
27404 case OPC_PRECEQU_PH_QBR:
27405 case OPC_PRECEQU_PH_QBLA:
27406 case OPC_PRECEQU_PH_QBRA:
27407 case OPC_PRECEU_PH_QBL:
27408 case OPC_PRECEU_PH_QBR:
27409 case OPC_PRECEU_PH_QBLA:
27410 case OPC_PRECEU_PH_QBRA:
27411 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27412 break;
27413 case OPC_BITREV:
27414 case OPC_REPL_QB:
27415 case OPC_REPLV_QB:
27416 case OPC_REPL_PH:
27417 case OPC_REPLV_PH:
27418 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27419 break;
27420 default:
27421 MIPS_INVAL("MASK ABSQ_S.PH");
27422 gen_reserved_instruction(ctx);
27423 break;
27425 break;
27426 case OPC_ADDU_QB_DSP:
27427 op2 = MASK_ADDU_QB(ctx->opcode);
27428 switch (op2) {
27429 case OPC_ADDQ_PH:
27430 case OPC_ADDQ_S_PH:
27431 case OPC_ADDQ_S_W:
27432 case OPC_ADDU_QB:
27433 case OPC_ADDU_S_QB:
27434 case OPC_ADDU_PH:
27435 case OPC_ADDU_S_PH:
27436 case OPC_SUBQ_PH:
27437 case OPC_SUBQ_S_PH:
27438 case OPC_SUBQ_S_W:
27439 case OPC_SUBU_QB:
27440 case OPC_SUBU_S_QB:
27441 case OPC_SUBU_PH:
27442 case OPC_SUBU_S_PH:
27443 case OPC_ADDSC:
27444 case OPC_ADDWC:
27445 case OPC_MODSUB:
27446 case OPC_RADDU_W_QB:
27447 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27448 break;
27449 case OPC_MULEU_S_PH_QBL:
27450 case OPC_MULEU_S_PH_QBR:
27451 case OPC_MULQ_RS_PH:
27452 case OPC_MULEQ_S_W_PHL:
27453 case OPC_MULEQ_S_W_PHR:
27454 case OPC_MULQ_S_PH:
27455 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27456 break;
27457 default: /* Invalid */
27458 MIPS_INVAL("MASK ADDU.QB");
27459 gen_reserved_instruction(ctx);
27460 break;
27463 break;
27464 case OPC_CMPU_EQ_QB_DSP:
27465 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
27466 switch (op2) {
27467 case OPC_PRECR_SRA_PH_W:
27468 case OPC_PRECR_SRA_R_PH_W:
27469 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
27470 break;
27471 case OPC_PRECR_QB_PH:
27472 case OPC_PRECRQ_QB_PH:
27473 case OPC_PRECRQ_PH_W:
27474 case OPC_PRECRQ_RS_PH_W:
27475 case OPC_PRECRQU_S_QB_PH:
27476 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27477 break;
27478 case OPC_CMPU_EQ_QB:
27479 case OPC_CMPU_LT_QB:
27480 case OPC_CMPU_LE_QB:
27481 case OPC_CMP_EQ_PH:
27482 case OPC_CMP_LT_PH:
27483 case OPC_CMP_LE_PH:
27484 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
27485 break;
27486 case OPC_CMPGU_EQ_QB:
27487 case OPC_CMPGU_LT_QB:
27488 case OPC_CMPGU_LE_QB:
27489 case OPC_CMPGDU_EQ_QB:
27490 case OPC_CMPGDU_LT_QB:
27491 case OPC_CMPGDU_LE_QB:
27492 case OPC_PICK_QB:
27493 case OPC_PICK_PH:
27494 case OPC_PACKRL_PH:
27495 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27496 break;
27497 default: /* Invalid */
27498 MIPS_INVAL("MASK CMPU.EQ.QB");
27499 gen_reserved_instruction(ctx);
27500 break;
27502 break;
27503 case OPC_SHLL_QB_DSP:
27504 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27505 break;
27506 case OPC_DPA_W_PH_DSP:
27507 op2 = MASK_DPA_W_PH(ctx->opcode);
27508 switch (op2) {
27509 case OPC_DPAU_H_QBL:
27510 case OPC_DPAU_H_QBR:
27511 case OPC_DPSU_H_QBL:
27512 case OPC_DPSU_H_QBR:
27513 case OPC_DPA_W_PH:
27514 case OPC_DPAX_W_PH:
27515 case OPC_DPAQ_S_W_PH:
27516 case OPC_DPAQX_S_W_PH:
27517 case OPC_DPAQX_SA_W_PH:
27518 case OPC_DPS_W_PH:
27519 case OPC_DPSX_W_PH:
27520 case OPC_DPSQ_S_W_PH:
27521 case OPC_DPSQX_S_W_PH:
27522 case OPC_DPSQX_SA_W_PH:
27523 case OPC_MULSAQ_S_W_PH:
27524 case OPC_DPAQ_SA_L_W:
27525 case OPC_DPSQ_SA_L_W:
27526 case OPC_MAQ_S_W_PHL:
27527 case OPC_MAQ_S_W_PHR:
27528 case OPC_MAQ_SA_W_PHL:
27529 case OPC_MAQ_SA_W_PHR:
27530 case OPC_MULSA_W_PH:
27531 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27532 break;
27533 default: /* Invalid */
27534 MIPS_INVAL("MASK DPAW.PH");
27535 gen_reserved_instruction(ctx);
27536 break;
27538 break;
27539 case OPC_INSV_DSP:
27540 op2 = MASK_INSV(ctx->opcode);
27541 switch (op2) {
27542 case OPC_INSV:
27543 check_dsp(ctx);
27545 TCGv t0, t1;
27547 if (rt == 0) {
27548 break;
27551 t0 = tcg_temp_new();
27552 t1 = tcg_temp_new();
27554 gen_load_gpr(t0, rt);
27555 gen_load_gpr(t1, rs);
27557 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
27559 tcg_temp_free(t0);
27560 tcg_temp_free(t1);
27561 break;
27563 default: /* Invalid */
27564 MIPS_INVAL("MASK INSV");
27565 gen_reserved_instruction(ctx);
27566 break;
27568 break;
27569 case OPC_APPEND_DSP:
27570 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27571 break;
27572 case OPC_EXTR_W_DSP:
27573 op2 = MASK_EXTR_W(ctx->opcode);
27574 switch (op2) {
27575 case OPC_EXTR_W:
27576 case OPC_EXTR_R_W:
27577 case OPC_EXTR_RS_W:
27578 case OPC_EXTR_S_H:
27579 case OPC_EXTRV_S_H:
27580 case OPC_EXTRV_W:
27581 case OPC_EXTRV_R_W:
27582 case OPC_EXTRV_RS_W:
27583 case OPC_EXTP:
27584 case OPC_EXTPV:
27585 case OPC_EXTPDP:
27586 case OPC_EXTPDPV:
27587 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27588 break;
27589 case OPC_RDDSP:
27590 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
27591 break;
27592 case OPC_SHILO:
27593 case OPC_SHILOV:
27594 case OPC_MTHLIP:
27595 case OPC_WRDSP:
27596 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27597 break;
27598 default: /* Invalid */
27599 MIPS_INVAL("MASK EXTR.W");
27600 gen_reserved_instruction(ctx);
27601 break;
27603 break;
27604 #if defined(TARGET_MIPS64)
27605 case OPC_DDIV_G_2E:
27606 case OPC_DDIVU_G_2E:
27607 case OPC_DMULT_G_2E:
27608 case OPC_DMULTU_G_2E:
27609 case OPC_DMOD_G_2E:
27610 case OPC_DMODU_G_2E:
27611 check_insn(ctx, INSN_LOONGSON2E);
27612 gen_loongson_integer(ctx, op1, rd, rs, rt);
27613 break;
27614 case OPC_ABSQ_S_QH_DSP:
27615 op2 = MASK_ABSQ_S_QH(ctx->opcode);
27616 switch (op2) {
27617 case OPC_PRECEQ_L_PWL:
27618 case OPC_PRECEQ_L_PWR:
27619 case OPC_PRECEQ_PW_QHL:
27620 case OPC_PRECEQ_PW_QHR:
27621 case OPC_PRECEQ_PW_QHLA:
27622 case OPC_PRECEQ_PW_QHRA:
27623 case OPC_PRECEQU_QH_OBL:
27624 case OPC_PRECEQU_QH_OBR:
27625 case OPC_PRECEQU_QH_OBLA:
27626 case OPC_PRECEQU_QH_OBRA:
27627 case OPC_PRECEU_QH_OBL:
27628 case OPC_PRECEU_QH_OBR:
27629 case OPC_PRECEU_QH_OBLA:
27630 case OPC_PRECEU_QH_OBRA:
27631 case OPC_ABSQ_S_OB:
27632 case OPC_ABSQ_S_PW:
27633 case OPC_ABSQ_S_QH:
27634 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27635 break;
27636 case OPC_REPL_OB:
27637 case OPC_REPL_PW:
27638 case OPC_REPL_QH:
27639 case OPC_REPLV_OB:
27640 case OPC_REPLV_PW:
27641 case OPC_REPLV_QH:
27642 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27643 break;
27644 default: /* Invalid */
27645 MIPS_INVAL("MASK ABSQ_S.QH");
27646 gen_reserved_instruction(ctx);
27647 break;
27649 break;
27650 case OPC_ADDU_OB_DSP:
27651 op2 = MASK_ADDU_OB(ctx->opcode);
27652 switch (op2) {
27653 case OPC_RADDU_L_OB:
27654 case OPC_SUBQ_PW:
27655 case OPC_SUBQ_S_PW:
27656 case OPC_SUBQ_QH:
27657 case OPC_SUBQ_S_QH:
27658 case OPC_SUBU_OB:
27659 case OPC_SUBU_S_OB:
27660 case OPC_SUBU_QH:
27661 case OPC_SUBU_S_QH:
27662 case OPC_SUBUH_OB:
27663 case OPC_SUBUH_R_OB:
27664 case OPC_ADDQ_PW:
27665 case OPC_ADDQ_S_PW:
27666 case OPC_ADDQ_QH:
27667 case OPC_ADDQ_S_QH:
27668 case OPC_ADDU_OB:
27669 case OPC_ADDU_S_OB:
27670 case OPC_ADDU_QH:
27671 case OPC_ADDU_S_QH:
27672 case OPC_ADDUH_OB:
27673 case OPC_ADDUH_R_OB:
27674 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27675 break;
27676 case OPC_MULEQ_S_PW_QHL:
27677 case OPC_MULEQ_S_PW_QHR:
27678 case OPC_MULEU_S_QH_OBL:
27679 case OPC_MULEU_S_QH_OBR:
27680 case OPC_MULQ_RS_QH:
27681 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27682 break;
27683 default: /* Invalid */
27684 MIPS_INVAL("MASK ADDU.OB");
27685 gen_reserved_instruction(ctx);
27686 break;
27688 break;
27689 case OPC_CMPU_EQ_OB_DSP:
27690 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
27691 switch (op2) {
27692 case OPC_PRECR_SRA_QH_PW:
27693 case OPC_PRECR_SRA_R_QH_PW:
27694 /* Return value is rt. */
27695 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
27696 break;
27697 case OPC_PRECR_OB_QH:
27698 case OPC_PRECRQ_OB_QH:
27699 case OPC_PRECRQ_PW_L:
27700 case OPC_PRECRQ_QH_PW:
27701 case OPC_PRECRQ_RS_QH_PW:
27702 case OPC_PRECRQU_S_OB_QH:
27703 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27704 break;
27705 case OPC_CMPU_EQ_OB:
27706 case OPC_CMPU_LT_OB:
27707 case OPC_CMPU_LE_OB:
27708 case OPC_CMP_EQ_QH:
27709 case OPC_CMP_LT_QH:
27710 case OPC_CMP_LE_QH:
27711 case OPC_CMP_EQ_PW:
27712 case OPC_CMP_LT_PW:
27713 case OPC_CMP_LE_PW:
27714 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
27715 break;
27716 case OPC_CMPGDU_EQ_OB:
27717 case OPC_CMPGDU_LT_OB:
27718 case OPC_CMPGDU_LE_OB:
27719 case OPC_CMPGU_EQ_OB:
27720 case OPC_CMPGU_LT_OB:
27721 case OPC_CMPGU_LE_OB:
27722 case OPC_PACKRL_PW:
27723 case OPC_PICK_OB:
27724 case OPC_PICK_PW:
27725 case OPC_PICK_QH:
27726 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27727 break;
27728 default: /* Invalid */
27729 MIPS_INVAL("MASK CMPU_EQ.OB");
27730 gen_reserved_instruction(ctx);
27731 break;
27733 break;
27734 case OPC_DAPPEND_DSP:
27735 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27736 break;
27737 case OPC_DEXTR_W_DSP:
27738 op2 = MASK_DEXTR_W(ctx->opcode);
27739 switch (op2) {
27740 case OPC_DEXTP:
27741 case OPC_DEXTPDP:
27742 case OPC_DEXTPDPV:
27743 case OPC_DEXTPV:
27744 case OPC_DEXTR_L:
27745 case OPC_DEXTR_R_L:
27746 case OPC_DEXTR_RS_L:
27747 case OPC_DEXTR_W:
27748 case OPC_DEXTR_R_W:
27749 case OPC_DEXTR_RS_W:
27750 case OPC_DEXTR_S_H:
27751 case OPC_DEXTRV_L:
27752 case OPC_DEXTRV_R_L:
27753 case OPC_DEXTRV_RS_L:
27754 case OPC_DEXTRV_S_H:
27755 case OPC_DEXTRV_W:
27756 case OPC_DEXTRV_R_W:
27757 case OPC_DEXTRV_RS_W:
27758 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27759 break;
27760 case OPC_DMTHLIP:
27761 case OPC_DSHILO:
27762 case OPC_DSHILOV:
27763 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27764 break;
27765 default: /* Invalid */
27766 MIPS_INVAL("MASK EXTR.W");
27767 gen_reserved_instruction(ctx);
27768 break;
27770 break;
27771 case OPC_DPAQ_W_QH_DSP:
27772 op2 = MASK_DPAQ_W_QH(ctx->opcode);
27773 switch (op2) {
27774 case OPC_DPAU_H_OBL:
27775 case OPC_DPAU_H_OBR:
27776 case OPC_DPSU_H_OBL:
27777 case OPC_DPSU_H_OBR:
27778 case OPC_DPA_W_QH:
27779 case OPC_DPAQ_S_W_QH:
27780 case OPC_DPS_W_QH:
27781 case OPC_DPSQ_S_W_QH:
27782 case OPC_MULSAQ_S_W_QH:
27783 case OPC_DPAQ_SA_L_PW:
27784 case OPC_DPSQ_SA_L_PW:
27785 case OPC_MULSAQ_S_L_PW:
27786 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27787 break;
27788 case OPC_MAQ_S_W_QHLL:
27789 case OPC_MAQ_S_W_QHLR:
27790 case OPC_MAQ_S_W_QHRL:
27791 case OPC_MAQ_S_W_QHRR:
27792 case OPC_MAQ_SA_W_QHLL:
27793 case OPC_MAQ_SA_W_QHLR:
27794 case OPC_MAQ_SA_W_QHRL:
27795 case OPC_MAQ_SA_W_QHRR:
27796 case OPC_MAQ_S_L_PWL:
27797 case OPC_MAQ_S_L_PWR:
27798 case OPC_DMADD:
27799 case OPC_DMADDU:
27800 case OPC_DMSUB:
27801 case OPC_DMSUBU:
27802 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27803 break;
27804 default: /* Invalid */
27805 MIPS_INVAL("MASK DPAQ.W.QH");
27806 gen_reserved_instruction(ctx);
27807 break;
27809 break;
27810 case OPC_DINSV_DSP:
27811 op2 = MASK_INSV(ctx->opcode);
27812 switch (op2) {
27813 case OPC_DINSV:
27815 TCGv t0, t1;
27817 if (rt == 0) {
27818 break;
27820 check_dsp(ctx);
27822 t0 = tcg_temp_new();
27823 t1 = tcg_temp_new();
27825 gen_load_gpr(t0, rt);
27826 gen_load_gpr(t1, rs);
27828 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
27830 tcg_temp_free(t0);
27831 tcg_temp_free(t1);
27832 break;
27834 default: /* Invalid */
27835 MIPS_INVAL("MASK DINSV");
27836 gen_reserved_instruction(ctx);
27837 break;
27839 break;
27840 case OPC_SHLL_OB_DSP:
27841 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27842 break;
27843 #endif
27844 default: /* Invalid */
27845 MIPS_INVAL("special3_legacy");
27846 gen_reserved_instruction(ctx);
27847 break;
27852 #if defined(TARGET_MIPS64)
27854 static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx)
27856 uint32_t opc = MASK_MMI0(ctx->opcode);
27858 switch (opc) {
27859 case MMI_OPC_0_PADDW: /* TODO: MMI_OPC_0_PADDW */
27860 case MMI_OPC_0_PSUBW: /* TODO: MMI_OPC_0_PSUBW */
27861 case MMI_OPC_0_PCGTW: /* TODO: MMI_OPC_0_PCGTW */
27862 case MMI_OPC_0_PMAXW: /* TODO: MMI_OPC_0_PMAXW */
27863 case MMI_OPC_0_PADDH: /* TODO: MMI_OPC_0_PADDH */
27864 case MMI_OPC_0_PSUBH: /* TODO: MMI_OPC_0_PSUBH */
27865 case MMI_OPC_0_PCGTH: /* TODO: MMI_OPC_0_PCGTH */
27866 case MMI_OPC_0_PMAXH: /* TODO: MMI_OPC_0_PMAXH */
27867 case MMI_OPC_0_PADDB: /* TODO: MMI_OPC_0_PADDB */
27868 case MMI_OPC_0_PSUBB: /* TODO: MMI_OPC_0_PSUBB */
27869 case MMI_OPC_0_PCGTB: /* TODO: MMI_OPC_0_PCGTB */
27870 case MMI_OPC_0_PADDSW: /* TODO: MMI_OPC_0_PADDSW */
27871 case MMI_OPC_0_PSUBSW: /* TODO: MMI_OPC_0_PSUBSW */
27872 case MMI_OPC_0_PEXTLW: /* TODO: MMI_OPC_0_PEXTLW */
27873 case MMI_OPC_0_PPACW: /* TODO: MMI_OPC_0_PPACW */
27874 case MMI_OPC_0_PADDSH: /* TODO: MMI_OPC_0_PADDSH */
27875 case MMI_OPC_0_PSUBSH: /* TODO: MMI_OPC_0_PSUBSH */
27876 case MMI_OPC_0_PEXTLH: /* TODO: MMI_OPC_0_PEXTLH */
27877 case MMI_OPC_0_PPACH: /* TODO: MMI_OPC_0_PPACH */
27878 case MMI_OPC_0_PADDSB: /* TODO: MMI_OPC_0_PADDSB */
27879 case MMI_OPC_0_PSUBSB: /* TODO: MMI_OPC_0_PSUBSB */
27880 case MMI_OPC_0_PEXTLB: /* TODO: MMI_OPC_0_PEXTLB */
27881 case MMI_OPC_0_PPACB: /* TODO: MMI_OPC_0_PPACB */
27882 case MMI_OPC_0_PEXT5: /* TODO: MMI_OPC_0_PEXT5 */
27883 case MMI_OPC_0_PPAC5: /* TODO: MMI_OPC_0_PPAC5 */
27884 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI0 */
27885 break;
27886 default:
27887 MIPS_INVAL("TX79 MMI class MMI0");
27888 gen_reserved_instruction(ctx);
27889 break;
27893 static void decode_mmi1(CPUMIPSState *env, DisasContext *ctx)
27895 uint32_t opc = MASK_MMI1(ctx->opcode);
27897 switch (opc) {
27898 case MMI_OPC_1_PABSW: /* TODO: MMI_OPC_1_PABSW */
27899 case MMI_OPC_1_PCEQW: /* TODO: MMI_OPC_1_PCEQW */
27900 case MMI_OPC_1_PMINW: /* TODO: MMI_OPC_1_PMINW */
27901 case MMI_OPC_1_PADSBH: /* TODO: MMI_OPC_1_PADSBH */
27902 case MMI_OPC_1_PABSH: /* TODO: MMI_OPC_1_PABSH */
27903 case MMI_OPC_1_PCEQH: /* TODO: MMI_OPC_1_PCEQH */
27904 case MMI_OPC_1_PMINH: /* TODO: MMI_OPC_1_PMINH */
27905 case MMI_OPC_1_PCEQB: /* TODO: MMI_OPC_1_PCEQB */
27906 case MMI_OPC_1_PADDUW: /* TODO: MMI_OPC_1_PADDUW */
27907 case MMI_OPC_1_PSUBUW: /* TODO: MMI_OPC_1_PSUBUW */
27908 case MMI_OPC_1_PEXTUW: /* TODO: MMI_OPC_1_PEXTUW */
27909 case MMI_OPC_1_PADDUH: /* TODO: MMI_OPC_1_PADDUH */
27910 case MMI_OPC_1_PSUBUH: /* TODO: MMI_OPC_1_PSUBUH */
27911 case MMI_OPC_1_PEXTUH: /* TODO: MMI_OPC_1_PEXTUH */
27912 case MMI_OPC_1_PADDUB: /* TODO: MMI_OPC_1_PADDUB */
27913 case MMI_OPC_1_PSUBUB: /* TODO: MMI_OPC_1_PSUBUB */
27914 case MMI_OPC_1_PEXTUB: /* TODO: MMI_OPC_1_PEXTUB */
27915 case MMI_OPC_1_QFSRV: /* TODO: MMI_OPC_1_QFSRV */
27916 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI1 */
27917 break;
27918 default:
27919 MIPS_INVAL("TX79 MMI class MMI1");
27920 gen_reserved_instruction(ctx);
27921 break;
27925 static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx)
27927 uint32_t opc = MASK_MMI2(ctx->opcode);
27929 switch (opc) {
27930 case MMI_OPC_2_PMADDW: /* TODO: MMI_OPC_2_PMADDW */
27931 case MMI_OPC_2_PSLLVW: /* TODO: MMI_OPC_2_PSLLVW */
27932 case MMI_OPC_2_PSRLVW: /* TODO: MMI_OPC_2_PSRLVW */
27933 case MMI_OPC_2_PMSUBW: /* TODO: MMI_OPC_2_PMSUBW */
27934 case MMI_OPC_2_PMFHI: /* TODO: MMI_OPC_2_PMFHI */
27935 case MMI_OPC_2_PMFLO: /* TODO: MMI_OPC_2_PMFLO */
27936 case MMI_OPC_2_PINTH: /* TODO: MMI_OPC_2_PINTH */
27937 case MMI_OPC_2_PMULTW: /* TODO: MMI_OPC_2_PMULTW */
27938 case MMI_OPC_2_PDIVW: /* TODO: MMI_OPC_2_PDIVW */
27939 case MMI_OPC_2_PMADDH: /* TODO: MMI_OPC_2_PMADDH */
27940 case MMI_OPC_2_PHMADH: /* TODO: MMI_OPC_2_PHMADH */
27941 case MMI_OPC_2_PAND: /* TODO: MMI_OPC_2_PAND */
27942 case MMI_OPC_2_PXOR: /* TODO: MMI_OPC_2_PXOR */
27943 case MMI_OPC_2_PMSUBH: /* TODO: MMI_OPC_2_PMSUBH */
27944 case MMI_OPC_2_PHMSBH: /* TODO: MMI_OPC_2_PHMSBH */
27945 case MMI_OPC_2_PEXEH: /* TODO: MMI_OPC_2_PEXEH */
27946 case MMI_OPC_2_PREVH: /* TODO: MMI_OPC_2_PREVH */
27947 case MMI_OPC_2_PMULTH: /* TODO: MMI_OPC_2_PMULTH */
27948 case MMI_OPC_2_PDIVBW: /* TODO: MMI_OPC_2_PDIVBW */
27949 case MMI_OPC_2_PEXEW: /* TODO: MMI_OPC_2_PEXEW */
27950 case MMI_OPC_2_PROT3W: /* TODO: MMI_OPC_2_PROT3W */
27951 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI2 */
27952 break;
27953 case MMI_OPC_2_PCPYLD:
27954 gen_mmi_pcpyld(ctx);
27955 break;
27956 default:
27957 MIPS_INVAL("TX79 MMI class MMI2");
27958 gen_reserved_instruction(ctx);
27959 break;
27963 static void decode_mmi3(CPUMIPSState *env, DisasContext *ctx)
27965 uint32_t opc = MASK_MMI3(ctx->opcode);
27967 switch (opc) {
27968 case MMI_OPC_3_PMADDUW: /* TODO: MMI_OPC_3_PMADDUW */
27969 case MMI_OPC_3_PSRAVW: /* TODO: MMI_OPC_3_PSRAVW */
27970 case MMI_OPC_3_PMTHI: /* TODO: MMI_OPC_3_PMTHI */
27971 case MMI_OPC_3_PMTLO: /* TODO: MMI_OPC_3_PMTLO */
27972 case MMI_OPC_3_PINTEH: /* TODO: MMI_OPC_3_PINTEH */
27973 case MMI_OPC_3_PMULTUW: /* TODO: MMI_OPC_3_PMULTUW */
27974 case MMI_OPC_3_PDIVUW: /* TODO: MMI_OPC_3_PDIVUW */
27975 case MMI_OPC_3_POR: /* TODO: MMI_OPC_3_POR */
27976 case MMI_OPC_3_PNOR: /* TODO: MMI_OPC_3_PNOR */
27977 case MMI_OPC_3_PEXCH: /* TODO: MMI_OPC_3_PEXCH */
27978 case MMI_OPC_3_PEXCW: /* TODO: MMI_OPC_3_PEXCW */
27979 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI3 */
27980 break;
27981 case MMI_OPC_3_PCPYH:
27982 gen_mmi_pcpyh(ctx);
27983 break;
27984 case MMI_OPC_3_PCPYUD:
27985 gen_mmi_pcpyud(ctx);
27986 break;
27987 default:
27988 MIPS_INVAL("TX79 MMI class MMI3");
27989 gen_reserved_instruction(ctx);
27990 break;
27994 static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
27996 uint32_t opc = MASK_MMI(ctx->opcode);
27997 int rs = extract32(ctx->opcode, 21, 5);
27998 int rt = extract32(ctx->opcode, 16, 5);
27999 int rd = extract32(ctx->opcode, 11, 5);
28001 switch (opc) {
28002 case MMI_OPC_CLASS_MMI0:
28003 decode_mmi0(env, ctx);
28004 break;
28005 case MMI_OPC_CLASS_MMI1:
28006 decode_mmi1(env, ctx);
28007 break;
28008 case MMI_OPC_CLASS_MMI2:
28009 decode_mmi2(env, ctx);
28010 break;
28011 case MMI_OPC_CLASS_MMI3:
28012 decode_mmi3(env, ctx);
28013 break;
28014 case MMI_OPC_MULT1:
28015 case MMI_OPC_MULTU1:
28016 case MMI_OPC_MADD:
28017 case MMI_OPC_MADDU:
28018 case MMI_OPC_MADD1:
28019 case MMI_OPC_MADDU1:
28020 gen_mul_txx9(ctx, opc, rd, rs, rt);
28021 break;
28022 case MMI_OPC_DIV1:
28023 case MMI_OPC_DIVU1:
28024 gen_div1_tx79(ctx, opc, rs, rt);
28025 break;
28026 case MMI_OPC_MTLO1:
28027 case MMI_OPC_MTHI1:
28028 gen_HILO1_tx79(ctx, opc, rs);
28029 break;
28030 case MMI_OPC_MFLO1:
28031 case MMI_OPC_MFHI1:
28032 gen_HILO1_tx79(ctx, opc, rd);
28033 break;
28034 case MMI_OPC_PLZCW: /* TODO: MMI_OPC_PLZCW */
28035 case MMI_OPC_PMFHL: /* TODO: MMI_OPC_PMFHL */
28036 case MMI_OPC_PMTHL: /* TODO: MMI_OPC_PMTHL */
28037 case MMI_OPC_PSLLH: /* TODO: MMI_OPC_PSLLH */
28038 case MMI_OPC_PSRLH: /* TODO: MMI_OPC_PSRLH */
28039 case MMI_OPC_PSRAH: /* TODO: MMI_OPC_PSRAH */
28040 case MMI_OPC_PSLLW: /* TODO: MMI_OPC_PSLLW */
28041 case MMI_OPC_PSRLW: /* TODO: MMI_OPC_PSRLW */
28042 case MMI_OPC_PSRAW: /* TODO: MMI_OPC_PSRAW */
28043 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI */
28044 break;
28045 default:
28046 MIPS_INVAL("TX79 MMI class");
28047 gen_reserved_instruction(ctx);
28048 break;
28052 static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
28054 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_LQ */
28057 static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
28059 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_SQ */
28063 * The TX79-specific instruction Store Quadword
28065 * +--------+-------+-------+------------------------+
28066 * | 011111 | base | rt | offset | SQ
28067 * +--------+-------+-------+------------------------+
28068 * 6 5 5 16
28070 * has the same opcode as the Read Hardware Register instruction
28072 * +--------+-------+-------+-------+-------+--------+
28073 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
28074 * +--------+-------+-------+-------+-------+--------+
28075 * 6 5 5 5 5 6
28077 * that is required, trapped and emulated by the Linux kernel. However, all
28078 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
28079 * offset is odd. Therefore all valid SQ instructions can execute normally.
28080 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
28081 * between SQ and RDHWR, as the Linux kernel does.
28083 static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
28085 int base = extract32(ctx->opcode, 21, 5);
28086 int rt = extract32(ctx->opcode, 16, 5);
28087 int offset = extract32(ctx->opcode, 0, 16);
28089 #ifdef CONFIG_USER_ONLY
28090 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
28091 uint32_t op2 = extract32(ctx->opcode, 6, 5);
28093 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
28094 int rd = extract32(ctx->opcode, 11, 5);
28096 gen_rdhwr(ctx, rt, rd, 0);
28097 return;
28099 #endif
28101 gen_mmi_sq(ctx, base, rt, offset);
28104 #endif
28106 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
28108 int rs, rt, rd, sa;
28109 uint32_t op1, op2;
28110 int16_t imm;
28112 rs = (ctx->opcode >> 21) & 0x1f;
28113 rt = (ctx->opcode >> 16) & 0x1f;
28114 rd = (ctx->opcode >> 11) & 0x1f;
28115 sa = (ctx->opcode >> 6) & 0x1f;
28116 imm = sextract32(ctx->opcode, 7, 9);
28118 op1 = MASK_SPECIAL3(ctx->opcode);
28121 * EVA loads and stores overlap Loongson 2E instructions decoded by
28122 * decode_opc_special3_legacy(), so be careful to allow their decoding when
28123 * EVA is absent.
28125 if (ctx->eva) {
28126 switch (op1) {
28127 case OPC_LWLE:
28128 case OPC_LWRE:
28129 case OPC_LBUE:
28130 case OPC_LHUE:
28131 case OPC_LBE:
28132 case OPC_LHE:
28133 case OPC_LLE:
28134 case OPC_LWE:
28135 check_cp0_enabled(ctx);
28136 gen_ld(ctx, op1, rt, rs, imm);
28137 return;
28138 case OPC_SWLE:
28139 case OPC_SWRE:
28140 case OPC_SBE:
28141 case OPC_SHE:
28142 case OPC_SWE:
28143 check_cp0_enabled(ctx);
28144 gen_st(ctx, op1, rt, rs, imm);
28145 return;
28146 case OPC_SCE:
28147 check_cp0_enabled(ctx);
28148 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
28149 return;
28150 case OPC_CACHEE:
28151 check_cp0_enabled(ctx);
28152 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
28153 gen_cache_operation(ctx, rt, rs, imm);
28155 /* Treat as NOP. */
28156 return;
28157 case OPC_PREFE:
28158 check_cp0_enabled(ctx);
28159 /* Treat as NOP. */
28160 return;
28164 switch (op1) {
28165 case OPC_EXT:
28166 case OPC_INS:
28167 check_insn(ctx, ISA_MIPS_R2);
28168 gen_bitops(ctx, op1, rt, rs, sa, rd);
28169 break;
28170 case OPC_BSHFL:
28171 op2 = MASK_BSHFL(ctx->opcode);
28172 switch (op2) {
28173 case OPC_ALIGN:
28174 case OPC_ALIGN_1:
28175 case OPC_ALIGN_2:
28176 case OPC_ALIGN_3:
28177 case OPC_BITSWAP:
28178 check_insn(ctx, ISA_MIPS_R6);
28179 decode_opc_special3_r6(env, ctx);
28180 break;
28181 default:
28182 check_insn(ctx, ISA_MIPS_R2);
28183 gen_bshfl(ctx, op2, rt, rd);
28184 break;
28186 break;
28187 #if defined(TARGET_MIPS64)
28188 case OPC_DEXTM:
28189 case OPC_DEXTU:
28190 case OPC_DEXT:
28191 case OPC_DINSM:
28192 case OPC_DINSU:
28193 case OPC_DINS:
28194 check_insn(ctx, ISA_MIPS_R2);
28195 check_mips_64(ctx);
28196 gen_bitops(ctx, op1, rt, rs, sa, rd);
28197 break;
28198 case OPC_DBSHFL:
28199 op2 = MASK_DBSHFL(ctx->opcode);
28200 switch (op2) {
28201 case OPC_DALIGN:
28202 case OPC_DALIGN_1:
28203 case OPC_DALIGN_2:
28204 case OPC_DALIGN_3:
28205 case OPC_DALIGN_4:
28206 case OPC_DALIGN_5:
28207 case OPC_DALIGN_6:
28208 case OPC_DALIGN_7:
28209 case OPC_DBITSWAP:
28210 check_insn(ctx, ISA_MIPS_R6);
28211 decode_opc_special3_r6(env, ctx);
28212 break;
28213 default:
28214 check_insn(ctx, ISA_MIPS_R2);
28215 check_mips_64(ctx);
28216 op2 = MASK_DBSHFL(ctx->opcode);
28217 gen_bshfl(ctx, op2, rt, rd);
28218 break;
28220 break;
28221 #endif
28222 case OPC_RDHWR:
28223 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
28224 break;
28225 case OPC_FORK:
28226 check_mt(ctx);
28228 TCGv t0 = tcg_temp_new();
28229 TCGv t1 = tcg_temp_new();
28231 gen_load_gpr(t0, rt);
28232 gen_load_gpr(t1, rs);
28233 gen_helper_fork(t0, t1);
28234 tcg_temp_free(t0);
28235 tcg_temp_free(t1);
28237 break;
28238 case OPC_YIELD:
28239 check_mt(ctx);
28241 TCGv t0 = tcg_temp_new();
28243 gen_load_gpr(t0, rs);
28244 gen_helper_yield(t0, cpu_env, t0);
28245 gen_store_gpr(t0, rd);
28246 tcg_temp_free(t0);
28248 break;
28249 default:
28250 if (ctx->insn_flags & ISA_MIPS_R6) {
28251 decode_opc_special3_r6(env, ctx);
28252 } else {
28253 decode_opc_special3_legacy(env, ctx);
28258 static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx)
28260 int32_t offset;
28261 int rs, rt, rd, sa;
28262 uint32_t op, op1;
28263 int16_t imm;
28265 op = MASK_OP_MAJOR(ctx->opcode);
28266 rs = (ctx->opcode >> 21) & 0x1f;
28267 rt = (ctx->opcode >> 16) & 0x1f;
28268 rd = (ctx->opcode >> 11) & 0x1f;
28269 sa = (ctx->opcode >> 6) & 0x1f;
28270 imm = (int16_t)ctx->opcode;
28271 switch (op) {
28272 case OPC_SPECIAL:
28273 decode_opc_special(env, ctx);
28274 break;
28275 case OPC_SPECIAL2:
28276 #if defined(TARGET_MIPS64)
28277 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
28278 decode_mmi(env, ctx);
28279 #else
28280 if (ctx->insn_flags & ASE_MXU) {
28281 decode_opc_mxu(env, ctx);
28282 #endif
28283 } else {
28284 decode_opc_special2_legacy(env, ctx);
28286 break;
28287 case OPC_SPECIAL3:
28288 #if defined(TARGET_MIPS64)
28289 if (ctx->insn_flags & INSN_R5900) {
28290 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
28291 } else {
28292 decode_opc_special3(env, ctx);
28294 #else
28295 decode_opc_special3(env, ctx);
28296 #endif
28297 break;
28298 case OPC_REGIMM:
28299 op1 = MASK_REGIMM(ctx->opcode);
28300 switch (op1) {
28301 case OPC_BLTZL: /* REGIMM branches */
28302 case OPC_BGEZL:
28303 case OPC_BLTZALL:
28304 case OPC_BGEZALL:
28305 check_insn(ctx, ISA_MIPS2);
28306 check_insn_opc_removed(ctx, ISA_MIPS_R6);
28307 /* Fallthrough */
28308 case OPC_BLTZ:
28309 case OPC_BGEZ:
28310 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
28311 break;
28312 case OPC_BLTZAL:
28313 case OPC_BGEZAL:
28314 if (ctx->insn_flags & ISA_MIPS_R6) {
28315 if (rs == 0) {
28316 /* OPC_NAL, OPC_BAL */
28317 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
28318 } else {
28319 gen_reserved_instruction(ctx);
28321 } else {
28322 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
28324 break;
28325 case OPC_TGEI: /* REGIMM traps */
28326 case OPC_TGEIU:
28327 case OPC_TLTI:
28328 case OPC_TLTIU:
28329 case OPC_TEQI:
28331 case OPC_TNEI:
28332 check_insn(ctx, ISA_MIPS2);
28333 check_insn_opc_removed(ctx, ISA_MIPS_R6);
28334 gen_trap(ctx, op1, rs, -1, imm);
28335 break;
28336 case OPC_SIGRIE:
28337 check_insn(ctx, ISA_MIPS_R6);
28338 gen_reserved_instruction(ctx);
28339 break;
28340 case OPC_SYNCI:
28341 check_insn(ctx, ISA_MIPS_R2);
28343 * Break the TB to be able to sync copied instructions
28344 * immediately.
28346 ctx->base.is_jmp = DISAS_STOP;
28347 break;
28348 case OPC_BPOSGE32: /* MIPS DSP branch */
28349 #if defined(TARGET_MIPS64)
28350 case OPC_BPOSGE64:
28351 #endif
28352 check_dsp(ctx);
28353 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
28354 break;
28355 #if defined(TARGET_MIPS64)
28356 case OPC_DAHI:
28357 check_insn(ctx, ISA_MIPS_R6);
28358 check_mips_64(ctx);
28359 if (rs != 0) {
28360 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
28362 break;
28363 case OPC_DATI:
28364 check_insn(ctx, ISA_MIPS_R6);
28365 check_mips_64(ctx);
28366 if (rs != 0) {
28367 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
28369 break;
28370 #endif
28371 default: /* Invalid */
28372 MIPS_INVAL("regimm");
28373 gen_reserved_instruction(ctx);
28374 break;
28376 break;
28377 case OPC_CP0:
28378 check_cp0_enabled(ctx);
28379 op1 = MASK_CP0(ctx->opcode);
28380 switch (op1) {
28381 case OPC_MFC0:
28382 case OPC_MTC0:
28383 case OPC_MFTR:
28384 case OPC_MTTR:
28385 case OPC_MFHC0:
28386 case OPC_MTHC0:
28387 #if defined(TARGET_MIPS64)
28388 case OPC_DMFC0:
28389 case OPC_DMTC0:
28390 #endif
28391 #ifndef CONFIG_USER_ONLY
28392 gen_cp0(env, ctx, op1, rt, rd);
28393 #endif /* !CONFIG_USER_ONLY */
28394 break;
28395 case OPC_C0:
28396 case OPC_C0_1:
28397 case OPC_C0_2:
28398 case OPC_C0_3:
28399 case OPC_C0_4:
28400 case OPC_C0_5:
28401 case OPC_C0_6:
28402 case OPC_C0_7:
28403 case OPC_C0_8:
28404 case OPC_C0_9:
28405 case OPC_C0_A:
28406 case OPC_C0_B:
28407 case OPC_C0_C:
28408 case OPC_C0_D:
28409 case OPC_C0_E:
28410 case OPC_C0_F:
28411 #ifndef CONFIG_USER_ONLY
28412 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
28413 #endif /* !CONFIG_USER_ONLY */
28414 break;
28415 case OPC_MFMC0:
28416 #ifndef CONFIG_USER_ONLY
28418 uint32_t op2;
28419 TCGv t0 = tcg_temp_new();
28421 op2 = MASK_MFMC0(ctx->opcode);
28422 switch (op2) {
28423 case OPC_DMT:
28424 check_cp0_mt(ctx);
28425 gen_helper_dmt(t0);
28426 gen_store_gpr(t0, rt);
28427 break;
28428 case OPC_EMT:
28429 check_cp0_mt(ctx);
28430 gen_helper_emt(t0);
28431 gen_store_gpr(t0, rt);
28432 break;
28433 case OPC_DVPE:
28434 check_cp0_mt(ctx);
28435 gen_helper_dvpe(t0, cpu_env);
28436 gen_store_gpr(t0, rt);
28437 break;
28438 case OPC_EVPE:
28439 check_cp0_mt(ctx);
28440 gen_helper_evpe(t0, cpu_env);
28441 gen_store_gpr(t0, rt);
28442 break;
28443 case OPC_DVP:
28444 check_insn(ctx, ISA_MIPS_R6);
28445 if (ctx->vp) {
28446 gen_helper_dvp(t0, cpu_env);
28447 gen_store_gpr(t0, rt);
28449 break;
28450 case OPC_EVP:
28451 check_insn(ctx, ISA_MIPS_R6);
28452 if (ctx->vp) {
28453 gen_helper_evp(t0, cpu_env);
28454 gen_store_gpr(t0, rt);
28456 break;
28457 case OPC_DI:
28458 check_insn(ctx, ISA_MIPS_R2);
28459 save_cpu_state(ctx, 1);
28460 gen_helper_di(t0, cpu_env);
28461 gen_store_gpr(t0, rt);
28463 * Stop translation as we may have switched
28464 * the execution mode.
28466 ctx->base.is_jmp = DISAS_STOP;
28467 break;
28468 case OPC_EI:
28469 check_insn(ctx, ISA_MIPS_R2);
28470 save_cpu_state(ctx, 1);
28471 gen_helper_ei(t0, cpu_env);
28472 gen_store_gpr(t0, rt);
28474 * DISAS_STOP isn't sufficient, we need to ensure we break
28475 * out of translated code to check for pending interrupts.
28477 gen_save_pc(ctx->base.pc_next + 4);
28478 ctx->base.is_jmp = DISAS_EXIT;
28479 break;
28480 default: /* Invalid */
28481 MIPS_INVAL("mfmc0");
28482 gen_reserved_instruction(ctx);
28483 break;
28485 tcg_temp_free(t0);
28487 #endif /* !CONFIG_USER_ONLY */
28488 break;
28489 case OPC_RDPGPR:
28490 check_insn(ctx, ISA_MIPS_R2);
28491 gen_load_srsgpr(rt, rd);
28492 break;
28493 case OPC_WRPGPR:
28494 check_insn(ctx, ISA_MIPS_R2);
28495 gen_store_srsgpr(rt, rd);
28496 break;
28497 default:
28498 MIPS_INVAL("cp0");
28499 gen_reserved_instruction(ctx);
28500 break;
28502 break;
28503 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
28504 if (ctx->insn_flags & ISA_MIPS_R6) {
28505 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
28506 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
28507 } else {
28508 /* OPC_ADDI */
28509 /* Arithmetic with immediate opcode */
28510 gen_arith_imm(ctx, op, rt, rs, imm);
28512 break;
28513 case OPC_ADDIU:
28514 gen_arith_imm(ctx, op, rt, rs, imm);
28515 break;
28516 case OPC_SLTI: /* Set on less than with immediate opcode */
28517 case OPC_SLTIU:
28518 gen_slt_imm(ctx, op, rt, rs, imm);
28519 break;
28520 case OPC_ANDI: /* Arithmetic with immediate opcode */
28521 case OPC_LUI: /* OPC_AUI */
28522 case OPC_ORI:
28523 case OPC_XORI:
28524 gen_logic_imm(ctx, op, rt, rs, imm);
28525 break;
28526 case OPC_J: /* Jump */
28527 case OPC_JAL:
28528 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
28529 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
28530 break;
28531 /* Branch */
28532 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
28533 if (ctx->insn_flags & ISA_MIPS_R6) {
28534 if (rt == 0) {
28535 gen_reserved_instruction(ctx);
28536 break;
28538 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
28539 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
28540 } else {
28541 /* OPC_BLEZL */
28542 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
28544 break;
28545 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
28546 if (ctx->insn_flags & ISA_MIPS_R6) {
28547 if (rt == 0) {
28548 gen_reserved_instruction(ctx);
28549 break;
28551 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
28552 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
28553 } else {
28554 /* OPC_BGTZL */
28555 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
28557 break;
28558 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
28559 if (rt == 0) {
28560 /* OPC_BLEZ */
28561 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
28562 } else {
28563 check_insn(ctx, ISA_MIPS_R6);
28564 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
28565 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
28567 break;
28568 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
28569 if (rt == 0) {
28570 /* OPC_BGTZ */
28571 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
28572 } else {
28573 check_insn(ctx, ISA_MIPS_R6);
28574 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
28575 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
28577 break;
28578 case OPC_BEQL:
28579 case OPC_BNEL:
28580 check_insn(ctx, ISA_MIPS2);
28581 check_insn_opc_removed(ctx, ISA_MIPS_R6);
28582 /* Fallthrough */
28583 case OPC_BEQ:
28584 case OPC_BNE:
28585 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
28586 break;
28587 case OPC_LL: /* Load and stores */
28588 check_insn(ctx, ISA_MIPS2);
28589 if (ctx->insn_flags & INSN_R5900) {
28590 check_insn_opc_user_only(ctx, INSN_R5900);
28592 /* Fallthrough */
28593 case OPC_LWL:
28594 case OPC_LWR:
28595 case OPC_LB:
28596 case OPC_LH:
28597 case OPC_LW:
28598 case OPC_LWPC:
28599 case OPC_LBU:
28600 case OPC_LHU:
28601 gen_ld(ctx, op, rt, rs, imm);
28602 break;
28603 case OPC_SWL:
28604 case OPC_SWR:
28605 case OPC_SB:
28606 case OPC_SH:
28607 case OPC_SW:
28608 gen_st(ctx, op, rt, rs, imm);
28609 break;
28610 case OPC_SC:
28611 check_insn(ctx, ISA_MIPS2);
28612 if (ctx->insn_flags & INSN_R5900) {
28613 check_insn_opc_user_only(ctx, INSN_R5900);
28615 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
28616 break;
28617 case OPC_CACHE:
28618 check_cp0_enabled(ctx);
28619 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
28620 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
28621 gen_cache_operation(ctx, rt, rs, imm);
28623 /* Treat as NOP. */
28624 break;
28625 case OPC_PREF:
28626 if (ctx->insn_flags & INSN_R5900) {
28627 /* Treat as NOP. */
28628 } else {
28629 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
28630 /* Treat as NOP. */
28632 break;
28634 /* Floating point (COP1). */
28635 case OPC_LWC1:
28636 case OPC_LDC1:
28637 case OPC_SWC1:
28638 case OPC_SDC1:
28639 gen_cop1_ldst(ctx, op, rt, rs, imm);
28640 break;
28642 case OPC_CP1:
28643 op1 = MASK_CP1(ctx->opcode);
28645 switch (op1) {
28646 case OPC_MFHC1:
28647 case OPC_MTHC1:
28648 check_cp1_enabled(ctx);
28649 check_insn(ctx, ISA_MIPS_R2);
28650 /* fall through */
28651 case OPC_MFC1:
28652 case OPC_CFC1:
28653 case OPC_MTC1:
28654 case OPC_CTC1:
28655 check_cp1_enabled(ctx);
28656 gen_cp1(ctx, op1, rt, rd);
28657 break;
28658 #if defined(TARGET_MIPS64)
28659 case OPC_DMFC1:
28660 case OPC_DMTC1:
28661 check_cp1_enabled(ctx);
28662 check_insn(ctx, ISA_MIPS3);
28663 check_mips_64(ctx);
28664 gen_cp1(ctx, op1, rt, rd);
28665 break;
28666 #endif
28667 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
28668 check_cp1_enabled(ctx);
28669 if (ctx->insn_flags & ISA_MIPS_R6) {
28670 /* OPC_BC1EQZ */
28671 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
28672 rt, imm << 2, 4);
28673 } else {
28674 /* OPC_BC1ANY2 */
28675 check_cop1x(ctx);
28676 check_insn(ctx, ASE_MIPS3D);
28677 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
28678 (rt >> 2) & 0x7, imm << 2);
28680 break;
28681 case OPC_BC1NEZ:
28682 check_cp1_enabled(ctx);
28683 check_insn(ctx, ISA_MIPS_R6);
28684 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
28685 rt, imm << 2, 4);
28686 break;
28687 case OPC_BC1ANY4:
28688 check_cp1_enabled(ctx);
28689 check_insn_opc_removed(ctx, ISA_MIPS_R6);
28690 check_cop1x(ctx);
28691 check_insn(ctx, ASE_MIPS3D);
28692 /* fall through */
28693 case OPC_BC1:
28694 check_cp1_enabled(ctx);
28695 check_insn_opc_removed(ctx, ISA_MIPS_R6);
28696 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
28697 (rt >> 2) & 0x7, imm << 2);
28698 break;
28699 case OPC_PS_FMT:
28700 check_ps(ctx);
28701 /* fall through */
28702 case OPC_S_FMT:
28703 case OPC_D_FMT:
28704 check_cp1_enabled(ctx);
28705 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
28706 (imm >> 8) & 0x7);
28707 break;
28708 case OPC_W_FMT:
28709 case OPC_L_FMT:
28711 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
28712 check_cp1_enabled(ctx);
28713 if (ctx->insn_flags & ISA_MIPS_R6) {
28714 switch (r6_op) {
28715 case R6_OPC_CMP_AF_S:
28716 case R6_OPC_CMP_UN_S:
28717 case R6_OPC_CMP_EQ_S:
28718 case R6_OPC_CMP_UEQ_S:
28719 case R6_OPC_CMP_LT_S:
28720 case R6_OPC_CMP_ULT_S:
28721 case R6_OPC_CMP_LE_S:
28722 case R6_OPC_CMP_ULE_S:
28723 case R6_OPC_CMP_SAF_S:
28724 case R6_OPC_CMP_SUN_S:
28725 case R6_OPC_CMP_SEQ_S:
28726 case R6_OPC_CMP_SEUQ_S:
28727 case R6_OPC_CMP_SLT_S:
28728 case R6_OPC_CMP_SULT_S:
28729 case R6_OPC_CMP_SLE_S:
28730 case R6_OPC_CMP_SULE_S:
28731 case R6_OPC_CMP_OR_S:
28732 case R6_OPC_CMP_UNE_S:
28733 case R6_OPC_CMP_NE_S:
28734 case R6_OPC_CMP_SOR_S:
28735 case R6_OPC_CMP_SUNE_S:
28736 case R6_OPC_CMP_SNE_S:
28737 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
28738 break;
28739 case R6_OPC_CMP_AF_D:
28740 case R6_OPC_CMP_UN_D:
28741 case R6_OPC_CMP_EQ_D:
28742 case R6_OPC_CMP_UEQ_D:
28743 case R6_OPC_CMP_LT_D:
28744 case R6_OPC_CMP_ULT_D:
28745 case R6_OPC_CMP_LE_D:
28746 case R6_OPC_CMP_ULE_D:
28747 case R6_OPC_CMP_SAF_D:
28748 case R6_OPC_CMP_SUN_D:
28749 case R6_OPC_CMP_SEQ_D:
28750 case R6_OPC_CMP_SEUQ_D:
28751 case R6_OPC_CMP_SLT_D:
28752 case R6_OPC_CMP_SULT_D:
28753 case R6_OPC_CMP_SLE_D:
28754 case R6_OPC_CMP_SULE_D:
28755 case R6_OPC_CMP_OR_D:
28756 case R6_OPC_CMP_UNE_D:
28757 case R6_OPC_CMP_NE_D:
28758 case R6_OPC_CMP_SOR_D:
28759 case R6_OPC_CMP_SUNE_D:
28760 case R6_OPC_CMP_SNE_D:
28761 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
28762 break;
28763 default:
28764 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
28765 rt, rd, sa, (imm >> 8) & 0x7);
28767 break;
28769 } else {
28770 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
28771 (imm >> 8) & 0x7);
28773 break;
28775 default:
28776 MIPS_INVAL("cp1");
28777 gen_reserved_instruction(ctx);
28778 break;
28780 break;
28782 /* Compact branches [R6] and COP2 [non-R6] */
28783 case OPC_BC: /* OPC_LWC2 */
28784 case OPC_BALC: /* OPC_SWC2 */
28785 if (ctx->insn_flags & ISA_MIPS_R6) {
28786 /* OPC_BC, OPC_BALC */
28787 gen_compute_compact_branch(ctx, op, 0, 0,
28788 sextract32(ctx->opcode << 2, 0, 28));
28789 } else if (ctx->insn_flags & ASE_LEXT) {
28790 gen_loongson_lswc2(ctx, rt, rs, rd);
28791 } else {
28792 /* OPC_LWC2, OPC_SWC2 */
28793 /* COP2: Not implemented. */
28794 generate_exception_err(ctx, EXCP_CpU, 2);
28796 break;
28797 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
28798 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
28799 if (ctx->insn_flags & ISA_MIPS_R6) {
28800 if (rs != 0) {
28801 /* OPC_BEQZC, OPC_BNEZC */
28802 gen_compute_compact_branch(ctx, op, rs, 0,
28803 sextract32(ctx->opcode << 2, 0, 23));
28804 } else {
28805 /* OPC_JIC, OPC_JIALC */
28806 gen_compute_compact_branch(ctx, op, 0, rt, imm);
28808 } else if (ctx->insn_flags & ASE_LEXT) {
28809 gen_loongson_lsdc2(ctx, rt, rs, rd);
28810 } else {
28811 /* OPC_LWC2, OPC_SWC2 */
28812 /* COP2: Not implemented. */
28813 generate_exception_err(ctx, EXCP_CpU, 2);
28815 break;
28816 case OPC_CP2:
28817 check_insn(ctx, ASE_LMMI);
28818 /* Note that these instructions use different fields. */
28819 gen_loongson_multimedia(ctx, sa, rd, rt);
28820 break;
28822 case OPC_CP3:
28823 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
28824 check_cp1_enabled(ctx);
28825 op1 = MASK_CP3(ctx->opcode);
28826 switch (op1) {
28827 case OPC_LUXC1:
28828 case OPC_SUXC1:
28829 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
28830 /* Fallthrough */
28831 case OPC_LWXC1:
28832 case OPC_LDXC1:
28833 case OPC_SWXC1:
28834 case OPC_SDXC1:
28835 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
28836 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
28837 break;
28838 case OPC_PREFX:
28839 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
28840 /* Treat as NOP. */
28841 break;
28842 case OPC_ALNV_PS:
28843 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
28844 /* Fallthrough */
28845 case OPC_MADD_S:
28846 case OPC_MADD_D:
28847 case OPC_MADD_PS:
28848 case OPC_MSUB_S:
28849 case OPC_MSUB_D:
28850 case OPC_MSUB_PS:
28851 case OPC_NMADD_S:
28852 case OPC_NMADD_D:
28853 case OPC_NMADD_PS:
28854 case OPC_NMSUB_S:
28855 case OPC_NMSUB_D:
28856 case OPC_NMSUB_PS:
28857 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
28858 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
28859 break;
28860 default:
28861 MIPS_INVAL("cp3");
28862 gen_reserved_instruction(ctx);
28863 break;
28865 } else {
28866 generate_exception_err(ctx, EXCP_CpU, 1);
28868 break;
28870 #if defined(TARGET_MIPS64)
28871 /* MIPS64 opcodes */
28872 case OPC_LLD:
28873 if (ctx->insn_flags & INSN_R5900) {
28874 check_insn_opc_user_only(ctx, INSN_R5900);
28876 /* fall through */
28877 case OPC_LDL:
28878 case OPC_LDR:
28879 case OPC_LWU:
28880 case OPC_LD:
28881 check_insn(ctx, ISA_MIPS3);
28882 check_mips_64(ctx);
28883 gen_ld(ctx, op, rt, rs, imm);
28884 break;
28885 case OPC_SDL:
28886 case OPC_SDR:
28887 case OPC_SD:
28888 check_insn(ctx, ISA_MIPS3);
28889 check_mips_64(ctx);
28890 gen_st(ctx, op, rt, rs, imm);
28891 break;
28892 case OPC_SCD:
28893 check_insn(ctx, ISA_MIPS3);
28894 if (ctx->insn_flags & INSN_R5900) {
28895 check_insn_opc_user_only(ctx, INSN_R5900);
28897 check_mips_64(ctx);
28898 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
28899 break;
28900 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
28901 if (ctx->insn_flags & ISA_MIPS_R6) {
28902 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
28903 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
28904 } else {
28905 /* OPC_DADDI */
28906 check_insn(ctx, ISA_MIPS3);
28907 check_mips_64(ctx);
28908 gen_arith_imm(ctx, op, rt, rs, imm);
28910 break;
28911 case OPC_DADDIU:
28912 check_insn(ctx, ISA_MIPS3);
28913 check_mips_64(ctx);
28914 gen_arith_imm(ctx, op, rt, rs, imm);
28915 break;
28916 #else
28917 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
28918 if (ctx->insn_flags & ISA_MIPS_R6) {
28919 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
28920 } else {
28921 MIPS_INVAL("major opcode");
28922 gen_reserved_instruction(ctx);
28924 break;
28925 #endif
28926 case OPC_DAUI: /* OPC_JALX */
28927 if (ctx->insn_flags & ISA_MIPS_R6) {
28928 #if defined(TARGET_MIPS64)
28929 /* OPC_DAUI */
28930 check_mips_64(ctx);
28931 if (rs == 0) {
28932 generate_exception(ctx, EXCP_RI);
28933 } else if (rt != 0) {
28934 TCGv t0 = tcg_temp_new();
28935 gen_load_gpr(t0, rs);
28936 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
28937 tcg_temp_free(t0);
28939 #else
28940 gen_reserved_instruction(ctx);
28941 MIPS_INVAL("major opcode");
28942 #endif
28943 } else {
28944 /* OPC_JALX */
28945 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
28946 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
28947 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
28949 break;
28950 case OPC_MDMX: /* MMI_OPC_LQ */
28951 if (ctx->insn_flags & INSN_R5900) {
28952 #if defined(TARGET_MIPS64)
28953 gen_mmi_lq(env, ctx);
28954 #endif
28955 } else {
28956 /* MDMX: Not implemented. */
28958 break;
28959 case OPC_PCREL:
28960 check_insn(ctx, ISA_MIPS_R6);
28961 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
28962 break;
28963 default: /* Invalid */
28964 MIPS_INVAL("major opcode");
28965 return false;
28967 return true;
28970 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
28972 /* make sure instructions are on a word boundary */
28973 if (ctx->base.pc_next & 0x3) {
28974 env->CP0_BadVAddr = ctx->base.pc_next;
28975 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
28976 return;
28979 /* Handle blikely not taken case */
28980 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
28981 TCGLabel *l1 = gen_new_label();
28983 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
28984 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
28985 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
28986 gen_set_label(l1);
28989 /* Transition to the auto-generated decoder. */
28991 /* ISA extensions */
28992 if (ase_msa_available(env) && decode_ase_msa(ctx, ctx->opcode)) {
28993 return;
28996 /* ISA (from latest to oldest) */
28997 if (cpu_supports_isa(env, ISA_MIPS_R6) && decode_isa_rel6(ctx, ctx->opcode)) {
28998 return;
29001 if (decode_opc_legacy(env, ctx)) {
29002 return;
29005 gen_reserved_instruction(ctx);
29008 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
29010 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29011 CPUMIPSState *env = cs->env_ptr;
29013 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
29014 ctx->saved_pc = -1;
29015 ctx->insn_flags = env->insn_flags;
29016 ctx->CP0_Config1 = env->CP0_Config1;
29017 ctx->CP0_Config2 = env->CP0_Config2;
29018 ctx->CP0_Config3 = env->CP0_Config3;
29019 ctx->CP0_Config5 = env->CP0_Config5;
29020 ctx->btarget = 0;
29021 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
29022 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
29023 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
29024 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
29025 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
29026 ctx->PAMask = env->PAMask;
29027 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
29028 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
29029 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
29030 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
29031 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
29032 /* Restore delay slot state from the tb context. */
29033 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
29034 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
29035 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
29036 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
29037 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
29038 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
29039 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
29040 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
29041 ctx->mi = (env->CP0_Config5 >> CP0C5_MI) & 1;
29042 ctx->gi = (env->CP0_Config5 >> CP0C5_GI) & 3;
29043 restore_cpu_state(env, ctx);
29044 #ifdef CONFIG_USER_ONLY
29045 ctx->mem_idx = MIPS_HFLAG_UM;
29046 #else
29047 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
29048 #endif
29049 ctx->default_tcg_memop_mask = (ctx->insn_flags & (ISA_MIPS_R6 |
29050 INSN_LOONGSON3A)) ? MO_UNALN : MO_ALIGN;
29052 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
29053 ctx->hflags);
29056 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
29060 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
29062 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29064 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
29065 ctx->btarget);
29068 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
29069 const CPUBreakpoint *bp)
29071 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29073 save_cpu_state(ctx, 1);
29074 ctx->base.is_jmp = DISAS_NORETURN;
29075 gen_helper_raise_exception_debug(cpu_env);
29077 * The address covered by the breakpoint must be included in
29078 * [tb->pc, tb->pc + tb->size) in order to for it to be
29079 * properly cleared -- thus we increment the PC here so that
29080 * the logic setting tb->size below does the right thing.
29082 ctx->base.pc_next += 4;
29083 return true;
29086 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
29088 CPUMIPSState *env = cs->env_ptr;
29089 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29090 int insn_bytes;
29091 int is_slot;
29093 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
29094 if (ctx->insn_flags & ISA_NANOMIPS32) {
29095 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
29096 insn_bytes = decode_nanomips_opc(env, ctx);
29097 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
29098 ctx->opcode = translator_ldl(env, ctx->base.pc_next);
29099 insn_bytes = 4;
29100 decode_opc(env, ctx);
29101 } else if (ctx->insn_flags & ASE_MICROMIPS) {
29102 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
29103 insn_bytes = decode_micromips_opc(env, ctx);
29104 } else if (ctx->insn_flags & ASE_MIPS16) {
29105 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
29106 insn_bytes = decode_mips16_opc(env, ctx);
29107 } else {
29108 gen_reserved_instruction(ctx);
29109 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
29110 return;
29113 if (ctx->hflags & MIPS_HFLAG_BMASK) {
29114 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
29115 MIPS_HFLAG_FBNSLOT))) {
29117 * Force to generate branch as there is neither delay nor
29118 * forbidden slot.
29120 is_slot = 1;
29122 if ((ctx->hflags & MIPS_HFLAG_M16) &&
29123 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
29125 * Force to generate branch as microMIPS R6 doesn't restrict
29126 * branches in the forbidden slot.
29128 is_slot = 1;
29131 if (is_slot) {
29132 gen_branch(ctx, insn_bytes);
29134 ctx->base.pc_next += insn_bytes;
29136 if (ctx->base.is_jmp != DISAS_NEXT) {
29137 return;
29140 * Execute a branch and its delay slot as a single instruction.
29141 * This is what GDB expects and is consistent with what the
29142 * hardware does (e.g. if a delay slot instruction faults, the
29143 * reported PC is the PC of the branch).
29145 if (ctx->base.singlestep_enabled &&
29146 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
29147 ctx->base.is_jmp = DISAS_TOO_MANY;
29149 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
29150 ctx->base.is_jmp = DISAS_TOO_MANY;
29154 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
29156 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29158 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
29159 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
29160 gen_helper_raise_exception_debug(cpu_env);
29161 } else {
29162 switch (ctx->base.is_jmp) {
29163 case DISAS_STOP:
29164 gen_save_pc(ctx->base.pc_next);
29165 tcg_gen_lookup_and_goto_ptr();
29166 break;
29167 case DISAS_NEXT:
29168 case DISAS_TOO_MANY:
29169 save_cpu_state(ctx, 0);
29170 gen_goto_tb(ctx, 0, ctx->base.pc_next);
29171 break;
29172 case DISAS_EXIT:
29173 tcg_gen_exit_tb(NULL, 0);
29174 break;
29175 case DISAS_NORETURN:
29176 break;
29177 default:
29178 g_assert_not_reached();
29183 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
29185 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
29186 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
29189 static const TranslatorOps mips_tr_ops = {
29190 .init_disas_context = mips_tr_init_disas_context,
29191 .tb_start = mips_tr_tb_start,
29192 .insn_start = mips_tr_insn_start,
29193 .breakpoint_check = mips_tr_breakpoint_check,
29194 .translate_insn = mips_tr_translate_insn,
29195 .tb_stop = mips_tr_tb_stop,
29196 .disas_log = mips_tr_disas_log,
29199 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
29201 DisasContext ctx;
29203 translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
29206 static void fpu_dump_state(CPUMIPSState *env, FILE * f, int flags)
29208 int i;
29209 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
29211 #define printfpr(fp) \
29212 do { \
29213 if (is_fpu64) \
29214 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
29215 " fd:%13g fs:%13g psu: %13g\n", \
29216 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
29217 (double)(fp)->fd, \
29218 (double)(fp)->fs[FP_ENDIAN_IDX], \
29219 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
29220 else { \
29221 fpr_t tmp; \
29222 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
29223 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
29224 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
29225 " fd:%13g fs:%13g psu:%13g\n", \
29226 tmp.w[FP_ENDIAN_IDX], tmp.d, \
29227 (double)tmp.fd, \
29228 (double)tmp.fs[FP_ENDIAN_IDX], \
29229 (double)tmp.fs[!FP_ENDIAN_IDX]); \
29231 } while (0)
29234 qemu_fprintf(f,
29235 "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
29236 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
29237 get_float_exception_flags(&env->active_fpu.fp_status));
29238 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
29239 qemu_fprintf(f, "%3s: ", fregnames[i]);
29240 printfpr(&env->active_fpu.fpr[i]);
29243 #undef printfpr
29246 void mips_cpu_dump_state(CPUState *cs, FILE *f, int flags)
29248 MIPSCPU *cpu = MIPS_CPU(cs);
29249 CPUMIPSState *env = &cpu->env;
29250 int i;
29252 qemu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
29253 " LO=0x" TARGET_FMT_lx " ds %04x "
29254 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
29255 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
29256 env->hflags, env->btarget, env->bcond);
29257 for (i = 0; i < 32; i++) {
29258 if ((i & 3) == 0) {
29259 qemu_fprintf(f, "GPR%02d:", i);
29261 qemu_fprintf(f, " %s " TARGET_FMT_lx,
29262 regnames[i], env->active_tc.gpr[i]);
29263 if ((i & 3) == 3) {
29264 qemu_fprintf(f, "\n");
29268 qemu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x"
29269 TARGET_FMT_lx "\n",
29270 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
29271 qemu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
29272 PRIx64 "\n",
29273 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
29274 qemu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
29275 env->CP0_Config2, env->CP0_Config3);
29276 qemu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
29277 env->CP0_Config4, env->CP0_Config5);
29278 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
29279 fpu_dump_state(env, f, flags);
29283 void mips_tcg_init(void)
29285 int i;
29287 cpu_gpr[0] = NULL;
29288 for (i = 1; i < 32; i++)
29289 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
29290 offsetof(CPUMIPSState,
29291 active_tc.gpr[i]),
29292 regnames[i]);
29293 #if defined(TARGET_MIPS64)
29294 cpu_gpr_hi[0] = NULL;
29296 for (unsigned i = 1; i < 32; i++) {
29297 g_autofree char *rname = g_strdup_printf("%s[hi]", regnames[i]);
29299 cpu_gpr_hi[i] = tcg_global_mem_new_i64(cpu_env,
29300 offsetof(CPUMIPSState,
29301 active_tc.gpr_hi[i]),
29302 rname);
29304 #endif /* !TARGET_MIPS64 */
29305 for (i = 0; i < 32; i++) {
29306 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
29308 fpu_f64[i] = tcg_global_mem_new_i64(cpu_env, off, fregnames[i]);
29310 msa_translate_init();
29311 cpu_PC = tcg_global_mem_new(cpu_env,
29312 offsetof(CPUMIPSState, active_tc.PC), "PC");
29313 for (i = 0; i < MIPS_DSP_ACC; i++) {
29314 cpu_HI[i] = tcg_global_mem_new(cpu_env,
29315 offsetof(CPUMIPSState, active_tc.HI[i]),
29316 regnames_HI[i]);
29317 cpu_LO[i] = tcg_global_mem_new(cpu_env,
29318 offsetof(CPUMIPSState, active_tc.LO[i]),
29319 regnames_LO[i]);
29321 cpu_dspctrl = tcg_global_mem_new(cpu_env,
29322 offsetof(CPUMIPSState,
29323 active_tc.DSPControl),
29324 "DSPControl");
29325 bcond = tcg_global_mem_new(cpu_env,
29326 offsetof(CPUMIPSState, bcond), "bcond");
29327 btarget = tcg_global_mem_new(cpu_env,
29328 offsetof(CPUMIPSState, btarget), "btarget");
29329 hflags = tcg_global_mem_new_i32(cpu_env,
29330 offsetof(CPUMIPSState, hflags), "hflags");
29332 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
29333 offsetof(CPUMIPSState, active_fpu.fcr0),
29334 "fcr0");
29335 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
29336 offsetof(CPUMIPSState, active_fpu.fcr31),
29337 "fcr31");
29338 cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
29339 "lladdr");
29340 cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
29341 "llval");
29343 #if !defined(TARGET_MIPS64)
29344 for (i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
29345 mxu_gpr[i] = tcg_global_mem_new(cpu_env,
29346 offsetof(CPUMIPSState,
29347 active_tc.mxu_gpr[i]),
29348 mxuregnames[i]);
29351 mxu_CR = tcg_global_mem_new(cpu_env,
29352 offsetof(CPUMIPSState, active_tc.mxu_cr),
29353 mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
29354 #endif /* !TARGET_MIPS64 */
29357 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
29358 target_ulong *data)
29360 env->active_tc.PC = data[0];
29361 env->hflags &= ~MIPS_HFLAG_BMASK;
29362 env->hflags |= data[1];
29363 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
29364 case MIPS_HFLAG_BR:
29365 break;
29366 case MIPS_HFLAG_BC:
29367 case MIPS_HFLAG_BL:
29368 case MIPS_HFLAG_B:
29369 env->btarget = data[2];
29370 break;