target/mips: Clean up handling of CP0 register 10
[qemu/ar7.git] / target / mips / translate.c
blob50863cf61f830dac89f1f7ceaafb9d58bfaab55f
1 /*
2 * MIPS emulation for QEMU - main translation routines
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
8 * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
24 #include "qemu/osdep.h"
25 #include "cpu.h"
26 #include "internal.h"
27 #include "disas/disas.h"
28 #include "exec/exec-all.h"
29 #include "tcg-op.h"
30 #include "exec/cpu_ldst.h"
31 #include "hw/mips/cpudevs.h"
33 #include "exec/helper-proto.h"
34 #include "exec/helper-gen.h"
35 #include "hw/semihosting/semihost.h"
37 #include "target/mips/trace.h"
38 #include "trace-tcg.h"
39 #include "exec/translator.h"
40 #include "exec/log.h"
41 #include "qemu/qemu-print.h"
43 #define MIPS_DEBUG_DISAS 0
45 /* MIPS major opcodes */
46 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
48 enum {
49 /* indirect opcode tables */
50 OPC_SPECIAL = (0x00 << 26),
51 OPC_REGIMM = (0x01 << 26),
52 OPC_CP0 = (0x10 << 26),
53 OPC_CP1 = (0x11 << 26),
54 OPC_CP2 = (0x12 << 26),
55 OPC_CP3 = (0x13 << 26),
56 OPC_SPECIAL2 = (0x1C << 26),
57 OPC_SPECIAL3 = (0x1F << 26),
58 /* arithmetic with immediate */
59 OPC_ADDI = (0x08 << 26),
60 OPC_ADDIU = (0x09 << 26),
61 OPC_SLTI = (0x0A << 26),
62 OPC_SLTIU = (0x0B << 26),
63 /* logic with immediate */
64 OPC_ANDI = (0x0C << 26),
65 OPC_ORI = (0x0D << 26),
66 OPC_XORI = (0x0E << 26),
67 OPC_LUI = (0x0F << 26),
68 /* arithmetic with immediate */
69 OPC_DADDI = (0x18 << 26),
70 OPC_DADDIU = (0x19 << 26),
71 /* Jump and branches */
72 OPC_J = (0x02 << 26),
73 OPC_JAL = (0x03 << 26),
74 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
75 OPC_BEQL = (0x14 << 26),
76 OPC_BNE = (0x05 << 26),
77 OPC_BNEL = (0x15 << 26),
78 OPC_BLEZ = (0x06 << 26),
79 OPC_BLEZL = (0x16 << 26),
80 OPC_BGTZ = (0x07 << 26),
81 OPC_BGTZL = (0x17 << 26),
82 OPC_JALX = (0x1D << 26),
83 OPC_DAUI = (0x1D << 26),
84 /* Load and stores */
85 OPC_LDL = (0x1A << 26),
86 OPC_LDR = (0x1B << 26),
87 OPC_LB = (0x20 << 26),
88 OPC_LH = (0x21 << 26),
89 OPC_LWL = (0x22 << 26),
90 OPC_LW = (0x23 << 26),
91 OPC_LWPC = OPC_LW | 0x5,
92 OPC_LBU = (0x24 << 26),
93 OPC_LHU = (0x25 << 26),
94 OPC_LWR = (0x26 << 26),
95 OPC_LWU = (0x27 << 26),
96 OPC_SB = (0x28 << 26),
97 OPC_SH = (0x29 << 26),
98 OPC_SWL = (0x2A << 26),
99 OPC_SW = (0x2B << 26),
100 OPC_SDL = (0x2C << 26),
101 OPC_SDR = (0x2D << 26),
102 OPC_SWR = (0x2E << 26),
103 OPC_LL = (0x30 << 26),
104 OPC_LLD = (0x34 << 26),
105 OPC_LD = (0x37 << 26),
106 OPC_LDPC = OPC_LD | 0x5,
107 OPC_SC = (0x38 << 26),
108 OPC_SCD = (0x3C << 26),
109 OPC_SD = (0x3F << 26),
110 /* Floating point load/store */
111 OPC_LWC1 = (0x31 << 26),
112 OPC_LWC2 = (0x32 << 26),
113 OPC_LDC1 = (0x35 << 26),
114 OPC_LDC2 = (0x36 << 26),
115 OPC_SWC1 = (0x39 << 26),
116 OPC_SWC2 = (0x3A << 26),
117 OPC_SDC1 = (0x3D << 26),
118 OPC_SDC2 = (0x3E << 26),
119 /* Compact Branches */
120 OPC_BLEZALC = (0x06 << 26),
121 OPC_BGEZALC = (0x06 << 26),
122 OPC_BGEUC = (0x06 << 26),
123 OPC_BGTZALC = (0x07 << 26),
124 OPC_BLTZALC = (0x07 << 26),
125 OPC_BLTUC = (0x07 << 26),
126 OPC_BOVC = (0x08 << 26),
127 OPC_BEQZALC = (0x08 << 26),
128 OPC_BEQC = (0x08 << 26),
129 OPC_BLEZC = (0x16 << 26),
130 OPC_BGEZC = (0x16 << 26),
131 OPC_BGEC = (0x16 << 26),
132 OPC_BGTZC = (0x17 << 26),
133 OPC_BLTZC = (0x17 << 26),
134 OPC_BLTC = (0x17 << 26),
135 OPC_BNVC = (0x18 << 26),
136 OPC_BNEZALC = (0x18 << 26),
137 OPC_BNEC = (0x18 << 26),
138 OPC_BC = (0x32 << 26),
139 OPC_BEQZC = (0x36 << 26),
140 OPC_JIC = (0x36 << 26),
141 OPC_BALC = (0x3A << 26),
142 OPC_BNEZC = (0x3E << 26),
143 OPC_JIALC = (0x3E << 26),
144 /* MDMX ASE specific */
145 OPC_MDMX = (0x1E << 26),
146 /* MSA ASE, same as MDMX */
147 OPC_MSA = OPC_MDMX,
148 /* Cache and prefetch */
149 OPC_CACHE = (0x2F << 26),
150 OPC_PREF = (0x33 << 26),
151 /* PC-relative address computation / loads */
152 OPC_PCREL = (0x3B << 26),
155 /* PC-relative address computation / loads */
156 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
157 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
158 enum {
159 /* Instructions determined by bits 19 and 20 */
160 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
161 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
162 OPC_LWUPC = OPC_PCREL | (2 << 19),
164 /* Instructions determined by bits 16 ... 20 */
165 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
166 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
168 /* Other */
169 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
172 /* MIPS special opcodes */
173 #define MASK_SPECIAL(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
175 enum {
176 /* Shifts */
177 OPC_SLL = 0x00 | OPC_SPECIAL,
178 /* NOP is SLL r0, r0, 0 */
179 /* SSNOP is SLL r0, r0, 1 */
180 /* EHB is SLL r0, r0, 3 */
181 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
182 OPC_ROTR = OPC_SRL | (1 << 21),
183 OPC_SRA = 0x03 | OPC_SPECIAL,
184 OPC_SLLV = 0x04 | OPC_SPECIAL,
185 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
186 OPC_ROTRV = OPC_SRLV | (1 << 6),
187 OPC_SRAV = 0x07 | OPC_SPECIAL,
188 OPC_DSLLV = 0x14 | OPC_SPECIAL,
189 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
190 OPC_DROTRV = OPC_DSRLV | (1 << 6),
191 OPC_DSRAV = 0x17 | OPC_SPECIAL,
192 OPC_DSLL = 0x38 | OPC_SPECIAL,
193 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
194 OPC_DROTR = OPC_DSRL | (1 << 21),
195 OPC_DSRA = 0x3B | OPC_SPECIAL,
196 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
197 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
198 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
199 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
200 /* Multiplication / division */
201 OPC_MULT = 0x18 | OPC_SPECIAL,
202 OPC_MULTU = 0x19 | OPC_SPECIAL,
203 OPC_DIV = 0x1A | OPC_SPECIAL,
204 OPC_DIVU = 0x1B | OPC_SPECIAL,
205 OPC_DMULT = 0x1C | OPC_SPECIAL,
206 OPC_DMULTU = 0x1D | OPC_SPECIAL,
207 OPC_DDIV = 0x1E | OPC_SPECIAL,
208 OPC_DDIVU = 0x1F | OPC_SPECIAL,
210 /* 2 registers arithmetic / logic */
211 OPC_ADD = 0x20 | OPC_SPECIAL,
212 OPC_ADDU = 0x21 | OPC_SPECIAL,
213 OPC_SUB = 0x22 | OPC_SPECIAL,
214 OPC_SUBU = 0x23 | OPC_SPECIAL,
215 OPC_AND = 0x24 | OPC_SPECIAL,
216 OPC_OR = 0x25 | OPC_SPECIAL,
217 OPC_XOR = 0x26 | OPC_SPECIAL,
218 OPC_NOR = 0x27 | OPC_SPECIAL,
219 OPC_SLT = 0x2A | OPC_SPECIAL,
220 OPC_SLTU = 0x2B | OPC_SPECIAL,
221 OPC_DADD = 0x2C | OPC_SPECIAL,
222 OPC_DADDU = 0x2D | OPC_SPECIAL,
223 OPC_DSUB = 0x2E | OPC_SPECIAL,
224 OPC_DSUBU = 0x2F | OPC_SPECIAL,
225 /* Jumps */
226 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
227 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
228 /* Traps */
229 OPC_TGE = 0x30 | OPC_SPECIAL,
230 OPC_TGEU = 0x31 | OPC_SPECIAL,
231 OPC_TLT = 0x32 | OPC_SPECIAL,
232 OPC_TLTU = 0x33 | OPC_SPECIAL,
233 OPC_TEQ = 0x34 | OPC_SPECIAL,
234 OPC_TNE = 0x36 | OPC_SPECIAL,
235 /* HI / LO registers load & stores */
236 OPC_MFHI = 0x10 | OPC_SPECIAL,
237 OPC_MTHI = 0x11 | OPC_SPECIAL,
238 OPC_MFLO = 0x12 | OPC_SPECIAL,
239 OPC_MTLO = 0x13 | OPC_SPECIAL,
240 /* Conditional moves */
241 OPC_MOVZ = 0x0A | OPC_SPECIAL,
242 OPC_MOVN = 0x0B | OPC_SPECIAL,
244 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
245 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
247 OPC_MOVCI = 0x01 | OPC_SPECIAL,
249 /* Special */
250 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
251 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
252 OPC_BREAK = 0x0D | OPC_SPECIAL,
253 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
254 OPC_SYNC = 0x0F | OPC_SPECIAL,
256 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
257 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
258 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
259 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
263 * R6 Multiply and Divide instructions have the same opcode
264 * and function field as legacy OPC_MULT[U]/OPC_DIV[U]
266 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
268 enum {
269 R6_OPC_MUL = OPC_MULT | (2 << 6),
270 R6_OPC_MUH = OPC_MULT | (3 << 6),
271 R6_OPC_MULU = OPC_MULTU | (2 << 6),
272 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
273 R6_OPC_DIV = OPC_DIV | (2 << 6),
274 R6_OPC_MOD = OPC_DIV | (3 << 6),
275 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
276 R6_OPC_MODU = OPC_DIVU | (3 << 6),
278 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
279 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
280 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
281 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
282 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
283 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
284 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
285 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
287 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
288 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
289 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
290 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
291 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
293 OPC_LSA = 0x05 | OPC_SPECIAL,
294 OPC_DLSA = 0x15 | OPC_SPECIAL,
297 /* Multiplication variants of the vr54xx. */
298 #define MASK_MUL_VR54XX(op) (MASK_SPECIAL(op) | (op & (0x1F << 6)))
300 enum {
301 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
302 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
303 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
304 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
305 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
306 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
307 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
308 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
309 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
310 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
311 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
312 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
313 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
314 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
317 /* REGIMM (rt field) opcodes */
318 #define MASK_REGIMM(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 16)))
320 enum {
321 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
322 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
323 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
324 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
325 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
326 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
327 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
328 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
329 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
330 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
331 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
332 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
333 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
334 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
335 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
336 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
338 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
339 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
342 /* Special2 opcodes */
343 #define MASK_SPECIAL2(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
345 enum {
346 /* Multiply & xxx operations */
347 OPC_MADD = 0x00 | OPC_SPECIAL2,
348 OPC_MADDU = 0x01 | OPC_SPECIAL2,
349 OPC_MUL = 0x02 | OPC_SPECIAL2,
350 OPC_MSUB = 0x04 | OPC_SPECIAL2,
351 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
352 /* Loongson 2F */
353 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
354 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
355 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
356 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
357 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
358 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
359 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
360 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
361 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
362 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
363 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
364 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
365 /* Misc */
366 OPC_CLZ = 0x20 | OPC_SPECIAL2,
367 OPC_CLO = 0x21 | OPC_SPECIAL2,
368 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
369 OPC_DCLO = 0x25 | OPC_SPECIAL2,
370 /* Special */
371 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
374 /* Special3 opcodes */
375 #define MASK_SPECIAL3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
377 enum {
378 OPC_EXT = 0x00 | OPC_SPECIAL3,
379 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
380 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
381 OPC_DEXT = 0x03 | OPC_SPECIAL3,
382 OPC_INS = 0x04 | OPC_SPECIAL3,
383 OPC_DINSM = 0x05 | OPC_SPECIAL3,
384 OPC_DINSU = 0x06 | OPC_SPECIAL3,
385 OPC_DINS = 0x07 | OPC_SPECIAL3,
386 OPC_FORK = 0x08 | OPC_SPECIAL3,
387 OPC_YIELD = 0x09 | OPC_SPECIAL3,
388 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
389 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
390 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
392 /* Loongson 2E */
393 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
394 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
395 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
396 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
397 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
398 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
399 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
400 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
401 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
402 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
403 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
404 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
406 /* MIPS DSP Load */
407 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
408 /* MIPS DSP Arithmetic */
409 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
410 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
411 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
412 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
413 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
414 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
415 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
416 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
417 /* MIPS DSP GPR-Based Shift Sub-class */
418 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
419 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
420 /* MIPS DSP Multiply Sub-class insns */
421 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
422 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
423 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
424 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
425 /* DSP Bit/Manipulation Sub-class */
426 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
427 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
428 /* MIPS DSP Append Sub-class */
429 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
430 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
431 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
432 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
433 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
435 /* EVA */
436 OPC_LWLE = 0x19 | OPC_SPECIAL3,
437 OPC_LWRE = 0x1A | OPC_SPECIAL3,
438 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
439 OPC_SBE = 0x1C | OPC_SPECIAL3,
440 OPC_SHE = 0x1D | OPC_SPECIAL3,
441 OPC_SCE = 0x1E | OPC_SPECIAL3,
442 OPC_SWE = 0x1F | OPC_SPECIAL3,
443 OPC_SWLE = 0x21 | OPC_SPECIAL3,
444 OPC_SWRE = 0x22 | OPC_SPECIAL3,
445 OPC_PREFE = 0x23 | OPC_SPECIAL3,
446 OPC_LBUE = 0x28 | OPC_SPECIAL3,
447 OPC_LHUE = 0x29 | OPC_SPECIAL3,
448 OPC_LBE = 0x2C | OPC_SPECIAL3,
449 OPC_LHE = 0x2D | OPC_SPECIAL3,
450 OPC_LLE = 0x2E | OPC_SPECIAL3,
451 OPC_LWE = 0x2F | OPC_SPECIAL3,
453 /* R6 */
454 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
455 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
456 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
457 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
458 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
459 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
462 /* BSHFL opcodes */
463 #define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
465 enum {
466 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
467 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
468 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
469 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
470 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
471 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
472 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
473 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
476 /* DBSHFL opcodes */
477 #define MASK_DBSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
479 enum {
480 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
481 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
482 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
483 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
484 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
485 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
486 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
487 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
488 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
489 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
490 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
493 /* MIPS DSP REGIMM opcodes */
494 enum {
495 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
496 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
499 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
500 /* MIPS DSP Load */
501 enum {
502 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
503 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
504 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
505 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
508 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
509 enum {
510 /* MIPS DSP Arithmetic Sub-class */
511 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
512 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
513 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
514 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
515 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
516 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
517 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
518 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
519 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
520 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
521 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
522 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
523 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
524 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
525 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
526 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
527 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
528 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
529 /* MIPS DSP Multiply Sub-class insns */
530 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
531 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
532 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
533 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
534 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
535 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
538 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
539 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
540 enum {
541 /* MIPS DSP Arithmetic Sub-class */
542 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
543 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
544 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
545 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
546 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
547 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
548 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
549 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
550 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
551 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
552 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
553 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
554 /* MIPS DSP Multiply Sub-class insns */
555 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
556 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
557 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
558 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
561 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
562 enum {
563 /* MIPS DSP Arithmetic Sub-class */
564 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
565 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
566 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
567 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
568 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
569 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
570 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
571 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
572 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
573 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
574 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
575 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
576 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
577 /* DSP Bit/Manipulation Sub-class */
578 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
579 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
580 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
581 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
582 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
585 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
586 enum {
587 /* MIPS DSP Arithmetic Sub-class */
588 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
589 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
590 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
591 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
592 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
593 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
594 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
595 /* DSP Compare-Pick Sub-class */
596 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
597 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
598 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
599 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
600 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
601 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
602 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
603 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
604 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
605 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
606 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
607 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
608 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
609 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
610 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
613 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
614 enum {
615 /* MIPS DSP GPR-Based Shift Sub-class */
616 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
617 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
618 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
619 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
620 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
621 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
622 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
623 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
624 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
625 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
626 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
627 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
628 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
629 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
630 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
631 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
632 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
633 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
634 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
635 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
636 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
637 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
640 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
641 enum {
642 /* MIPS DSP Multiply Sub-class insns */
643 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
644 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
645 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
646 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
647 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
648 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
649 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
650 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
651 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
652 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
653 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
654 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
655 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
656 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
657 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
658 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
659 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
660 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
661 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
662 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
663 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
664 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
667 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
668 enum {
669 /* DSP Bit/Manipulation Sub-class */
670 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
673 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
674 enum {
675 /* MIPS DSP Append Sub-class */
676 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
677 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
678 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
681 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
682 enum {
683 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
684 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
685 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
686 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
687 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
688 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
689 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
690 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
691 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
692 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
693 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
694 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
695 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
696 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
697 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
698 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
699 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
700 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
703 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
704 enum {
705 /* MIPS DSP Arithmetic Sub-class */
706 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
707 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
708 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
709 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
710 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
711 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
712 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
713 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
714 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
715 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
716 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
717 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
718 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
719 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
720 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
721 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
722 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
723 /* DSP Bit/Manipulation Sub-class */
724 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
725 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
726 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
727 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
728 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
729 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
732 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
733 enum {
734 /* MIPS DSP Multiply Sub-class insns */
735 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
736 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
737 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
738 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
739 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
740 /* MIPS DSP Arithmetic Sub-class */
741 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
742 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
743 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
744 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
745 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
746 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
747 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
748 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
749 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
750 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
751 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
752 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
753 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
754 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
755 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
756 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
757 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
758 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
759 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
760 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
761 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
764 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
765 enum {
766 /* DSP Compare-Pick Sub-class */
767 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
768 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
769 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
770 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
771 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
772 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
773 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
774 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
775 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
776 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
777 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
778 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
779 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
780 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
781 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
782 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
783 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
784 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
785 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
786 /* MIPS DSP Arithmetic Sub-class */
787 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
788 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
789 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
790 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
791 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
792 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
793 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
794 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
797 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
798 enum {
799 /* DSP Append Sub-class */
800 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
801 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
802 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
803 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
806 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
807 enum {
808 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
809 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
810 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
811 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
812 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
813 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
814 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
815 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
816 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
817 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
818 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
819 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
820 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
821 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
822 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
823 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
824 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
825 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
826 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
827 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
828 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
829 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
832 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
833 enum {
834 /* DSP Bit/Manipulation Sub-class */
835 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
838 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
839 enum {
840 /* MIPS DSP Multiply Sub-class insns */
841 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
842 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
843 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
844 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
845 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
846 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
847 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
848 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
849 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
850 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
851 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
852 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
853 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
854 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
855 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
856 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
857 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
858 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
859 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
860 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
861 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
862 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
863 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
864 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
865 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
866 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
869 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
870 enum {
871 /* MIPS DSP GPR-Based Shift Sub-class */
872 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
873 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
874 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
875 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
876 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
877 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
878 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
879 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
880 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
881 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
882 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
883 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
884 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
885 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
886 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
887 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
888 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
889 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
890 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
891 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
892 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
893 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
894 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
895 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
896 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
897 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
900 /* Coprocessor 0 (rs field) */
901 #define MASK_CP0(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
903 enum {
904 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
905 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
906 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
907 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
908 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
909 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
910 OPC_MFTR = (0x08 << 21) | OPC_CP0,
911 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
912 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
913 OPC_MTTR = (0x0C << 21) | OPC_CP0,
914 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
915 OPC_C0 = (0x10 << 21) | OPC_CP0,
916 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
917 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
918 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
919 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
920 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
921 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
922 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
923 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
924 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
925 OPC_C0_A = (0x1A << 21) | OPC_CP0,
926 OPC_C0_B = (0x1B << 21) | OPC_CP0,
927 OPC_C0_C = (0x1C << 21) | OPC_CP0,
928 OPC_C0_D = (0x1D << 21) | OPC_CP0,
929 OPC_C0_E = (0x1E << 21) | OPC_CP0,
930 OPC_C0_F = (0x1F << 21) | OPC_CP0,
933 /* MFMC0 opcodes */
934 #define MASK_MFMC0(op) (MASK_CP0(op) | (op & 0xFFFF))
936 enum {
937 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
938 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
939 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
940 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
941 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
942 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
943 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
944 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
947 /* Coprocessor 0 (with rs == C0) */
948 #define MASK_C0(op) (MASK_CP0(op) | (op & 0x3F))
950 enum {
951 OPC_TLBR = 0x01 | OPC_C0,
952 OPC_TLBWI = 0x02 | OPC_C0,
953 OPC_TLBINV = 0x03 | OPC_C0,
954 OPC_TLBINVF = 0x04 | OPC_C0,
955 OPC_TLBWR = 0x06 | OPC_C0,
956 OPC_TLBP = 0x08 | OPC_C0,
957 OPC_RFE = 0x10 | OPC_C0,
958 OPC_ERET = 0x18 | OPC_C0,
959 OPC_DERET = 0x1F | OPC_C0,
960 OPC_WAIT = 0x20 | OPC_C0,
963 /* Coprocessor 1 (rs field) */
964 #define MASK_CP1(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
966 /* Values for the fmt field in FP instructions */
967 enum {
968 /* 0 - 15 are reserved */
969 FMT_S = 16, /* single fp */
970 FMT_D = 17, /* double fp */
971 FMT_E = 18, /* extended fp */
972 FMT_Q = 19, /* quad fp */
973 FMT_W = 20, /* 32-bit fixed */
974 FMT_L = 21, /* 64-bit fixed */
975 FMT_PS = 22, /* paired single fp */
976 /* 23 - 31 are reserved */
979 enum {
980 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
981 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
982 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
983 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
984 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
985 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
986 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
987 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
988 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
989 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
990 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
991 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
992 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
993 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
994 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
995 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
996 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
997 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
998 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
999 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
1000 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
1001 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
1002 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
1003 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
1004 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
1005 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
1006 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
1007 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
1008 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
1009 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
1012 #define MASK_CP1_FUNC(op) (MASK_CP1(op) | (op & 0x3F))
1013 #define MASK_BC1(op) (MASK_CP1(op) | (op & (0x3 << 16)))
1015 enum {
1016 OPC_BC1F = (0x00 << 16) | OPC_BC1,
1017 OPC_BC1T = (0x01 << 16) | OPC_BC1,
1018 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
1019 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
1022 enum {
1023 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
1024 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
1027 enum {
1028 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
1029 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
1032 #define MASK_CP2(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
1034 enum {
1035 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1036 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1037 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1038 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1039 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1040 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1041 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1042 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1043 OPC_BC2 = (0x08 << 21) | OPC_CP2,
1044 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1045 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1048 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1050 enum {
1051 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1052 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1053 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1054 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1055 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1056 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1057 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1058 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1060 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1061 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1062 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1063 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1064 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1065 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1066 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1067 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1069 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1070 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1071 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1072 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1073 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1074 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1075 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1076 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1078 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1079 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1080 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1081 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1082 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1083 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1084 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1085 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1087 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1088 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1089 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1090 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1091 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1092 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1094 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1095 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1096 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1097 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1098 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1099 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1101 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1102 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1103 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1104 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1105 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1106 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1108 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1109 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1110 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1111 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1112 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1113 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1115 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1116 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1117 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1118 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1119 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1120 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1122 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1123 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1124 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1125 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1126 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1127 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1129 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1130 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1131 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1132 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1133 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1134 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1136 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1137 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1138 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1139 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1140 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1141 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1145 #define MASK_CP3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1147 enum {
1148 OPC_LWXC1 = 0x00 | OPC_CP3,
1149 OPC_LDXC1 = 0x01 | OPC_CP3,
1150 OPC_LUXC1 = 0x05 | OPC_CP3,
1151 OPC_SWXC1 = 0x08 | OPC_CP3,
1152 OPC_SDXC1 = 0x09 | OPC_CP3,
1153 OPC_SUXC1 = 0x0D | OPC_CP3,
1154 OPC_PREFX = 0x0F | OPC_CP3,
1155 OPC_ALNV_PS = 0x1E | OPC_CP3,
1156 OPC_MADD_S = 0x20 | OPC_CP3,
1157 OPC_MADD_D = 0x21 | OPC_CP3,
1158 OPC_MADD_PS = 0x26 | OPC_CP3,
1159 OPC_MSUB_S = 0x28 | OPC_CP3,
1160 OPC_MSUB_D = 0x29 | OPC_CP3,
1161 OPC_MSUB_PS = 0x2E | OPC_CP3,
1162 OPC_NMADD_S = 0x30 | OPC_CP3,
1163 OPC_NMADD_D = 0x31 | OPC_CP3,
1164 OPC_NMADD_PS = 0x36 | OPC_CP3,
1165 OPC_NMSUB_S = 0x38 | OPC_CP3,
1166 OPC_NMSUB_D = 0x39 | OPC_CP3,
1167 OPC_NMSUB_PS = 0x3E | OPC_CP3,
1170 /* MSA Opcodes */
1171 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1172 enum {
1173 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1174 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1175 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1176 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1177 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1178 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1179 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1180 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1181 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1182 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1183 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1184 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1185 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1186 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1187 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1188 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1189 OPC_MSA_ELM = 0x19 | OPC_MSA,
1190 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1191 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1192 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1193 OPC_MSA_VEC = 0x1E | OPC_MSA,
1195 /* MI10 instruction */
1196 OPC_LD_B = (0x20) | OPC_MSA,
1197 OPC_LD_H = (0x21) | OPC_MSA,
1198 OPC_LD_W = (0x22) | OPC_MSA,
1199 OPC_LD_D = (0x23) | OPC_MSA,
1200 OPC_ST_B = (0x24) | OPC_MSA,
1201 OPC_ST_H = (0x25) | OPC_MSA,
1202 OPC_ST_W = (0x26) | OPC_MSA,
1203 OPC_ST_D = (0x27) | OPC_MSA,
1206 enum {
1207 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1208 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1209 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1210 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1211 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1212 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1213 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1214 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1215 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1216 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1217 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1218 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1219 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1221 /* I8 instruction */
1222 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1223 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1224 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1225 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1226 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1227 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1228 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1229 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1230 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1231 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1233 /* VEC/2R/2RF instruction */
1234 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1235 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1236 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1237 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1238 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1239 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1240 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1242 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1243 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1245 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1246 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1247 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1248 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1249 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1251 /* 2RF instruction df(bit 16) = _w, _d */
1252 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1253 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1254 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1255 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1256 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1257 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1258 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1259 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1260 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1261 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1262 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1263 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1264 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1265 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1266 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1267 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1269 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1270 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1271 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1272 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1273 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1274 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1275 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1276 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1277 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1278 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1279 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1280 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1281 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1282 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1283 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1284 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1285 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1286 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1287 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1288 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1289 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1290 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1291 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1292 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1293 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1294 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1295 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1296 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1297 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1298 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1299 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1300 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1301 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1302 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1303 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1304 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1305 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1306 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1307 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1308 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1309 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1310 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1311 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1312 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1313 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1314 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1315 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1316 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1317 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1318 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1319 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1320 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1321 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1322 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1323 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1324 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1325 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1326 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1327 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1328 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1329 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1330 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1331 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1332 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1334 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1335 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1336 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1337 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1338 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1339 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1340 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1341 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1342 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1343 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1345 /* 3RF instruction _df(bit 21) = _w, _d */
1346 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1347 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1348 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1349 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1350 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1351 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1352 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1353 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1354 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1355 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1356 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1357 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1358 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1359 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1360 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1361 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1362 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1363 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1364 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1365 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1366 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1367 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1368 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1369 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1370 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1371 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1372 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1373 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1374 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1375 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1376 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1377 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1378 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1379 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1380 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1381 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1382 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1383 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1384 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1385 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1386 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1388 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1389 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1390 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1391 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1392 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1393 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1394 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1395 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1396 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1397 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1398 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1399 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1400 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1406 * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
1407 * ============================================
1410 * MXU (full name: MIPS eXtension/enhanced Unit) is a SIMD extension of MIPS32
1411 * instructions set. It is designed to fit the needs of signal, graphical and
1412 * video processing applications. MXU instruction set is used in Xburst family
1413 * of microprocessors by Ingenic.
1415 * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
1416 * the control register.
1419 * The notation used in MXU assembler mnemonics
1420 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1422 * Register operands:
1424 * XRa, XRb, XRc, XRd - MXU registers
1425 * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
1427 * Non-register operands:
1429 * aptn1 - 1-bit accumulate add/subtract pattern
1430 * aptn2 - 2-bit accumulate add/subtract pattern
1431 * eptn2 - 2-bit execute add/subtract pattern
1432 * optn2 - 2-bit operand pattern
1433 * optn3 - 3-bit operand pattern
1434 * sft4 - 4-bit shift amount
1435 * strd2 - 2-bit stride amount
1437 * Prefixes:
1439 * Level of parallelism: Operand size:
1440 * S - single operation at a time 32 - word
1441 * D - two operations in parallel 16 - half word
1442 * Q - four operations in parallel 8 - byte
1444 * Operations:
1446 * ADD - Add or subtract
1447 * ADDC - Add with carry-in
1448 * ACC - Accumulate
1449 * ASUM - Sum together then accumulate (add or subtract)
1450 * ASUMC - Sum together then accumulate (add or subtract) with carry-in
1451 * AVG - Average between 2 operands
1452 * ABD - Absolute difference
1453 * ALN - Align data
1454 * AND - Logical bitwise 'and' operation
1455 * CPS - Copy sign
1456 * EXTR - Extract bits
1457 * I2M - Move from GPR register to MXU register
1458 * LDD - Load data from memory to XRF
1459 * LDI - Load data from memory to XRF (and increase the address base)
1460 * LUI - Load unsigned immediate
1461 * MUL - Multiply
1462 * MULU - Unsigned multiply
1463 * MADD - 64-bit operand add 32x32 product
1464 * MSUB - 64-bit operand subtract 32x32 product
1465 * MAC - Multiply and accumulate (add or subtract)
1466 * MAD - Multiply and add or subtract
1467 * MAX - Maximum between 2 operands
1468 * MIN - Minimum between 2 operands
1469 * M2I - Move from MXU register to GPR register
1470 * MOVZ - Move if zero
1471 * MOVN - Move if non-zero
1472 * NOR - Logical bitwise 'nor' operation
1473 * OR - Logical bitwise 'or' operation
1474 * STD - Store data from XRF to memory
1475 * SDI - Store data from XRF to memory (and increase the address base)
1476 * SLT - Set of less than comparison
1477 * SAD - Sum of absolute differences
1478 * SLL - Logical shift left
1479 * SLR - Logical shift right
1480 * SAR - Arithmetic shift right
1481 * SAT - Saturation
1482 * SFL - Shuffle
1483 * SCOP - Calculate x’s scope (-1, means x<0; 0, means x==0; 1, means x>0)
1484 * XOR - Logical bitwise 'exclusive or' operation
1486 * Suffixes:
1488 * E - Expand results
1489 * F - Fixed point multiplication
1490 * L - Low part result
1491 * R - Doing rounding
1492 * V - Variable instead of immediate
1493 * W - Combine above L and V
1496 * The list of MXU instructions grouped by functionality
1497 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1499 * Load/Store instructions Multiplication instructions
1500 * ----------------------- ---------------------------
1502 * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
1503 * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
1504 * S32LDDV XRa, Rb, rc, strd2 S32MSUB XRa, XRd, Rs, Rt
1505 * S32STDV XRa, Rb, rc, strd2 S32MSUBU XRa, XRd, Rs, Rt
1506 * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
1507 * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
1508 * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
1509 * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
1510 * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
1511 * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
1512 * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
1513 * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
1514 * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
1515 * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
1516 * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
1517 * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
1518 * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
1519 * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
1520 * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
1521 * S16SDI XRa, Rb, s10, eptn2
1522 * S8LDD XRa, Rb, s8, eptn3
1523 * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
1524 * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
1525 * S8SDI XRa, Rb, s8, eptn3
1526 * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
1527 * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
1528 * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
1529 * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
1530 * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
1531 * S32CPS XRa, XRb, XRc
1532 * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
1533 * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
1534 * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
1535 * D16ASUM XRa, XRb, XRc, XRd, eptn2
1536 * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
1537 * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
1538 * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
1539 * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
1540 * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
1541 * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
1542 * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
1543 * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
1544 * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
1545 * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
1546 * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
1547 * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
1548 * Q8SLT XRa, XRb, XRc
1549 * Q8SLTU XRa, XRb, XRc
1550 * Q8MOVZ XRa, XRb, XRc Shift instructions
1551 * Q8MOVN XRa, XRb, XRc ------------------
1553 * D32SLL XRa, XRb, XRc, XRd, sft4
1554 * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
1555 * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
1556 * D32SARL XRa, XRb, XRc, sft4
1557 * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
1558 * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
1559 * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
1560 * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
1561 * Q16SLL XRa, XRb, XRc, XRd, sft4
1562 * Q16SLR XRa, XRb, XRc, XRd, sft4
1563 * Miscellaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
1564 * ------------------------- Q16SLLV XRa, XRb, Rb
1565 * Q16SLRV XRa, XRb, Rb
1566 * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
1567 * S32ALN XRa, XRb, XRc, Rb
1568 * S32ALNI XRa, XRb, XRc, s3
1569 * S32LUI XRa, s8, optn3 Move instructions
1570 * S32EXTR XRa, XRb, Rb, bits5 -----------------
1571 * S32EXTRV XRa, XRb, Rs, Rt
1572 * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
1573 * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
1576 * The opcode organization of MXU instructions
1577 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1579 * The bits 31..26 of all MXU instructions are equal to 0x1C (also referred
1580 * as opcode SPECIAL2 in the base MIPS ISA). The organization and meaning of
1581 * other bits up to the instruction level is as follows:
1583 * bits
1584 * 05..00
1586 * ┌─ 000000 ─ OPC_MXU_S32MADD
1587 * ├─ 000001 ─ OPC_MXU_S32MADDU
1588 * ├─ 000010 ─ <not assigned> (non-MXU OPC_MUL)
1589 * │
1590 * │ 20..18
1591 * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
1592 * │ ├─ 001 ─ OPC_MXU_S32MIN
1593 * │ ├─ 010 ─ OPC_MXU_D16MAX
1594 * │ ├─ 011 ─ OPC_MXU_D16MIN
1595 * │ ├─ 100 ─ OPC_MXU_Q8MAX
1596 * │ ├─ 101 ─ OPC_MXU_Q8MIN
1597 * │ ├─ 110 ─ OPC_MXU_Q8SLT
1598 * │ └─ 111 ─ OPC_MXU_Q8SLTU
1599 * ├─ 000100 ─ OPC_MXU_S32MSUB
1600 * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
1601 * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
1602 * │ ├─ 001 ─ OPC_MXU_D16SLT
1603 * │ ├─ 010 ─ OPC_MXU_D16AVG
1604 * │ ├─ 011 ─ OPC_MXU_D16AVGR
1605 * │ ├─ 100 ─ OPC_MXU_Q8AVG
1606 * │ ├─ 101 ─ OPC_MXU_Q8AVGR
1607 * │ └─ 111 ─ OPC_MXU_Q8ADD
1608 * │
1609 * │ 20..18
1610 * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
1611 * │ ├─ 010 ─ OPC_MXU_D16CPS
1612 * │ ├─ 100 ─ OPC_MXU_Q8ABD
1613 * │ └─ 110 ─ OPC_MXU_Q16SAT
1614 * ├─ 001000 ─ OPC_MXU_D16MUL
1615 * │ 25..24
1616 * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
1617 * │ └─ 01 ─ OPC_MXU_D16MULE
1618 * ├─ 001010 ─ OPC_MXU_D16MAC
1619 * ├─ 001011 ─ OPC_MXU_D16MACF
1620 * ├─ 001100 ─ OPC_MXU_D16MADL
1621 * ├─ 001101 ─ OPC_MXU_S16MAD
1622 * ├─ 001110 ─ OPC_MXU_Q16ADD
1623 * ├─ 001111 ─ OPC_MXU_D16MACE 23
1624 * │ ┌─ 0 ─ OPC_MXU_S32LDD
1625 * ├─ 010000 ─ OPC_MXU__POOL04 ─┴─ 1 ─ OPC_MXU_S32LDDR
1626 * │
1627 * │ 23
1628 * ├─ 010001 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32STD
1629 * │ └─ 1 ─ OPC_MXU_S32STDR
1630 * │
1631 * │ 13..10
1632 * ├─ 010010 ─ OPC_MXU__POOL06 ─┬─ 0000 ─ OPC_MXU_S32LDDV
1633 * │ └─ 0001 ─ OPC_MXU_S32LDDVR
1634 * │
1635 * │ 13..10
1636 * ├─ 010011 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32STDV
1637 * │ └─ 0001 ─ OPC_MXU_S32STDVR
1638 * │
1639 * │ 23
1640 * ├─ 010100 ─ OPC_MXU__POOL08 ─┬─ 0 ─ OPC_MXU_S32LDI
1641 * │ └─ 1 ─ OPC_MXU_S32LDIR
1642 * │
1643 * │ 23
1644 * ├─ 010101 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32SDI
1645 * │ └─ 1 ─ OPC_MXU_S32SDIR
1646 * │
1647 * │ 13..10
1648 * ├─ 010110 ─ OPC_MXU__POOL10 ─┬─ 0000 ─ OPC_MXU_S32LDIV
1649 * │ └─ 0001 ─ OPC_MXU_S32LDIVR
1650 * │
1651 * │ 13..10
1652 * ├─ 010111 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32SDIV
1653 * │ └─ 0001 ─ OPC_MXU_S32SDIVR
1654 * ├─ 011000 ─ OPC_MXU_D32ADD
1655 * │ 23..22
1656 * MXU ├─ 011001 ─ OPC_MXU__POOL12 ─┬─ 00 ─ OPC_MXU_D32ACC
1657 * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
1658 * │ └─ 10 ─ OPC_MXU_D32ASUM
1659 * ├─ 011010 ─ <not assigned>
1660 * │ 23..22
1661 * ├─ 011011 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_Q16ACC
1662 * │ ├─ 01 ─ OPC_MXU_Q16ACCM
1663 * │ └─ 10 ─ OPC_MXU_Q16ASUM
1664 * │
1665 * │ 23..22
1666 * ├─ 011100 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q8ADDE
1667 * │ ├─ 01 ─ OPC_MXU_D8SUM
1668 * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
1669 * ├─ 011110 ─ <not assigned>
1670 * ├─ 011111 ─ <not assigned>
1671 * ├─ 100000 ─ <not assigned> (overlaps with CLZ)
1672 * ├─ 100001 ─ <not assigned> (overlaps with CLO)
1673 * ├─ 100010 ─ OPC_MXU_S8LDD
1674 * ├─ 100011 ─ OPC_MXU_S8STD 15..14
1675 * ├─ 100100 ─ OPC_MXU_S8LDI ┌─ 00 ─ OPC_MXU_S32MUL
1676 * ├─ 100101 ─ OPC_MXU_S8SDI ├─ 00 ─ OPC_MXU_S32MULU
1677 * │ ├─ 00 ─ OPC_MXU_S32EXTR
1678 * ├─ 100110 ─ OPC_MXU__POOL15 ─┴─ 00 ─ OPC_MXU_S32EXTRV
1679 * │
1680 * │ 20..18
1681 * ├─ 100111 ─ OPC_MXU__POOL16 ─┬─ 000 ─ OPC_MXU_D32SARW
1682 * │ ├─ 001 ─ OPC_MXU_S32ALN
1683 * │ ├─ 010 ─ OPC_MXU_S32ALNI
1684 * │ ├─ 011 ─ OPC_MXU_S32LUI
1685 * │ ├─ 100 ─ OPC_MXU_S32NOR
1686 * │ ├─ 101 ─ OPC_MXU_S32AND
1687 * │ ├─ 110 ─ OPC_MXU_S32OR
1688 * │ └─ 111 ─ OPC_MXU_S32XOR
1689 * │
1690 * │ 7..5
1691 * ├─ 101000 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_LXB
1692 * │ ├─ 001 ─ OPC_MXU_LXH
1693 * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_LXW
1694 * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_LXBU
1695 * ├─ 101011 ─ OPC_MXU_S16STD └─ 101 ─ OPC_MXU_LXHU
1696 * ├─ 101100 ─ OPC_MXU_S16LDI
1697 * ├─ 101101 ─ OPC_MXU_S16SDI
1698 * ├─ 101110 ─ OPC_MXU_S32M2I
1699 * ├─ 101111 ─ OPC_MXU_S32I2M
1700 * ├─ 110000 ─ OPC_MXU_D32SLL
1701 * ├─ 110001 ─ OPC_MXU_D32SLR 20..18
1702 * ├─ 110010 ─ OPC_MXU_D32SARL ┌─ 000 ─ OPC_MXU_D32SLLV
1703 * ├─ 110011 ─ OPC_MXU_D32SAR ├─ 001 ─ OPC_MXU_D32SLRV
1704 * ├─ 110100 ─ OPC_MXU_Q16SLL ├─ 010 ─ OPC_MXU_D32SARV
1705 * ├─ 110101 ─ OPC_MXU_Q16SLR ├─ 011 ─ OPC_MXU_Q16SLLV
1706 * │ ├─ 100 ─ OPC_MXU_Q16SLRV
1707 * ├─ 110110 ─ OPC_MXU__POOL18 ─┴─ 101 ─ OPC_MXU_Q16SARV
1708 * │
1709 * ├─ 110111 ─ OPC_MXU_Q16SAR
1710 * │ 23..22
1711 * ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL
1712 * │ └─ 01 ─ OPC_MXU_Q8MULSU
1713 * │
1714 * │ 20..18
1715 * ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
1716 * │ ├─ 001 ─ OPC_MXU_Q8MOVN
1717 * │ ├─ 010 ─ OPC_MXU_D16MOVZ
1718 * │ ├─ 011 ─ OPC_MXU_D16MOVN
1719 * │ ├─ 100 ─ OPC_MXU_S32MOVZ
1720 * │ └─ 101 ─ OPC_MXU_S32MOVN
1721 * │
1722 * │ 23..22
1723 * ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC
1724 * │ └─ 10 ─ OPC_MXU_Q8MACSU
1725 * ├─ 111011 ─ OPC_MXU_Q16SCOP
1726 * ├─ 111100 ─ OPC_MXU_Q8MADL
1727 * ├─ 111101 ─ OPC_MXU_S32SFL
1728 * ├─ 111110 ─ OPC_MXU_Q8SAD
1729 * └─ 111111 ─ <not assigned> (overlaps with SDBBP)
1732 * Compiled after:
1734 * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
1735 * Programming Manual", Ingenic Semiconductor Co, Ltd., revision June 2, 2017
1738 enum {
1739 OPC_MXU_S32MADD = 0x00,
1740 OPC_MXU_S32MADDU = 0x01,
1741 OPC__MXU_MUL = 0x02,
1742 OPC_MXU__POOL00 = 0x03,
1743 OPC_MXU_S32MSUB = 0x04,
1744 OPC_MXU_S32MSUBU = 0x05,
1745 OPC_MXU__POOL01 = 0x06,
1746 OPC_MXU__POOL02 = 0x07,
1747 OPC_MXU_D16MUL = 0x08,
1748 OPC_MXU__POOL03 = 0x09,
1749 OPC_MXU_D16MAC = 0x0A,
1750 OPC_MXU_D16MACF = 0x0B,
1751 OPC_MXU_D16MADL = 0x0C,
1752 OPC_MXU_S16MAD = 0x0D,
1753 OPC_MXU_Q16ADD = 0x0E,
1754 OPC_MXU_D16MACE = 0x0F,
1755 OPC_MXU__POOL04 = 0x10,
1756 OPC_MXU__POOL05 = 0x11,
1757 OPC_MXU__POOL06 = 0x12,
1758 OPC_MXU__POOL07 = 0x13,
1759 OPC_MXU__POOL08 = 0x14,
1760 OPC_MXU__POOL09 = 0x15,
1761 OPC_MXU__POOL10 = 0x16,
1762 OPC_MXU__POOL11 = 0x17,
1763 OPC_MXU_D32ADD = 0x18,
1764 OPC_MXU__POOL12 = 0x19,
1765 /* not assigned 0x1A */
1766 OPC_MXU__POOL13 = 0x1B,
1767 OPC_MXU__POOL14 = 0x1C,
1768 OPC_MXU_Q8ACCE = 0x1D,
1769 /* not assigned 0x1E */
1770 /* not assigned 0x1F */
1771 /* not assigned 0x20 */
1772 /* not assigned 0x21 */
1773 OPC_MXU_S8LDD = 0x22,
1774 OPC_MXU_S8STD = 0x23,
1775 OPC_MXU_S8LDI = 0x24,
1776 OPC_MXU_S8SDI = 0x25,
1777 OPC_MXU__POOL15 = 0x26,
1778 OPC_MXU__POOL16 = 0x27,
1779 OPC_MXU__POOL17 = 0x28,
1780 /* not assigned 0x29 */
1781 OPC_MXU_S16LDD = 0x2A,
1782 OPC_MXU_S16STD = 0x2B,
1783 OPC_MXU_S16LDI = 0x2C,
1784 OPC_MXU_S16SDI = 0x2D,
1785 OPC_MXU_S32M2I = 0x2E,
1786 OPC_MXU_S32I2M = 0x2F,
1787 OPC_MXU_D32SLL = 0x30,
1788 OPC_MXU_D32SLR = 0x31,
1789 OPC_MXU_D32SARL = 0x32,
1790 OPC_MXU_D32SAR = 0x33,
1791 OPC_MXU_Q16SLL = 0x34,
1792 OPC_MXU_Q16SLR = 0x35,
1793 OPC_MXU__POOL18 = 0x36,
1794 OPC_MXU_Q16SAR = 0x37,
1795 OPC_MXU__POOL19 = 0x38,
1796 OPC_MXU__POOL20 = 0x39,
1797 OPC_MXU__POOL21 = 0x3A,
1798 OPC_MXU_Q16SCOP = 0x3B,
1799 OPC_MXU_Q8MADL = 0x3C,
1800 OPC_MXU_S32SFL = 0x3D,
1801 OPC_MXU_Q8SAD = 0x3E,
1802 /* not assigned 0x3F */
1807 * MXU pool 00
1809 enum {
1810 OPC_MXU_S32MAX = 0x00,
1811 OPC_MXU_S32MIN = 0x01,
1812 OPC_MXU_D16MAX = 0x02,
1813 OPC_MXU_D16MIN = 0x03,
1814 OPC_MXU_Q8MAX = 0x04,
1815 OPC_MXU_Q8MIN = 0x05,
1816 OPC_MXU_Q8SLT = 0x06,
1817 OPC_MXU_Q8SLTU = 0x07,
1821 * MXU pool 01
1823 enum {
1824 OPC_MXU_S32SLT = 0x00,
1825 OPC_MXU_D16SLT = 0x01,
1826 OPC_MXU_D16AVG = 0x02,
1827 OPC_MXU_D16AVGR = 0x03,
1828 OPC_MXU_Q8AVG = 0x04,
1829 OPC_MXU_Q8AVGR = 0x05,
1830 OPC_MXU_Q8ADD = 0x07,
1834 * MXU pool 02
1836 enum {
1837 OPC_MXU_S32CPS = 0x00,
1838 OPC_MXU_D16CPS = 0x02,
1839 OPC_MXU_Q8ABD = 0x04,
1840 OPC_MXU_Q16SAT = 0x06,
1844 * MXU pool 03
1846 enum {
1847 OPC_MXU_D16MULF = 0x00,
1848 OPC_MXU_D16MULE = 0x01,
1852 * MXU pool 04
1854 enum {
1855 OPC_MXU_S32LDD = 0x00,
1856 OPC_MXU_S32LDDR = 0x01,
1860 * MXU pool 05
1862 enum {
1863 OPC_MXU_S32STD = 0x00,
1864 OPC_MXU_S32STDR = 0x01,
1868 * MXU pool 06
1870 enum {
1871 OPC_MXU_S32LDDV = 0x00,
1872 OPC_MXU_S32LDDVR = 0x01,
1876 * MXU pool 07
1878 enum {
1879 OPC_MXU_S32STDV = 0x00,
1880 OPC_MXU_S32STDVR = 0x01,
1884 * MXU pool 08
1886 enum {
1887 OPC_MXU_S32LDI = 0x00,
1888 OPC_MXU_S32LDIR = 0x01,
1892 * MXU pool 09
1894 enum {
1895 OPC_MXU_S32SDI = 0x00,
1896 OPC_MXU_S32SDIR = 0x01,
1900 * MXU pool 10
1902 enum {
1903 OPC_MXU_S32LDIV = 0x00,
1904 OPC_MXU_S32LDIVR = 0x01,
1908 * MXU pool 11
1910 enum {
1911 OPC_MXU_S32SDIV = 0x00,
1912 OPC_MXU_S32SDIVR = 0x01,
1916 * MXU pool 12
1918 enum {
1919 OPC_MXU_D32ACC = 0x00,
1920 OPC_MXU_D32ACCM = 0x01,
1921 OPC_MXU_D32ASUM = 0x02,
1925 * MXU pool 13
1927 enum {
1928 OPC_MXU_Q16ACC = 0x00,
1929 OPC_MXU_Q16ACCM = 0x01,
1930 OPC_MXU_Q16ASUM = 0x02,
1934 * MXU pool 14
1936 enum {
1937 OPC_MXU_Q8ADDE = 0x00,
1938 OPC_MXU_D8SUM = 0x01,
1939 OPC_MXU_D8SUMC = 0x02,
1943 * MXU pool 15
1945 enum {
1946 OPC_MXU_S32MUL = 0x00,
1947 OPC_MXU_S32MULU = 0x01,
1948 OPC_MXU_S32EXTR = 0x02,
1949 OPC_MXU_S32EXTRV = 0x03,
1953 * MXU pool 16
1955 enum {
1956 OPC_MXU_D32SARW = 0x00,
1957 OPC_MXU_S32ALN = 0x01,
1958 OPC_MXU_S32ALNI = 0x02,
1959 OPC_MXU_S32LUI = 0x03,
1960 OPC_MXU_S32NOR = 0x04,
1961 OPC_MXU_S32AND = 0x05,
1962 OPC_MXU_S32OR = 0x06,
1963 OPC_MXU_S32XOR = 0x07,
1967 * MXU pool 17
1969 enum {
1970 OPC_MXU_LXB = 0x00,
1971 OPC_MXU_LXH = 0x01,
1972 OPC_MXU_LXW = 0x03,
1973 OPC_MXU_LXBU = 0x04,
1974 OPC_MXU_LXHU = 0x05,
1978 * MXU pool 18
1980 enum {
1981 OPC_MXU_D32SLLV = 0x00,
1982 OPC_MXU_D32SLRV = 0x01,
1983 OPC_MXU_D32SARV = 0x03,
1984 OPC_MXU_Q16SLLV = 0x04,
1985 OPC_MXU_Q16SLRV = 0x05,
1986 OPC_MXU_Q16SARV = 0x07,
1990 * MXU pool 19
1992 enum {
1993 OPC_MXU_Q8MUL = 0x00,
1994 OPC_MXU_Q8MULSU = 0x01,
1998 * MXU pool 20
2000 enum {
2001 OPC_MXU_Q8MOVZ = 0x00,
2002 OPC_MXU_Q8MOVN = 0x01,
2003 OPC_MXU_D16MOVZ = 0x02,
2004 OPC_MXU_D16MOVN = 0x03,
2005 OPC_MXU_S32MOVZ = 0x04,
2006 OPC_MXU_S32MOVN = 0x05,
2010 * MXU pool 21
2012 enum {
2013 OPC_MXU_Q8MAC = 0x00,
2014 OPC_MXU_Q8MACSU = 0x01,
2018 * Overview of the TX79-specific instruction set
2019 * =============================================
2021 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
2022 * are only used by the specific quadword (128-bit) LQ/SQ load/store
2023 * instructions and certain multimedia instructions (MMIs). These MMIs
2024 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
2025 * or sixteen 8-bit paths.
2027 * Reference:
2029 * The Toshiba TX System RISC TX79 Core Architecture manual,
2030 * https://wiki.qemu.org/File:C790.pdf
2032 * Three-Operand Multiply and Multiply-Add (4 instructions)
2033 * --------------------------------------------------------
2034 * MADD [rd,] rs, rt Multiply/Add
2035 * MADDU [rd,] rs, rt Multiply/Add Unsigned
2036 * MULT [rd,] rs, rt Multiply (3-operand)
2037 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
2039 * Multiply Instructions for Pipeline 1 (10 instructions)
2040 * ------------------------------------------------------
2041 * MULT1 [rd,] rs, rt Multiply Pipeline 1
2042 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
2043 * DIV1 rs, rt Divide Pipeline 1
2044 * DIVU1 rs, rt Divide Unsigned Pipeline 1
2045 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
2046 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
2047 * MFHI1 rd Move From HI1 Register
2048 * MFLO1 rd Move From LO1 Register
2049 * MTHI1 rs Move To HI1 Register
2050 * MTLO1 rs Move To LO1 Register
2052 * Arithmetic (19 instructions)
2053 * ----------------------------
2054 * PADDB rd, rs, rt Parallel Add Byte
2055 * PSUBB rd, rs, rt Parallel Subtract Byte
2056 * PADDH rd, rs, rt Parallel Add Halfword
2057 * PSUBH rd, rs, rt Parallel Subtract Halfword
2058 * PADDW rd, rs, rt Parallel Add Word
2059 * PSUBW rd, rs, rt Parallel Subtract Word
2060 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
2061 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
2062 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
2063 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
2064 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
2065 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
2066 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
2067 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
2068 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
2069 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
2070 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
2071 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
2072 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
2074 * Min/Max (4 instructions)
2075 * ------------------------
2076 * PMAXH rd, rs, rt Parallel Maximum Halfword
2077 * PMINH rd, rs, rt Parallel Minimum Halfword
2078 * PMAXW rd, rs, rt Parallel Maximum Word
2079 * PMINW rd, rs, rt Parallel Minimum Word
2081 * Absolute (2 instructions)
2082 * -------------------------
2083 * PABSH rd, rt Parallel Absolute Halfword
2084 * PABSW rd, rt Parallel Absolute Word
2086 * Logical (4 instructions)
2087 * ------------------------
2088 * PAND rd, rs, rt Parallel AND
2089 * POR rd, rs, rt Parallel OR
2090 * PXOR rd, rs, rt Parallel XOR
2091 * PNOR rd, rs, rt Parallel NOR
2093 * Shift (9 instructions)
2094 * ----------------------
2095 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
2096 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
2097 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
2098 * PSLLW rd, rt, sa Parallel Shift Left Logical Word
2099 * PSRLW rd, rt, sa Parallel Shift Right Logical Word
2100 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
2101 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
2102 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
2103 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
2105 * Compare (6 instructions)
2106 * ------------------------
2107 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
2108 * PCEQB rd, rs, rt Parallel Compare for Equal Byte
2109 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
2110 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
2111 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
2112 * PCEQW rd, rs, rt Parallel Compare for Equal Word
2114 * LZC (1 instruction)
2115 * -------------------
2116 * PLZCW rd, rs Parallel Leading Zero or One Count Word
2118 * Quadword Load and Store (2 instructions)
2119 * ----------------------------------------
2120 * LQ rt, offset(base) Load Quadword
2121 * SQ rt, offset(base) Store Quadword
2123 * Multiply and Divide (19 instructions)
2124 * -------------------------------------
2125 * PMULTW rd, rs, rt Parallel Multiply Word
2126 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
2127 * PDIVW rs, rt Parallel Divide Word
2128 * PDIVUW rs, rt Parallel Divide Unsigned Word
2129 * PMADDW rd, rs, rt Parallel Multiply-Add Word
2130 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
2131 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
2132 * PMULTH rd, rs, rt Parallel Multiply Halfword
2133 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
2134 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
2135 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
2136 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
2137 * PDIVBW rs, rt Parallel Divide Broadcast Word
2138 * PMFHI rd Parallel Move From HI Register
2139 * PMFLO rd Parallel Move From LO Register
2140 * PMTHI rs Parallel Move To HI Register
2141 * PMTLO rs Parallel Move To LO Register
2142 * PMFHL rd Parallel Move From HI/LO Register
2143 * PMTHL rs Parallel Move To HI/LO Register
2145 * Pack/Extend (11 instructions)
2146 * -----------------------------
2147 * PPAC5 rd, rt Parallel Pack to 5 bits
2148 * PPACB rd, rs, rt Parallel Pack to Byte
2149 * PPACH rd, rs, rt Parallel Pack to Halfword
2150 * PPACW rd, rs, rt Parallel Pack to Word
2151 * PEXT5 rd, rt Parallel Extend Upper from 5 bits
2152 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
2153 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
2154 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
2155 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
2156 * PEXTUW rd, rs, rt Parallel Extend Upper from Word
2157 * PEXTLW rd, rs, rt Parallel Extend Lower from Word
2159 * Others (16 instructions)
2160 * ------------------------
2161 * PCPYH rd, rt Parallel Copy Halfword
2162 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
2163 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
2164 * PREVH rd, rt Parallel Reverse Halfword
2165 * PINTH rd, rs, rt Parallel Interleave Halfword
2166 * PINTEH rd, rs, rt Parallel Interleave Even Halfword
2167 * PEXEH rd, rt Parallel Exchange Even Halfword
2168 * PEXCH rd, rt Parallel Exchange Center Halfword
2169 * PEXEW rd, rt Parallel Exchange Even Word
2170 * PEXCW rd, rt Parallel Exchange Center Word
2171 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
2172 * MFSA rd Move from Shift Amount Register
2173 * MTSA rs Move to Shift Amount Register
2174 * MTSAB rs, immediate Move Byte Count to Shift Amount Register
2175 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
2176 * PROT3W rd, rt Parallel Rotate 3 Words
2178 * MMI (MultiMedia Instruction) encodings
2179 * ======================================
2181 * MMI instructions encoding table keys:
2183 * * This code is reserved for future use. An attempt to execute it
2184 * causes a Reserved Instruction exception.
2185 * % This code indicates an instruction class. The instruction word
2186 * must be further decoded by examining additional tables that show
2187 * the values for other instruction fields.
2188 * # This code is reserved for the unsupported instructions DMULT,
2189 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
2190 * to execute it causes a Reserved Instruction exception.
2192 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
2194 * 31 26 0
2195 * +--------+----------------------------------------+
2196 * | opcode | |
2197 * +--------+----------------------------------------+
2199 * opcode bits 28..26
2200 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2201 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2202 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2203 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
2204 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
2205 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
2206 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
2207 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
2208 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
2209 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
2210 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
2213 enum {
2214 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
2215 MMI_OPC_LQ = 0x1E << 26, /* Same as OPC_MSA */
2216 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
2220 * MMI instructions with opcode field = MMI:
2222 * 31 26 5 0
2223 * +--------+-------------------------------+--------+
2224 * | MMI | |function|
2225 * +--------+-------------------------------+--------+
2227 * function bits 2..0
2228 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2229 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2230 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2231 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
2232 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
2233 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
2234 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
2235 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
2236 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
2237 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
2238 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
2241 #define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
2242 enum {
2243 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
2244 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
2245 MMI_OPC_PLZCW = 0x04 | MMI_OPC_CLASS_MMI,
2246 MMI_OPC_CLASS_MMI0 = 0x08 | MMI_OPC_CLASS_MMI,
2247 MMI_OPC_CLASS_MMI2 = 0x09 | MMI_OPC_CLASS_MMI,
2248 MMI_OPC_MFHI1 = 0x10 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFHI */
2249 MMI_OPC_MTHI1 = 0x11 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTHI */
2250 MMI_OPC_MFLO1 = 0x12 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFLO */
2251 MMI_OPC_MTLO1 = 0x13 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTLO */
2252 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
2253 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
2254 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
2255 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
2256 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
2257 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
2258 MMI_OPC_CLASS_MMI1 = 0x28 | MMI_OPC_CLASS_MMI,
2259 MMI_OPC_CLASS_MMI3 = 0x29 | MMI_OPC_CLASS_MMI,
2260 MMI_OPC_PMFHL = 0x30 | MMI_OPC_CLASS_MMI,
2261 MMI_OPC_PMTHL = 0x31 | MMI_OPC_CLASS_MMI,
2262 MMI_OPC_PSLLH = 0x34 | MMI_OPC_CLASS_MMI,
2263 MMI_OPC_PSRLH = 0x36 | MMI_OPC_CLASS_MMI,
2264 MMI_OPC_PSRAH = 0x37 | MMI_OPC_CLASS_MMI,
2265 MMI_OPC_PSLLW = 0x3C | MMI_OPC_CLASS_MMI,
2266 MMI_OPC_PSRLW = 0x3E | MMI_OPC_CLASS_MMI,
2267 MMI_OPC_PSRAW = 0x3F | MMI_OPC_CLASS_MMI,
2271 * MMI instructions with opcode field = MMI and bits 5..0 = MMI0:
2273 * 31 26 10 6 5 0
2274 * +--------+----------------------+--------+--------+
2275 * | MMI | |function| MMI0 |
2276 * +--------+----------------------+--------+--------+
2278 * function bits 7..6
2279 * bits | 0 | 1 | 2 | 3
2280 * 10..8 | 00 | 01 | 10 | 11
2281 * -------+-------+-------+-------+-------
2282 * 0 000 | PADDW | PSUBW | PCGTW | PMAXW
2283 * 1 001 | PADDH | PSUBH | PCGTH | PMAXH
2284 * 2 010 | PADDB | PSUBB | PCGTB | *
2285 * 3 011 | * | * | * | *
2286 * 4 100 | PADDSW| PSUBSW| PEXTLW| PPACW
2287 * 5 101 | PADDSH| PSUBSH| PEXTLH| PPACH
2288 * 6 110 | PADDSB| PSUBSB| PEXTLB| PPACB
2289 * 7 111 | * | * | PEXT5 | PPAC5
2292 #define MASK_MMI0(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2293 enum {
2294 MMI_OPC_0_PADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI0,
2295 MMI_OPC_0_PSUBW = (0x01 << 6) | MMI_OPC_CLASS_MMI0,
2296 MMI_OPC_0_PCGTW = (0x02 << 6) | MMI_OPC_CLASS_MMI0,
2297 MMI_OPC_0_PMAXW = (0x03 << 6) | MMI_OPC_CLASS_MMI0,
2298 MMI_OPC_0_PADDH = (0x04 << 6) | MMI_OPC_CLASS_MMI0,
2299 MMI_OPC_0_PSUBH = (0x05 << 6) | MMI_OPC_CLASS_MMI0,
2300 MMI_OPC_0_PCGTH = (0x06 << 6) | MMI_OPC_CLASS_MMI0,
2301 MMI_OPC_0_PMAXH = (0x07 << 6) | MMI_OPC_CLASS_MMI0,
2302 MMI_OPC_0_PADDB = (0x08 << 6) | MMI_OPC_CLASS_MMI0,
2303 MMI_OPC_0_PSUBB = (0x09 << 6) | MMI_OPC_CLASS_MMI0,
2304 MMI_OPC_0_PCGTB = (0x0A << 6) | MMI_OPC_CLASS_MMI0,
2305 MMI_OPC_0_PADDSW = (0x10 << 6) | MMI_OPC_CLASS_MMI0,
2306 MMI_OPC_0_PSUBSW = (0x11 << 6) | MMI_OPC_CLASS_MMI0,
2307 MMI_OPC_0_PEXTLW = (0x12 << 6) | MMI_OPC_CLASS_MMI0,
2308 MMI_OPC_0_PPACW = (0x13 << 6) | MMI_OPC_CLASS_MMI0,
2309 MMI_OPC_0_PADDSH = (0x14 << 6) | MMI_OPC_CLASS_MMI0,
2310 MMI_OPC_0_PSUBSH = (0x15 << 6) | MMI_OPC_CLASS_MMI0,
2311 MMI_OPC_0_PEXTLH = (0x16 << 6) | MMI_OPC_CLASS_MMI0,
2312 MMI_OPC_0_PPACH = (0x17 << 6) | MMI_OPC_CLASS_MMI0,
2313 MMI_OPC_0_PADDSB = (0x18 << 6) | MMI_OPC_CLASS_MMI0,
2314 MMI_OPC_0_PSUBSB = (0x19 << 6) | MMI_OPC_CLASS_MMI0,
2315 MMI_OPC_0_PEXTLB = (0x1A << 6) | MMI_OPC_CLASS_MMI0,
2316 MMI_OPC_0_PPACB = (0x1B << 6) | MMI_OPC_CLASS_MMI0,
2317 MMI_OPC_0_PEXT5 = (0x1E << 6) | MMI_OPC_CLASS_MMI0,
2318 MMI_OPC_0_PPAC5 = (0x1F << 6) | MMI_OPC_CLASS_MMI0,
2322 * MMI instructions with opcode field = MMI and bits 5..0 = MMI1:
2324 * 31 26 10 6 5 0
2325 * +--------+----------------------+--------+--------+
2326 * | MMI | |function| MMI1 |
2327 * +--------+----------------------+--------+--------+
2329 * function bits 7..6
2330 * bits | 0 | 1 | 2 | 3
2331 * 10..8 | 00 | 01 | 10 | 11
2332 * -------+-------+-------+-------+-------
2333 * 0 000 | * | PABSW | PCEQW | PMINW
2334 * 1 001 | PADSBH| PABSH | PCEQH | PMINH
2335 * 2 010 | * | * | PCEQB | *
2336 * 3 011 | * | * | * | *
2337 * 4 100 | PADDUW| PSUBUW| PEXTUW| *
2338 * 5 101 | PADDUH| PSUBUH| PEXTUH| *
2339 * 6 110 | PADDUB| PSUBUB| PEXTUB| QFSRV
2340 * 7 111 | * | * | * | *
2343 #define MASK_MMI1(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2344 enum {
2345 MMI_OPC_1_PABSW = (0x01 << 6) | MMI_OPC_CLASS_MMI1,
2346 MMI_OPC_1_PCEQW = (0x02 << 6) | MMI_OPC_CLASS_MMI1,
2347 MMI_OPC_1_PMINW = (0x03 << 6) | MMI_OPC_CLASS_MMI1,
2348 MMI_OPC_1_PADSBH = (0x04 << 6) | MMI_OPC_CLASS_MMI1,
2349 MMI_OPC_1_PABSH = (0x05 << 6) | MMI_OPC_CLASS_MMI1,
2350 MMI_OPC_1_PCEQH = (0x06 << 6) | MMI_OPC_CLASS_MMI1,
2351 MMI_OPC_1_PMINH = (0x07 << 6) | MMI_OPC_CLASS_MMI1,
2352 MMI_OPC_1_PCEQB = (0x0A << 6) | MMI_OPC_CLASS_MMI1,
2353 MMI_OPC_1_PADDUW = (0x10 << 6) | MMI_OPC_CLASS_MMI1,
2354 MMI_OPC_1_PSUBUW = (0x11 << 6) | MMI_OPC_CLASS_MMI1,
2355 MMI_OPC_1_PEXTUW = (0x12 << 6) | MMI_OPC_CLASS_MMI1,
2356 MMI_OPC_1_PADDUH = (0x14 << 6) | MMI_OPC_CLASS_MMI1,
2357 MMI_OPC_1_PSUBUH = (0x15 << 6) | MMI_OPC_CLASS_MMI1,
2358 MMI_OPC_1_PEXTUH = (0x16 << 6) | MMI_OPC_CLASS_MMI1,
2359 MMI_OPC_1_PADDUB = (0x18 << 6) | MMI_OPC_CLASS_MMI1,
2360 MMI_OPC_1_PSUBUB = (0x19 << 6) | MMI_OPC_CLASS_MMI1,
2361 MMI_OPC_1_PEXTUB = (0x1A << 6) | MMI_OPC_CLASS_MMI1,
2362 MMI_OPC_1_QFSRV = (0x1B << 6) | MMI_OPC_CLASS_MMI1,
2366 * MMI instructions with opcode field = MMI and bits 5..0 = MMI2:
2368 * 31 26 10 6 5 0
2369 * +--------+----------------------+--------+--------+
2370 * | MMI | |function| MMI2 |
2371 * +--------+----------------------+--------+--------+
2373 * function bits 7..6
2374 * bits | 0 | 1 | 2 | 3
2375 * 10..8 | 00 | 01 | 10 | 11
2376 * -------+-------+-------+-------+-------
2377 * 0 000 | PMADDW| * | PSLLVW| PSRLVW
2378 * 1 001 | PMSUBW| * | * | *
2379 * 2 010 | PMFHI | PMFLO | PINTH | *
2380 * 3 011 | PMULTW| PDIVW | PCPYLD| *
2381 * 4 100 | PMADDH| PHMADH| PAND | PXOR
2382 * 5 101 | PMSUBH| PHMSBH| * | *
2383 * 6 110 | * | * | PEXEH | PREVH
2384 * 7 111 | PMULTH| PDIVBW| PEXEW | PROT3W
2387 #define MASK_MMI2(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2388 enum {
2389 MMI_OPC_2_PMADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI2,
2390 MMI_OPC_2_PSLLVW = (0x02 << 6) | MMI_OPC_CLASS_MMI2,
2391 MMI_OPC_2_PSRLVW = (0x03 << 6) | MMI_OPC_CLASS_MMI2,
2392 MMI_OPC_2_PMSUBW = (0x04 << 6) | MMI_OPC_CLASS_MMI2,
2393 MMI_OPC_2_PMFHI = (0x08 << 6) | MMI_OPC_CLASS_MMI2,
2394 MMI_OPC_2_PMFLO = (0x09 << 6) | MMI_OPC_CLASS_MMI2,
2395 MMI_OPC_2_PINTH = (0x0A << 6) | MMI_OPC_CLASS_MMI2,
2396 MMI_OPC_2_PMULTW = (0x0C << 6) | MMI_OPC_CLASS_MMI2,
2397 MMI_OPC_2_PDIVW = (0x0D << 6) | MMI_OPC_CLASS_MMI2,
2398 MMI_OPC_2_PCPYLD = (0x0E << 6) | MMI_OPC_CLASS_MMI2,
2399 MMI_OPC_2_PMADDH = (0x10 << 6) | MMI_OPC_CLASS_MMI2,
2400 MMI_OPC_2_PHMADH = (0x11 << 6) | MMI_OPC_CLASS_MMI2,
2401 MMI_OPC_2_PAND = (0x12 << 6) | MMI_OPC_CLASS_MMI2,
2402 MMI_OPC_2_PXOR = (0x13 << 6) | MMI_OPC_CLASS_MMI2,
2403 MMI_OPC_2_PMSUBH = (0x14 << 6) | MMI_OPC_CLASS_MMI2,
2404 MMI_OPC_2_PHMSBH = (0x15 << 6) | MMI_OPC_CLASS_MMI2,
2405 MMI_OPC_2_PEXEH = (0x1A << 6) | MMI_OPC_CLASS_MMI2,
2406 MMI_OPC_2_PREVH = (0x1B << 6) | MMI_OPC_CLASS_MMI2,
2407 MMI_OPC_2_PMULTH = (0x1C << 6) | MMI_OPC_CLASS_MMI2,
2408 MMI_OPC_2_PDIVBW = (0x1D << 6) | MMI_OPC_CLASS_MMI2,
2409 MMI_OPC_2_PEXEW = (0x1E << 6) | MMI_OPC_CLASS_MMI2,
2410 MMI_OPC_2_PROT3W = (0x1F << 6) | MMI_OPC_CLASS_MMI2,
2414 * MMI instructions with opcode field = MMI and bits 5..0 = MMI3:
2416 * 31 26 10 6 5 0
2417 * +--------+----------------------+--------+--------+
2418 * | MMI | |function| MMI3 |
2419 * +--------+----------------------+--------+--------+
2421 * function bits 7..6
2422 * bits | 0 | 1 | 2 | 3
2423 * 10..8 | 00 | 01 | 10 | 11
2424 * -------+-------+-------+-------+-------
2425 * 0 000 |PMADDUW| * | * | PSRAVW
2426 * 1 001 | * | * | * | *
2427 * 2 010 | PMTHI | PMTLO | PINTEH| *
2428 * 3 011 |PMULTUW| PDIVUW| PCPYUD| *
2429 * 4 100 | * | * | POR | PNOR
2430 * 5 101 | * | * | * | *
2431 * 6 110 | * | * | PEXCH | PCPYH
2432 * 7 111 | * | * | PEXCW | *
2435 #define MASK_MMI3(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2436 enum {
2437 MMI_OPC_3_PMADDUW = (0x00 << 6) | MMI_OPC_CLASS_MMI3,
2438 MMI_OPC_3_PSRAVW = (0x03 << 6) | MMI_OPC_CLASS_MMI3,
2439 MMI_OPC_3_PMTHI = (0x08 << 6) | MMI_OPC_CLASS_MMI3,
2440 MMI_OPC_3_PMTLO = (0x09 << 6) | MMI_OPC_CLASS_MMI3,
2441 MMI_OPC_3_PINTEH = (0x0A << 6) | MMI_OPC_CLASS_MMI3,
2442 MMI_OPC_3_PMULTUW = (0x0C << 6) | MMI_OPC_CLASS_MMI3,
2443 MMI_OPC_3_PDIVUW = (0x0D << 6) | MMI_OPC_CLASS_MMI3,
2444 MMI_OPC_3_PCPYUD = (0x0E << 6) | MMI_OPC_CLASS_MMI3,
2445 MMI_OPC_3_POR = (0x12 << 6) | MMI_OPC_CLASS_MMI3,
2446 MMI_OPC_3_PNOR = (0x13 << 6) | MMI_OPC_CLASS_MMI3,
2447 MMI_OPC_3_PEXCH = (0x1A << 6) | MMI_OPC_CLASS_MMI3,
2448 MMI_OPC_3_PCPYH = (0x1B << 6) | MMI_OPC_CLASS_MMI3,
2449 MMI_OPC_3_PEXCW = (0x1E << 6) | MMI_OPC_CLASS_MMI3,
2452 /* global register indices */
2453 static TCGv cpu_gpr[32], cpu_PC;
2454 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
2455 static TCGv cpu_dspctrl, btarget, bcond;
2456 static TCGv cpu_lladdr, cpu_llval;
2457 static TCGv_i32 hflags;
2458 static TCGv_i32 fpu_fcr0, fpu_fcr31;
2459 static TCGv_i64 fpu_f64[32];
2460 static TCGv_i64 msa_wr_d[64];
2462 #if defined(TARGET_MIPS64)
2463 /* Upper halves of R5900's 128-bit registers: MMRs (multimedia registers) */
2464 static TCGv_i64 cpu_mmr[32];
2465 #endif
2467 #if !defined(TARGET_MIPS64)
2468 /* MXU registers */
2469 static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1];
2470 static TCGv mxu_CR;
2471 #endif
2473 #include "exec/gen-icount.h"
2475 #define gen_helper_0e0i(name, arg) do { \
2476 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
2477 gen_helper_##name(cpu_env, helper_tmp); \
2478 tcg_temp_free_i32(helper_tmp); \
2479 } while (0)
2481 #define gen_helper_0e1i(name, arg1, arg2) do { \
2482 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2483 gen_helper_##name(cpu_env, arg1, helper_tmp); \
2484 tcg_temp_free_i32(helper_tmp); \
2485 } while (0)
2487 #define gen_helper_1e0i(name, ret, arg1) do { \
2488 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
2489 gen_helper_##name(ret, cpu_env, helper_tmp); \
2490 tcg_temp_free_i32(helper_tmp); \
2491 } while (0)
2493 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
2494 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2495 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
2496 tcg_temp_free_i32(helper_tmp); \
2497 } while (0)
2499 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
2500 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2501 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
2502 tcg_temp_free_i32(helper_tmp); \
2503 } while (0)
2505 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
2506 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2507 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
2508 tcg_temp_free_i32(helper_tmp); \
2509 } while (0)
2511 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
2512 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
2513 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
2514 tcg_temp_free_i32(helper_tmp); \
2515 } while (0)
2517 typedef struct DisasContext {
2518 DisasContextBase base;
2519 target_ulong saved_pc;
2520 target_ulong page_start;
2521 uint32_t opcode;
2522 uint64_t insn_flags;
2523 int32_t CP0_Config1;
2524 int32_t CP0_Config2;
2525 int32_t CP0_Config3;
2526 int32_t CP0_Config5;
2527 /* Routine used to access memory */
2528 int mem_idx;
2529 TCGMemOp default_tcg_memop_mask;
2530 uint32_t hflags, saved_hflags;
2531 target_ulong btarget;
2532 bool ulri;
2533 int kscrexist;
2534 bool rxi;
2535 int ie;
2536 bool bi;
2537 bool bp;
2538 uint64_t PAMask;
2539 bool mvh;
2540 bool eva;
2541 bool sc;
2542 int CP0_LLAddr_shift;
2543 bool ps;
2544 bool vp;
2545 bool cmgcr;
2546 bool mrp;
2547 bool nan2008;
2548 bool abs2008;
2549 bool saar;
2550 } DisasContext;
2552 #define DISAS_STOP DISAS_TARGET_0
2553 #define DISAS_EXIT DISAS_TARGET_1
2555 static const char * const regnames[] = {
2556 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2557 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2558 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2559 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2562 static const char * const regnames_HI[] = {
2563 "HI0", "HI1", "HI2", "HI3",
2566 static const char * const regnames_LO[] = {
2567 "LO0", "LO1", "LO2", "LO3",
2570 static const char * const fregnames[] = {
2571 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2572 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2573 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2574 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2577 static const char * const msaregnames[] = {
2578 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
2579 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
2580 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
2581 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
2582 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
2583 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
2584 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
2585 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
2586 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
2587 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
2588 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
2589 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
2590 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
2591 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
2592 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
2593 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
2596 #if !defined(TARGET_MIPS64)
2597 static const char * const mxuregnames[] = {
2598 "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8",
2599 "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR",
2601 #endif
2603 #define LOG_DISAS(...) \
2604 do { \
2605 if (MIPS_DEBUG_DISAS) { \
2606 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
2608 } while (0)
2610 #define MIPS_INVAL(op) \
2611 do { \
2612 if (MIPS_DEBUG_DISAS) { \
2613 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
2614 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
2615 ctx->base.pc_next, ctx->opcode, op, \
2616 ctx->opcode >> 26, ctx->opcode & 0x3F, \
2617 ((ctx->opcode >> 16) & 0x1F)); \
2619 } while (0)
2621 /* General purpose registers moves. */
2622 static inline void gen_load_gpr(TCGv t, int reg)
2624 if (reg == 0) {
2625 tcg_gen_movi_tl(t, 0);
2626 } else {
2627 tcg_gen_mov_tl(t, cpu_gpr[reg]);
2631 static inline void gen_store_gpr(TCGv t, int reg)
2633 if (reg != 0) {
2634 tcg_gen_mov_tl(cpu_gpr[reg], t);
2638 /* Moves to/from shadow registers. */
2639 static inline void gen_load_srsgpr(int from, int to)
2641 TCGv t0 = tcg_temp_new();
2643 if (from == 0) {
2644 tcg_gen_movi_tl(t0, 0);
2645 } else {
2646 TCGv_i32 t2 = tcg_temp_new_i32();
2647 TCGv_ptr addr = tcg_temp_new_ptr();
2649 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2650 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2651 tcg_gen_andi_i32(t2, t2, 0xf);
2652 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2653 tcg_gen_ext_i32_ptr(addr, t2);
2654 tcg_gen_add_ptr(addr, cpu_env, addr);
2656 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
2657 tcg_temp_free_ptr(addr);
2658 tcg_temp_free_i32(t2);
2660 gen_store_gpr(t0, to);
2661 tcg_temp_free(t0);
2664 static inline void gen_store_srsgpr(int from, int to)
2666 if (to != 0) {
2667 TCGv t0 = tcg_temp_new();
2668 TCGv_i32 t2 = tcg_temp_new_i32();
2669 TCGv_ptr addr = tcg_temp_new_ptr();
2671 gen_load_gpr(t0, from);
2672 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2673 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2674 tcg_gen_andi_i32(t2, t2, 0xf);
2675 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2676 tcg_gen_ext_i32_ptr(addr, t2);
2677 tcg_gen_add_ptr(addr, cpu_env, addr);
2679 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
2680 tcg_temp_free_ptr(addr);
2681 tcg_temp_free_i32(t2);
2682 tcg_temp_free(t0);
2686 #if !defined(TARGET_MIPS64)
2687 /* MXU General purpose registers moves. */
2688 static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg)
2690 if (reg == 0) {
2691 tcg_gen_movi_tl(t, 0);
2692 } else if (reg <= 15) {
2693 tcg_gen_mov_tl(t, mxu_gpr[reg - 1]);
2697 static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg)
2699 if (reg > 0 && reg <= 15) {
2700 tcg_gen_mov_tl(mxu_gpr[reg - 1], t);
2704 /* MXU control register moves. */
2705 static inline void gen_load_mxu_cr(TCGv t)
2707 tcg_gen_mov_tl(t, mxu_CR);
2710 static inline void gen_store_mxu_cr(TCGv t)
2712 /* TODO: Add handling of RW rules for MXU_CR. */
2713 tcg_gen_mov_tl(mxu_CR, t);
2715 #endif
2718 /* Tests */
2719 static inline void gen_save_pc(target_ulong pc)
2721 tcg_gen_movi_tl(cpu_PC, pc);
2724 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2726 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
2727 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2728 gen_save_pc(ctx->base.pc_next);
2729 ctx->saved_pc = ctx->base.pc_next;
2731 if (ctx->hflags != ctx->saved_hflags) {
2732 tcg_gen_movi_i32(hflags, ctx->hflags);
2733 ctx->saved_hflags = ctx->hflags;
2734 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2735 case MIPS_HFLAG_BR:
2736 break;
2737 case MIPS_HFLAG_BC:
2738 case MIPS_HFLAG_BL:
2739 case MIPS_HFLAG_B:
2740 tcg_gen_movi_tl(btarget, ctx->btarget);
2741 break;
2746 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2748 ctx->saved_hflags = ctx->hflags;
2749 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2750 case MIPS_HFLAG_BR:
2751 break;
2752 case MIPS_HFLAG_BC:
2753 case MIPS_HFLAG_BL:
2754 case MIPS_HFLAG_B:
2755 ctx->btarget = env->btarget;
2756 break;
2760 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
2762 TCGv_i32 texcp = tcg_const_i32(excp);
2763 TCGv_i32 terr = tcg_const_i32(err);
2764 save_cpu_state(ctx, 1);
2765 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2766 tcg_temp_free_i32(terr);
2767 tcg_temp_free_i32(texcp);
2768 ctx->base.is_jmp = DISAS_NORETURN;
2771 static inline void generate_exception(DisasContext *ctx, int excp)
2773 gen_helper_0e0i(raise_exception, excp);
2776 static inline void generate_exception_end(DisasContext *ctx, int excp)
2778 generate_exception_err(ctx, excp, 0);
2781 /* Floating point register moves. */
2782 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2784 if (ctx->hflags & MIPS_HFLAG_FRE) {
2785 generate_exception(ctx, EXCP_RI);
2787 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
2790 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2792 TCGv_i64 t64;
2793 if (ctx->hflags & MIPS_HFLAG_FRE) {
2794 generate_exception(ctx, EXCP_RI);
2796 t64 = tcg_temp_new_i64();
2797 tcg_gen_extu_i32_i64(t64, t);
2798 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2799 tcg_temp_free_i64(t64);
2802 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2804 if (ctx->hflags & MIPS_HFLAG_F64) {
2805 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
2806 } else {
2807 gen_load_fpr32(ctx, t, reg | 1);
2811 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2813 if (ctx->hflags & MIPS_HFLAG_F64) {
2814 TCGv_i64 t64 = tcg_temp_new_i64();
2815 tcg_gen_extu_i32_i64(t64, t);
2816 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2817 tcg_temp_free_i64(t64);
2818 } else {
2819 gen_store_fpr32(ctx, t, reg | 1);
2823 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2825 if (ctx->hflags & MIPS_HFLAG_F64) {
2826 tcg_gen_mov_i64(t, fpu_f64[reg]);
2827 } else {
2828 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
2832 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2834 if (ctx->hflags & MIPS_HFLAG_F64) {
2835 tcg_gen_mov_i64(fpu_f64[reg], t);
2836 } else {
2837 TCGv_i64 t0;
2838 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2839 t0 = tcg_temp_new_i64();
2840 tcg_gen_shri_i64(t0, t, 32);
2841 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
2842 tcg_temp_free_i64(t0);
2846 static inline int get_fp_bit(int cc)
2848 if (cc) {
2849 return 24 + cc;
2850 } else {
2851 return 23;
2855 /* Addresses computation */
2856 static inline void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0,
2857 TCGv arg1)
2859 tcg_gen_add_tl(ret, arg0, arg1);
2861 #if defined(TARGET_MIPS64)
2862 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2863 tcg_gen_ext32s_i64(ret, ret);
2865 #endif
2868 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2869 target_long ofs)
2871 tcg_gen_addi_tl(ret, base, ofs);
2873 #if defined(TARGET_MIPS64)
2874 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2875 tcg_gen_ext32s_i64(ret, ret);
2877 #endif
2880 /* Addresses computation (translation time) */
2881 static target_long addr_add(DisasContext *ctx, target_long base,
2882 target_long offset)
2884 target_long sum = base + offset;
2886 #if defined(TARGET_MIPS64)
2887 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2888 sum = (int32_t)sum;
2890 #endif
2891 return sum;
2894 /* Sign-extract the low 32-bits to a target_long. */
2895 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
2897 #if defined(TARGET_MIPS64)
2898 tcg_gen_ext32s_i64(ret, arg);
2899 #else
2900 tcg_gen_extrl_i64_i32(ret, arg);
2901 #endif
2904 /* Sign-extract the high 32-bits to a target_long. */
2905 static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
2907 #if defined(TARGET_MIPS64)
2908 tcg_gen_sari_i64(ret, arg, 32);
2909 #else
2910 tcg_gen_extrh_i64_i32(ret, arg);
2911 #endif
2914 static inline void check_cp0_enabled(DisasContext *ctx)
2916 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
2917 generate_exception_err(ctx, EXCP_CpU, 0);
2921 static inline void check_cp1_enabled(DisasContext *ctx)
2923 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) {
2924 generate_exception_err(ctx, EXCP_CpU, 1);
2929 * Verify that the processor is running with COP1X instructions enabled.
2930 * This is associated with the nabla symbol in the MIPS32 and MIPS64
2931 * opcode tables.
2933 static inline void check_cop1x(DisasContext *ctx)
2935 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) {
2936 generate_exception_end(ctx, EXCP_RI);
2941 * Verify that the processor is running with 64-bit floating-point
2942 * operations enabled.
2944 static inline void check_cp1_64bitmode(DisasContext *ctx)
2946 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) {
2947 generate_exception_end(ctx, EXCP_RI);
2952 * Verify if floating point register is valid; an operation is not defined
2953 * if bit 0 of any register specification is set and the FR bit in the
2954 * Status register equals zero, since the register numbers specify an
2955 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2956 * in the Status register equals one, both even and odd register numbers
2957 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2959 * Multiple 64 bit wide registers can be checked by calling
2960 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2962 static inline void check_cp1_registers(DisasContext *ctx, int regs)
2964 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) {
2965 generate_exception_end(ctx, EXCP_RI);
2970 * Verify that the processor is running with DSP instructions enabled.
2971 * This is enabled by CP0 Status register MX(24) bit.
2973 static inline void check_dsp(DisasContext *ctx)
2975 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
2976 if (ctx->insn_flags & ASE_DSP) {
2977 generate_exception_end(ctx, EXCP_DSPDIS);
2978 } else {
2979 generate_exception_end(ctx, EXCP_RI);
2984 static inline void check_dsp_r2(DisasContext *ctx)
2986 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
2987 if (ctx->insn_flags & ASE_DSP) {
2988 generate_exception_end(ctx, EXCP_DSPDIS);
2989 } else {
2990 generate_exception_end(ctx, EXCP_RI);
2995 static inline void check_dsp_r3(DisasContext *ctx)
2997 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
2998 if (ctx->insn_flags & ASE_DSP) {
2999 generate_exception_end(ctx, EXCP_DSPDIS);
3000 } else {
3001 generate_exception_end(ctx, EXCP_RI);
3007 * This code generates a "reserved instruction" exception if the
3008 * CPU does not support the instruction set corresponding to flags.
3010 static inline void check_insn(DisasContext *ctx, uint64_t flags)
3012 if (unlikely(!(ctx->insn_flags & flags))) {
3013 generate_exception_end(ctx, EXCP_RI);
3018 * This code generates a "reserved instruction" exception if the
3019 * CPU has corresponding flag set which indicates that the instruction
3020 * has been removed.
3022 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
3024 if (unlikely(ctx->insn_flags & flags)) {
3025 generate_exception_end(ctx, EXCP_RI);
3030 * The Linux kernel traps certain reserved instruction exceptions to
3031 * emulate the corresponding instructions. QEMU is the kernel in user
3032 * mode, so those traps are emulated by accepting the instructions.
3034 * A reserved instruction exception is generated for flagged CPUs if
3035 * QEMU runs in system mode.
3037 static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
3039 #ifndef CONFIG_USER_ONLY
3040 check_insn_opc_removed(ctx, flags);
3041 #endif
3045 * This code generates a "reserved instruction" exception if the
3046 * CPU does not support 64-bit paired-single (PS) floating point data type.
3048 static inline void check_ps(DisasContext *ctx)
3050 if (unlikely(!ctx->ps)) {
3051 generate_exception(ctx, EXCP_RI);
3053 check_cp1_64bitmode(ctx);
3056 #ifdef TARGET_MIPS64
3058 * This code generates a "reserved instruction" exception if 64-bit
3059 * instructions are not enabled.
3061 static inline void check_mips_64(DisasContext *ctx)
3063 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64))) {
3064 generate_exception_end(ctx, EXCP_RI);
3067 #endif
3069 #ifndef CONFIG_USER_ONLY
3070 static inline void check_mvh(DisasContext *ctx)
3072 if (unlikely(!ctx->mvh)) {
3073 generate_exception(ctx, EXCP_RI);
3076 #endif
3079 * This code generates a "reserved instruction" exception if the
3080 * Config5 XNP bit is set.
3082 static inline void check_xnp(DisasContext *ctx)
3084 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
3085 generate_exception_end(ctx, EXCP_RI);
3089 #ifndef CONFIG_USER_ONLY
3091 * This code generates a "reserved instruction" exception if the
3092 * Config3 PW bit is NOT set.
3094 static inline void check_pw(DisasContext *ctx)
3096 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
3097 generate_exception_end(ctx, EXCP_RI);
3100 #endif
3103 * This code generates a "reserved instruction" exception if the
3104 * Config3 MT bit is NOT set.
3106 static inline void check_mt(DisasContext *ctx)
3108 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3109 generate_exception_end(ctx, EXCP_RI);
3113 #ifndef CONFIG_USER_ONLY
3115 * This code generates a "coprocessor unusable" exception if CP0 is not
3116 * available, and, if that is not the case, generates a "reserved instruction"
3117 * exception if the Config5 MT bit is NOT set. This is needed for availability
3118 * control of some of MT ASE instructions.
3120 static inline void check_cp0_mt(DisasContext *ctx)
3122 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
3123 generate_exception_err(ctx, EXCP_CpU, 0);
3124 } else {
3125 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3126 generate_exception_err(ctx, EXCP_RI, 0);
3130 #endif
3133 * This code generates a "reserved instruction" exception if the
3134 * Config5 NMS bit is set.
3136 static inline void check_nms(DisasContext *ctx)
3138 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
3139 generate_exception_end(ctx, EXCP_RI);
3144 * This code generates a "reserved instruction" exception if the
3145 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
3146 * Config2 TL, and Config5 L2C are unset.
3148 static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
3150 if (unlikely((ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
3151 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
3152 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
3153 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
3154 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
3155 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))) {
3156 generate_exception_end(ctx, EXCP_RI);
3161 * This code generates a "reserved instruction" exception if the
3162 * Config5 EVA bit is NOT set.
3164 static inline void check_eva(DisasContext *ctx)
3166 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
3167 generate_exception_end(ctx, EXCP_RI);
3173 * Define small wrappers for gen_load_fpr* so that we have a uniform
3174 * calling interface for 32 and 64-bit FPRs. No sense in changing
3175 * all callers for gen_load_fpr32 when we need the CTX parameter for
3176 * this one use.
3178 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
3179 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
3180 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
3181 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
3182 int ft, int fs, int cc) \
3184 TCGv_i##bits fp0 = tcg_temp_new_i##bits(); \
3185 TCGv_i##bits fp1 = tcg_temp_new_i##bits(); \
3186 switch (ifmt) { \
3187 case FMT_PS: \
3188 check_ps(ctx); \
3189 break; \
3190 case FMT_D: \
3191 if (abs) { \
3192 check_cop1x(ctx); \
3194 check_cp1_registers(ctx, fs | ft); \
3195 break; \
3196 case FMT_S: \
3197 if (abs) { \
3198 check_cop1x(ctx); \
3200 break; \
3202 gen_ldcmp_fpr##bits(ctx, fp0, fs); \
3203 gen_ldcmp_fpr##bits(ctx, fp1, ft); \
3204 switch (n) { \
3205 case 0: \
3206 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); \
3207 break; \
3208 case 1: \
3209 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); \
3210 break; \
3211 case 2: \
3212 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); \
3213 break; \
3214 case 3: \
3215 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); \
3216 break; \
3217 case 4: \
3218 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); \
3219 break; \
3220 case 5: \
3221 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); \
3222 break; \
3223 case 6: \
3224 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); \
3225 break; \
3226 case 7: \
3227 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); \
3228 break; \
3229 case 8: \
3230 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); \
3231 break; \
3232 case 9: \
3233 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); \
3234 break; \
3235 case 10: \
3236 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); \
3237 break; \
3238 case 11: \
3239 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); \
3240 break; \
3241 case 12: \
3242 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); \
3243 break; \
3244 case 13: \
3245 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); \
3246 break; \
3247 case 14: \
3248 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); \
3249 break; \
3250 case 15: \
3251 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); \
3252 break; \
3253 default: \
3254 abort(); \
3256 tcg_temp_free_i##bits(fp0); \
3257 tcg_temp_free_i##bits(fp1); \
3260 FOP_CONDS(, 0, d, FMT_D, 64)
3261 FOP_CONDS(abs, 1, d, FMT_D, 64)
3262 FOP_CONDS(, 0, s, FMT_S, 32)
3263 FOP_CONDS(abs, 1, s, FMT_S, 32)
3264 FOP_CONDS(, 0, ps, FMT_PS, 64)
3265 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
3266 #undef FOP_CONDS
3268 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
3269 static inline void gen_r6_cmp_ ## fmt(DisasContext *ctx, int n, \
3270 int ft, int fs, int fd) \
3272 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
3273 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
3274 if (ifmt == FMT_D) { \
3275 check_cp1_registers(ctx, fs | ft | fd); \
3277 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
3278 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
3279 switch (n) { \
3280 case 0: \
3281 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
3282 break; \
3283 case 1: \
3284 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
3285 break; \
3286 case 2: \
3287 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
3288 break; \
3289 case 3: \
3290 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
3291 break; \
3292 case 4: \
3293 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
3294 break; \
3295 case 5: \
3296 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
3297 break; \
3298 case 6: \
3299 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
3300 break; \
3301 case 7: \
3302 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
3303 break; \
3304 case 8: \
3305 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
3306 break; \
3307 case 9: \
3308 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
3309 break; \
3310 case 10: \
3311 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
3312 break; \
3313 case 11: \
3314 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
3315 break; \
3316 case 12: \
3317 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
3318 break; \
3319 case 13: \
3320 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
3321 break; \
3322 case 14: \
3323 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
3324 break; \
3325 case 15: \
3326 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
3327 break; \
3328 case 17: \
3329 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
3330 break; \
3331 case 18: \
3332 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
3333 break; \
3334 case 19: \
3335 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
3336 break; \
3337 case 25: \
3338 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
3339 break; \
3340 case 26: \
3341 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
3342 break; \
3343 case 27: \
3344 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
3345 break; \
3346 default: \
3347 abort(); \
3349 STORE; \
3350 tcg_temp_free_i ## bits(fp0); \
3351 tcg_temp_free_i ## bits(fp1); \
3354 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
3355 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3356 #undef FOP_CONDNS
3357 #undef gen_ldcmp_fpr32
3358 #undef gen_ldcmp_fpr64
3360 /* load/store instructions. */
3361 #ifdef CONFIG_USER_ONLY
3362 #define OP_LD_ATOMIC(insn, fname) \
3363 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3364 DisasContext *ctx) \
3366 TCGv t0 = tcg_temp_new(); \
3367 tcg_gen_mov_tl(t0, arg1); \
3368 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
3369 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3370 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
3371 tcg_temp_free(t0); \
3373 #else
3374 #define OP_LD_ATOMIC(insn, fname) \
3375 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3376 DisasContext *ctx) \
3378 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
3380 #endif
3381 OP_LD_ATOMIC(ll, ld32s);
3382 #if defined(TARGET_MIPS64)
3383 OP_LD_ATOMIC(lld, ld64);
3384 #endif
3385 #undef OP_LD_ATOMIC
3387 static void gen_base_offset_addr(DisasContext *ctx, TCGv addr,
3388 int base, int offset)
3390 if (base == 0) {
3391 tcg_gen_movi_tl(addr, offset);
3392 } else if (offset == 0) {
3393 gen_load_gpr(addr, base);
3394 } else {
3395 tcg_gen_movi_tl(addr, offset);
3396 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
3400 static target_ulong pc_relative_pc(DisasContext *ctx)
3402 target_ulong pc = ctx->base.pc_next;
3404 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3405 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
3407 pc -= branch_bytes;
3410 pc &= ~(target_ulong)3;
3411 return pc;
3414 /* Load */
3415 static void gen_ld(DisasContext *ctx, uint32_t opc,
3416 int rt, int base, int offset)
3418 TCGv t0, t1, t2;
3419 int mem_idx = ctx->mem_idx;
3421 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
3423 * Loongson CPU uses a load to zero register for prefetch.
3424 * We emulate it as a NOP. On other CPU we must perform the
3425 * actual memory access.
3427 return;
3430 t0 = tcg_temp_new();
3431 gen_base_offset_addr(ctx, t0, base, offset);
3433 switch (opc) {
3434 #if defined(TARGET_MIPS64)
3435 case OPC_LWU:
3436 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
3437 ctx->default_tcg_memop_mask);
3438 gen_store_gpr(t0, rt);
3439 break;
3440 case OPC_LD:
3441 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
3442 ctx->default_tcg_memop_mask);
3443 gen_store_gpr(t0, rt);
3444 break;
3445 case OPC_LLD:
3446 case R6_OPC_LLD:
3447 op_ld_lld(t0, t0, mem_idx, ctx);
3448 gen_store_gpr(t0, rt);
3449 break;
3450 case OPC_LDL:
3451 t1 = tcg_temp_new();
3453 * Do a byte access to possibly trigger a page
3454 * fault with the unaligned address.
3456 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3457 tcg_gen_andi_tl(t1, t0, 7);
3458 #ifndef TARGET_WORDS_BIGENDIAN
3459 tcg_gen_xori_tl(t1, t1, 7);
3460 #endif
3461 tcg_gen_shli_tl(t1, t1, 3);
3462 tcg_gen_andi_tl(t0, t0, ~7);
3463 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3464 tcg_gen_shl_tl(t0, t0, t1);
3465 t2 = tcg_const_tl(-1);
3466 tcg_gen_shl_tl(t2, t2, t1);
3467 gen_load_gpr(t1, rt);
3468 tcg_gen_andc_tl(t1, t1, t2);
3469 tcg_temp_free(t2);
3470 tcg_gen_or_tl(t0, t0, t1);
3471 tcg_temp_free(t1);
3472 gen_store_gpr(t0, rt);
3473 break;
3474 case OPC_LDR:
3475 t1 = tcg_temp_new();
3477 * Do a byte access to possibly trigger a page
3478 * fault with the unaligned address.
3480 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3481 tcg_gen_andi_tl(t1, t0, 7);
3482 #ifdef TARGET_WORDS_BIGENDIAN
3483 tcg_gen_xori_tl(t1, t1, 7);
3484 #endif
3485 tcg_gen_shli_tl(t1, t1, 3);
3486 tcg_gen_andi_tl(t0, t0, ~7);
3487 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3488 tcg_gen_shr_tl(t0, t0, t1);
3489 tcg_gen_xori_tl(t1, t1, 63);
3490 t2 = tcg_const_tl(0xfffffffffffffffeull);
3491 tcg_gen_shl_tl(t2, t2, t1);
3492 gen_load_gpr(t1, rt);
3493 tcg_gen_and_tl(t1, t1, t2);
3494 tcg_temp_free(t2);
3495 tcg_gen_or_tl(t0, t0, t1);
3496 tcg_temp_free(t1);
3497 gen_store_gpr(t0, rt);
3498 break;
3499 case OPC_LDPC:
3500 t1 = tcg_const_tl(pc_relative_pc(ctx));
3501 gen_op_addr_add(ctx, t0, t0, t1);
3502 tcg_temp_free(t1);
3503 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3504 gen_store_gpr(t0, rt);
3505 break;
3506 #endif
3507 case OPC_LWPC:
3508 t1 = tcg_const_tl(pc_relative_pc(ctx));
3509 gen_op_addr_add(ctx, t0, t0, t1);
3510 tcg_temp_free(t1);
3511 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
3512 gen_store_gpr(t0, rt);
3513 break;
3514 case OPC_LWE:
3515 mem_idx = MIPS_HFLAG_UM;
3516 /* fall through */
3517 case OPC_LW:
3518 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
3519 ctx->default_tcg_memop_mask);
3520 gen_store_gpr(t0, rt);
3521 break;
3522 case OPC_LHE:
3523 mem_idx = MIPS_HFLAG_UM;
3524 /* fall through */
3525 case OPC_LH:
3526 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
3527 ctx->default_tcg_memop_mask);
3528 gen_store_gpr(t0, rt);
3529 break;
3530 case OPC_LHUE:
3531 mem_idx = MIPS_HFLAG_UM;
3532 /* fall through */
3533 case OPC_LHU:
3534 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
3535 ctx->default_tcg_memop_mask);
3536 gen_store_gpr(t0, rt);
3537 break;
3538 case OPC_LBE:
3539 mem_idx = MIPS_HFLAG_UM;
3540 /* fall through */
3541 case OPC_LB:
3542 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
3543 gen_store_gpr(t0, rt);
3544 break;
3545 case OPC_LBUE:
3546 mem_idx = MIPS_HFLAG_UM;
3547 /* fall through */
3548 case OPC_LBU:
3549 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
3550 gen_store_gpr(t0, rt);
3551 break;
3552 case OPC_LWLE:
3553 mem_idx = MIPS_HFLAG_UM;
3554 /* fall through */
3555 case OPC_LWL:
3556 t1 = tcg_temp_new();
3558 * Do a byte access to possibly trigger a page
3559 * fault with the unaligned address.
3561 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3562 tcg_gen_andi_tl(t1, t0, 3);
3563 #ifndef TARGET_WORDS_BIGENDIAN
3564 tcg_gen_xori_tl(t1, t1, 3);
3565 #endif
3566 tcg_gen_shli_tl(t1, t1, 3);
3567 tcg_gen_andi_tl(t0, t0, ~3);
3568 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3569 tcg_gen_shl_tl(t0, t0, t1);
3570 t2 = tcg_const_tl(-1);
3571 tcg_gen_shl_tl(t2, t2, t1);
3572 gen_load_gpr(t1, rt);
3573 tcg_gen_andc_tl(t1, t1, t2);
3574 tcg_temp_free(t2);
3575 tcg_gen_or_tl(t0, t0, t1);
3576 tcg_temp_free(t1);
3577 tcg_gen_ext32s_tl(t0, t0);
3578 gen_store_gpr(t0, rt);
3579 break;
3580 case OPC_LWRE:
3581 mem_idx = MIPS_HFLAG_UM;
3582 /* fall through */
3583 case OPC_LWR:
3584 t1 = tcg_temp_new();
3586 * Do a byte access to possibly trigger a page
3587 * fault with the unaligned address.
3589 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3590 tcg_gen_andi_tl(t1, t0, 3);
3591 #ifdef TARGET_WORDS_BIGENDIAN
3592 tcg_gen_xori_tl(t1, t1, 3);
3593 #endif
3594 tcg_gen_shli_tl(t1, t1, 3);
3595 tcg_gen_andi_tl(t0, t0, ~3);
3596 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3597 tcg_gen_shr_tl(t0, t0, t1);
3598 tcg_gen_xori_tl(t1, t1, 31);
3599 t2 = tcg_const_tl(0xfffffffeull);
3600 tcg_gen_shl_tl(t2, t2, t1);
3601 gen_load_gpr(t1, rt);
3602 tcg_gen_and_tl(t1, t1, t2);
3603 tcg_temp_free(t2);
3604 tcg_gen_or_tl(t0, t0, t1);
3605 tcg_temp_free(t1);
3606 tcg_gen_ext32s_tl(t0, t0);
3607 gen_store_gpr(t0, rt);
3608 break;
3609 case OPC_LLE:
3610 mem_idx = MIPS_HFLAG_UM;
3611 /* fall through */
3612 case OPC_LL:
3613 case R6_OPC_LL:
3614 op_ld_ll(t0, t0, mem_idx, ctx);
3615 gen_store_gpr(t0, rt);
3616 break;
3618 tcg_temp_free(t0);
3621 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3622 uint32_t reg1, uint32_t reg2)
3624 TCGv taddr = tcg_temp_new();
3625 TCGv_i64 tval = tcg_temp_new_i64();
3626 TCGv tmp1 = tcg_temp_new();
3627 TCGv tmp2 = tcg_temp_new();
3629 gen_base_offset_addr(ctx, taddr, base, offset);
3630 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3631 #ifdef TARGET_WORDS_BIGENDIAN
3632 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3633 #else
3634 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3635 #endif
3636 gen_store_gpr(tmp1, reg1);
3637 tcg_temp_free(tmp1);
3638 gen_store_gpr(tmp2, reg2);
3639 tcg_temp_free(tmp2);
3640 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3641 tcg_temp_free_i64(tval);
3642 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3643 tcg_temp_free(taddr);
3646 /* Store */
3647 static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
3648 int base, int offset)
3650 TCGv t0 = tcg_temp_new();
3651 TCGv t1 = tcg_temp_new();
3652 int mem_idx = ctx->mem_idx;
3654 gen_base_offset_addr(ctx, t0, base, offset);
3655 gen_load_gpr(t1, rt);
3656 switch (opc) {
3657 #if defined(TARGET_MIPS64)
3658 case OPC_SD:
3659 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
3660 ctx->default_tcg_memop_mask);
3661 break;
3662 case OPC_SDL:
3663 gen_helper_0e2i(sdl, t1, t0, mem_idx);
3664 break;
3665 case OPC_SDR:
3666 gen_helper_0e2i(sdr, t1, t0, mem_idx);
3667 break;
3668 #endif
3669 case OPC_SWE:
3670 mem_idx = MIPS_HFLAG_UM;
3671 /* fall through */
3672 case OPC_SW:
3673 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
3674 ctx->default_tcg_memop_mask);
3675 break;
3676 case OPC_SHE:
3677 mem_idx = MIPS_HFLAG_UM;
3678 /* fall through */
3679 case OPC_SH:
3680 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
3681 ctx->default_tcg_memop_mask);
3682 break;
3683 case OPC_SBE:
3684 mem_idx = MIPS_HFLAG_UM;
3685 /* fall through */
3686 case OPC_SB:
3687 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
3688 break;
3689 case OPC_SWLE:
3690 mem_idx = MIPS_HFLAG_UM;
3691 /* fall through */
3692 case OPC_SWL:
3693 gen_helper_0e2i(swl, t1, t0, mem_idx);
3694 break;
3695 case OPC_SWRE:
3696 mem_idx = MIPS_HFLAG_UM;
3697 /* fall through */
3698 case OPC_SWR:
3699 gen_helper_0e2i(swr, t1, t0, mem_idx);
3700 break;
3702 tcg_temp_free(t0);
3703 tcg_temp_free(t1);
3707 /* Store conditional */
3708 static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
3709 TCGMemOp tcg_mo, bool eva)
3711 TCGv addr, t0, val;
3712 TCGLabel *l1 = gen_new_label();
3713 TCGLabel *done = gen_new_label();
3715 t0 = tcg_temp_new();
3716 addr = tcg_temp_new();
3717 /* compare the address against that of the preceeding LL */
3718 gen_base_offset_addr(ctx, addr, base, offset);
3719 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
3720 tcg_temp_free(addr);
3721 tcg_gen_movi_tl(t0, 0);
3722 gen_store_gpr(t0, rt);
3723 tcg_gen_br(done);
3725 gen_set_label(l1);
3726 /* generate cmpxchg */
3727 val = tcg_temp_new();
3728 gen_load_gpr(val, rt);
3729 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
3730 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
3731 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
3732 gen_store_gpr(t0, rt);
3733 tcg_temp_free(val);
3735 gen_set_label(done);
3736 tcg_temp_free(t0);
3740 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
3741 uint32_t reg1, uint32_t reg2, bool eva)
3743 TCGv taddr = tcg_temp_local_new();
3744 TCGv lladdr = tcg_temp_local_new();
3745 TCGv_i64 tval = tcg_temp_new_i64();
3746 TCGv_i64 llval = tcg_temp_new_i64();
3747 TCGv_i64 val = tcg_temp_new_i64();
3748 TCGv tmp1 = tcg_temp_new();
3749 TCGv tmp2 = tcg_temp_new();
3750 TCGLabel *lab_fail = gen_new_label();
3751 TCGLabel *lab_done = gen_new_label();
3753 gen_base_offset_addr(ctx, taddr, base, offset);
3755 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3756 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3758 gen_load_gpr(tmp1, reg1);
3759 gen_load_gpr(tmp2, reg2);
3761 #ifdef TARGET_WORDS_BIGENDIAN
3762 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3763 #else
3764 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3765 #endif
3767 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3768 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
3769 eva ? MIPS_HFLAG_UM : ctx->mem_idx, MO_64);
3770 if (reg1 != 0) {
3771 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3773 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3775 gen_set_label(lab_fail);
3777 if (reg1 != 0) {
3778 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3780 gen_set_label(lab_done);
3781 tcg_gen_movi_tl(lladdr, -1);
3782 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3785 /* Load and store */
3786 static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
3787 TCGv t0)
3790 * Don't do NOP if destination is zero: we must perform the actual
3791 * memory access.
3793 switch (opc) {
3794 case OPC_LWC1:
3796 TCGv_i32 fp0 = tcg_temp_new_i32();
3797 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3798 ctx->default_tcg_memop_mask);
3799 gen_store_fpr32(ctx, fp0, ft);
3800 tcg_temp_free_i32(fp0);
3802 break;
3803 case OPC_SWC1:
3805 TCGv_i32 fp0 = tcg_temp_new_i32();
3806 gen_load_fpr32(ctx, fp0, ft);
3807 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3808 ctx->default_tcg_memop_mask);
3809 tcg_temp_free_i32(fp0);
3811 break;
3812 case OPC_LDC1:
3814 TCGv_i64 fp0 = tcg_temp_new_i64();
3815 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3816 ctx->default_tcg_memop_mask);
3817 gen_store_fpr64(ctx, fp0, ft);
3818 tcg_temp_free_i64(fp0);
3820 break;
3821 case OPC_SDC1:
3823 TCGv_i64 fp0 = tcg_temp_new_i64();
3824 gen_load_fpr64(ctx, fp0, ft);
3825 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3826 ctx->default_tcg_memop_mask);
3827 tcg_temp_free_i64(fp0);
3829 break;
3830 default:
3831 MIPS_INVAL("flt_ldst");
3832 generate_exception_end(ctx, EXCP_RI);
3833 break;
3837 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3838 int rs, int16_t imm)
3840 TCGv t0 = tcg_temp_new();
3842 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3843 check_cp1_enabled(ctx);
3844 switch (op) {
3845 case OPC_LDC1:
3846 case OPC_SDC1:
3847 check_insn(ctx, ISA_MIPS2);
3848 /* Fallthrough */
3849 default:
3850 gen_base_offset_addr(ctx, t0, rs, imm);
3851 gen_flt_ldst(ctx, op, rt, t0);
3853 } else {
3854 generate_exception_err(ctx, EXCP_CpU, 1);
3856 tcg_temp_free(t0);
3859 /* Arithmetic with immediate operand */
3860 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
3861 int rt, int rs, int imm)
3863 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3865 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
3867 * If no destination, treat it as a NOP.
3868 * For addi, we must generate the overflow exception when needed.
3870 return;
3872 switch (opc) {
3873 case OPC_ADDI:
3875 TCGv t0 = tcg_temp_local_new();
3876 TCGv t1 = tcg_temp_new();
3877 TCGv t2 = tcg_temp_new();
3878 TCGLabel *l1 = gen_new_label();
3880 gen_load_gpr(t1, rs);
3881 tcg_gen_addi_tl(t0, t1, uimm);
3882 tcg_gen_ext32s_tl(t0, t0);
3884 tcg_gen_xori_tl(t1, t1, ~uimm);
3885 tcg_gen_xori_tl(t2, t0, uimm);
3886 tcg_gen_and_tl(t1, t1, t2);
3887 tcg_temp_free(t2);
3888 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3889 tcg_temp_free(t1);
3890 /* operands of same sign, result different sign */
3891 generate_exception(ctx, EXCP_OVERFLOW);
3892 gen_set_label(l1);
3893 tcg_gen_ext32s_tl(t0, t0);
3894 gen_store_gpr(t0, rt);
3895 tcg_temp_free(t0);
3897 break;
3898 case OPC_ADDIU:
3899 if (rs != 0) {
3900 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3901 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3902 } else {
3903 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3905 break;
3906 #if defined(TARGET_MIPS64)
3907 case OPC_DADDI:
3909 TCGv t0 = tcg_temp_local_new();
3910 TCGv t1 = tcg_temp_new();
3911 TCGv t2 = tcg_temp_new();
3912 TCGLabel *l1 = gen_new_label();
3914 gen_load_gpr(t1, rs);
3915 tcg_gen_addi_tl(t0, t1, uimm);
3917 tcg_gen_xori_tl(t1, t1, ~uimm);
3918 tcg_gen_xori_tl(t2, t0, uimm);
3919 tcg_gen_and_tl(t1, t1, t2);
3920 tcg_temp_free(t2);
3921 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3922 tcg_temp_free(t1);
3923 /* operands of same sign, result different sign */
3924 generate_exception(ctx, EXCP_OVERFLOW);
3925 gen_set_label(l1);
3926 gen_store_gpr(t0, rt);
3927 tcg_temp_free(t0);
3929 break;
3930 case OPC_DADDIU:
3931 if (rs != 0) {
3932 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3933 } else {
3934 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3936 break;
3937 #endif
3941 /* Logic with immediate operand */
3942 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
3943 int rt, int rs, int16_t imm)
3945 target_ulong uimm;
3947 if (rt == 0) {
3948 /* If no destination, treat it as a NOP. */
3949 return;
3951 uimm = (uint16_t)imm;
3952 switch (opc) {
3953 case OPC_ANDI:
3954 if (likely(rs != 0)) {
3955 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3956 } else {
3957 tcg_gen_movi_tl(cpu_gpr[rt], 0);
3959 break;
3960 case OPC_ORI:
3961 if (rs != 0) {
3962 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3963 } else {
3964 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3966 break;
3967 case OPC_XORI:
3968 if (likely(rs != 0)) {
3969 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3970 } else {
3971 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3973 break;
3974 case OPC_LUI:
3975 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
3976 /* OPC_AUI */
3977 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3978 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3979 } else {
3980 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
3982 break;
3984 default:
3985 break;
3989 /* Set on less than with immediate operand */
3990 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
3991 int rt, int rs, int16_t imm)
3993 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3994 TCGv t0;
3996 if (rt == 0) {
3997 /* If no destination, treat it as a NOP. */
3998 return;
4000 t0 = tcg_temp_new();
4001 gen_load_gpr(t0, rs);
4002 switch (opc) {
4003 case OPC_SLTI:
4004 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
4005 break;
4006 case OPC_SLTIU:
4007 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
4008 break;
4010 tcg_temp_free(t0);
4013 /* Shifts with immediate operand */
4014 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
4015 int rt, int rs, int16_t imm)
4017 target_ulong uimm = ((uint16_t)imm) & 0x1f;
4018 TCGv t0;
4020 if (rt == 0) {
4021 /* If no destination, treat it as a NOP. */
4022 return;
4025 t0 = tcg_temp_new();
4026 gen_load_gpr(t0, rs);
4027 switch (opc) {
4028 case OPC_SLL:
4029 tcg_gen_shli_tl(t0, t0, uimm);
4030 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
4031 break;
4032 case OPC_SRA:
4033 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
4034 break;
4035 case OPC_SRL:
4036 if (uimm != 0) {
4037 tcg_gen_ext32u_tl(t0, t0);
4038 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
4039 } else {
4040 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
4042 break;
4043 case OPC_ROTR:
4044 if (uimm != 0) {
4045 TCGv_i32 t1 = tcg_temp_new_i32();
4047 tcg_gen_trunc_tl_i32(t1, t0);
4048 tcg_gen_rotri_i32(t1, t1, uimm);
4049 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
4050 tcg_temp_free_i32(t1);
4051 } else {
4052 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
4054 break;
4055 #if defined(TARGET_MIPS64)
4056 case OPC_DSLL:
4057 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
4058 break;
4059 case OPC_DSRA:
4060 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
4061 break;
4062 case OPC_DSRL:
4063 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
4064 break;
4065 case OPC_DROTR:
4066 if (uimm != 0) {
4067 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
4068 } else {
4069 tcg_gen_mov_tl(cpu_gpr[rt], t0);
4071 break;
4072 case OPC_DSLL32:
4073 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
4074 break;
4075 case OPC_DSRA32:
4076 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
4077 break;
4078 case OPC_DSRL32:
4079 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
4080 break;
4081 case OPC_DROTR32:
4082 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
4083 break;
4084 #endif
4086 tcg_temp_free(t0);
4089 /* Arithmetic */
4090 static void gen_arith(DisasContext *ctx, uint32_t opc,
4091 int rd, int rs, int rt)
4093 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
4094 && opc != OPC_DADD && opc != OPC_DSUB) {
4096 * If no destination, treat it as a NOP.
4097 * For add & sub, we must generate the overflow exception when needed.
4099 return;
4102 switch (opc) {
4103 case OPC_ADD:
4105 TCGv t0 = tcg_temp_local_new();
4106 TCGv t1 = tcg_temp_new();
4107 TCGv t2 = tcg_temp_new();
4108 TCGLabel *l1 = gen_new_label();
4110 gen_load_gpr(t1, rs);
4111 gen_load_gpr(t2, rt);
4112 tcg_gen_add_tl(t0, t1, t2);
4113 tcg_gen_ext32s_tl(t0, t0);
4114 tcg_gen_xor_tl(t1, t1, t2);
4115 tcg_gen_xor_tl(t2, t0, t2);
4116 tcg_gen_andc_tl(t1, t2, t1);
4117 tcg_temp_free(t2);
4118 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4119 tcg_temp_free(t1);
4120 /* operands of same sign, result different sign */
4121 generate_exception(ctx, EXCP_OVERFLOW);
4122 gen_set_label(l1);
4123 gen_store_gpr(t0, rd);
4124 tcg_temp_free(t0);
4126 break;
4127 case OPC_ADDU:
4128 if (rs != 0 && rt != 0) {
4129 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4130 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4131 } else if (rs == 0 && rt != 0) {
4132 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4133 } else if (rs != 0 && rt == 0) {
4134 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4135 } else {
4136 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4138 break;
4139 case OPC_SUB:
4141 TCGv t0 = tcg_temp_local_new();
4142 TCGv t1 = tcg_temp_new();
4143 TCGv t2 = tcg_temp_new();
4144 TCGLabel *l1 = gen_new_label();
4146 gen_load_gpr(t1, rs);
4147 gen_load_gpr(t2, rt);
4148 tcg_gen_sub_tl(t0, t1, t2);
4149 tcg_gen_ext32s_tl(t0, t0);
4150 tcg_gen_xor_tl(t2, t1, t2);
4151 tcg_gen_xor_tl(t1, t0, t1);
4152 tcg_gen_and_tl(t1, t1, t2);
4153 tcg_temp_free(t2);
4154 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4155 tcg_temp_free(t1);
4157 * operands of different sign, first operand and the result
4158 * of different sign
4160 generate_exception(ctx, EXCP_OVERFLOW);
4161 gen_set_label(l1);
4162 gen_store_gpr(t0, rd);
4163 tcg_temp_free(t0);
4165 break;
4166 case OPC_SUBU:
4167 if (rs != 0 && rt != 0) {
4168 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4169 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4170 } else if (rs == 0 && rt != 0) {
4171 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4172 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4173 } else if (rs != 0 && rt == 0) {
4174 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4175 } else {
4176 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4178 break;
4179 #if defined(TARGET_MIPS64)
4180 case OPC_DADD:
4182 TCGv t0 = tcg_temp_local_new();
4183 TCGv t1 = tcg_temp_new();
4184 TCGv t2 = tcg_temp_new();
4185 TCGLabel *l1 = gen_new_label();
4187 gen_load_gpr(t1, rs);
4188 gen_load_gpr(t2, rt);
4189 tcg_gen_add_tl(t0, t1, t2);
4190 tcg_gen_xor_tl(t1, t1, t2);
4191 tcg_gen_xor_tl(t2, t0, t2);
4192 tcg_gen_andc_tl(t1, t2, t1);
4193 tcg_temp_free(t2);
4194 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4195 tcg_temp_free(t1);
4196 /* operands of same sign, result different sign */
4197 generate_exception(ctx, EXCP_OVERFLOW);
4198 gen_set_label(l1);
4199 gen_store_gpr(t0, rd);
4200 tcg_temp_free(t0);
4202 break;
4203 case OPC_DADDU:
4204 if (rs != 0 && rt != 0) {
4205 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4206 } else if (rs == 0 && rt != 0) {
4207 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4208 } else if (rs != 0 && rt == 0) {
4209 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4210 } else {
4211 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4213 break;
4214 case OPC_DSUB:
4216 TCGv t0 = tcg_temp_local_new();
4217 TCGv t1 = tcg_temp_new();
4218 TCGv t2 = tcg_temp_new();
4219 TCGLabel *l1 = gen_new_label();
4221 gen_load_gpr(t1, rs);
4222 gen_load_gpr(t2, rt);
4223 tcg_gen_sub_tl(t0, t1, t2);
4224 tcg_gen_xor_tl(t2, t1, t2);
4225 tcg_gen_xor_tl(t1, t0, t1);
4226 tcg_gen_and_tl(t1, t1, t2);
4227 tcg_temp_free(t2);
4228 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4229 tcg_temp_free(t1);
4231 * Operands of different sign, first operand and result different
4232 * sign.
4234 generate_exception(ctx, EXCP_OVERFLOW);
4235 gen_set_label(l1);
4236 gen_store_gpr(t0, rd);
4237 tcg_temp_free(t0);
4239 break;
4240 case OPC_DSUBU:
4241 if (rs != 0 && rt != 0) {
4242 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4243 } else if (rs == 0 && rt != 0) {
4244 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4245 } else if (rs != 0 && rt == 0) {
4246 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4247 } else {
4248 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4250 break;
4251 #endif
4252 case OPC_MUL:
4253 if (likely(rs != 0 && rt != 0)) {
4254 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4255 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4256 } else {
4257 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4259 break;
4263 /* Conditional move */
4264 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
4265 int rd, int rs, int rt)
4267 TCGv t0, t1, t2;
4269 if (rd == 0) {
4270 /* If no destination, treat it as a NOP. */
4271 return;
4274 t0 = tcg_temp_new();
4275 gen_load_gpr(t0, rt);
4276 t1 = tcg_const_tl(0);
4277 t2 = tcg_temp_new();
4278 gen_load_gpr(t2, rs);
4279 switch (opc) {
4280 case OPC_MOVN:
4281 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4282 break;
4283 case OPC_MOVZ:
4284 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4285 break;
4286 case OPC_SELNEZ:
4287 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
4288 break;
4289 case OPC_SELEQZ:
4290 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
4291 break;
4293 tcg_temp_free(t2);
4294 tcg_temp_free(t1);
4295 tcg_temp_free(t0);
4298 /* Logic */
4299 static void gen_logic(DisasContext *ctx, uint32_t opc,
4300 int rd, int rs, int rt)
4302 if (rd == 0) {
4303 /* If no destination, treat it as a NOP. */
4304 return;
4307 switch (opc) {
4308 case OPC_AND:
4309 if (likely(rs != 0 && rt != 0)) {
4310 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4311 } else {
4312 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4314 break;
4315 case OPC_NOR:
4316 if (rs != 0 && rt != 0) {
4317 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4318 } else if (rs == 0 && rt != 0) {
4319 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
4320 } else if (rs != 0 && rt == 0) {
4321 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
4322 } else {
4323 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
4325 break;
4326 case OPC_OR:
4327 if (likely(rs != 0 && rt != 0)) {
4328 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4329 } else if (rs == 0 && rt != 0) {
4330 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4331 } else if (rs != 0 && rt == 0) {
4332 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4333 } else {
4334 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4336 break;
4337 case OPC_XOR:
4338 if (likely(rs != 0 && rt != 0)) {
4339 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4340 } else if (rs == 0 && rt != 0) {
4341 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4342 } else if (rs != 0 && rt == 0) {
4343 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4344 } else {
4345 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4347 break;
4351 /* Set on lower than */
4352 static void gen_slt(DisasContext *ctx, uint32_t opc,
4353 int rd, int rs, int rt)
4355 TCGv t0, t1;
4357 if (rd == 0) {
4358 /* If no destination, treat it as a NOP. */
4359 return;
4362 t0 = tcg_temp_new();
4363 t1 = tcg_temp_new();
4364 gen_load_gpr(t0, rs);
4365 gen_load_gpr(t1, rt);
4366 switch (opc) {
4367 case OPC_SLT:
4368 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
4369 break;
4370 case OPC_SLTU:
4371 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
4372 break;
4374 tcg_temp_free(t0);
4375 tcg_temp_free(t1);
4378 /* Shifts */
4379 static void gen_shift(DisasContext *ctx, uint32_t opc,
4380 int rd, int rs, int rt)
4382 TCGv t0, t1;
4384 if (rd == 0) {
4386 * If no destination, treat it as a NOP.
4387 * For add & sub, we must generate the overflow exception when needed.
4389 return;
4392 t0 = tcg_temp_new();
4393 t1 = tcg_temp_new();
4394 gen_load_gpr(t0, rs);
4395 gen_load_gpr(t1, rt);
4396 switch (opc) {
4397 case OPC_SLLV:
4398 tcg_gen_andi_tl(t0, t0, 0x1f);
4399 tcg_gen_shl_tl(t0, t1, t0);
4400 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4401 break;
4402 case OPC_SRAV:
4403 tcg_gen_andi_tl(t0, t0, 0x1f);
4404 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4405 break;
4406 case OPC_SRLV:
4407 tcg_gen_ext32u_tl(t1, t1);
4408 tcg_gen_andi_tl(t0, t0, 0x1f);
4409 tcg_gen_shr_tl(t0, t1, t0);
4410 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4411 break;
4412 case OPC_ROTRV:
4414 TCGv_i32 t2 = tcg_temp_new_i32();
4415 TCGv_i32 t3 = tcg_temp_new_i32();
4417 tcg_gen_trunc_tl_i32(t2, t0);
4418 tcg_gen_trunc_tl_i32(t3, t1);
4419 tcg_gen_andi_i32(t2, t2, 0x1f);
4420 tcg_gen_rotr_i32(t2, t3, t2);
4421 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4422 tcg_temp_free_i32(t2);
4423 tcg_temp_free_i32(t3);
4425 break;
4426 #if defined(TARGET_MIPS64)
4427 case OPC_DSLLV:
4428 tcg_gen_andi_tl(t0, t0, 0x3f);
4429 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
4430 break;
4431 case OPC_DSRAV:
4432 tcg_gen_andi_tl(t0, t0, 0x3f);
4433 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4434 break;
4435 case OPC_DSRLV:
4436 tcg_gen_andi_tl(t0, t0, 0x3f);
4437 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
4438 break;
4439 case OPC_DROTRV:
4440 tcg_gen_andi_tl(t0, t0, 0x3f);
4441 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
4442 break;
4443 #endif
4445 tcg_temp_free(t0);
4446 tcg_temp_free(t1);
4449 #if defined(TARGET_MIPS64)
4450 /* Copy GPR to and from TX79 HI1/LO1 register. */
4451 static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg)
4453 if (reg == 0 && (opc == MMI_OPC_MFHI1 || opc == MMI_OPC_MFLO1)) {
4454 /* Treat as NOP. */
4455 return;
4458 switch (opc) {
4459 case MMI_OPC_MFHI1:
4460 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[1]);
4461 break;
4462 case MMI_OPC_MFLO1:
4463 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[1]);
4464 break;
4465 case MMI_OPC_MTHI1:
4466 if (reg != 0) {
4467 tcg_gen_mov_tl(cpu_HI[1], cpu_gpr[reg]);
4468 } else {
4469 tcg_gen_movi_tl(cpu_HI[1], 0);
4471 break;
4472 case MMI_OPC_MTLO1:
4473 if (reg != 0) {
4474 tcg_gen_mov_tl(cpu_LO[1], cpu_gpr[reg]);
4475 } else {
4476 tcg_gen_movi_tl(cpu_LO[1], 0);
4478 break;
4479 default:
4480 MIPS_INVAL("mfthilo1 TX79");
4481 generate_exception_end(ctx, EXCP_RI);
4482 break;
4485 #endif
4487 /* Arithmetic on HI/LO registers */
4488 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
4490 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
4491 /* Treat as NOP. */
4492 return;
4495 if (acc != 0) {
4496 check_dsp(ctx);
4499 switch (opc) {
4500 case OPC_MFHI:
4501 #if defined(TARGET_MIPS64)
4502 if (acc != 0) {
4503 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
4504 } else
4505 #endif
4507 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
4509 break;
4510 case OPC_MFLO:
4511 #if defined(TARGET_MIPS64)
4512 if (acc != 0) {
4513 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
4514 } else
4515 #endif
4517 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
4519 break;
4520 case OPC_MTHI:
4521 if (reg != 0) {
4522 #if defined(TARGET_MIPS64)
4523 if (acc != 0) {
4524 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
4525 } else
4526 #endif
4528 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
4530 } else {
4531 tcg_gen_movi_tl(cpu_HI[acc], 0);
4533 break;
4534 case OPC_MTLO:
4535 if (reg != 0) {
4536 #if defined(TARGET_MIPS64)
4537 if (acc != 0) {
4538 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
4539 } else
4540 #endif
4542 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
4544 } else {
4545 tcg_gen_movi_tl(cpu_LO[acc], 0);
4547 break;
4551 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
4552 TCGMemOp memop)
4554 TCGv t0 = tcg_const_tl(addr);
4555 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
4556 gen_store_gpr(t0, reg);
4557 tcg_temp_free(t0);
4560 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
4561 int rs)
4563 target_long offset;
4564 target_long addr;
4566 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
4567 case OPC_ADDIUPC:
4568 if (rs != 0) {
4569 offset = sextract32(ctx->opcode << 2, 0, 21);
4570 addr = addr_add(ctx, pc, offset);
4571 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4573 break;
4574 case R6_OPC_LWPC:
4575 offset = sextract32(ctx->opcode << 2, 0, 21);
4576 addr = addr_add(ctx, pc, offset);
4577 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4578 break;
4579 #if defined(TARGET_MIPS64)
4580 case OPC_LWUPC:
4581 check_mips_64(ctx);
4582 offset = sextract32(ctx->opcode << 2, 0, 21);
4583 addr = addr_add(ctx, pc, offset);
4584 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4585 break;
4586 #endif
4587 default:
4588 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
4589 case OPC_AUIPC:
4590 if (rs != 0) {
4591 offset = sextract32(ctx->opcode, 0, 16) << 16;
4592 addr = addr_add(ctx, pc, offset);
4593 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4595 break;
4596 case OPC_ALUIPC:
4597 if (rs != 0) {
4598 offset = sextract32(ctx->opcode, 0, 16) << 16;
4599 addr = ~0xFFFF & addr_add(ctx, pc, offset);
4600 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4602 break;
4603 #if defined(TARGET_MIPS64)
4604 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4605 case R6_OPC_LDPC + (1 << 16):
4606 case R6_OPC_LDPC + (2 << 16):
4607 case R6_OPC_LDPC + (3 << 16):
4608 check_mips_64(ctx);
4609 offset = sextract32(ctx->opcode << 3, 0, 21);
4610 addr = addr_add(ctx, (pc & ~0x7), offset);
4611 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4612 break;
4613 #endif
4614 default:
4615 MIPS_INVAL("OPC_PCREL");
4616 generate_exception_end(ctx, EXCP_RI);
4617 break;
4619 break;
4623 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4625 TCGv t0, t1;
4627 if (rd == 0) {
4628 /* Treat as NOP. */
4629 return;
4632 t0 = tcg_temp_new();
4633 t1 = tcg_temp_new();
4635 gen_load_gpr(t0, rs);
4636 gen_load_gpr(t1, rt);
4638 switch (opc) {
4639 case R6_OPC_DIV:
4641 TCGv t2 = tcg_temp_new();
4642 TCGv t3 = tcg_temp_new();
4643 tcg_gen_ext32s_tl(t0, t0);
4644 tcg_gen_ext32s_tl(t1, t1);
4645 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4646 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4647 tcg_gen_and_tl(t2, t2, t3);
4648 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4649 tcg_gen_or_tl(t2, t2, t3);
4650 tcg_gen_movi_tl(t3, 0);
4651 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4652 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4653 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4654 tcg_temp_free(t3);
4655 tcg_temp_free(t2);
4657 break;
4658 case R6_OPC_MOD:
4660 TCGv t2 = tcg_temp_new();
4661 TCGv t3 = tcg_temp_new();
4662 tcg_gen_ext32s_tl(t0, t0);
4663 tcg_gen_ext32s_tl(t1, t1);
4664 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4665 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4666 tcg_gen_and_tl(t2, t2, t3);
4667 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4668 tcg_gen_or_tl(t2, t2, t3);
4669 tcg_gen_movi_tl(t3, 0);
4670 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4671 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4672 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4673 tcg_temp_free(t3);
4674 tcg_temp_free(t2);
4676 break;
4677 case R6_OPC_DIVU:
4679 TCGv t2 = tcg_const_tl(0);
4680 TCGv t3 = tcg_const_tl(1);
4681 tcg_gen_ext32u_tl(t0, t0);
4682 tcg_gen_ext32u_tl(t1, t1);
4683 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4684 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4685 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4686 tcg_temp_free(t3);
4687 tcg_temp_free(t2);
4689 break;
4690 case R6_OPC_MODU:
4692 TCGv t2 = tcg_const_tl(0);
4693 TCGv t3 = tcg_const_tl(1);
4694 tcg_gen_ext32u_tl(t0, t0);
4695 tcg_gen_ext32u_tl(t1, t1);
4696 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4697 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4698 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4699 tcg_temp_free(t3);
4700 tcg_temp_free(t2);
4702 break;
4703 case R6_OPC_MUL:
4705 TCGv_i32 t2 = tcg_temp_new_i32();
4706 TCGv_i32 t3 = tcg_temp_new_i32();
4707 tcg_gen_trunc_tl_i32(t2, t0);
4708 tcg_gen_trunc_tl_i32(t3, t1);
4709 tcg_gen_mul_i32(t2, t2, t3);
4710 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4711 tcg_temp_free_i32(t2);
4712 tcg_temp_free_i32(t3);
4714 break;
4715 case R6_OPC_MUH:
4717 TCGv_i32 t2 = tcg_temp_new_i32();
4718 TCGv_i32 t3 = tcg_temp_new_i32();
4719 tcg_gen_trunc_tl_i32(t2, t0);
4720 tcg_gen_trunc_tl_i32(t3, t1);
4721 tcg_gen_muls2_i32(t2, t3, t2, t3);
4722 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4723 tcg_temp_free_i32(t2);
4724 tcg_temp_free_i32(t3);
4726 break;
4727 case R6_OPC_MULU:
4729 TCGv_i32 t2 = tcg_temp_new_i32();
4730 TCGv_i32 t3 = tcg_temp_new_i32();
4731 tcg_gen_trunc_tl_i32(t2, t0);
4732 tcg_gen_trunc_tl_i32(t3, t1);
4733 tcg_gen_mul_i32(t2, t2, t3);
4734 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4735 tcg_temp_free_i32(t2);
4736 tcg_temp_free_i32(t3);
4738 break;
4739 case R6_OPC_MUHU:
4741 TCGv_i32 t2 = tcg_temp_new_i32();
4742 TCGv_i32 t3 = tcg_temp_new_i32();
4743 tcg_gen_trunc_tl_i32(t2, t0);
4744 tcg_gen_trunc_tl_i32(t3, t1);
4745 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4746 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4747 tcg_temp_free_i32(t2);
4748 tcg_temp_free_i32(t3);
4750 break;
4751 #if defined(TARGET_MIPS64)
4752 case R6_OPC_DDIV:
4754 TCGv t2 = tcg_temp_new();
4755 TCGv t3 = tcg_temp_new();
4756 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4757 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4758 tcg_gen_and_tl(t2, t2, t3);
4759 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4760 tcg_gen_or_tl(t2, t2, t3);
4761 tcg_gen_movi_tl(t3, 0);
4762 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4763 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4764 tcg_temp_free(t3);
4765 tcg_temp_free(t2);
4767 break;
4768 case R6_OPC_DMOD:
4770 TCGv t2 = tcg_temp_new();
4771 TCGv t3 = tcg_temp_new();
4772 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4773 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4774 tcg_gen_and_tl(t2, t2, t3);
4775 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4776 tcg_gen_or_tl(t2, t2, t3);
4777 tcg_gen_movi_tl(t3, 0);
4778 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4779 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4780 tcg_temp_free(t3);
4781 tcg_temp_free(t2);
4783 break;
4784 case R6_OPC_DDIVU:
4786 TCGv t2 = tcg_const_tl(0);
4787 TCGv t3 = tcg_const_tl(1);
4788 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4789 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4790 tcg_temp_free(t3);
4791 tcg_temp_free(t2);
4793 break;
4794 case R6_OPC_DMODU:
4796 TCGv t2 = tcg_const_tl(0);
4797 TCGv t3 = tcg_const_tl(1);
4798 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4799 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4800 tcg_temp_free(t3);
4801 tcg_temp_free(t2);
4803 break;
4804 case R6_OPC_DMUL:
4805 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4806 break;
4807 case R6_OPC_DMUH:
4809 TCGv t2 = tcg_temp_new();
4810 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4811 tcg_temp_free(t2);
4813 break;
4814 case R6_OPC_DMULU:
4815 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4816 break;
4817 case R6_OPC_DMUHU:
4819 TCGv t2 = tcg_temp_new();
4820 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4821 tcg_temp_free(t2);
4823 break;
4824 #endif
4825 default:
4826 MIPS_INVAL("r6 mul/div");
4827 generate_exception_end(ctx, EXCP_RI);
4828 goto out;
4830 out:
4831 tcg_temp_free(t0);
4832 tcg_temp_free(t1);
4835 #if defined(TARGET_MIPS64)
4836 static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
4838 TCGv t0, t1;
4840 t0 = tcg_temp_new();
4841 t1 = tcg_temp_new();
4843 gen_load_gpr(t0, rs);
4844 gen_load_gpr(t1, rt);
4846 switch (opc) {
4847 case MMI_OPC_DIV1:
4849 TCGv t2 = tcg_temp_new();
4850 TCGv t3 = tcg_temp_new();
4851 tcg_gen_ext32s_tl(t0, t0);
4852 tcg_gen_ext32s_tl(t1, t1);
4853 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4854 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4855 tcg_gen_and_tl(t2, t2, t3);
4856 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4857 tcg_gen_or_tl(t2, t2, t3);
4858 tcg_gen_movi_tl(t3, 0);
4859 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4860 tcg_gen_div_tl(cpu_LO[1], t0, t1);
4861 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
4862 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4863 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4864 tcg_temp_free(t3);
4865 tcg_temp_free(t2);
4867 break;
4868 case MMI_OPC_DIVU1:
4870 TCGv t2 = tcg_const_tl(0);
4871 TCGv t3 = tcg_const_tl(1);
4872 tcg_gen_ext32u_tl(t0, t0);
4873 tcg_gen_ext32u_tl(t1, t1);
4874 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4875 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
4876 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
4877 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4878 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4879 tcg_temp_free(t3);
4880 tcg_temp_free(t2);
4882 break;
4883 default:
4884 MIPS_INVAL("div1 TX79");
4885 generate_exception_end(ctx, EXCP_RI);
4886 goto out;
4888 out:
4889 tcg_temp_free(t0);
4890 tcg_temp_free(t1);
4892 #endif
4894 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4895 int acc, int rs, int rt)
4897 TCGv t0, t1;
4899 t0 = tcg_temp_new();
4900 t1 = tcg_temp_new();
4902 gen_load_gpr(t0, rs);
4903 gen_load_gpr(t1, rt);
4905 if (acc != 0) {
4906 check_dsp(ctx);
4909 switch (opc) {
4910 case OPC_DIV:
4912 TCGv t2 = tcg_temp_new();
4913 TCGv t3 = tcg_temp_new();
4914 tcg_gen_ext32s_tl(t0, t0);
4915 tcg_gen_ext32s_tl(t1, t1);
4916 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4917 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4918 tcg_gen_and_tl(t2, t2, t3);
4919 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4920 tcg_gen_or_tl(t2, t2, t3);
4921 tcg_gen_movi_tl(t3, 0);
4922 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4923 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4924 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4925 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4926 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4927 tcg_temp_free(t3);
4928 tcg_temp_free(t2);
4930 break;
4931 case OPC_DIVU:
4933 TCGv t2 = tcg_const_tl(0);
4934 TCGv t3 = tcg_const_tl(1);
4935 tcg_gen_ext32u_tl(t0, t0);
4936 tcg_gen_ext32u_tl(t1, t1);
4937 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4938 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4939 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4940 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4941 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4942 tcg_temp_free(t3);
4943 tcg_temp_free(t2);
4945 break;
4946 case OPC_MULT:
4948 TCGv_i32 t2 = tcg_temp_new_i32();
4949 TCGv_i32 t3 = tcg_temp_new_i32();
4950 tcg_gen_trunc_tl_i32(t2, t0);
4951 tcg_gen_trunc_tl_i32(t3, t1);
4952 tcg_gen_muls2_i32(t2, t3, t2, t3);
4953 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4954 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4955 tcg_temp_free_i32(t2);
4956 tcg_temp_free_i32(t3);
4958 break;
4959 case OPC_MULTU:
4961 TCGv_i32 t2 = tcg_temp_new_i32();
4962 TCGv_i32 t3 = tcg_temp_new_i32();
4963 tcg_gen_trunc_tl_i32(t2, t0);
4964 tcg_gen_trunc_tl_i32(t3, t1);
4965 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4966 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4967 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4968 tcg_temp_free_i32(t2);
4969 tcg_temp_free_i32(t3);
4971 break;
4972 #if defined(TARGET_MIPS64)
4973 case OPC_DDIV:
4975 TCGv t2 = tcg_temp_new();
4976 TCGv t3 = tcg_temp_new();
4977 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4978 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4979 tcg_gen_and_tl(t2, t2, t3);
4980 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4981 tcg_gen_or_tl(t2, t2, t3);
4982 tcg_gen_movi_tl(t3, 0);
4983 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4984 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4985 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4986 tcg_temp_free(t3);
4987 tcg_temp_free(t2);
4989 break;
4990 case OPC_DDIVU:
4992 TCGv t2 = tcg_const_tl(0);
4993 TCGv t3 = tcg_const_tl(1);
4994 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4995 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
4996 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
4997 tcg_temp_free(t3);
4998 tcg_temp_free(t2);
5000 break;
5001 case OPC_DMULT:
5002 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
5003 break;
5004 case OPC_DMULTU:
5005 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
5006 break;
5007 #endif
5008 case OPC_MADD:
5010 TCGv_i64 t2 = tcg_temp_new_i64();
5011 TCGv_i64 t3 = tcg_temp_new_i64();
5013 tcg_gen_ext_tl_i64(t2, t0);
5014 tcg_gen_ext_tl_i64(t3, t1);
5015 tcg_gen_mul_i64(t2, t2, t3);
5016 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5017 tcg_gen_add_i64(t2, t2, t3);
5018 tcg_temp_free_i64(t3);
5019 gen_move_low32(cpu_LO[acc], t2);
5020 gen_move_high32(cpu_HI[acc], t2);
5021 tcg_temp_free_i64(t2);
5023 break;
5024 case OPC_MADDU:
5026 TCGv_i64 t2 = tcg_temp_new_i64();
5027 TCGv_i64 t3 = tcg_temp_new_i64();
5029 tcg_gen_ext32u_tl(t0, t0);
5030 tcg_gen_ext32u_tl(t1, t1);
5031 tcg_gen_extu_tl_i64(t2, t0);
5032 tcg_gen_extu_tl_i64(t3, t1);
5033 tcg_gen_mul_i64(t2, t2, t3);
5034 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5035 tcg_gen_add_i64(t2, t2, t3);
5036 tcg_temp_free_i64(t3);
5037 gen_move_low32(cpu_LO[acc], t2);
5038 gen_move_high32(cpu_HI[acc], t2);
5039 tcg_temp_free_i64(t2);
5041 break;
5042 case OPC_MSUB:
5044 TCGv_i64 t2 = tcg_temp_new_i64();
5045 TCGv_i64 t3 = tcg_temp_new_i64();
5047 tcg_gen_ext_tl_i64(t2, t0);
5048 tcg_gen_ext_tl_i64(t3, t1);
5049 tcg_gen_mul_i64(t2, t2, t3);
5050 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5051 tcg_gen_sub_i64(t2, t3, t2);
5052 tcg_temp_free_i64(t3);
5053 gen_move_low32(cpu_LO[acc], t2);
5054 gen_move_high32(cpu_HI[acc], t2);
5055 tcg_temp_free_i64(t2);
5057 break;
5058 case OPC_MSUBU:
5060 TCGv_i64 t2 = tcg_temp_new_i64();
5061 TCGv_i64 t3 = tcg_temp_new_i64();
5063 tcg_gen_ext32u_tl(t0, t0);
5064 tcg_gen_ext32u_tl(t1, t1);
5065 tcg_gen_extu_tl_i64(t2, t0);
5066 tcg_gen_extu_tl_i64(t3, t1);
5067 tcg_gen_mul_i64(t2, t2, t3);
5068 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5069 tcg_gen_sub_i64(t2, t3, t2);
5070 tcg_temp_free_i64(t3);
5071 gen_move_low32(cpu_LO[acc], t2);
5072 gen_move_high32(cpu_HI[acc], t2);
5073 tcg_temp_free_i64(t2);
5075 break;
5076 default:
5077 MIPS_INVAL("mul/div");
5078 generate_exception_end(ctx, EXCP_RI);
5079 goto out;
5081 out:
5082 tcg_temp_free(t0);
5083 tcg_temp_free(t1);
5087 * These MULT[U] and MADD[U] instructions implemented in for example
5088 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
5089 * architectures are special three-operand variants with the syntax
5091 * MULT[U][1] rd, rs, rt
5093 * such that
5095 * (rd, LO, HI) <- rs * rt
5097 * and
5099 * MADD[U][1] rd, rs, rt
5101 * such that
5103 * (rd, LO, HI) <- (LO, HI) + rs * rt
5105 * where the low-order 32-bits of the result is placed into both the
5106 * GPR rd and the special register LO. The high-order 32-bits of the
5107 * result is placed into the special register HI.
5109 * If the GPR rd is omitted in assembly language, it is taken to be 0,
5110 * which is the zero register that always reads as 0.
5112 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
5113 int rd, int rs, int rt)
5115 TCGv t0 = tcg_temp_new();
5116 TCGv t1 = tcg_temp_new();
5117 int acc = 0;
5119 gen_load_gpr(t0, rs);
5120 gen_load_gpr(t1, rt);
5122 switch (opc) {
5123 case MMI_OPC_MULT1:
5124 acc = 1;
5125 /* Fall through */
5126 case OPC_MULT:
5128 TCGv_i32 t2 = tcg_temp_new_i32();
5129 TCGv_i32 t3 = tcg_temp_new_i32();
5130 tcg_gen_trunc_tl_i32(t2, t0);
5131 tcg_gen_trunc_tl_i32(t3, t1);
5132 tcg_gen_muls2_i32(t2, t3, t2, t3);
5133 if (rd) {
5134 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5136 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5137 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5138 tcg_temp_free_i32(t2);
5139 tcg_temp_free_i32(t3);
5141 break;
5142 case MMI_OPC_MULTU1:
5143 acc = 1;
5144 /* Fall through */
5145 case OPC_MULTU:
5147 TCGv_i32 t2 = tcg_temp_new_i32();
5148 TCGv_i32 t3 = tcg_temp_new_i32();
5149 tcg_gen_trunc_tl_i32(t2, t0);
5150 tcg_gen_trunc_tl_i32(t3, t1);
5151 tcg_gen_mulu2_i32(t2, t3, t2, t3);
5152 if (rd) {
5153 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5155 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5156 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5157 tcg_temp_free_i32(t2);
5158 tcg_temp_free_i32(t3);
5160 break;
5161 case MMI_OPC_MADD1:
5162 acc = 1;
5163 /* Fall through */
5164 case MMI_OPC_MADD:
5166 TCGv_i64 t2 = tcg_temp_new_i64();
5167 TCGv_i64 t3 = tcg_temp_new_i64();
5169 tcg_gen_ext_tl_i64(t2, t0);
5170 tcg_gen_ext_tl_i64(t3, t1);
5171 tcg_gen_mul_i64(t2, t2, t3);
5172 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5173 tcg_gen_add_i64(t2, t2, t3);
5174 tcg_temp_free_i64(t3);
5175 gen_move_low32(cpu_LO[acc], t2);
5176 gen_move_high32(cpu_HI[acc], t2);
5177 if (rd) {
5178 gen_move_low32(cpu_gpr[rd], t2);
5180 tcg_temp_free_i64(t2);
5182 break;
5183 case MMI_OPC_MADDU1:
5184 acc = 1;
5185 /* Fall through */
5186 case MMI_OPC_MADDU:
5188 TCGv_i64 t2 = tcg_temp_new_i64();
5189 TCGv_i64 t3 = tcg_temp_new_i64();
5191 tcg_gen_ext32u_tl(t0, t0);
5192 tcg_gen_ext32u_tl(t1, t1);
5193 tcg_gen_extu_tl_i64(t2, t0);
5194 tcg_gen_extu_tl_i64(t3, t1);
5195 tcg_gen_mul_i64(t2, t2, t3);
5196 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5197 tcg_gen_add_i64(t2, t2, t3);
5198 tcg_temp_free_i64(t3);
5199 gen_move_low32(cpu_LO[acc], t2);
5200 gen_move_high32(cpu_HI[acc], t2);
5201 if (rd) {
5202 gen_move_low32(cpu_gpr[rd], t2);
5204 tcg_temp_free_i64(t2);
5206 break;
5207 default:
5208 MIPS_INVAL("mul/madd TXx9");
5209 generate_exception_end(ctx, EXCP_RI);
5210 goto out;
5213 out:
5214 tcg_temp_free(t0);
5215 tcg_temp_free(t1);
5218 static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc,
5219 int rd, int rs, int rt)
5221 TCGv t0 = tcg_temp_new();
5222 TCGv t1 = tcg_temp_new();
5224 gen_load_gpr(t0, rs);
5225 gen_load_gpr(t1, rt);
5227 switch (opc) {
5228 case OPC_VR54XX_MULS:
5229 gen_helper_muls(t0, cpu_env, t0, t1);
5230 break;
5231 case OPC_VR54XX_MULSU:
5232 gen_helper_mulsu(t0, cpu_env, t0, t1);
5233 break;
5234 case OPC_VR54XX_MACC:
5235 gen_helper_macc(t0, cpu_env, t0, t1);
5236 break;
5237 case OPC_VR54XX_MACCU:
5238 gen_helper_maccu(t0, cpu_env, t0, t1);
5239 break;
5240 case OPC_VR54XX_MSAC:
5241 gen_helper_msac(t0, cpu_env, t0, t1);
5242 break;
5243 case OPC_VR54XX_MSACU:
5244 gen_helper_msacu(t0, cpu_env, t0, t1);
5245 break;
5246 case OPC_VR54XX_MULHI:
5247 gen_helper_mulhi(t0, cpu_env, t0, t1);
5248 break;
5249 case OPC_VR54XX_MULHIU:
5250 gen_helper_mulhiu(t0, cpu_env, t0, t1);
5251 break;
5252 case OPC_VR54XX_MULSHI:
5253 gen_helper_mulshi(t0, cpu_env, t0, t1);
5254 break;
5255 case OPC_VR54XX_MULSHIU:
5256 gen_helper_mulshiu(t0, cpu_env, t0, t1);
5257 break;
5258 case OPC_VR54XX_MACCHI:
5259 gen_helper_macchi(t0, cpu_env, t0, t1);
5260 break;
5261 case OPC_VR54XX_MACCHIU:
5262 gen_helper_macchiu(t0, cpu_env, t0, t1);
5263 break;
5264 case OPC_VR54XX_MSACHI:
5265 gen_helper_msachi(t0, cpu_env, t0, t1);
5266 break;
5267 case OPC_VR54XX_MSACHIU:
5268 gen_helper_msachiu(t0, cpu_env, t0, t1);
5269 break;
5270 default:
5271 MIPS_INVAL("mul vr54xx");
5272 generate_exception_end(ctx, EXCP_RI);
5273 goto out;
5275 gen_store_gpr(t0, rd);
5277 out:
5278 tcg_temp_free(t0);
5279 tcg_temp_free(t1);
5282 static void gen_cl(DisasContext *ctx, uint32_t opc,
5283 int rd, int rs)
5285 TCGv t0;
5287 if (rd == 0) {
5288 /* Treat as NOP. */
5289 return;
5291 t0 = cpu_gpr[rd];
5292 gen_load_gpr(t0, rs);
5294 switch (opc) {
5295 case OPC_CLO:
5296 case R6_OPC_CLO:
5297 #if defined(TARGET_MIPS64)
5298 case OPC_DCLO:
5299 case R6_OPC_DCLO:
5300 #endif
5301 tcg_gen_not_tl(t0, t0);
5302 break;
5305 switch (opc) {
5306 case OPC_CLO:
5307 case R6_OPC_CLO:
5308 case OPC_CLZ:
5309 case R6_OPC_CLZ:
5310 tcg_gen_ext32u_tl(t0, t0);
5311 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
5312 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
5313 break;
5314 #if defined(TARGET_MIPS64)
5315 case OPC_DCLO:
5316 case R6_OPC_DCLO:
5317 case OPC_DCLZ:
5318 case R6_OPC_DCLZ:
5319 tcg_gen_clzi_i64(t0, t0, 64);
5320 break;
5321 #endif
5325 /* Godson integer instructions */
5326 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
5327 int rd, int rs, int rt)
5329 TCGv t0, t1;
5331 if (rd == 0) {
5332 /* Treat as NOP. */
5333 return;
5336 switch (opc) {
5337 case OPC_MULT_G_2E:
5338 case OPC_MULT_G_2F:
5339 case OPC_MULTU_G_2E:
5340 case OPC_MULTU_G_2F:
5341 #if defined(TARGET_MIPS64)
5342 case OPC_DMULT_G_2E:
5343 case OPC_DMULT_G_2F:
5344 case OPC_DMULTU_G_2E:
5345 case OPC_DMULTU_G_2F:
5346 #endif
5347 t0 = tcg_temp_new();
5348 t1 = tcg_temp_new();
5349 break;
5350 default:
5351 t0 = tcg_temp_local_new();
5352 t1 = tcg_temp_local_new();
5353 break;
5356 gen_load_gpr(t0, rs);
5357 gen_load_gpr(t1, rt);
5359 switch (opc) {
5360 case OPC_MULT_G_2E:
5361 case OPC_MULT_G_2F:
5362 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5363 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5364 break;
5365 case OPC_MULTU_G_2E:
5366 case OPC_MULTU_G_2F:
5367 tcg_gen_ext32u_tl(t0, t0);
5368 tcg_gen_ext32u_tl(t1, t1);
5369 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5370 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5371 break;
5372 case OPC_DIV_G_2E:
5373 case OPC_DIV_G_2F:
5375 TCGLabel *l1 = gen_new_label();
5376 TCGLabel *l2 = gen_new_label();
5377 TCGLabel *l3 = gen_new_label();
5378 tcg_gen_ext32s_tl(t0, t0);
5379 tcg_gen_ext32s_tl(t1, t1);
5380 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5381 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5382 tcg_gen_br(l3);
5383 gen_set_label(l1);
5384 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5385 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5386 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5387 tcg_gen_br(l3);
5388 gen_set_label(l2);
5389 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5390 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5391 gen_set_label(l3);
5393 break;
5394 case OPC_DIVU_G_2E:
5395 case OPC_DIVU_G_2F:
5397 TCGLabel *l1 = gen_new_label();
5398 TCGLabel *l2 = gen_new_label();
5399 tcg_gen_ext32u_tl(t0, t0);
5400 tcg_gen_ext32u_tl(t1, t1);
5401 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5402 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5403 tcg_gen_br(l2);
5404 gen_set_label(l1);
5405 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5406 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5407 gen_set_label(l2);
5409 break;
5410 case OPC_MOD_G_2E:
5411 case OPC_MOD_G_2F:
5413 TCGLabel *l1 = gen_new_label();
5414 TCGLabel *l2 = gen_new_label();
5415 TCGLabel *l3 = gen_new_label();
5416 tcg_gen_ext32u_tl(t0, t0);
5417 tcg_gen_ext32u_tl(t1, t1);
5418 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5419 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5420 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5421 gen_set_label(l1);
5422 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5423 tcg_gen_br(l3);
5424 gen_set_label(l2);
5425 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5426 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5427 gen_set_label(l3);
5429 break;
5430 case OPC_MODU_G_2E:
5431 case OPC_MODU_G_2F:
5433 TCGLabel *l1 = gen_new_label();
5434 TCGLabel *l2 = gen_new_label();
5435 tcg_gen_ext32u_tl(t0, t0);
5436 tcg_gen_ext32u_tl(t1, t1);
5437 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5438 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5439 tcg_gen_br(l2);
5440 gen_set_label(l1);
5441 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5442 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5443 gen_set_label(l2);
5445 break;
5446 #if defined(TARGET_MIPS64)
5447 case OPC_DMULT_G_2E:
5448 case OPC_DMULT_G_2F:
5449 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5450 break;
5451 case OPC_DMULTU_G_2E:
5452 case OPC_DMULTU_G_2F:
5453 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5454 break;
5455 case OPC_DDIV_G_2E:
5456 case OPC_DDIV_G_2F:
5458 TCGLabel *l1 = gen_new_label();
5459 TCGLabel *l2 = gen_new_label();
5460 TCGLabel *l3 = gen_new_label();
5461 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5462 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5463 tcg_gen_br(l3);
5464 gen_set_label(l1);
5465 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5466 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5467 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5468 tcg_gen_br(l3);
5469 gen_set_label(l2);
5470 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5471 gen_set_label(l3);
5473 break;
5474 case OPC_DDIVU_G_2E:
5475 case OPC_DDIVU_G_2F:
5477 TCGLabel *l1 = gen_new_label();
5478 TCGLabel *l2 = gen_new_label();
5479 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5480 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5481 tcg_gen_br(l2);
5482 gen_set_label(l1);
5483 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5484 gen_set_label(l2);
5486 break;
5487 case OPC_DMOD_G_2E:
5488 case OPC_DMOD_G_2F:
5490 TCGLabel *l1 = gen_new_label();
5491 TCGLabel *l2 = gen_new_label();
5492 TCGLabel *l3 = gen_new_label();
5493 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5494 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5495 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5496 gen_set_label(l1);
5497 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5498 tcg_gen_br(l3);
5499 gen_set_label(l2);
5500 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5501 gen_set_label(l3);
5503 break;
5504 case OPC_DMODU_G_2E:
5505 case OPC_DMODU_G_2F:
5507 TCGLabel *l1 = gen_new_label();
5508 TCGLabel *l2 = gen_new_label();
5509 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5510 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5511 tcg_gen_br(l2);
5512 gen_set_label(l1);
5513 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5514 gen_set_label(l2);
5516 break;
5517 #endif
5520 tcg_temp_free(t0);
5521 tcg_temp_free(t1);
5524 /* Loongson multimedia instructions */
5525 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
5527 uint32_t opc, shift_max;
5528 TCGv_i64 t0, t1;
5530 opc = MASK_LMI(ctx->opcode);
5531 switch (opc) {
5532 case OPC_ADD_CP2:
5533 case OPC_SUB_CP2:
5534 case OPC_DADD_CP2:
5535 case OPC_DSUB_CP2:
5536 t0 = tcg_temp_local_new_i64();
5537 t1 = tcg_temp_local_new_i64();
5538 break;
5539 default:
5540 t0 = tcg_temp_new_i64();
5541 t1 = tcg_temp_new_i64();
5542 break;
5545 check_cp1_enabled(ctx);
5546 gen_load_fpr64(ctx, t0, rs);
5547 gen_load_fpr64(ctx, t1, rt);
5549 #define LMI_HELPER(UP, LO) \
5550 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
5551 #define LMI_HELPER_1(UP, LO) \
5552 case OPC_##UP: gen_helper_##LO(t0, t0); break
5553 #define LMI_DIRECT(UP, LO, OP) \
5554 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
5556 switch (opc) {
5557 LMI_HELPER(PADDSH, paddsh);
5558 LMI_HELPER(PADDUSH, paddush);
5559 LMI_HELPER(PADDH, paddh);
5560 LMI_HELPER(PADDW, paddw);
5561 LMI_HELPER(PADDSB, paddsb);
5562 LMI_HELPER(PADDUSB, paddusb);
5563 LMI_HELPER(PADDB, paddb);
5565 LMI_HELPER(PSUBSH, psubsh);
5566 LMI_HELPER(PSUBUSH, psubush);
5567 LMI_HELPER(PSUBH, psubh);
5568 LMI_HELPER(PSUBW, psubw);
5569 LMI_HELPER(PSUBSB, psubsb);
5570 LMI_HELPER(PSUBUSB, psubusb);
5571 LMI_HELPER(PSUBB, psubb);
5573 LMI_HELPER(PSHUFH, pshufh);
5574 LMI_HELPER(PACKSSWH, packsswh);
5575 LMI_HELPER(PACKSSHB, packsshb);
5576 LMI_HELPER(PACKUSHB, packushb);
5578 LMI_HELPER(PUNPCKLHW, punpcklhw);
5579 LMI_HELPER(PUNPCKHHW, punpckhhw);
5580 LMI_HELPER(PUNPCKLBH, punpcklbh);
5581 LMI_HELPER(PUNPCKHBH, punpckhbh);
5582 LMI_HELPER(PUNPCKLWD, punpcklwd);
5583 LMI_HELPER(PUNPCKHWD, punpckhwd);
5585 LMI_HELPER(PAVGH, pavgh);
5586 LMI_HELPER(PAVGB, pavgb);
5587 LMI_HELPER(PMAXSH, pmaxsh);
5588 LMI_HELPER(PMINSH, pminsh);
5589 LMI_HELPER(PMAXUB, pmaxub);
5590 LMI_HELPER(PMINUB, pminub);
5592 LMI_HELPER(PCMPEQW, pcmpeqw);
5593 LMI_HELPER(PCMPGTW, pcmpgtw);
5594 LMI_HELPER(PCMPEQH, pcmpeqh);
5595 LMI_HELPER(PCMPGTH, pcmpgth);
5596 LMI_HELPER(PCMPEQB, pcmpeqb);
5597 LMI_HELPER(PCMPGTB, pcmpgtb);
5599 LMI_HELPER(PSLLW, psllw);
5600 LMI_HELPER(PSLLH, psllh);
5601 LMI_HELPER(PSRLW, psrlw);
5602 LMI_HELPER(PSRLH, psrlh);
5603 LMI_HELPER(PSRAW, psraw);
5604 LMI_HELPER(PSRAH, psrah);
5606 LMI_HELPER(PMULLH, pmullh);
5607 LMI_HELPER(PMULHH, pmulhh);
5608 LMI_HELPER(PMULHUH, pmulhuh);
5609 LMI_HELPER(PMADDHW, pmaddhw);
5611 LMI_HELPER(PASUBUB, pasubub);
5612 LMI_HELPER_1(BIADD, biadd);
5613 LMI_HELPER_1(PMOVMSKB, pmovmskb);
5615 LMI_DIRECT(PADDD, paddd, add);
5616 LMI_DIRECT(PSUBD, psubd, sub);
5617 LMI_DIRECT(XOR_CP2, xor, xor);
5618 LMI_DIRECT(NOR_CP2, nor, nor);
5619 LMI_DIRECT(AND_CP2, and, and);
5620 LMI_DIRECT(OR_CP2, or, or);
5622 case OPC_PANDN:
5623 tcg_gen_andc_i64(t0, t1, t0);
5624 break;
5626 case OPC_PINSRH_0:
5627 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
5628 break;
5629 case OPC_PINSRH_1:
5630 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
5631 break;
5632 case OPC_PINSRH_2:
5633 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
5634 break;
5635 case OPC_PINSRH_3:
5636 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
5637 break;
5639 case OPC_PEXTRH:
5640 tcg_gen_andi_i64(t1, t1, 3);
5641 tcg_gen_shli_i64(t1, t1, 4);
5642 tcg_gen_shr_i64(t0, t0, t1);
5643 tcg_gen_ext16u_i64(t0, t0);
5644 break;
5646 case OPC_ADDU_CP2:
5647 tcg_gen_add_i64(t0, t0, t1);
5648 tcg_gen_ext32s_i64(t0, t0);
5649 break;
5650 case OPC_SUBU_CP2:
5651 tcg_gen_sub_i64(t0, t0, t1);
5652 tcg_gen_ext32s_i64(t0, t0);
5653 break;
5655 case OPC_SLL_CP2:
5656 shift_max = 32;
5657 goto do_shift;
5658 case OPC_SRL_CP2:
5659 shift_max = 32;
5660 goto do_shift;
5661 case OPC_SRA_CP2:
5662 shift_max = 32;
5663 goto do_shift;
5664 case OPC_DSLL_CP2:
5665 shift_max = 64;
5666 goto do_shift;
5667 case OPC_DSRL_CP2:
5668 shift_max = 64;
5669 goto do_shift;
5670 case OPC_DSRA_CP2:
5671 shift_max = 64;
5672 goto do_shift;
5673 do_shift:
5674 /* Make sure shift count isn't TCG undefined behaviour. */
5675 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5677 switch (opc) {
5678 case OPC_SLL_CP2:
5679 case OPC_DSLL_CP2:
5680 tcg_gen_shl_i64(t0, t0, t1);
5681 break;
5682 case OPC_SRA_CP2:
5683 case OPC_DSRA_CP2:
5685 * Since SRA is UndefinedResult without sign-extended inputs,
5686 * we can treat SRA and DSRA the same.
5688 tcg_gen_sar_i64(t0, t0, t1);
5689 break;
5690 case OPC_SRL_CP2:
5691 /* We want to shift in zeros for SRL; zero-extend first. */
5692 tcg_gen_ext32u_i64(t0, t0);
5693 /* FALLTHRU */
5694 case OPC_DSRL_CP2:
5695 tcg_gen_shr_i64(t0, t0, t1);
5696 break;
5699 if (shift_max == 32) {
5700 tcg_gen_ext32s_i64(t0, t0);
5703 /* Shifts larger than MAX produce zero. */
5704 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5705 tcg_gen_neg_i64(t1, t1);
5706 tcg_gen_and_i64(t0, t0, t1);
5707 break;
5709 case OPC_ADD_CP2:
5710 case OPC_DADD_CP2:
5712 TCGv_i64 t2 = tcg_temp_new_i64();
5713 TCGLabel *lab = gen_new_label();
5715 tcg_gen_mov_i64(t2, t0);
5716 tcg_gen_add_i64(t0, t1, t2);
5717 if (opc == OPC_ADD_CP2) {
5718 tcg_gen_ext32s_i64(t0, t0);
5720 tcg_gen_xor_i64(t1, t1, t2);
5721 tcg_gen_xor_i64(t2, t2, t0);
5722 tcg_gen_andc_i64(t1, t2, t1);
5723 tcg_temp_free_i64(t2);
5724 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5725 generate_exception(ctx, EXCP_OVERFLOW);
5726 gen_set_label(lab);
5727 break;
5730 case OPC_SUB_CP2:
5731 case OPC_DSUB_CP2:
5733 TCGv_i64 t2 = tcg_temp_new_i64();
5734 TCGLabel *lab = gen_new_label();
5736 tcg_gen_mov_i64(t2, t0);
5737 tcg_gen_sub_i64(t0, t1, t2);
5738 if (opc == OPC_SUB_CP2) {
5739 tcg_gen_ext32s_i64(t0, t0);
5741 tcg_gen_xor_i64(t1, t1, t2);
5742 tcg_gen_xor_i64(t2, t2, t0);
5743 tcg_gen_and_i64(t1, t1, t2);
5744 tcg_temp_free_i64(t2);
5745 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5746 generate_exception(ctx, EXCP_OVERFLOW);
5747 gen_set_label(lab);
5748 break;
5751 case OPC_PMULUW:
5752 tcg_gen_ext32u_i64(t0, t0);
5753 tcg_gen_ext32u_i64(t1, t1);
5754 tcg_gen_mul_i64(t0, t0, t1);
5755 break;
5757 case OPC_SEQU_CP2:
5758 case OPC_SEQ_CP2:
5759 case OPC_SLTU_CP2:
5760 case OPC_SLT_CP2:
5761 case OPC_SLEU_CP2:
5762 case OPC_SLE_CP2:
5764 * ??? Document is unclear: Set FCC[CC]. Does that mean the
5765 * FD field is the CC field?
5767 default:
5768 MIPS_INVAL("loongson_cp2");
5769 generate_exception_end(ctx, EXCP_RI);
5770 return;
5773 #undef LMI_HELPER
5774 #undef LMI_DIRECT
5776 gen_store_fpr64(ctx, t0, rd);
5778 tcg_temp_free_i64(t0);
5779 tcg_temp_free_i64(t1);
5782 /* Traps */
5783 static void gen_trap(DisasContext *ctx, uint32_t opc,
5784 int rs, int rt, int16_t imm)
5786 int cond;
5787 TCGv t0 = tcg_temp_new();
5788 TCGv t1 = tcg_temp_new();
5790 cond = 0;
5791 /* Load needed operands */
5792 switch (opc) {
5793 case OPC_TEQ:
5794 case OPC_TGE:
5795 case OPC_TGEU:
5796 case OPC_TLT:
5797 case OPC_TLTU:
5798 case OPC_TNE:
5799 /* Compare two registers */
5800 if (rs != rt) {
5801 gen_load_gpr(t0, rs);
5802 gen_load_gpr(t1, rt);
5803 cond = 1;
5805 break;
5806 case OPC_TEQI:
5807 case OPC_TGEI:
5808 case OPC_TGEIU:
5809 case OPC_TLTI:
5810 case OPC_TLTIU:
5811 case OPC_TNEI:
5812 /* Compare register to immediate */
5813 if (rs != 0 || imm != 0) {
5814 gen_load_gpr(t0, rs);
5815 tcg_gen_movi_tl(t1, (int32_t)imm);
5816 cond = 1;
5818 break;
5820 if (cond == 0) {
5821 switch (opc) {
5822 case OPC_TEQ: /* rs == rs */
5823 case OPC_TEQI: /* r0 == 0 */
5824 case OPC_TGE: /* rs >= rs */
5825 case OPC_TGEI: /* r0 >= 0 */
5826 case OPC_TGEU: /* rs >= rs unsigned */
5827 case OPC_TGEIU: /* r0 >= 0 unsigned */
5828 /* Always trap */
5829 generate_exception_end(ctx, EXCP_TRAP);
5830 break;
5831 case OPC_TLT: /* rs < rs */
5832 case OPC_TLTI: /* r0 < 0 */
5833 case OPC_TLTU: /* rs < rs unsigned */
5834 case OPC_TLTIU: /* r0 < 0 unsigned */
5835 case OPC_TNE: /* rs != rs */
5836 case OPC_TNEI: /* r0 != 0 */
5837 /* Never trap: treat as NOP. */
5838 break;
5840 } else {
5841 TCGLabel *l1 = gen_new_label();
5843 switch (opc) {
5844 case OPC_TEQ:
5845 case OPC_TEQI:
5846 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
5847 break;
5848 case OPC_TGE:
5849 case OPC_TGEI:
5850 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
5851 break;
5852 case OPC_TGEU:
5853 case OPC_TGEIU:
5854 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
5855 break;
5856 case OPC_TLT:
5857 case OPC_TLTI:
5858 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
5859 break;
5860 case OPC_TLTU:
5861 case OPC_TLTIU:
5862 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
5863 break;
5864 case OPC_TNE:
5865 case OPC_TNEI:
5866 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
5867 break;
5869 generate_exception(ctx, EXCP_TRAP);
5870 gen_set_label(l1);
5872 tcg_temp_free(t0);
5873 tcg_temp_free(t1);
5876 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
5878 if (unlikely(ctx->base.singlestep_enabled)) {
5879 return false;
5882 #ifndef CONFIG_USER_ONLY
5883 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
5884 #else
5885 return true;
5886 #endif
5889 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
5891 if (use_goto_tb(ctx, dest)) {
5892 tcg_gen_goto_tb(n);
5893 gen_save_pc(dest);
5894 tcg_gen_exit_tb(ctx->base.tb, n);
5895 } else {
5896 gen_save_pc(dest);
5897 if (ctx->base.singlestep_enabled) {
5898 save_cpu_state(ctx, 0);
5899 gen_helper_raise_exception_debug(cpu_env);
5901 tcg_gen_lookup_and_goto_ptr();
5905 /* Branches (before delay slot) */
5906 static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
5907 int insn_bytes,
5908 int rs, int rt, int32_t offset,
5909 int delayslot_size)
5911 target_ulong btgt = -1;
5912 int blink = 0;
5913 int bcond_compute = 0;
5914 TCGv t0 = tcg_temp_new();
5915 TCGv t1 = tcg_temp_new();
5917 if (ctx->hflags & MIPS_HFLAG_BMASK) {
5918 #ifdef MIPS_DEBUG_DISAS
5919 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
5920 TARGET_FMT_lx "\n", ctx->base.pc_next);
5921 #endif
5922 generate_exception_end(ctx, EXCP_RI);
5923 goto out;
5926 /* Load needed operands */
5927 switch (opc) {
5928 case OPC_BEQ:
5929 case OPC_BEQL:
5930 case OPC_BNE:
5931 case OPC_BNEL:
5932 /* Compare two registers */
5933 if (rs != rt) {
5934 gen_load_gpr(t0, rs);
5935 gen_load_gpr(t1, rt);
5936 bcond_compute = 1;
5938 btgt = ctx->base.pc_next + insn_bytes + offset;
5939 break;
5940 case OPC_BGEZ:
5941 case OPC_BGEZAL:
5942 case OPC_BGEZALL:
5943 case OPC_BGEZL:
5944 case OPC_BGTZ:
5945 case OPC_BGTZL:
5946 case OPC_BLEZ:
5947 case OPC_BLEZL:
5948 case OPC_BLTZ:
5949 case OPC_BLTZAL:
5950 case OPC_BLTZALL:
5951 case OPC_BLTZL:
5952 /* Compare to zero */
5953 if (rs != 0) {
5954 gen_load_gpr(t0, rs);
5955 bcond_compute = 1;
5957 btgt = ctx->base.pc_next + insn_bytes + offset;
5958 break;
5959 case OPC_BPOSGE32:
5960 #if defined(TARGET_MIPS64)
5961 case OPC_BPOSGE64:
5962 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
5963 #else
5964 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5965 #endif
5966 bcond_compute = 1;
5967 btgt = ctx->base.pc_next + insn_bytes + offset;
5968 break;
5969 case OPC_J:
5970 case OPC_JAL:
5971 case OPC_JALX:
5972 /* Jump to immediate */
5973 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
5974 (uint32_t)offset;
5975 break;
5976 case OPC_JR:
5977 case OPC_JALR:
5978 /* Jump to register */
5979 if (offset != 0 && offset != 16) {
5981 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5982 * others are reserved.
5984 MIPS_INVAL("jump hint");
5985 generate_exception_end(ctx, EXCP_RI);
5986 goto out;
5988 gen_load_gpr(btarget, rs);
5989 break;
5990 default:
5991 MIPS_INVAL("branch/jump");
5992 generate_exception_end(ctx, EXCP_RI);
5993 goto out;
5995 if (bcond_compute == 0) {
5996 /* No condition to be computed */
5997 switch (opc) {
5998 case OPC_BEQ: /* rx == rx */
5999 case OPC_BEQL: /* rx == rx likely */
6000 case OPC_BGEZ: /* 0 >= 0 */
6001 case OPC_BGEZL: /* 0 >= 0 likely */
6002 case OPC_BLEZ: /* 0 <= 0 */
6003 case OPC_BLEZL: /* 0 <= 0 likely */
6004 /* Always take */
6005 ctx->hflags |= MIPS_HFLAG_B;
6006 break;
6007 case OPC_BGEZAL: /* 0 >= 0 */
6008 case OPC_BGEZALL: /* 0 >= 0 likely */
6009 /* Always take and link */
6010 blink = 31;
6011 ctx->hflags |= MIPS_HFLAG_B;
6012 break;
6013 case OPC_BNE: /* rx != rx */
6014 case OPC_BGTZ: /* 0 > 0 */
6015 case OPC_BLTZ: /* 0 < 0 */
6016 /* Treat as NOP. */
6017 goto out;
6018 case OPC_BLTZAL: /* 0 < 0 */
6020 * Handle as an unconditional branch to get correct delay
6021 * slot checking.
6023 blink = 31;
6024 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
6025 ctx->hflags |= MIPS_HFLAG_B;
6026 break;
6027 case OPC_BLTZALL: /* 0 < 0 likely */
6028 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6029 /* Skip the instruction in the delay slot */
6030 ctx->base.pc_next += 4;
6031 goto out;
6032 case OPC_BNEL: /* rx != rx likely */
6033 case OPC_BGTZL: /* 0 > 0 likely */
6034 case OPC_BLTZL: /* 0 < 0 likely */
6035 /* Skip the instruction in the delay slot */
6036 ctx->base.pc_next += 4;
6037 goto out;
6038 case OPC_J:
6039 ctx->hflags |= MIPS_HFLAG_B;
6040 break;
6041 case OPC_JALX:
6042 ctx->hflags |= MIPS_HFLAG_BX;
6043 /* Fallthrough */
6044 case OPC_JAL:
6045 blink = 31;
6046 ctx->hflags |= MIPS_HFLAG_B;
6047 break;
6048 case OPC_JR:
6049 ctx->hflags |= MIPS_HFLAG_BR;
6050 break;
6051 case OPC_JALR:
6052 blink = rt;
6053 ctx->hflags |= MIPS_HFLAG_BR;
6054 break;
6055 default:
6056 MIPS_INVAL("branch/jump");
6057 generate_exception_end(ctx, EXCP_RI);
6058 goto out;
6060 } else {
6061 switch (opc) {
6062 case OPC_BEQ:
6063 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6064 goto not_likely;
6065 case OPC_BEQL:
6066 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6067 goto likely;
6068 case OPC_BNE:
6069 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6070 goto not_likely;
6071 case OPC_BNEL:
6072 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6073 goto likely;
6074 case OPC_BGEZ:
6075 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6076 goto not_likely;
6077 case OPC_BGEZL:
6078 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6079 goto likely;
6080 case OPC_BGEZAL:
6081 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6082 blink = 31;
6083 goto not_likely;
6084 case OPC_BGEZALL:
6085 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6086 blink = 31;
6087 goto likely;
6088 case OPC_BGTZ:
6089 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6090 goto not_likely;
6091 case OPC_BGTZL:
6092 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6093 goto likely;
6094 case OPC_BLEZ:
6095 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6096 goto not_likely;
6097 case OPC_BLEZL:
6098 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6099 goto likely;
6100 case OPC_BLTZ:
6101 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6102 goto not_likely;
6103 case OPC_BLTZL:
6104 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6105 goto likely;
6106 case OPC_BPOSGE32:
6107 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6108 goto not_likely;
6109 #if defined(TARGET_MIPS64)
6110 case OPC_BPOSGE64:
6111 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
6112 goto not_likely;
6113 #endif
6114 case OPC_BLTZAL:
6115 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6116 blink = 31;
6117 not_likely:
6118 ctx->hflags |= MIPS_HFLAG_BC;
6119 break;
6120 case OPC_BLTZALL:
6121 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6122 blink = 31;
6123 likely:
6124 ctx->hflags |= MIPS_HFLAG_BL;
6125 break;
6126 default:
6127 MIPS_INVAL("conditional branch/jump");
6128 generate_exception_end(ctx, EXCP_RI);
6129 goto out;
6133 ctx->btarget = btgt;
6135 switch (delayslot_size) {
6136 case 2:
6137 ctx->hflags |= MIPS_HFLAG_BDS16;
6138 break;
6139 case 4:
6140 ctx->hflags |= MIPS_HFLAG_BDS32;
6141 break;
6144 if (blink > 0) {
6145 int post_delay = insn_bytes + delayslot_size;
6146 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
6148 tcg_gen_movi_tl(cpu_gpr[blink],
6149 ctx->base.pc_next + post_delay + lowbit);
6152 out:
6153 if (insn_bytes == 2) {
6154 ctx->hflags |= MIPS_HFLAG_B16;
6156 tcg_temp_free(t0);
6157 tcg_temp_free(t1);
6161 /* nanoMIPS Branches */
6162 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
6163 int insn_bytes,
6164 int rs, int rt, int32_t offset)
6166 target_ulong btgt = -1;
6167 int bcond_compute = 0;
6168 TCGv t0 = tcg_temp_new();
6169 TCGv t1 = tcg_temp_new();
6171 /* Load needed operands */
6172 switch (opc) {
6173 case OPC_BEQ:
6174 case OPC_BNE:
6175 /* Compare two registers */
6176 if (rs != rt) {
6177 gen_load_gpr(t0, rs);
6178 gen_load_gpr(t1, rt);
6179 bcond_compute = 1;
6181 btgt = ctx->base.pc_next + insn_bytes + offset;
6182 break;
6183 case OPC_BGEZAL:
6184 /* Compare to zero */
6185 if (rs != 0) {
6186 gen_load_gpr(t0, rs);
6187 bcond_compute = 1;
6189 btgt = ctx->base.pc_next + insn_bytes + offset;
6190 break;
6191 case OPC_BPOSGE32:
6192 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6193 bcond_compute = 1;
6194 btgt = ctx->base.pc_next + insn_bytes + offset;
6195 break;
6196 case OPC_JR:
6197 case OPC_JALR:
6198 /* Jump to register */
6199 if (offset != 0 && offset != 16) {
6201 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6202 * others are reserved.
6204 MIPS_INVAL("jump hint");
6205 generate_exception_end(ctx, EXCP_RI);
6206 goto out;
6208 gen_load_gpr(btarget, rs);
6209 break;
6210 default:
6211 MIPS_INVAL("branch/jump");
6212 generate_exception_end(ctx, EXCP_RI);
6213 goto out;
6215 if (bcond_compute == 0) {
6216 /* No condition to be computed */
6217 switch (opc) {
6218 case OPC_BEQ: /* rx == rx */
6219 /* Always take */
6220 ctx->hflags |= MIPS_HFLAG_B;
6221 break;
6222 case OPC_BGEZAL: /* 0 >= 0 */
6223 /* Always take and link */
6224 tcg_gen_movi_tl(cpu_gpr[31],
6225 ctx->base.pc_next + insn_bytes);
6226 ctx->hflags |= MIPS_HFLAG_B;
6227 break;
6228 case OPC_BNE: /* rx != rx */
6229 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6230 /* Skip the instruction in the delay slot */
6231 ctx->base.pc_next += 4;
6232 goto out;
6233 case OPC_JR:
6234 ctx->hflags |= MIPS_HFLAG_BR;
6235 break;
6236 case OPC_JALR:
6237 if (rt > 0) {
6238 tcg_gen_movi_tl(cpu_gpr[rt],
6239 ctx->base.pc_next + insn_bytes);
6241 ctx->hflags |= MIPS_HFLAG_BR;
6242 break;
6243 default:
6244 MIPS_INVAL("branch/jump");
6245 generate_exception_end(ctx, EXCP_RI);
6246 goto out;
6248 } else {
6249 switch (opc) {
6250 case OPC_BEQ:
6251 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6252 goto not_likely;
6253 case OPC_BNE:
6254 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6255 goto not_likely;
6256 case OPC_BGEZAL:
6257 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6258 tcg_gen_movi_tl(cpu_gpr[31],
6259 ctx->base.pc_next + insn_bytes);
6260 goto not_likely;
6261 case OPC_BPOSGE32:
6262 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6263 not_likely:
6264 ctx->hflags |= MIPS_HFLAG_BC;
6265 break;
6266 default:
6267 MIPS_INVAL("conditional branch/jump");
6268 generate_exception_end(ctx, EXCP_RI);
6269 goto out;
6273 ctx->btarget = btgt;
6275 out:
6276 if (insn_bytes == 2) {
6277 ctx->hflags |= MIPS_HFLAG_B16;
6279 tcg_temp_free(t0);
6280 tcg_temp_free(t1);
6284 /* special3 bitfield operations */
6285 static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
6286 int rs, int lsb, int msb)
6288 TCGv t0 = tcg_temp_new();
6289 TCGv t1 = tcg_temp_new();
6291 gen_load_gpr(t1, rs);
6292 switch (opc) {
6293 case OPC_EXT:
6294 if (lsb + msb > 31) {
6295 goto fail;
6297 if (msb != 31) {
6298 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6299 } else {
6301 * The two checks together imply that lsb == 0,
6302 * so this is a simple sign-extension.
6304 tcg_gen_ext32s_tl(t0, t1);
6306 break;
6307 #if defined(TARGET_MIPS64)
6308 case OPC_DEXTU:
6309 lsb += 32;
6310 goto do_dext;
6311 case OPC_DEXTM:
6312 msb += 32;
6313 goto do_dext;
6314 case OPC_DEXT:
6315 do_dext:
6316 if (lsb + msb > 63) {
6317 goto fail;
6319 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6320 break;
6321 #endif
6322 case OPC_INS:
6323 if (lsb > msb) {
6324 goto fail;
6326 gen_load_gpr(t0, rt);
6327 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6328 tcg_gen_ext32s_tl(t0, t0);
6329 break;
6330 #if defined(TARGET_MIPS64)
6331 case OPC_DINSU:
6332 lsb += 32;
6333 /* FALLTHRU */
6334 case OPC_DINSM:
6335 msb += 32;
6336 /* FALLTHRU */
6337 case OPC_DINS:
6338 if (lsb > msb) {
6339 goto fail;
6341 gen_load_gpr(t0, rt);
6342 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6343 break;
6344 #endif
6345 default:
6346 fail:
6347 MIPS_INVAL("bitops");
6348 generate_exception_end(ctx, EXCP_RI);
6349 tcg_temp_free(t0);
6350 tcg_temp_free(t1);
6351 return;
6353 gen_store_gpr(t0, rt);
6354 tcg_temp_free(t0);
6355 tcg_temp_free(t1);
6358 static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
6360 TCGv t0;
6362 if (rd == 0) {
6363 /* If no destination, treat it as a NOP. */
6364 return;
6367 t0 = tcg_temp_new();
6368 gen_load_gpr(t0, rt);
6369 switch (op2) {
6370 case OPC_WSBH:
6372 TCGv t1 = tcg_temp_new();
6373 TCGv t2 = tcg_const_tl(0x00FF00FF);
6375 tcg_gen_shri_tl(t1, t0, 8);
6376 tcg_gen_and_tl(t1, t1, t2);
6377 tcg_gen_and_tl(t0, t0, t2);
6378 tcg_gen_shli_tl(t0, t0, 8);
6379 tcg_gen_or_tl(t0, t0, t1);
6380 tcg_temp_free(t2);
6381 tcg_temp_free(t1);
6382 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6384 break;
6385 case OPC_SEB:
6386 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
6387 break;
6388 case OPC_SEH:
6389 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
6390 break;
6391 #if defined(TARGET_MIPS64)
6392 case OPC_DSBH:
6394 TCGv t1 = tcg_temp_new();
6395 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
6397 tcg_gen_shri_tl(t1, t0, 8);
6398 tcg_gen_and_tl(t1, t1, t2);
6399 tcg_gen_and_tl(t0, t0, t2);
6400 tcg_gen_shli_tl(t0, t0, 8);
6401 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6402 tcg_temp_free(t2);
6403 tcg_temp_free(t1);
6405 break;
6406 case OPC_DSHD:
6408 TCGv t1 = tcg_temp_new();
6409 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
6411 tcg_gen_shri_tl(t1, t0, 16);
6412 tcg_gen_and_tl(t1, t1, t2);
6413 tcg_gen_and_tl(t0, t0, t2);
6414 tcg_gen_shli_tl(t0, t0, 16);
6415 tcg_gen_or_tl(t0, t0, t1);
6416 tcg_gen_shri_tl(t1, t0, 32);
6417 tcg_gen_shli_tl(t0, t0, 32);
6418 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6419 tcg_temp_free(t2);
6420 tcg_temp_free(t1);
6422 break;
6423 #endif
6424 default:
6425 MIPS_INVAL("bsfhl");
6426 generate_exception_end(ctx, EXCP_RI);
6427 tcg_temp_free(t0);
6428 return;
6430 tcg_temp_free(t0);
6433 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
6434 int imm2)
6436 TCGv t0;
6437 TCGv t1;
6438 if (rd == 0) {
6439 /* Treat as NOP. */
6440 return;
6442 t0 = tcg_temp_new();
6443 t1 = tcg_temp_new();
6444 gen_load_gpr(t0, rs);
6445 gen_load_gpr(t1, rt);
6446 tcg_gen_shli_tl(t0, t0, imm2 + 1);
6447 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
6448 if (opc == OPC_LSA) {
6449 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
6452 tcg_temp_free(t1);
6453 tcg_temp_free(t0);
6455 return;
6458 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
6459 int rt, int bits)
6461 TCGv t0;
6462 if (rd == 0) {
6463 /* Treat as NOP. */
6464 return;
6466 t0 = tcg_temp_new();
6467 if (bits == 0 || bits == wordsz) {
6468 if (bits == 0) {
6469 gen_load_gpr(t0, rt);
6470 } else {
6471 gen_load_gpr(t0, rs);
6473 switch (wordsz) {
6474 case 32:
6475 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6476 break;
6477 #if defined(TARGET_MIPS64)
6478 case 64:
6479 tcg_gen_mov_tl(cpu_gpr[rd], t0);
6480 break;
6481 #endif
6483 } else {
6484 TCGv t1 = tcg_temp_new();
6485 gen_load_gpr(t0, rt);
6486 gen_load_gpr(t1, rs);
6487 switch (wordsz) {
6488 case 32:
6490 TCGv_i64 t2 = tcg_temp_new_i64();
6491 tcg_gen_concat_tl_i64(t2, t1, t0);
6492 tcg_gen_shri_i64(t2, t2, 32 - bits);
6493 gen_move_low32(cpu_gpr[rd], t2);
6494 tcg_temp_free_i64(t2);
6496 break;
6497 #if defined(TARGET_MIPS64)
6498 case 64:
6499 tcg_gen_shli_tl(t0, t0, bits);
6500 tcg_gen_shri_tl(t1, t1, 64 - bits);
6501 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
6502 break;
6503 #endif
6505 tcg_temp_free(t1);
6508 tcg_temp_free(t0);
6511 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6512 int bp)
6514 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
6517 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6518 int shift)
6520 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
6523 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
6525 TCGv t0;
6526 if (rd == 0) {
6527 /* Treat as NOP. */
6528 return;
6530 t0 = tcg_temp_new();
6531 gen_load_gpr(t0, rt);
6532 switch (opc) {
6533 case OPC_BITSWAP:
6534 gen_helper_bitswap(cpu_gpr[rd], t0);
6535 break;
6536 #if defined(TARGET_MIPS64)
6537 case OPC_DBITSWAP:
6538 gen_helper_dbitswap(cpu_gpr[rd], t0);
6539 break;
6540 #endif
6542 tcg_temp_free(t0);
6545 #ifndef CONFIG_USER_ONLY
6546 /* CP0 (MMU and control) */
6547 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
6549 TCGv_i64 t0 = tcg_temp_new_i64();
6550 TCGv_i64 t1 = tcg_temp_new_i64();
6552 tcg_gen_ext_tl_i64(t0, arg);
6553 tcg_gen_ld_i64(t1, cpu_env, off);
6554 #if defined(TARGET_MIPS64)
6555 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
6556 #else
6557 tcg_gen_concat32_i64(t1, t1, t0);
6558 #endif
6559 tcg_gen_st_i64(t1, cpu_env, off);
6560 tcg_temp_free_i64(t1);
6561 tcg_temp_free_i64(t0);
6564 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
6566 TCGv_i64 t0 = tcg_temp_new_i64();
6567 TCGv_i64 t1 = tcg_temp_new_i64();
6569 tcg_gen_ext_tl_i64(t0, arg);
6570 tcg_gen_ld_i64(t1, cpu_env, off);
6571 tcg_gen_concat32_i64(t1, t1, t0);
6572 tcg_gen_st_i64(t1, cpu_env, off);
6573 tcg_temp_free_i64(t1);
6574 tcg_temp_free_i64(t0);
6577 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
6579 TCGv_i64 t0 = tcg_temp_new_i64();
6581 tcg_gen_ld_i64(t0, cpu_env, off);
6582 #if defined(TARGET_MIPS64)
6583 tcg_gen_shri_i64(t0, t0, 30);
6584 #else
6585 tcg_gen_shri_i64(t0, t0, 32);
6586 #endif
6587 gen_move_low32(arg, t0);
6588 tcg_temp_free_i64(t0);
6591 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
6593 TCGv_i64 t0 = tcg_temp_new_i64();
6595 tcg_gen_ld_i64(t0, cpu_env, off);
6596 tcg_gen_shri_i64(t0, t0, 32 + shift);
6597 gen_move_low32(arg, t0);
6598 tcg_temp_free_i64(t0);
6601 static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
6603 TCGv_i32 t0 = tcg_temp_new_i32();
6605 tcg_gen_ld_i32(t0, cpu_env, off);
6606 tcg_gen_ext_i32_tl(arg, t0);
6607 tcg_temp_free_i32(t0);
6610 static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
6612 tcg_gen_ld_tl(arg, cpu_env, off);
6613 tcg_gen_ext32s_tl(arg, arg);
6616 static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
6618 TCGv_i32 t0 = tcg_temp_new_i32();
6620 tcg_gen_trunc_tl_i32(t0, arg);
6621 tcg_gen_st_i32(t0, cpu_env, off);
6622 tcg_temp_free_i32(t0);
6625 #define CP0_CHECK(c) \
6626 do { \
6627 if (!(c)) { \
6628 goto cp0_unimplemented; \
6630 } while (0)
6632 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6634 const char *register_name = "invalid";
6636 switch (reg) {
6637 case CP0_REGISTER_02:
6638 switch (sel) {
6639 case 0:
6640 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6641 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6642 register_name = "EntryLo0";
6643 break;
6644 default:
6645 goto cp0_unimplemented;
6647 break;
6648 case CP0_REGISTER_03:
6649 switch (sel) {
6650 case CP0_REG03__ENTRYLO1:
6651 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6652 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6653 register_name = "EntryLo1";
6654 break;
6655 default:
6656 goto cp0_unimplemented;
6658 break;
6659 case CP0_REGISTER_09:
6660 switch (sel) {
6661 case CP0_REG09__SAAR:
6662 CP0_CHECK(ctx->saar);
6663 gen_helper_mfhc0_saar(arg, cpu_env);
6664 register_name = "SAAR";
6665 break;
6666 default:
6667 goto cp0_unimplemented;
6669 break;
6670 case CP0_REGISTER_17:
6671 switch (sel) {
6672 case 0:
6673 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
6674 ctx->CP0_LLAddr_shift);
6675 register_name = "LLAddr";
6676 break;
6677 case 1:
6678 CP0_CHECK(ctx->mrp);
6679 gen_helper_mfhc0_maar(arg, cpu_env);
6680 register_name = "MAAR";
6681 break;
6682 default:
6683 goto cp0_unimplemented;
6685 break;
6686 case CP0_REGISTER_28:
6687 switch (sel) {
6688 case 0:
6689 case 2:
6690 case 4:
6691 case 6:
6692 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
6693 register_name = "TagLo";
6694 break;
6695 default:
6696 goto cp0_unimplemented;
6698 break;
6699 default:
6700 goto cp0_unimplemented;
6702 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
6703 return;
6705 cp0_unimplemented:
6706 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
6707 register_name, reg, sel);
6708 tcg_gen_movi_tl(arg, 0);
6711 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6713 const char *register_name = "invalid";
6714 uint64_t mask = ctx->PAMask >> 36;
6716 switch (reg) {
6717 case CP0_REGISTER_02:
6718 switch (sel) {
6719 case 0:
6720 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6721 tcg_gen_andi_tl(arg, arg, mask);
6722 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6723 register_name = "EntryLo0";
6724 break;
6725 default:
6726 goto cp0_unimplemented;
6728 break;
6729 case CP0_REGISTER_03:
6730 switch (sel) {
6731 case CP0_REG03__ENTRYLO1:
6732 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6733 tcg_gen_andi_tl(arg, arg, mask);
6734 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6735 register_name = "EntryLo1";
6736 break;
6737 default:
6738 goto cp0_unimplemented;
6740 break;
6741 case CP0_REGISTER_09:
6742 switch (sel) {
6743 case CP0_REG09__SAAR:
6744 CP0_CHECK(ctx->saar);
6745 gen_helper_mthc0_saar(cpu_env, arg);
6746 register_name = "SAAR";
6747 break;
6748 default:
6749 goto cp0_unimplemented;
6751 break;
6752 case CP0_REGISTER_17:
6753 switch (sel) {
6754 case 0:
6756 * LLAddr is read-only (the only exception is bit 0 if LLB is
6757 * supported); the CP0_LLAddr_rw_bitmask does not seem to be
6758 * relevant for modern MIPS cores supporting MTHC0, therefore
6759 * treating MTHC0 to LLAddr as NOP.
6761 register_name = "LLAddr";
6762 break;
6763 case 1:
6764 CP0_CHECK(ctx->mrp);
6765 gen_helper_mthc0_maar(cpu_env, arg);
6766 register_name = "MAAR";
6767 break;
6768 default:
6769 goto cp0_unimplemented;
6771 break;
6772 case CP0_REGISTER_28:
6773 switch (sel) {
6774 case 0:
6775 case 2:
6776 case 4:
6777 case 6:
6778 tcg_gen_andi_tl(arg, arg, mask);
6779 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
6780 register_name = "TagLo";
6781 break;
6782 default:
6783 goto cp0_unimplemented;
6785 break;
6786 default:
6787 goto cp0_unimplemented;
6789 trace_mips_translate_c0("mthc0", register_name, reg, sel);
6791 cp0_unimplemented:
6792 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
6793 register_name, reg, sel);
6796 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
6798 if (ctx->insn_flags & ISA_MIPS32R6) {
6799 tcg_gen_movi_tl(arg, 0);
6800 } else {
6801 tcg_gen_movi_tl(arg, ~0);
6805 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6807 const char *register_name = "invalid";
6809 if (sel != 0) {
6810 check_insn(ctx, ISA_MIPS32);
6813 switch (reg) {
6814 case CP0_REGISTER_00:
6815 switch (sel) {
6816 case CP0_REG00__INDEX:
6817 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6818 register_name = "Index";
6819 break;
6820 case CP0_REG00__MVPCONTROL:
6821 CP0_CHECK(ctx->insn_flags & ASE_MT);
6822 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6823 register_name = "MVPControl";
6824 break;
6825 case CP0_REG00__MVPCONF0:
6826 CP0_CHECK(ctx->insn_flags & ASE_MT);
6827 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6828 register_name = "MVPConf0";
6829 break;
6830 case CP0_REG00__MVPCONF1:
6831 CP0_CHECK(ctx->insn_flags & ASE_MT);
6832 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6833 register_name = "MVPConf1";
6834 break;
6835 case CP0_REG00__VPCONTROL:
6836 CP0_CHECK(ctx->vp);
6837 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6838 register_name = "VPControl";
6839 break;
6840 default:
6841 goto cp0_unimplemented;
6843 break;
6844 case CP0_REGISTER_01:
6845 switch (sel) {
6846 case CP0_REG01__RANDOM:
6847 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6848 gen_helper_mfc0_random(arg, cpu_env);
6849 register_name = "Random";
6850 break;
6851 case CP0_REG01__VPECONTROL:
6852 CP0_CHECK(ctx->insn_flags & ASE_MT);
6853 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6854 register_name = "VPEControl";
6855 break;
6856 case CP0_REG01__VPECONF0:
6857 CP0_CHECK(ctx->insn_flags & ASE_MT);
6858 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6859 register_name = "VPEConf0";
6860 break;
6861 case CP0_REG01__VPECONF1:
6862 CP0_CHECK(ctx->insn_flags & ASE_MT);
6863 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6864 register_name = "VPEConf1";
6865 break;
6866 case CP0_REG01__YQMASK:
6867 CP0_CHECK(ctx->insn_flags & ASE_MT);
6868 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
6869 register_name = "YQMask";
6870 break;
6871 case CP0_REG01__VPESCHEDULE:
6872 CP0_CHECK(ctx->insn_flags & ASE_MT);
6873 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
6874 register_name = "VPESchedule";
6875 break;
6876 case CP0_REG01__VPESCHEFBACK:
6877 CP0_CHECK(ctx->insn_flags & ASE_MT);
6878 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6879 register_name = "VPEScheFBack";
6880 break;
6881 case CP0_REG01__VPEOPT:
6882 CP0_CHECK(ctx->insn_flags & ASE_MT);
6883 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6884 register_name = "VPEOpt";
6885 break;
6886 default:
6887 goto cp0_unimplemented;
6889 break;
6890 case CP0_REGISTER_02:
6891 switch (sel) {
6892 case CP0_REG02__ENTRYLO0:
6894 TCGv_i64 tmp = tcg_temp_new_i64();
6895 tcg_gen_ld_i64(tmp, cpu_env,
6896 offsetof(CPUMIPSState, CP0_EntryLo0));
6897 #if defined(TARGET_MIPS64)
6898 if (ctx->rxi) {
6899 /* Move RI/XI fields to bits 31:30 */
6900 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6901 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6903 #endif
6904 gen_move_low32(arg, tmp);
6905 tcg_temp_free_i64(tmp);
6907 register_name = "EntryLo0";
6908 break;
6909 case CP0_REG02__TCSTATUS:
6910 CP0_CHECK(ctx->insn_flags & ASE_MT);
6911 gen_helper_mfc0_tcstatus(arg, cpu_env);
6912 register_name = "TCStatus";
6913 break;
6914 case CP0_REG02__TCBIND:
6915 CP0_CHECK(ctx->insn_flags & ASE_MT);
6916 gen_helper_mfc0_tcbind(arg, cpu_env);
6917 register_name = "TCBind";
6918 break;
6919 case CP0_REG02__TCRESTART:
6920 CP0_CHECK(ctx->insn_flags & ASE_MT);
6921 gen_helper_mfc0_tcrestart(arg, cpu_env);
6922 register_name = "TCRestart";
6923 break;
6924 case CP0_REG02__TCHALT:
6925 CP0_CHECK(ctx->insn_flags & ASE_MT);
6926 gen_helper_mfc0_tchalt(arg, cpu_env);
6927 register_name = "TCHalt";
6928 break;
6929 case CP0_REG02__TCCONTEXT:
6930 CP0_CHECK(ctx->insn_flags & ASE_MT);
6931 gen_helper_mfc0_tccontext(arg, cpu_env);
6932 register_name = "TCContext";
6933 break;
6934 case CP0_REG02__TCSCHEDULE:
6935 CP0_CHECK(ctx->insn_flags & ASE_MT);
6936 gen_helper_mfc0_tcschedule(arg, cpu_env);
6937 register_name = "TCSchedule";
6938 break;
6939 case CP0_REG02__TCSCHEFBACK:
6940 CP0_CHECK(ctx->insn_flags & ASE_MT);
6941 gen_helper_mfc0_tcschefback(arg, cpu_env);
6942 register_name = "TCScheFBack";
6943 break;
6944 default:
6945 goto cp0_unimplemented;
6947 break;
6948 case CP0_REGISTER_03:
6949 switch (sel) {
6950 case CP0_REG03__ENTRYLO1:
6952 TCGv_i64 tmp = tcg_temp_new_i64();
6953 tcg_gen_ld_i64(tmp, cpu_env,
6954 offsetof(CPUMIPSState, CP0_EntryLo1));
6955 #if defined(TARGET_MIPS64)
6956 if (ctx->rxi) {
6957 /* Move RI/XI fields to bits 31:30 */
6958 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6959 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6961 #endif
6962 gen_move_low32(arg, tmp);
6963 tcg_temp_free_i64(tmp);
6965 register_name = "EntryLo1";
6966 break;
6967 case CP0_REG03__GLOBALNUM:
6968 CP0_CHECK(ctx->vp);
6969 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6970 register_name = "GlobalNumber";
6971 break;
6972 default:
6973 goto cp0_unimplemented;
6975 break;
6976 case CP0_REGISTER_04:
6977 switch (sel) {
6978 case CP0_REG04__CONTEXT:
6979 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6980 tcg_gen_ext32s_tl(arg, arg);
6981 register_name = "Context";
6982 break;
6983 case CP0_REG04__CONTEXTCONFIG:
6984 /* SmartMIPS ASE */
6985 /* gen_helper_mfc0_contextconfig(arg); */
6986 register_name = "ContextConfig";
6987 goto cp0_unimplemented;
6988 case CP0_REG04__USERLOCAL:
6989 CP0_CHECK(ctx->ulri);
6990 tcg_gen_ld_tl(arg, cpu_env,
6991 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6992 tcg_gen_ext32s_tl(arg, arg);
6993 register_name = "UserLocal";
6994 break;
6995 default:
6996 goto cp0_unimplemented;
6998 break;
6999 case CP0_REGISTER_05:
7000 switch (sel) {
7001 case CP0_REG05__PAGEMASK:
7002 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
7003 register_name = "PageMask";
7004 break;
7005 case CP0_REG05__PAGEGRAIN:
7006 check_insn(ctx, ISA_MIPS32R2);
7007 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
7008 register_name = "PageGrain";
7009 break;
7010 case CP0_REG05__SEGCTL0:
7011 CP0_CHECK(ctx->sc);
7012 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
7013 tcg_gen_ext32s_tl(arg, arg);
7014 register_name = "SegCtl0";
7015 break;
7016 case CP0_REG05__SEGCTL1:
7017 CP0_CHECK(ctx->sc);
7018 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
7019 tcg_gen_ext32s_tl(arg, arg);
7020 register_name = "SegCtl1";
7021 break;
7022 case CP0_REG05__SEGCTL2:
7023 CP0_CHECK(ctx->sc);
7024 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
7025 tcg_gen_ext32s_tl(arg, arg);
7026 register_name = "SegCtl2";
7027 break;
7028 case CP0_REG05__PWBASE:
7029 check_pw(ctx);
7030 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7031 register_name = "PWBase";
7032 break;
7033 case CP0_REG05__PWFIELD:
7034 check_pw(ctx);
7035 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
7036 register_name = "PWField";
7037 break;
7038 case CP0_REG05__PWSIZE:
7039 check_pw(ctx);
7040 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
7041 register_name = "PWSize";
7042 break;
7043 default:
7044 goto cp0_unimplemented;
7046 break;
7047 case CP0_REGISTER_06:
7048 switch (sel) {
7049 case CP0_REG06__WIRED:
7050 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
7051 register_name = "Wired";
7052 break;
7053 case CP0_REG06__SRSCONF0:
7054 check_insn(ctx, ISA_MIPS32R2);
7055 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
7056 register_name = "SRSConf0";
7057 break;
7058 case CP0_REG06__SRSCONF1:
7059 check_insn(ctx, ISA_MIPS32R2);
7060 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
7061 register_name = "SRSConf1";
7062 break;
7063 case CP0_REG06__SRSCONF2:
7064 check_insn(ctx, ISA_MIPS32R2);
7065 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
7066 register_name = "SRSConf2";
7067 break;
7068 case CP0_REG06__SRSCONF3:
7069 check_insn(ctx, ISA_MIPS32R2);
7070 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
7071 register_name = "SRSConf3";
7072 break;
7073 case CP0_REG06__SRSCONF4:
7074 check_insn(ctx, ISA_MIPS32R2);
7075 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
7076 register_name = "SRSConf4";
7077 break;
7078 case CP0_REG06__PWCTL:
7079 check_pw(ctx);
7080 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
7081 register_name = "PWCtl";
7082 break;
7083 default:
7084 goto cp0_unimplemented;
7086 break;
7087 case CP0_REGISTER_07:
7088 switch (sel) {
7089 case CP0_REG07__HWRENA:
7090 check_insn(ctx, ISA_MIPS32R2);
7091 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
7092 register_name = "HWREna";
7093 break;
7094 default:
7095 goto cp0_unimplemented;
7097 break;
7098 case CP0_REGISTER_08:
7099 switch (sel) {
7100 case CP0_REG08__BADVADDR:
7101 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
7102 tcg_gen_ext32s_tl(arg, arg);
7103 register_name = "BadVAddr";
7104 break;
7105 case CP0_REG08__BADINSTR:
7106 CP0_CHECK(ctx->bi);
7107 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
7108 register_name = "BadInstr";
7109 break;
7110 case CP0_REG08__BADINSTRP:
7111 CP0_CHECK(ctx->bp);
7112 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
7113 register_name = "BadInstrP";
7114 break;
7115 case CP0_REG08__BADINSTRX:
7116 CP0_CHECK(ctx->bi);
7117 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7118 tcg_gen_andi_tl(arg, arg, ~0xffff);
7119 register_name = "BadInstrX";
7120 break;
7121 default:
7122 goto cp0_unimplemented;
7124 break;
7125 case CP0_REGISTER_09:
7126 switch (sel) {
7127 case CP0_REG09__COUNT:
7128 /* Mark as an IO operation because we read the time. */
7129 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7130 gen_io_start();
7132 gen_helper_mfc0_count(arg, cpu_env);
7134 * Break the TB to be able to take timer interrupts immediately
7135 * after reading count. DISAS_STOP isn't sufficient, we need to
7136 * ensure we break completely out of translated code.
7138 gen_save_pc(ctx->base.pc_next + 4);
7139 ctx->base.is_jmp = DISAS_EXIT;
7140 register_name = "Count";
7141 break;
7142 case CP0_REG09__SAARI:
7143 CP0_CHECK(ctx->saar);
7144 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
7145 register_name = "SAARI";
7146 break;
7147 case CP0_REG09__SAAR:
7148 CP0_CHECK(ctx->saar);
7149 gen_helper_mfc0_saar(arg, cpu_env);
7150 register_name = "SAAR";
7151 break;
7152 default:
7153 goto cp0_unimplemented;
7155 break;
7156 case CP0_REGISTER_10:
7157 switch (sel) {
7158 case CP0_REG10__ENTRYHI:
7159 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
7160 tcg_gen_ext32s_tl(arg, arg);
7161 register_name = "EntryHi";
7162 break;
7163 default:
7164 goto cp0_unimplemented;
7166 break;
7167 case CP0_REGISTER_11:
7168 switch (sel) {
7169 case 0:
7170 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
7171 register_name = "Compare";
7172 break;
7173 /* 6,7 are implementation dependent */
7174 default:
7175 goto cp0_unimplemented;
7177 break;
7178 case CP0_REGISTER_12:
7179 switch (sel) {
7180 case 0:
7181 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
7182 register_name = "Status";
7183 break;
7184 case 1:
7185 check_insn(ctx, ISA_MIPS32R2);
7186 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
7187 register_name = "IntCtl";
7188 break;
7189 case 2:
7190 check_insn(ctx, ISA_MIPS32R2);
7191 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
7192 register_name = "SRSCtl";
7193 break;
7194 case 3:
7195 check_insn(ctx, ISA_MIPS32R2);
7196 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7197 register_name = "SRSMap";
7198 break;
7199 default:
7200 goto cp0_unimplemented;
7202 break;
7203 case CP0_REGISTER_13:
7204 switch (sel) {
7205 case 0:
7206 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
7207 register_name = "Cause";
7208 break;
7209 default:
7210 goto cp0_unimplemented;
7212 break;
7213 case CP0_REGISTER_14:
7214 switch (sel) {
7215 case 0:
7216 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7217 tcg_gen_ext32s_tl(arg, arg);
7218 register_name = "EPC";
7219 break;
7220 default:
7221 goto cp0_unimplemented;
7223 break;
7224 case CP0_REGISTER_15:
7225 switch (sel) {
7226 case 0:
7227 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
7228 register_name = "PRid";
7229 break;
7230 case 1:
7231 check_insn(ctx, ISA_MIPS32R2);
7232 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7233 tcg_gen_ext32s_tl(arg, arg);
7234 register_name = "EBase";
7235 break;
7236 case 3:
7237 check_insn(ctx, ISA_MIPS32R2);
7238 CP0_CHECK(ctx->cmgcr);
7239 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7240 tcg_gen_ext32s_tl(arg, arg);
7241 register_name = "CMGCRBase";
7242 break;
7243 default:
7244 goto cp0_unimplemented;
7246 break;
7247 case CP0_REGISTER_16:
7248 switch (sel) {
7249 case 0:
7250 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
7251 register_name = "Config";
7252 break;
7253 case 1:
7254 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
7255 register_name = "Config1";
7256 break;
7257 case 2:
7258 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7259 register_name = "Config2";
7260 break;
7261 case 3:
7262 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7263 register_name = "Config3";
7264 break;
7265 case 4:
7266 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7267 register_name = "Config4";
7268 break;
7269 case 5:
7270 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7271 register_name = "Config5";
7272 break;
7273 /* 6,7 are implementation dependent */
7274 case 6:
7275 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
7276 register_name = "Config6";
7277 break;
7278 case 7:
7279 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
7280 register_name = "Config7";
7281 break;
7282 default:
7283 goto cp0_unimplemented;
7285 break;
7286 case CP0_REGISTER_17:
7287 switch (sel) {
7288 case 0:
7289 gen_helper_mfc0_lladdr(arg, cpu_env);
7290 register_name = "LLAddr";
7291 break;
7292 case 1:
7293 CP0_CHECK(ctx->mrp);
7294 gen_helper_mfc0_maar(arg, cpu_env);
7295 register_name = "MAAR";
7296 break;
7297 case 2:
7298 CP0_CHECK(ctx->mrp);
7299 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7300 register_name = "MAARI";
7301 break;
7302 default:
7303 goto cp0_unimplemented;
7305 break;
7306 case CP0_REGISTER_18:
7307 switch (sel) {
7308 case 0:
7309 case 1:
7310 case 2:
7311 case 3:
7312 case 4:
7313 case 5:
7314 case 6:
7315 case 7:
7316 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7317 gen_helper_1e0i(mfc0_watchlo, arg, sel);
7318 register_name = "WatchLo";
7319 break;
7320 default:
7321 goto cp0_unimplemented;
7323 break;
7324 case CP0_REGISTER_19:
7325 switch (sel) {
7326 case 0:
7327 case 1:
7328 case 2:
7329 case 3:
7330 case 4:
7331 case 5:
7332 case 6:
7333 case 7:
7334 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7335 gen_helper_1e0i(mfc0_watchhi, arg, sel);
7336 register_name = "WatchHi";
7337 break;
7338 default:
7339 goto cp0_unimplemented;
7341 break;
7342 case CP0_REGISTER_20:
7343 switch (sel) {
7344 case 0:
7345 #if defined(TARGET_MIPS64)
7346 check_insn(ctx, ISA_MIPS3);
7347 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
7348 tcg_gen_ext32s_tl(arg, arg);
7349 register_name = "XContext";
7350 break;
7351 #endif
7352 default:
7353 goto cp0_unimplemented;
7355 break;
7356 case CP0_REGISTER_21:
7357 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7358 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7359 switch (sel) {
7360 case 0:
7361 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
7362 register_name = "Framemask";
7363 break;
7364 default:
7365 goto cp0_unimplemented;
7367 break;
7368 case CP0_REGISTER_22:
7369 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7370 register_name = "'Diagnostic"; /* implementation dependent */
7371 break;
7372 case CP0_REGISTER_23:
7373 switch (sel) {
7374 case 0:
7375 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
7376 register_name = "Debug";
7377 break;
7378 case 1:
7379 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
7380 register_name = "TraceControl";
7381 goto cp0_unimplemented;
7382 case 2:
7383 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
7384 register_name = "TraceControl2";
7385 goto cp0_unimplemented;
7386 case 3:
7387 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
7388 register_name = "UserTraceData";
7389 goto cp0_unimplemented;
7390 case 4:
7391 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
7392 register_name = "TraceBPC";
7393 goto cp0_unimplemented;
7394 default:
7395 goto cp0_unimplemented;
7397 break;
7398 case CP0_REGISTER_24:
7399 switch (sel) {
7400 case 0:
7401 /* EJTAG support */
7402 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7403 tcg_gen_ext32s_tl(arg, arg);
7404 register_name = "DEPC";
7405 break;
7406 default:
7407 goto cp0_unimplemented;
7409 break;
7410 case CP0_REGISTER_25:
7411 switch (sel) {
7412 case 0:
7413 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
7414 register_name = "Performance0";
7415 break;
7416 case 1:
7417 /* gen_helper_mfc0_performance1(arg); */
7418 register_name = "Performance1";
7419 goto cp0_unimplemented;
7420 case 2:
7421 /* gen_helper_mfc0_performance2(arg); */
7422 register_name = "Performance2";
7423 goto cp0_unimplemented;
7424 case 3:
7425 /* gen_helper_mfc0_performance3(arg); */
7426 register_name = "Performance3";
7427 goto cp0_unimplemented;
7428 case 4:
7429 /* gen_helper_mfc0_performance4(arg); */
7430 register_name = "Performance4";
7431 goto cp0_unimplemented;
7432 case 5:
7433 /* gen_helper_mfc0_performance5(arg); */
7434 register_name = "Performance5";
7435 goto cp0_unimplemented;
7436 case 6:
7437 /* gen_helper_mfc0_performance6(arg); */
7438 register_name = "Performance6";
7439 goto cp0_unimplemented;
7440 case 7:
7441 /* gen_helper_mfc0_performance7(arg); */
7442 register_name = "Performance7";
7443 goto cp0_unimplemented;
7444 default:
7445 goto cp0_unimplemented;
7447 break;
7448 case CP0_REGISTER_26:
7449 switch (sel) {
7450 case 0:
7451 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7452 register_name = "ErrCtl";
7453 break;
7454 default:
7455 goto cp0_unimplemented;
7457 break;
7458 case CP0_REGISTER_27:
7459 switch (sel) {
7460 case 0:
7461 case 1:
7462 case 2:
7463 case 3:
7464 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7465 register_name = "CacheErr";
7466 break;
7467 default:
7468 goto cp0_unimplemented;
7470 break;
7471 case CP0_REGISTER_28:
7472 switch (sel) {
7473 case 0:
7474 case 2:
7475 case 4:
7476 case 6:
7478 TCGv_i64 tmp = tcg_temp_new_i64();
7479 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
7480 gen_move_low32(arg, tmp);
7481 tcg_temp_free_i64(tmp);
7483 register_name = "TagLo";
7484 break;
7485 case 1:
7486 case 3:
7487 case 5:
7488 case 7:
7489 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7490 register_name = "DataLo";
7491 break;
7492 default:
7493 goto cp0_unimplemented;
7495 break;
7496 case CP0_REGISTER_29:
7497 switch (sel) {
7498 case 0:
7499 case 2:
7500 case 4:
7501 case 6:
7502 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7503 register_name = "TagHi";
7504 break;
7505 case 1:
7506 case 3:
7507 case 5:
7508 case 7:
7509 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7510 register_name = "DataHi";
7511 break;
7512 default:
7513 goto cp0_unimplemented;
7515 break;
7516 case CP0_REGISTER_30:
7517 switch (sel) {
7518 case 0:
7519 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7520 tcg_gen_ext32s_tl(arg, arg);
7521 register_name = "ErrorEPC";
7522 break;
7523 default:
7524 goto cp0_unimplemented;
7526 break;
7527 case CP0_REGISTER_31:
7528 switch (sel) {
7529 case 0:
7530 /* EJTAG support */
7531 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7532 register_name = "DESAVE";
7533 break;
7534 case 2:
7535 case 3:
7536 case 4:
7537 case 5:
7538 case 6:
7539 case 7:
7540 CP0_CHECK(ctx->kscrexist & (1 << sel));
7541 tcg_gen_ld_tl(arg, cpu_env,
7542 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7543 tcg_gen_ext32s_tl(arg, arg);
7544 register_name = "KScratch";
7545 break;
7546 default:
7547 goto cp0_unimplemented;
7549 break;
7550 default:
7551 goto cp0_unimplemented;
7553 trace_mips_translate_c0("mfc0", register_name, reg, sel);
7554 return;
7556 cp0_unimplemented:
7557 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
7558 register_name, reg, sel);
7559 gen_mfc0_unimplemented(ctx, arg);
7562 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7564 const char *register_name = "invalid";
7566 if (sel != 0) {
7567 check_insn(ctx, ISA_MIPS32);
7570 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7571 gen_io_start();
7574 switch (reg) {
7575 case CP0_REGISTER_00:
7576 switch (sel) {
7577 case CP0_REG00__INDEX:
7578 gen_helper_mtc0_index(cpu_env, arg);
7579 register_name = "Index";
7580 break;
7581 case CP0_REG00__MVPCONTROL:
7582 CP0_CHECK(ctx->insn_flags & ASE_MT);
7583 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7584 register_name = "MVPControl";
7585 break;
7586 case CP0_REG00__MVPCONF0:
7587 CP0_CHECK(ctx->insn_flags & ASE_MT);
7588 /* ignored */
7589 register_name = "MVPConf0";
7590 break;
7591 case CP0_REG00__MVPCONF1:
7592 CP0_CHECK(ctx->insn_flags & ASE_MT);
7593 /* ignored */
7594 register_name = "MVPConf1";
7595 break;
7596 case CP0_REG00__VPCONTROL:
7597 CP0_CHECK(ctx->vp);
7598 /* ignored */
7599 register_name = "VPControl";
7600 break;
7601 default:
7602 goto cp0_unimplemented;
7604 break;
7605 case CP0_REGISTER_01:
7606 switch (sel) {
7607 case CP0_REG01__RANDOM:
7608 /* ignored */
7609 register_name = "Random";
7610 break;
7611 case CP0_REG01__VPECONTROL:
7612 CP0_CHECK(ctx->insn_flags & ASE_MT);
7613 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7614 register_name = "VPEControl";
7615 break;
7616 case CP0_REG01__VPECONF0:
7617 CP0_CHECK(ctx->insn_flags & ASE_MT);
7618 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7619 register_name = "VPEConf0";
7620 break;
7621 case CP0_REG01__VPECONF1:
7622 CP0_CHECK(ctx->insn_flags & ASE_MT);
7623 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7624 register_name = "VPEConf1";
7625 break;
7626 case CP0_REG01__YQMASK:
7627 CP0_CHECK(ctx->insn_flags & ASE_MT);
7628 gen_helper_mtc0_yqmask(cpu_env, arg);
7629 register_name = "YQMask";
7630 break;
7631 case CP0_REG01__VPESCHEDULE:
7632 CP0_CHECK(ctx->insn_flags & ASE_MT);
7633 tcg_gen_st_tl(arg, cpu_env,
7634 offsetof(CPUMIPSState, CP0_VPESchedule));
7635 register_name = "VPESchedule";
7636 break;
7637 case CP0_REG01__VPESCHEFBACK:
7638 CP0_CHECK(ctx->insn_flags & ASE_MT);
7639 tcg_gen_st_tl(arg, cpu_env,
7640 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7641 register_name = "VPEScheFBack";
7642 break;
7643 case CP0_REG01__VPEOPT:
7644 CP0_CHECK(ctx->insn_flags & ASE_MT);
7645 gen_helper_mtc0_vpeopt(cpu_env, arg);
7646 register_name = "VPEOpt";
7647 break;
7648 default:
7649 goto cp0_unimplemented;
7651 break;
7652 case CP0_REGISTER_02:
7653 switch (sel) {
7654 case CP0_REG02__ENTRYLO0:
7655 gen_helper_mtc0_entrylo0(cpu_env, arg);
7656 register_name = "EntryLo0";
7657 break;
7658 case CP0_REG02__TCSTATUS:
7659 CP0_CHECK(ctx->insn_flags & ASE_MT);
7660 gen_helper_mtc0_tcstatus(cpu_env, arg);
7661 register_name = "TCStatus";
7662 break;
7663 case CP0_REG02__TCBIND:
7664 CP0_CHECK(ctx->insn_flags & ASE_MT);
7665 gen_helper_mtc0_tcbind(cpu_env, arg);
7666 register_name = "TCBind";
7667 break;
7668 case CP0_REG02__TCRESTART:
7669 CP0_CHECK(ctx->insn_flags & ASE_MT);
7670 gen_helper_mtc0_tcrestart(cpu_env, arg);
7671 register_name = "TCRestart";
7672 break;
7673 case CP0_REG02__TCHALT:
7674 CP0_CHECK(ctx->insn_flags & ASE_MT);
7675 gen_helper_mtc0_tchalt(cpu_env, arg);
7676 register_name = "TCHalt";
7677 break;
7678 case CP0_REG02__TCCONTEXT:
7679 CP0_CHECK(ctx->insn_flags & ASE_MT);
7680 gen_helper_mtc0_tccontext(cpu_env, arg);
7681 register_name = "TCContext";
7682 break;
7683 case CP0_REG02__TCSCHEDULE:
7684 CP0_CHECK(ctx->insn_flags & ASE_MT);
7685 gen_helper_mtc0_tcschedule(cpu_env, arg);
7686 register_name = "TCSchedule";
7687 break;
7688 case CP0_REG02__TCSCHEFBACK:
7689 CP0_CHECK(ctx->insn_flags & ASE_MT);
7690 gen_helper_mtc0_tcschefback(cpu_env, arg);
7691 register_name = "TCScheFBack";
7692 break;
7693 default:
7694 goto cp0_unimplemented;
7696 break;
7697 case CP0_REGISTER_03:
7698 switch (sel) {
7699 case CP0_REG03__ENTRYLO1:
7700 gen_helper_mtc0_entrylo1(cpu_env, arg);
7701 register_name = "EntryLo1";
7702 break;
7703 case CP0_REG03__GLOBALNUM:
7704 CP0_CHECK(ctx->vp);
7705 /* ignored */
7706 register_name = "GlobalNumber";
7707 break;
7708 default:
7709 goto cp0_unimplemented;
7711 break;
7712 case CP0_REGISTER_04:
7713 switch (sel) {
7714 case CP0_REG04__CONTEXT:
7715 gen_helper_mtc0_context(cpu_env, arg);
7716 register_name = "Context";
7717 break;
7718 case CP0_REG04__CONTEXTCONFIG:
7719 /* SmartMIPS ASE */
7720 /* gen_helper_mtc0_contextconfig(arg); */
7721 register_name = "ContextConfig";
7722 goto cp0_unimplemented;
7723 case CP0_REG04__USERLOCAL:
7724 CP0_CHECK(ctx->ulri);
7725 tcg_gen_st_tl(arg, cpu_env,
7726 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7727 register_name = "UserLocal";
7728 break;
7729 default:
7730 goto cp0_unimplemented;
7732 break;
7733 case CP0_REGISTER_05:
7734 switch (sel) {
7735 case CP0_REG05__PAGEMASK:
7736 gen_helper_mtc0_pagemask(cpu_env, arg);
7737 register_name = "PageMask";
7738 break;
7739 case CP0_REG05__PAGEGRAIN:
7740 check_insn(ctx, ISA_MIPS32R2);
7741 gen_helper_mtc0_pagegrain(cpu_env, arg);
7742 register_name = "PageGrain";
7743 ctx->base.is_jmp = DISAS_STOP;
7744 break;
7745 case CP0_REG05__SEGCTL0:
7746 CP0_CHECK(ctx->sc);
7747 gen_helper_mtc0_segctl0(cpu_env, arg);
7748 register_name = "SegCtl0";
7749 break;
7750 case CP0_REG05__SEGCTL1:
7751 CP0_CHECK(ctx->sc);
7752 gen_helper_mtc0_segctl1(cpu_env, arg);
7753 register_name = "SegCtl1";
7754 break;
7755 case CP0_REG05__SEGCTL2:
7756 CP0_CHECK(ctx->sc);
7757 gen_helper_mtc0_segctl2(cpu_env, arg);
7758 register_name = "SegCtl2";
7759 break;
7760 case CP0_REG05__PWBASE:
7761 check_pw(ctx);
7762 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7763 register_name = "PWBase";
7764 break;
7765 case CP0_REG05__PWFIELD:
7766 check_pw(ctx);
7767 gen_helper_mtc0_pwfield(cpu_env, arg);
7768 register_name = "PWField";
7769 break;
7770 case CP0_REG05__PWSIZE:
7771 check_pw(ctx);
7772 gen_helper_mtc0_pwsize(cpu_env, arg);
7773 register_name = "PWSize";
7774 break;
7775 default:
7776 goto cp0_unimplemented;
7778 break;
7779 case CP0_REGISTER_06:
7780 switch (sel) {
7781 case CP0_REG06__WIRED:
7782 gen_helper_mtc0_wired(cpu_env, arg);
7783 register_name = "Wired";
7784 break;
7785 case CP0_REG06__SRSCONF0:
7786 check_insn(ctx, ISA_MIPS32R2);
7787 gen_helper_mtc0_srsconf0(cpu_env, arg);
7788 register_name = "SRSConf0";
7789 break;
7790 case CP0_REG06__SRSCONF1:
7791 check_insn(ctx, ISA_MIPS32R2);
7792 gen_helper_mtc0_srsconf1(cpu_env, arg);
7793 register_name = "SRSConf1";
7794 break;
7795 case CP0_REG06__SRSCONF2:
7796 check_insn(ctx, ISA_MIPS32R2);
7797 gen_helper_mtc0_srsconf2(cpu_env, arg);
7798 register_name = "SRSConf2";
7799 break;
7800 case CP0_REG06__SRSCONF3:
7801 check_insn(ctx, ISA_MIPS32R2);
7802 gen_helper_mtc0_srsconf3(cpu_env, arg);
7803 register_name = "SRSConf3";
7804 break;
7805 case CP0_REG06__SRSCONF4:
7806 check_insn(ctx, ISA_MIPS32R2);
7807 gen_helper_mtc0_srsconf4(cpu_env, arg);
7808 register_name = "SRSConf4";
7809 break;
7810 case CP0_REG06__PWCTL:
7811 check_pw(ctx);
7812 gen_helper_mtc0_pwctl(cpu_env, arg);
7813 register_name = "PWCtl";
7814 break;
7815 default:
7816 goto cp0_unimplemented;
7818 break;
7819 case CP0_REGISTER_07:
7820 switch (sel) {
7821 case CP0_REG07__HWRENA:
7822 check_insn(ctx, ISA_MIPS32R2);
7823 gen_helper_mtc0_hwrena(cpu_env, arg);
7824 ctx->base.is_jmp = DISAS_STOP;
7825 register_name = "HWREna";
7826 break;
7827 default:
7828 goto cp0_unimplemented;
7830 break;
7831 case CP0_REGISTER_08:
7832 switch (sel) {
7833 case CP0_REG08__BADVADDR:
7834 /* ignored */
7835 register_name = "BadVAddr";
7836 break;
7837 case CP0_REG08__BADINSTR:
7838 /* ignored */
7839 register_name = "BadInstr";
7840 break;
7841 case CP0_REG08__BADINSTRP:
7842 /* ignored */
7843 register_name = "BadInstrP";
7844 break;
7845 case CP0_REG08__BADINSTRX:
7846 /* ignored */
7847 register_name = "BadInstrX";
7848 break;
7849 default:
7850 goto cp0_unimplemented;
7852 break;
7853 case CP0_REGISTER_09:
7854 switch (sel) {
7855 case CP0_REG09__COUNT:
7856 gen_helper_mtc0_count(cpu_env, arg);
7857 register_name = "Count";
7858 break;
7859 case CP0_REG09__SAARI:
7860 CP0_CHECK(ctx->saar);
7861 gen_helper_mtc0_saari(cpu_env, arg);
7862 register_name = "SAARI";
7863 break;
7864 case CP0_REG09__SAAR:
7865 CP0_CHECK(ctx->saar);
7866 gen_helper_mtc0_saar(cpu_env, arg);
7867 register_name = "SAAR";
7868 break;
7869 default:
7870 goto cp0_unimplemented;
7872 break;
7873 case CP0_REGISTER_10:
7874 switch (sel) {
7875 case CP0_REG10__ENTRYHI:
7876 gen_helper_mtc0_entryhi(cpu_env, arg);
7877 register_name = "EntryHi";
7878 break;
7879 default:
7880 goto cp0_unimplemented;
7882 break;
7883 case CP0_REGISTER_11:
7884 switch (sel) {
7885 case 0:
7886 gen_helper_mtc0_compare(cpu_env, arg);
7887 register_name = "Compare";
7888 break;
7889 /* 6,7 are implementation dependent */
7890 default:
7891 goto cp0_unimplemented;
7893 break;
7894 case CP0_REGISTER_12:
7895 switch (sel) {
7896 case 0:
7897 save_cpu_state(ctx, 1);
7898 gen_helper_mtc0_status(cpu_env, arg);
7899 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7900 gen_save_pc(ctx->base.pc_next + 4);
7901 ctx->base.is_jmp = DISAS_EXIT;
7902 register_name = "Status";
7903 break;
7904 case 1:
7905 check_insn(ctx, ISA_MIPS32R2);
7906 gen_helper_mtc0_intctl(cpu_env, arg);
7907 /* Stop translation as we may have switched the execution mode */
7908 ctx->base.is_jmp = DISAS_STOP;
7909 register_name = "IntCtl";
7910 break;
7911 case 2:
7912 check_insn(ctx, ISA_MIPS32R2);
7913 gen_helper_mtc0_srsctl(cpu_env, arg);
7914 /* Stop translation as we may have switched the execution mode */
7915 ctx->base.is_jmp = DISAS_STOP;
7916 register_name = "SRSCtl";
7917 break;
7918 case 3:
7919 check_insn(ctx, ISA_MIPS32R2);
7920 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7921 /* Stop translation as we may have switched the execution mode */
7922 ctx->base.is_jmp = DISAS_STOP;
7923 register_name = "SRSMap";
7924 break;
7925 default:
7926 goto cp0_unimplemented;
7928 break;
7929 case CP0_REGISTER_13:
7930 switch (sel) {
7931 case 0:
7932 save_cpu_state(ctx, 1);
7933 gen_helper_mtc0_cause(cpu_env, arg);
7935 * Stop translation as we may have triggered an interrupt.
7936 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7937 * translated code to check for pending interrupts.
7939 gen_save_pc(ctx->base.pc_next + 4);
7940 ctx->base.is_jmp = DISAS_EXIT;
7941 register_name = "Cause";
7942 break;
7943 default:
7944 goto cp0_unimplemented;
7946 break;
7947 case CP0_REGISTER_14:
7948 switch (sel) {
7949 case 0:
7950 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7951 register_name = "EPC";
7952 break;
7953 default:
7954 goto cp0_unimplemented;
7956 break;
7957 case CP0_REGISTER_15:
7958 switch (sel) {
7959 case 0:
7960 /* ignored */
7961 register_name = "PRid";
7962 break;
7963 case 1:
7964 check_insn(ctx, ISA_MIPS32R2);
7965 gen_helper_mtc0_ebase(cpu_env, arg);
7966 register_name = "EBase";
7967 break;
7968 default:
7969 goto cp0_unimplemented;
7971 break;
7972 case CP0_REGISTER_16:
7973 switch (sel) {
7974 case 0:
7975 gen_helper_mtc0_config0(cpu_env, arg);
7976 register_name = "Config";
7977 /* Stop translation as we may have switched the execution mode */
7978 ctx->base.is_jmp = DISAS_STOP;
7979 break;
7980 case 1:
7981 /* ignored, read only */
7982 register_name = "Config1";
7983 break;
7984 case 2:
7985 gen_helper_mtc0_config2(cpu_env, arg);
7986 register_name = "Config2";
7987 /* Stop translation as we may have switched the execution mode */
7988 ctx->base.is_jmp = DISAS_STOP;
7989 break;
7990 case 3:
7991 gen_helper_mtc0_config3(cpu_env, arg);
7992 register_name = "Config3";
7993 /* Stop translation as we may have switched the execution mode */
7994 ctx->base.is_jmp = DISAS_STOP;
7995 break;
7996 case 4:
7997 gen_helper_mtc0_config4(cpu_env, arg);
7998 register_name = "Config4";
7999 ctx->base.is_jmp = DISAS_STOP;
8000 break;
8001 case 5:
8002 gen_helper_mtc0_config5(cpu_env, arg);
8003 register_name = "Config5";
8004 /* Stop translation as we may have switched the execution mode */
8005 ctx->base.is_jmp = DISAS_STOP;
8006 break;
8007 /* 6,7 are implementation dependent */
8008 case 6:
8009 /* ignored */
8010 register_name = "Config6";
8011 break;
8012 case 7:
8013 /* ignored */
8014 register_name = "Config7";
8015 break;
8016 default:
8017 register_name = "Invalid config selector";
8018 goto cp0_unimplemented;
8020 break;
8021 case CP0_REGISTER_17:
8022 switch (sel) {
8023 case 0:
8024 gen_helper_mtc0_lladdr(cpu_env, arg);
8025 register_name = "LLAddr";
8026 break;
8027 case 1:
8028 CP0_CHECK(ctx->mrp);
8029 gen_helper_mtc0_maar(cpu_env, arg);
8030 register_name = "MAAR";
8031 break;
8032 case 2:
8033 CP0_CHECK(ctx->mrp);
8034 gen_helper_mtc0_maari(cpu_env, arg);
8035 register_name = "MAARI";
8036 break;
8037 default:
8038 goto cp0_unimplemented;
8040 break;
8041 case CP0_REGISTER_18:
8042 switch (sel) {
8043 case 0:
8044 case 1:
8045 case 2:
8046 case 3:
8047 case 4:
8048 case 5:
8049 case 6:
8050 case 7:
8051 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8052 gen_helper_0e1i(mtc0_watchlo, arg, sel);
8053 register_name = "WatchLo";
8054 break;
8055 default:
8056 goto cp0_unimplemented;
8058 break;
8059 case CP0_REGISTER_19:
8060 switch (sel) {
8061 case 0:
8062 case 1:
8063 case 2:
8064 case 3:
8065 case 4:
8066 case 5:
8067 case 6:
8068 case 7:
8069 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8070 gen_helper_0e1i(mtc0_watchhi, arg, sel);
8071 register_name = "WatchHi";
8072 break;
8073 default:
8074 goto cp0_unimplemented;
8076 break;
8077 case CP0_REGISTER_20:
8078 switch (sel) {
8079 case 0:
8080 #if defined(TARGET_MIPS64)
8081 check_insn(ctx, ISA_MIPS3);
8082 gen_helper_mtc0_xcontext(cpu_env, arg);
8083 register_name = "XContext";
8084 break;
8085 #endif
8086 default:
8087 goto cp0_unimplemented;
8089 break;
8090 case CP0_REGISTER_21:
8091 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8092 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8093 switch (sel) {
8094 case 0:
8095 gen_helper_mtc0_framemask(cpu_env, arg);
8096 register_name = "Framemask";
8097 break;
8098 default:
8099 goto cp0_unimplemented;
8101 break;
8102 case CP0_REGISTER_22:
8103 /* ignored */
8104 register_name = "Diagnostic"; /* implementation dependent */
8105 break;
8106 case CP0_REGISTER_23:
8107 switch (sel) {
8108 case 0:
8109 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8110 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8111 gen_save_pc(ctx->base.pc_next + 4);
8112 ctx->base.is_jmp = DISAS_EXIT;
8113 register_name = "Debug";
8114 break;
8115 case 1:
8116 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
8117 register_name = "TraceControl";
8118 /* Stop translation as we may have switched the execution mode */
8119 ctx->base.is_jmp = DISAS_STOP;
8120 goto cp0_unimplemented;
8121 case 2:
8122 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
8123 register_name = "TraceControl2";
8124 /* Stop translation as we may have switched the execution mode */
8125 ctx->base.is_jmp = DISAS_STOP;
8126 goto cp0_unimplemented;
8127 case 3:
8128 /* Stop translation as we may have switched the execution mode */
8129 ctx->base.is_jmp = DISAS_STOP;
8130 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
8131 register_name = "UserTraceData";
8132 /* Stop translation as we may have switched the execution mode */
8133 ctx->base.is_jmp = DISAS_STOP;
8134 goto cp0_unimplemented;
8135 case 4:
8136 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
8137 /* Stop translation as we may have switched the execution mode */
8138 ctx->base.is_jmp = DISAS_STOP;
8139 register_name = "TraceBPC";
8140 goto cp0_unimplemented;
8141 default:
8142 goto cp0_unimplemented;
8144 break;
8145 case CP0_REGISTER_24:
8146 switch (sel) {
8147 case 0:
8148 /* EJTAG support */
8149 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8150 register_name = "DEPC";
8151 break;
8152 default:
8153 goto cp0_unimplemented;
8155 break;
8156 case CP0_REGISTER_25:
8157 switch (sel) {
8158 case 0:
8159 gen_helper_mtc0_performance0(cpu_env, arg);
8160 register_name = "Performance0";
8161 break;
8162 case 1:
8163 /* gen_helper_mtc0_performance1(arg); */
8164 register_name = "Performance1";
8165 goto cp0_unimplemented;
8166 case 2:
8167 /* gen_helper_mtc0_performance2(arg); */
8168 register_name = "Performance2";
8169 goto cp0_unimplemented;
8170 case 3:
8171 /* gen_helper_mtc0_performance3(arg); */
8172 register_name = "Performance3";
8173 goto cp0_unimplemented;
8174 case 4:
8175 /* gen_helper_mtc0_performance4(arg); */
8176 register_name = "Performance4";
8177 goto cp0_unimplemented;
8178 case 5:
8179 /* gen_helper_mtc0_performance5(arg); */
8180 register_name = "Performance5";
8181 goto cp0_unimplemented;
8182 case 6:
8183 /* gen_helper_mtc0_performance6(arg); */
8184 register_name = "Performance6";
8185 goto cp0_unimplemented;
8186 case 7:
8187 /* gen_helper_mtc0_performance7(arg); */
8188 register_name = "Performance7";
8189 goto cp0_unimplemented;
8190 default:
8191 goto cp0_unimplemented;
8193 break;
8194 case CP0_REGISTER_26:
8195 switch (sel) {
8196 case 0:
8197 gen_helper_mtc0_errctl(cpu_env, arg);
8198 ctx->base.is_jmp = DISAS_STOP;
8199 register_name = "ErrCtl";
8200 break;
8201 default:
8202 goto cp0_unimplemented;
8204 break;
8205 case CP0_REGISTER_27:
8206 switch (sel) {
8207 case 0:
8208 case 1:
8209 case 2:
8210 case 3:
8211 /* ignored */
8212 register_name = "CacheErr";
8213 break;
8214 default:
8215 goto cp0_unimplemented;
8217 break;
8218 case CP0_REGISTER_28:
8219 switch (sel) {
8220 case 0:
8221 case 2:
8222 case 4:
8223 case 6:
8224 gen_helper_mtc0_taglo(cpu_env, arg);
8225 register_name = "TagLo";
8226 break;
8227 case 1:
8228 case 3:
8229 case 5:
8230 case 7:
8231 gen_helper_mtc0_datalo(cpu_env, arg);
8232 register_name = "DataLo";
8233 break;
8234 default:
8235 goto cp0_unimplemented;
8237 break;
8238 case CP0_REGISTER_29:
8239 switch (sel) {
8240 case 0:
8241 case 2:
8242 case 4:
8243 case 6:
8244 gen_helper_mtc0_taghi(cpu_env, arg);
8245 register_name = "TagHi";
8246 break;
8247 case 1:
8248 case 3:
8249 case 5:
8250 case 7:
8251 gen_helper_mtc0_datahi(cpu_env, arg);
8252 register_name = "DataHi";
8253 break;
8254 default:
8255 register_name = "invalid sel";
8256 goto cp0_unimplemented;
8258 break;
8259 case CP0_REGISTER_30:
8260 switch (sel) {
8261 case 0:
8262 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8263 register_name = "ErrorEPC";
8264 break;
8265 default:
8266 goto cp0_unimplemented;
8268 break;
8269 case CP0_REGISTER_31:
8270 switch (sel) {
8271 case 0:
8272 /* EJTAG support */
8273 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8274 register_name = "DESAVE";
8275 break;
8276 case 2:
8277 case 3:
8278 case 4:
8279 case 5:
8280 case 6:
8281 case 7:
8282 CP0_CHECK(ctx->kscrexist & (1 << sel));
8283 tcg_gen_st_tl(arg, cpu_env,
8284 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
8285 register_name = "KScratch";
8286 break;
8287 default:
8288 goto cp0_unimplemented;
8290 break;
8291 default:
8292 goto cp0_unimplemented;
8294 trace_mips_translate_c0("mtc0", register_name, reg, sel);
8296 /* For simplicity assume that all writes can cause interrupts. */
8297 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8299 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8300 * translated code to check for pending interrupts.
8302 gen_save_pc(ctx->base.pc_next + 4);
8303 ctx->base.is_jmp = DISAS_EXIT;
8305 return;
8307 cp0_unimplemented:
8308 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
8309 register_name, reg, sel);
8312 #if defined(TARGET_MIPS64)
8313 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8315 const char *register_name = "invalid";
8317 if (sel != 0) {
8318 check_insn(ctx, ISA_MIPS64);
8321 switch (reg) {
8322 case CP0_REGISTER_00:
8323 switch (sel) {
8324 case CP0_REG00__INDEX:
8325 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
8326 register_name = "Index";
8327 break;
8328 case CP0_REG00__MVPCONTROL:
8329 CP0_CHECK(ctx->insn_flags & ASE_MT);
8330 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
8331 register_name = "MVPControl";
8332 break;
8333 case CP0_REG00__MVPCONF0:
8334 CP0_CHECK(ctx->insn_flags & ASE_MT);
8335 gen_helper_mfc0_mvpconf0(arg, cpu_env);
8336 register_name = "MVPConf0";
8337 break;
8338 case CP0_REG00__MVPCONF1:
8339 CP0_CHECK(ctx->insn_flags & ASE_MT);
8340 gen_helper_mfc0_mvpconf1(arg, cpu_env);
8341 register_name = "MVPConf1";
8342 break;
8343 case CP0_REG00__VPCONTROL:
8344 CP0_CHECK(ctx->vp);
8345 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
8346 register_name = "VPControl";
8347 break;
8348 default:
8349 goto cp0_unimplemented;
8351 break;
8352 case CP0_REGISTER_01:
8353 switch (sel) {
8354 case CP0_REG01__RANDOM:
8355 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8356 gen_helper_mfc0_random(arg, cpu_env);
8357 register_name = "Random";
8358 break;
8359 case CP0_REG01__VPECONTROL:
8360 CP0_CHECK(ctx->insn_flags & ASE_MT);
8361 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
8362 register_name = "VPEControl";
8363 break;
8364 case CP0_REG01__VPECONF0:
8365 CP0_CHECK(ctx->insn_flags & ASE_MT);
8366 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
8367 register_name = "VPEConf0";
8368 break;
8369 case CP0_REG01__VPECONF1:
8370 CP0_CHECK(ctx->insn_flags & ASE_MT);
8371 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
8372 register_name = "VPEConf1";
8373 break;
8374 case CP0_REG01__YQMASK:
8375 CP0_CHECK(ctx->insn_flags & ASE_MT);
8376 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
8377 register_name = "YQMask";
8378 break;
8379 case CP0_REG01__VPESCHEDULE:
8380 CP0_CHECK(ctx->insn_flags & ASE_MT);
8381 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
8382 register_name = "VPESchedule";
8383 break;
8384 case CP0_REG01__VPESCHEFBACK:
8385 CP0_CHECK(ctx->insn_flags & ASE_MT);
8386 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
8387 register_name = "VPEScheFBack";
8388 break;
8389 case CP0_REG01__VPEOPT:
8390 CP0_CHECK(ctx->insn_flags & ASE_MT);
8391 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
8392 register_name = "VPEOpt";
8393 break;
8394 default:
8395 goto cp0_unimplemented;
8397 break;
8398 case CP0_REGISTER_02:
8399 switch (sel) {
8400 case CP0_REG02__ENTRYLO0:
8401 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
8402 register_name = "EntryLo0";
8403 break;
8404 case CP0_REG02__TCSTATUS:
8405 CP0_CHECK(ctx->insn_flags & ASE_MT);
8406 gen_helper_mfc0_tcstatus(arg, cpu_env);
8407 register_name = "TCStatus";
8408 break;
8409 case CP0_REG02__TCBIND:
8410 CP0_CHECK(ctx->insn_flags & ASE_MT);
8411 gen_helper_mfc0_tcbind(arg, cpu_env);
8412 register_name = "TCBind";
8413 break;
8414 case CP0_REG02__TCRESTART:
8415 CP0_CHECK(ctx->insn_flags & ASE_MT);
8416 gen_helper_dmfc0_tcrestart(arg, cpu_env);
8417 register_name = "TCRestart";
8418 break;
8419 case CP0_REG02__TCHALT:
8420 CP0_CHECK(ctx->insn_flags & ASE_MT);
8421 gen_helper_dmfc0_tchalt(arg, cpu_env);
8422 register_name = "TCHalt";
8423 break;
8424 case CP0_REG02__TCCONTEXT:
8425 CP0_CHECK(ctx->insn_flags & ASE_MT);
8426 gen_helper_dmfc0_tccontext(arg, cpu_env);
8427 register_name = "TCContext";
8428 break;
8429 case CP0_REG02__TCSCHEDULE:
8430 CP0_CHECK(ctx->insn_flags & ASE_MT);
8431 gen_helper_dmfc0_tcschedule(arg, cpu_env);
8432 register_name = "TCSchedule";
8433 break;
8434 case CP0_REG02__TCSCHEFBACK:
8435 CP0_CHECK(ctx->insn_flags & ASE_MT);
8436 gen_helper_dmfc0_tcschefback(arg, cpu_env);
8437 register_name = "TCScheFBack";
8438 break;
8439 default:
8440 goto cp0_unimplemented;
8442 break;
8443 case CP0_REGISTER_03:
8444 switch (sel) {
8445 case CP0_REG03__ENTRYLO1:
8446 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
8447 register_name = "EntryLo1";
8448 break;
8449 case CP0_REG03__GLOBALNUM:
8450 CP0_CHECK(ctx->vp);
8451 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
8452 register_name = "GlobalNumber";
8453 break;
8454 default:
8455 goto cp0_unimplemented;
8457 break;
8458 case CP0_REGISTER_04:
8459 switch (sel) {
8460 case CP0_REG04__CONTEXT:
8461 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
8462 register_name = "Context";
8463 break;
8464 case CP0_REG04__CONTEXTCONFIG:
8465 /* SmartMIPS ASE */
8466 /* gen_helper_dmfc0_contextconfig(arg); */
8467 register_name = "ContextConfig";
8468 goto cp0_unimplemented;
8469 case CP0_REG04__USERLOCAL:
8470 CP0_CHECK(ctx->ulri);
8471 tcg_gen_ld_tl(arg, cpu_env,
8472 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8473 register_name = "UserLocal";
8474 break;
8475 default:
8476 goto cp0_unimplemented;
8478 break;
8479 case CP0_REGISTER_05:
8480 switch (sel) {
8481 case CP0_REG05__PAGEMASK:
8482 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
8483 register_name = "PageMask";
8484 break;
8485 case CP0_REG05__PAGEGRAIN:
8486 check_insn(ctx, ISA_MIPS32R2);
8487 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
8488 register_name = "PageGrain";
8489 break;
8490 case CP0_REG05__SEGCTL0:
8491 CP0_CHECK(ctx->sc);
8492 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
8493 register_name = "SegCtl0";
8494 break;
8495 case CP0_REG05__SEGCTL1:
8496 CP0_CHECK(ctx->sc);
8497 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
8498 register_name = "SegCtl1";
8499 break;
8500 case CP0_REG05__SEGCTL2:
8501 CP0_CHECK(ctx->sc);
8502 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
8503 register_name = "SegCtl2";
8504 break;
8505 case CP0_REG05__PWBASE:
8506 check_pw(ctx);
8507 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8508 register_name = "PWBase";
8509 break;
8510 case CP0_REG05__PWFIELD:
8511 check_pw(ctx);
8512 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
8513 register_name = "PWField";
8514 break;
8515 case CP0_REG05__PWSIZE:
8516 check_pw(ctx);
8517 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
8518 register_name = "PWSize";
8519 break;
8520 default:
8521 goto cp0_unimplemented;
8523 break;
8524 case CP0_REGISTER_06:
8525 switch (sel) {
8526 case CP0_REG06__WIRED:
8527 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
8528 register_name = "Wired";
8529 break;
8530 case CP0_REG06__SRSCONF0:
8531 check_insn(ctx, ISA_MIPS32R2);
8532 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
8533 register_name = "SRSConf0";
8534 break;
8535 case CP0_REG06__SRSCONF1:
8536 check_insn(ctx, ISA_MIPS32R2);
8537 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
8538 register_name = "SRSConf1";
8539 break;
8540 case CP0_REG06__SRSCONF2:
8541 check_insn(ctx, ISA_MIPS32R2);
8542 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
8543 register_name = "SRSConf2";
8544 break;
8545 case CP0_REG06__SRSCONF3:
8546 check_insn(ctx, ISA_MIPS32R2);
8547 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
8548 register_name = "SRSConf3";
8549 break;
8550 case CP0_REG06__SRSCONF4:
8551 check_insn(ctx, ISA_MIPS32R2);
8552 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
8553 register_name = "SRSConf4";
8554 break;
8555 case CP0_REG06__PWCTL:
8556 check_pw(ctx);
8557 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
8558 register_name = "PWCtl";
8559 break;
8560 default:
8561 goto cp0_unimplemented;
8563 break;
8564 case CP0_REGISTER_07:
8565 switch (sel) {
8566 case CP0_REG07__HWRENA:
8567 check_insn(ctx, ISA_MIPS32R2);
8568 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
8569 register_name = "HWREna";
8570 break;
8571 default:
8572 goto cp0_unimplemented;
8574 break;
8575 case CP0_REGISTER_08:
8576 switch (sel) {
8577 case CP0_REG08__BADVADDR:
8578 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
8579 register_name = "BadVAddr";
8580 break;
8581 case CP0_REG08__BADINSTR:
8582 CP0_CHECK(ctx->bi);
8583 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
8584 register_name = "BadInstr";
8585 break;
8586 case CP0_REG08__BADINSTRP:
8587 CP0_CHECK(ctx->bp);
8588 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
8589 register_name = "BadInstrP";
8590 break;
8591 case CP0_REG08__BADINSTRX:
8592 CP0_CHECK(ctx->bi);
8593 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
8594 tcg_gen_andi_tl(arg, arg, ~0xffff);
8595 register_name = "BadInstrX";
8596 break;
8597 default:
8598 goto cp0_unimplemented;
8600 break;
8601 case CP0_REGISTER_09:
8602 switch (sel) {
8603 case CP0_REG09__COUNT:
8604 /* Mark as an IO operation because we read the time. */
8605 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8606 gen_io_start();
8608 gen_helper_mfc0_count(arg, cpu_env);
8610 * Break the TB to be able to take timer interrupts immediately
8611 * after reading count. DISAS_STOP isn't sufficient, we need to
8612 * ensure we break completely out of translated code.
8614 gen_save_pc(ctx->base.pc_next + 4);
8615 ctx->base.is_jmp = DISAS_EXIT;
8616 register_name = "Count";
8617 break;
8618 case CP0_REG09__SAARI:
8619 CP0_CHECK(ctx->saar);
8620 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
8621 register_name = "SAARI";
8622 break;
8623 case CP0_REG09__SAAR:
8624 CP0_CHECK(ctx->saar);
8625 gen_helper_dmfc0_saar(arg, cpu_env);
8626 register_name = "SAAR";
8627 break;
8628 default:
8629 goto cp0_unimplemented;
8631 break;
8632 case CP0_REGISTER_10:
8633 switch (sel) {
8634 case CP0_REG10__ENTRYHI:
8635 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
8636 register_name = "EntryHi";
8637 break;
8638 default:
8639 goto cp0_unimplemented;
8641 break;
8642 case CP0_REGISTER_11:
8643 switch (sel) {
8644 case 0:
8645 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
8646 register_name = "Compare";
8647 break;
8648 /* 6,7 are implementation dependent */
8649 default:
8650 goto cp0_unimplemented;
8652 break;
8653 case CP0_REGISTER_12:
8654 switch (sel) {
8655 case 0:
8656 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
8657 register_name = "Status";
8658 break;
8659 case 1:
8660 check_insn(ctx, ISA_MIPS32R2);
8661 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
8662 register_name = "IntCtl";
8663 break;
8664 case 2:
8665 check_insn(ctx, ISA_MIPS32R2);
8666 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
8667 register_name = "SRSCtl";
8668 break;
8669 case 3:
8670 check_insn(ctx, ISA_MIPS32R2);
8671 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8672 register_name = "SRSMap";
8673 break;
8674 default:
8675 goto cp0_unimplemented;
8677 break;
8678 case CP0_REGISTER_13:
8679 switch (sel) {
8680 case 0:
8681 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
8682 register_name = "Cause";
8683 break;
8684 default:
8685 goto cp0_unimplemented;
8687 break;
8688 case CP0_REGISTER_14:
8689 switch (sel) {
8690 case 0:
8691 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8692 register_name = "EPC";
8693 break;
8694 default:
8695 goto cp0_unimplemented;
8697 break;
8698 case CP0_REGISTER_15:
8699 switch (sel) {
8700 case 0:
8701 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
8702 register_name = "PRid";
8703 break;
8704 case 1:
8705 check_insn(ctx, ISA_MIPS32R2);
8706 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
8707 register_name = "EBase";
8708 break;
8709 case 3:
8710 check_insn(ctx, ISA_MIPS32R2);
8711 CP0_CHECK(ctx->cmgcr);
8712 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
8713 register_name = "CMGCRBase";
8714 break;
8715 default:
8716 goto cp0_unimplemented;
8718 break;
8719 case CP0_REGISTER_16:
8720 switch (sel) {
8721 case 0:
8722 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
8723 register_name = "Config";
8724 break;
8725 case 1:
8726 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
8727 register_name = "Config1";
8728 break;
8729 case 2:
8730 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
8731 register_name = "Config2";
8732 break;
8733 case 3:
8734 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
8735 register_name = "Config3";
8736 break;
8737 case 4:
8738 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
8739 register_name = "Config4";
8740 break;
8741 case 5:
8742 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
8743 register_name = "Config5";
8744 break;
8745 /* 6,7 are implementation dependent */
8746 case 6:
8747 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
8748 register_name = "Config6";
8749 break;
8750 case 7:
8751 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
8752 register_name = "Config7";
8753 break;
8754 default:
8755 goto cp0_unimplemented;
8757 break;
8758 case CP0_REGISTER_17:
8759 switch (sel) {
8760 case 0:
8761 gen_helper_dmfc0_lladdr(arg, cpu_env);
8762 register_name = "LLAddr";
8763 break;
8764 case 1:
8765 CP0_CHECK(ctx->mrp);
8766 gen_helper_dmfc0_maar(arg, cpu_env);
8767 register_name = "MAAR";
8768 break;
8769 case 2:
8770 CP0_CHECK(ctx->mrp);
8771 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
8772 register_name = "MAARI";
8773 break;
8774 default:
8775 goto cp0_unimplemented;
8777 break;
8778 case CP0_REGISTER_18:
8779 switch (sel) {
8780 case 0:
8781 case 1:
8782 case 2:
8783 case 3:
8784 case 4:
8785 case 5:
8786 case 6:
8787 case 7:
8788 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8789 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
8790 register_name = "WatchLo";
8791 break;
8792 default:
8793 goto cp0_unimplemented;
8795 break;
8796 case CP0_REGISTER_19:
8797 switch (sel) {
8798 case 0:
8799 case 1:
8800 case 2:
8801 case 3:
8802 case 4:
8803 case 5:
8804 case 6:
8805 case 7:
8806 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8807 gen_helper_1e0i(mfc0_watchhi, arg, sel);
8808 register_name = "WatchHi";
8809 break;
8810 default:
8811 goto cp0_unimplemented;
8813 break;
8814 case CP0_REGISTER_20:
8815 switch (sel) {
8816 case 0:
8817 check_insn(ctx, ISA_MIPS3);
8818 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
8819 register_name = "XContext";
8820 break;
8821 default:
8822 goto cp0_unimplemented;
8824 break;
8825 case CP0_REGISTER_21:
8826 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8827 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8828 switch (sel) {
8829 case 0:
8830 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
8831 register_name = "Framemask";
8832 break;
8833 default:
8834 goto cp0_unimplemented;
8836 break;
8837 case CP0_REGISTER_22:
8838 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8839 register_name = "'Diagnostic"; /* implementation dependent */
8840 break;
8841 case CP0_REGISTER_23:
8842 switch (sel) {
8843 case 0:
8844 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
8845 register_name = "Debug";
8846 break;
8847 case 1:
8848 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
8849 register_name = "TraceControl";
8850 goto cp0_unimplemented;
8851 case 2:
8852 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
8853 register_name = "TraceControl2";
8854 goto cp0_unimplemented;
8855 case 3:
8856 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
8857 register_name = "UserTraceData";
8858 goto cp0_unimplemented;
8859 case 4:
8860 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
8861 register_name = "TraceBPC";
8862 goto cp0_unimplemented;
8863 default:
8864 goto cp0_unimplemented;
8866 break;
8867 case CP0_REGISTER_24:
8868 switch (sel) {
8869 case 0:
8870 /* EJTAG support */
8871 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8872 register_name = "DEPC";
8873 break;
8874 default:
8875 goto cp0_unimplemented;
8877 break;
8878 case CP0_REGISTER_25:
8879 switch (sel) {
8880 case 0:
8881 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
8882 register_name = "Performance0";
8883 break;
8884 case 1:
8885 /* gen_helper_dmfc0_performance1(arg); */
8886 register_name = "Performance1";
8887 goto cp0_unimplemented;
8888 case 2:
8889 /* gen_helper_dmfc0_performance2(arg); */
8890 register_name = "Performance2";
8891 goto cp0_unimplemented;
8892 case 3:
8893 /* gen_helper_dmfc0_performance3(arg); */
8894 register_name = "Performance3";
8895 goto cp0_unimplemented;
8896 case 4:
8897 /* gen_helper_dmfc0_performance4(arg); */
8898 register_name = "Performance4";
8899 goto cp0_unimplemented;
8900 case 5:
8901 /* gen_helper_dmfc0_performance5(arg); */
8902 register_name = "Performance5";
8903 goto cp0_unimplemented;
8904 case 6:
8905 /* gen_helper_dmfc0_performance6(arg); */
8906 register_name = "Performance6";
8907 goto cp0_unimplemented;
8908 case 7:
8909 /* gen_helper_dmfc0_performance7(arg); */
8910 register_name = "Performance7";
8911 goto cp0_unimplemented;
8912 default:
8913 goto cp0_unimplemented;
8915 break;
8916 case CP0_REGISTER_26:
8917 switch (sel) {
8918 case 0:
8919 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
8920 register_name = "ErrCtl";
8921 break;
8922 default:
8923 goto cp0_unimplemented;
8925 break;
8926 case CP0_REGISTER_27:
8927 switch (sel) {
8928 /* ignored */
8929 case 0:
8930 case 1:
8931 case 2:
8932 case 3:
8933 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8934 register_name = "CacheErr";
8935 break;
8936 default:
8937 goto cp0_unimplemented;
8939 break;
8940 case CP0_REGISTER_28:
8941 switch (sel) {
8942 case 0:
8943 case 2:
8944 case 4:
8945 case 6:
8946 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
8947 register_name = "TagLo";
8948 break;
8949 case 1:
8950 case 3:
8951 case 5:
8952 case 7:
8953 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
8954 register_name = "DataLo";
8955 break;
8956 default:
8957 goto cp0_unimplemented;
8959 break;
8960 case CP0_REGISTER_29:
8961 switch (sel) {
8962 case 0:
8963 case 2:
8964 case 4:
8965 case 6:
8966 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
8967 register_name = "TagHi";
8968 break;
8969 case 1:
8970 case 3:
8971 case 5:
8972 case 7:
8973 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
8974 register_name = "DataHi";
8975 break;
8976 default:
8977 goto cp0_unimplemented;
8979 break;
8980 case CP0_REGISTER_30:
8981 switch (sel) {
8982 case 0:
8983 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8984 register_name = "ErrorEPC";
8985 break;
8986 default:
8987 goto cp0_unimplemented;
8989 break;
8990 case CP0_REGISTER_31:
8991 switch (sel) {
8992 case 0:
8993 /* EJTAG support */
8994 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8995 register_name = "DESAVE";
8996 break;
8997 case 2:
8998 case 3:
8999 case 4:
9000 case 5:
9001 case 6:
9002 case 7:
9003 CP0_CHECK(ctx->kscrexist & (1 << sel));
9004 tcg_gen_ld_tl(arg, cpu_env,
9005 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
9006 register_name = "KScratch";
9007 break;
9008 default:
9009 goto cp0_unimplemented;
9011 break;
9012 default:
9013 goto cp0_unimplemented;
9015 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
9016 return;
9018 cp0_unimplemented:
9019 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
9020 register_name, reg, sel);
9021 gen_mfc0_unimplemented(ctx, arg);
9024 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9026 const char *register_name = "invalid";
9028 if (sel != 0) {
9029 check_insn(ctx, ISA_MIPS64);
9032 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9033 gen_io_start();
9036 switch (reg) {
9037 case CP0_REGISTER_00:
9038 switch (sel) {
9039 case CP0_REG00__INDEX:
9040 gen_helper_mtc0_index(cpu_env, arg);
9041 register_name = "Index";
9042 break;
9043 case CP0_REG00__MVPCONTROL:
9044 CP0_CHECK(ctx->insn_flags & ASE_MT);
9045 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
9046 register_name = "MVPControl";
9047 break;
9048 case CP0_REG00__MVPCONF0:
9049 CP0_CHECK(ctx->insn_flags & ASE_MT);
9050 /* ignored */
9051 register_name = "MVPConf0";
9052 break;
9053 case CP0_REG00__MVPCONF1:
9054 CP0_CHECK(ctx->insn_flags & ASE_MT);
9055 /* ignored */
9056 register_name = "MVPConf1";
9057 break;
9058 case CP0_REG00__VPCONTROL:
9059 CP0_CHECK(ctx->vp);
9060 /* ignored */
9061 register_name = "VPControl";
9062 break;
9063 default:
9064 goto cp0_unimplemented;
9066 break;
9067 case CP0_REGISTER_01:
9068 switch (sel) {
9069 case CP0_REG01__RANDOM:
9070 /* ignored */
9071 register_name = "Random";
9072 break;
9073 case CP0_REG01__VPECONTROL:
9074 CP0_CHECK(ctx->insn_flags & ASE_MT);
9075 gen_helper_mtc0_vpecontrol(cpu_env, arg);
9076 register_name = "VPEControl";
9077 break;
9078 case CP0_REG01__VPECONF0:
9079 CP0_CHECK(ctx->insn_flags & ASE_MT);
9080 gen_helper_mtc0_vpeconf0(cpu_env, arg);
9081 register_name = "VPEConf0";
9082 break;
9083 case CP0_REG01__VPECONF1:
9084 CP0_CHECK(ctx->insn_flags & ASE_MT);
9085 gen_helper_mtc0_vpeconf1(cpu_env, arg);
9086 register_name = "VPEConf1";
9087 break;
9088 case CP0_REG01__YQMASK:
9089 CP0_CHECK(ctx->insn_flags & ASE_MT);
9090 gen_helper_mtc0_yqmask(cpu_env, arg);
9091 register_name = "YQMask";
9092 break;
9093 case CP0_REG01__VPESCHEDULE:
9094 CP0_CHECK(ctx->insn_flags & ASE_MT);
9095 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
9096 register_name = "VPESchedule";
9097 break;
9098 case CP0_REG01__VPESCHEFBACK:
9099 CP0_CHECK(ctx->insn_flags & ASE_MT);
9100 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
9101 register_name = "VPEScheFBack";
9102 break;
9103 case CP0_REG01__VPEOPT:
9104 CP0_CHECK(ctx->insn_flags & ASE_MT);
9105 gen_helper_mtc0_vpeopt(cpu_env, arg);
9106 register_name = "VPEOpt";
9107 break;
9108 default:
9109 goto cp0_unimplemented;
9111 break;
9112 case CP0_REGISTER_02:
9113 switch (sel) {
9114 case CP0_REG02__ENTRYLO0:
9115 gen_helper_dmtc0_entrylo0(cpu_env, arg);
9116 register_name = "EntryLo0";
9117 break;
9118 case CP0_REG02__TCSTATUS:
9119 CP0_CHECK(ctx->insn_flags & ASE_MT);
9120 gen_helper_mtc0_tcstatus(cpu_env, arg);
9121 register_name = "TCStatus";
9122 break;
9123 case CP0_REG02__TCBIND:
9124 CP0_CHECK(ctx->insn_flags & ASE_MT);
9125 gen_helper_mtc0_tcbind(cpu_env, arg);
9126 register_name = "TCBind";
9127 break;
9128 case CP0_REG02__TCRESTART:
9129 CP0_CHECK(ctx->insn_flags & ASE_MT);
9130 gen_helper_mtc0_tcrestart(cpu_env, arg);
9131 register_name = "TCRestart";
9132 break;
9133 case CP0_REG02__TCHALT:
9134 CP0_CHECK(ctx->insn_flags & ASE_MT);
9135 gen_helper_mtc0_tchalt(cpu_env, arg);
9136 register_name = "TCHalt";
9137 break;
9138 case CP0_REG02__TCCONTEXT:
9139 CP0_CHECK(ctx->insn_flags & ASE_MT);
9140 gen_helper_mtc0_tccontext(cpu_env, arg);
9141 register_name = "TCContext";
9142 break;
9143 case CP0_REG02__TCSCHEDULE:
9144 CP0_CHECK(ctx->insn_flags & ASE_MT);
9145 gen_helper_mtc0_tcschedule(cpu_env, arg);
9146 register_name = "TCSchedule";
9147 break;
9148 case CP0_REG02__TCSCHEFBACK:
9149 CP0_CHECK(ctx->insn_flags & ASE_MT);
9150 gen_helper_mtc0_tcschefback(cpu_env, arg);
9151 register_name = "TCScheFBack";
9152 break;
9153 default:
9154 goto cp0_unimplemented;
9156 break;
9157 case CP0_REGISTER_03:
9158 switch (sel) {
9159 case CP0_REG03__ENTRYLO1:
9160 gen_helper_dmtc0_entrylo1(cpu_env, arg);
9161 register_name = "EntryLo1";
9162 break;
9163 case CP0_REG03__GLOBALNUM:
9164 CP0_CHECK(ctx->vp);
9165 /* ignored */
9166 register_name = "GlobalNumber";
9167 break;
9168 default:
9169 goto cp0_unimplemented;
9171 break;
9172 case CP0_REGISTER_04:
9173 switch (sel) {
9174 case CP0_REG04__CONTEXT:
9175 gen_helper_mtc0_context(cpu_env, arg);
9176 register_name = "Context";
9177 break;
9178 case CP0_REG04__CONTEXTCONFIG:
9179 /* SmartMIPS ASE */
9180 /* gen_helper_dmtc0_contextconfig(arg); */
9181 register_name = "ContextConfig";
9182 goto cp0_unimplemented;
9183 case CP0_REG04__USERLOCAL:
9184 CP0_CHECK(ctx->ulri);
9185 tcg_gen_st_tl(arg, cpu_env,
9186 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
9187 register_name = "UserLocal";
9188 break;
9189 default:
9190 goto cp0_unimplemented;
9192 break;
9193 case CP0_REGISTER_05:
9194 switch (sel) {
9195 case CP0_REG05__PAGEMASK:
9196 gen_helper_mtc0_pagemask(cpu_env, arg);
9197 register_name = "PageMask";
9198 break;
9199 case CP0_REG05__PAGEGRAIN:
9200 check_insn(ctx, ISA_MIPS32R2);
9201 gen_helper_mtc0_pagegrain(cpu_env, arg);
9202 register_name = "PageGrain";
9203 break;
9204 case CP0_REG05__SEGCTL0:
9205 CP0_CHECK(ctx->sc);
9206 gen_helper_mtc0_segctl0(cpu_env, arg);
9207 register_name = "SegCtl0";
9208 break;
9209 case CP0_REG05__SEGCTL1:
9210 CP0_CHECK(ctx->sc);
9211 gen_helper_mtc0_segctl1(cpu_env, arg);
9212 register_name = "SegCtl1";
9213 break;
9214 case CP0_REG05__SEGCTL2:
9215 CP0_CHECK(ctx->sc);
9216 gen_helper_mtc0_segctl2(cpu_env, arg);
9217 register_name = "SegCtl2";
9218 break;
9219 case CP0_REG05__PWBASE:
9220 check_pw(ctx);
9221 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
9222 register_name = "PWBase";
9223 break;
9224 case CP0_REG05__PWFIELD:
9225 check_pw(ctx);
9226 gen_helper_mtc0_pwfield(cpu_env, arg);
9227 register_name = "PWField";
9228 break;
9229 case CP0_REG05__PWSIZE:
9230 check_pw(ctx);
9231 gen_helper_mtc0_pwsize(cpu_env, arg);
9232 register_name = "PWSize";
9233 break;
9234 default:
9235 goto cp0_unimplemented;
9237 break;
9238 case CP0_REGISTER_06:
9239 switch (sel) {
9240 case CP0_REG06__WIRED:
9241 gen_helper_mtc0_wired(cpu_env, arg);
9242 register_name = "Wired";
9243 break;
9244 case CP0_REG06__SRSCONF0:
9245 check_insn(ctx, ISA_MIPS32R2);
9246 gen_helper_mtc0_srsconf0(cpu_env, arg);
9247 register_name = "SRSConf0";
9248 break;
9249 case CP0_REG06__SRSCONF1:
9250 check_insn(ctx, ISA_MIPS32R2);
9251 gen_helper_mtc0_srsconf1(cpu_env, arg);
9252 register_name = "SRSConf1";
9253 break;
9254 case CP0_REG06__SRSCONF2:
9255 check_insn(ctx, ISA_MIPS32R2);
9256 gen_helper_mtc0_srsconf2(cpu_env, arg);
9257 register_name = "SRSConf2";
9258 break;
9259 case CP0_REG06__SRSCONF3:
9260 check_insn(ctx, ISA_MIPS32R2);
9261 gen_helper_mtc0_srsconf3(cpu_env, arg);
9262 register_name = "SRSConf3";
9263 break;
9264 case CP0_REG06__SRSCONF4:
9265 check_insn(ctx, ISA_MIPS32R2);
9266 gen_helper_mtc0_srsconf4(cpu_env, arg);
9267 register_name = "SRSConf4";
9268 break;
9269 case CP0_REG06__PWCTL:
9270 check_pw(ctx);
9271 gen_helper_mtc0_pwctl(cpu_env, arg);
9272 register_name = "PWCtl";
9273 break;
9274 default:
9275 goto cp0_unimplemented;
9277 break;
9278 case CP0_REGISTER_07:
9279 switch (sel) {
9280 case CP0_REG07__HWRENA:
9281 check_insn(ctx, ISA_MIPS32R2);
9282 gen_helper_mtc0_hwrena(cpu_env, arg);
9283 ctx->base.is_jmp = DISAS_STOP;
9284 register_name = "HWREna";
9285 break;
9286 default:
9287 goto cp0_unimplemented;
9289 break;
9290 case CP0_REGISTER_08:
9291 switch (sel) {
9292 case CP0_REG08__BADVADDR:
9293 /* ignored */
9294 register_name = "BadVAddr";
9295 break;
9296 case CP0_REG08__BADINSTR:
9297 /* ignored */
9298 register_name = "BadInstr";
9299 break;
9300 case CP0_REG08__BADINSTRP:
9301 /* ignored */
9302 register_name = "BadInstrP";
9303 break;
9304 case CP0_REG08__BADINSTRX:
9305 /* ignored */
9306 register_name = "BadInstrX";
9307 break;
9308 default:
9309 goto cp0_unimplemented;
9311 break;
9312 case CP0_REGISTER_09:
9313 switch (sel) {
9314 case CP0_REG09__COUNT:
9315 gen_helper_mtc0_count(cpu_env, arg);
9316 register_name = "Count";
9317 break;
9318 case CP0_REG09__SAARI:
9319 CP0_CHECK(ctx->saar);
9320 gen_helper_mtc0_saari(cpu_env, arg);
9321 register_name = "SAARI";
9322 break;
9323 case CP0_REG09__SAAR:
9324 CP0_CHECK(ctx->saar);
9325 gen_helper_mtc0_saar(cpu_env, arg);
9326 register_name = "SAAR";
9327 break;
9328 default:
9329 goto cp0_unimplemented;
9331 /* Stop translation as we may have switched the execution mode */
9332 ctx->base.is_jmp = DISAS_STOP;
9333 break;
9334 case CP0_REGISTER_10:
9335 switch (sel) {
9336 case CP0_REG10__ENTRYHI:
9337 gen_helper_mtc0_entryhi(cpu_env, arg);
9338 register_name = "EntryHi";
9339 break;
9340 default:
9341 goto cp0_unimplemented;
9343 break;
9344 case CP0_REGISTER_11:
9345 switch (sel) {
9346 case 0:
9347 gen_helper_mtc0_compare(cpu_env, arg);
9348 register_name = "Compare";
9349 break;
9350 /* 6,7 are implementation dependent */
9351 default:
9352 goto cp0_unimplemented;
9354 /* Stop translation as we may have switched the execution mode */
9355 ctx->base.is_jmp = DISAS_STOP;
9356 break;
9357 case CP0_REGISTER_12:
9358 switch (sel) {
9359 case 0:
9360 save_cpu_state(ctx, 1);
9361 gen_helper_mtc0_status(cpu_env, arg);
9362 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9363 gen_save_pc(ctx->base.pc_next + 4);
9364 ctx->base.is_jmp = DISAS_EXIT;
9365 register_name = "Status";
9366 break;
9367 case 1:
9368 check_insn(ctx, ISA_MIPS32R2);
9369 gen_helper_mtc0_intctl(cpu_env, arg);
9370 /* Stop translation as we may have switched the execution mode */
9371 ctx->base.is_jmp = DISAS_STOP;
9372 register_name = "IntCtl";
9373 break;
9374 case 2:
9375 check_insn(ctx, ISA_MIPS32R2);
9376 gen_helper_mtc0_srsctl(cpu_env, arg);
9377 /* Stop translation as we may have switched the execution mode */
9378 ctx->base.is_jmp = DISAS_STOP;
9379 register_name = "SRSCtl";
9380 break;
9381 case 3:
9382 check_insn(ctx, ISA_MIPS32R2);
9383 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
9384 /* Stop translation as we may have switched the execution mode */
9385 ctx->base.is_jmp = DISAS_STOP;
9386 register_name = "SRSMap";
9387 break;
9388 default:
9389 goto cp0_unimplemented;
9391 break;
9392 case CP0_REGISTER_13:
9393 switch (sel) {
9394 case 0:
9395 save_cpu_state(ctx, 1);
9396 gen_helper_mtc0_cause(cpu_env, arg);
9398 * Stop translation as we may have triggered an interrupt.
9399 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9400 * translated code to check for pending interrupts.
9402 gen_save_pc(ctx->base.pc_next + 4);
9403 ctx->base.is_jmp = DISAS_EXIT;
9404 register_name = "Cause";
9405 break;
9406 default:
9407 goto cp0_unimplemented;
9409 break;
9410 case CP0_REGISTER_14:
9411 switch (sel) {
9412 case 0:
9413 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
9414 register_name = "EPC";
9415 break;
9416 default:
9417 goto cp0_unimplemented;
9419 break;
9420 case CP0_REGISTER_15:
9421 switch (sel) {
9422 case 0:
9423 /* ignored */
9424 register_name = "PRid";
9425 break;
9426 case 1:
9427 check_insn(ctx, ISA_MIPS32R2);
9428 gen_helper_mtc0_ebase(cpu_env, arg);
9429 register_name = "EBase";
9430 break;
9431 default:
9432 goto cp0_unimplemented;
9434 break;
9435 case CP0_REGISTER_16:
9436 switch (sel) {
9437 case 0:
9438 gen_helper_mtc0_config0(cpu_env, arg);
9439 register_name = "Config";
9440 /* Stop translation as we may have switched the execution mode */
9441 ctx->base.is_jmp = DISAS_STOP;
9442 break;
9443 case 1:
9444 /* ignored, read only */
9445 register_name = "Config1";
9446 break;
9447 case 2:
9448 gen_helper_mtc0_config2(cpu_env, arg);
9449 register_name = "Config2";
9450 /* Stop translation as we may have switched the execution mode */
9451 ctx->base.is_jmp = DISAS_STOP;
9452 break;
9453 case 3:
9454 gen_helper_mtc0_config3(cpu_env, arg);
9455 register_name = "Config3";
9456 /* Stop translation as we may have switched the execution mode */
9457 ctx->base.is_jmp = DISAS_STOP;
9458 break;
9459 case 4:
9460 /* currently ignored */
9461 register_name = "Config4";
9462 break;
9463 case 5:
9464 gen_helper_mtc0_config5(cpu_env, arg);
9465 register_name = "Config5";
9466 /* Stop translation as we may have switched the execution mode */
9467 ctx->base.is_jmp = DISAS_STOP;
9468 break;
9469 /* 6,7 are implementation dependent */
9470 default:
9471 register_name = "Invalid config selector";
9472 goto cp0_unimplemented;
9474 break;
9475 case CP0_REGISTER_17:
9476 switch (sel) {
9477 case 0:
9478 gen_helper_mtc0_lladdr(cpu_env, arg);
9479 register_name = "LLAddr";
9480 break;
9481 case 1:
9482 CP0_CHECK(ctx->mrp);
9483 gen_helper_mtc0_maar(cpu_env, arg);
9484 register_name = "MAAR";
9485 break;
9486 case 2:
9487 CP0_CHECK(ctx->mrp);
9488 gen_helper_mtc0_maari(cpu_env, arg);
9489 register_name = "MAARI";
9490 break;
9491 default:
9492 goto cp0_unimplemented;
9494 break;
9495 case CP0_REGISTER_18:
9496 switch (sel) {
9497 case 0:
9498 case 1:
9499 case 2:
9500 case 3:
9501 case 4:
9502 case 5:
9503 case 6:
9504 case 7:
9505 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9506 gen_helper_0e1i(mtc0_watchlo, arg, sel);
9507 register_name = "WatchLo";
9508 break;
9509 default:
9510 goto cp0_unimplemented;
9512 break;
9513 case CP0_REGISTER_19:
9514 switch (sel) {
9515 case 0:
9516 case 1:
9517 case 2:
9518 case 3:
9519 case 4:
9520 case 5:
9521 case 6:
9522 case 7:
9523 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9524 gen_helper_0e1i(mtc0_watchhi, arg, sel);
9525 register_name = "WatchHi";
9526 break;
9527 default:
9528 goto cp0_unimplemented;
9530 break;
9531 case CP0_REGISTER_20:
9532 switch (sel) {
9533 case 0:
9534 check_insn(ctx, ISA_MIPS3);
9535 gen_helper_mtc0_xcontext(cpu_env, arg);
9536 register_name = "XContext";
9537 break;
9538 default:
9539 goto cp0_unimplemented;
9541 break;
9542 case CP0_REGISTER_21:
9543 /* Officially reserved, but sel 0 is used for R1x000 framemask */
9544 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9545 switch (sel) {
9546 case 0:
9547 gen_helper_mtc0_framemask(cpu_env, arg);
9548 register_name = "Framemask";
9549 break;
9550 default:
9551 goto cp0_unimplemented;
9553 break;
9554 case CP0_REGISTER_22:
9555 /* ignored */
9556 register_name = "Diagnostic"; /* implementation dependent */
9557 break;
9558 case CP0_REGISTER_23:
9559 switch (sel) {
9560 case 0:
9561 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
9562 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9563 gen_save_pc(ctx->base.pc_next + 4);
9564 ctx->base.is_jmp = DISAS_EXIT;
9565 register_name = "Debug";
9566 break;
9567 case 1:
9568 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
9569 /* Stop translation as we may have switched the execution mode */
9570 ctx->base.is_jmp = DISAS_STOP;
9571 register_name = "TraceControl";
9572 goto cp0_unimplemented;
9573 case 2:
9574 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
9575 /* Stop translation as we may have switched the execution mode */
9576 ctx->base.is_jmp = DISAS_STOP;
9577 register_name = "TraceControl2";
9578 goto cp0_unimplemented;
9579 case 3:
9580 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
9581 /* Stop translation as we may have switched the execution mode */
9582 ctx->base.is_jmp = DISAS_STOP;
9583 register_name = "UserTraceData";
9584 goto cp0_unimplemented;
9585 case 4:
9586 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
9587 /* Stop translation as we may have switched the execution mode */
9588 ctx->base.is_jmp = DISAS_STOP;
9589 register_name = "TraceBPC";
9590 goto cp0_unimplemented;
9591 default:
9592 goto cp0_unimplemented;
9594 break;
9595 case CP0_REGISTER_24:
9596 switch (sel) {
9597 case 0:
9598 /* EJTAG support */
9599 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
9600 register_name = "DEPC";
9601 break;
9602 default:
9603 goto cp0_unimplemented;
9605 break;
9606 case CP0_REGISTER_25:
9607 switch (sel) {
9608 case 0:
9609 gen_helper_mtc0_performance0(cpu_env, arg);
9610 register_name = "Performance0";
9611 break;
9612 case 1:
9613 /* gen_helper_mtc0_performance1(cpu_env, arg); */
9614 register_name = "Performance1";
9615 goto cp0_unimplemented;
9616 case 2:
9617 /* gen_helper_mtc0_performance2(cpu_env, arg); */
9618 register_name = "Performance2";
9619 goto cp0_unimplemented;
9620 case 3:
9621 /* gen_helper_mtc0_performance3(cpu_env, arg); */
9622 register_name = "Performance3";
9623 goto cp0_unimplemented;
9624 case 4:
9625 /* gen_helper_mtc0_performance4(cpu_env, arg); */
9626 register_name = "Performance4";
9627 goto cp0_unimplemented;
9628 case 5:
9629 /* gen_helper_mtc0_performance5(cpu_env, arg); */
9630 register_name = "Performance5";
9631 goto cp0_unimplemented;
9632 case 6:
9633 /* gen_helper_mtc0_performance6(cpu_env, arg); */
9634 register_name = "Performance6";
9635 goto cp0_unimplemented;
9636 case 7:
9637 /* gen_helper_mtc0_performance7(cpu_env, arg); */
9638 register_name = "Performance7";
9639 goto cp0_unimplemented;
9640 default:
9641 goto cp0_unimplemented;
9643 break;
9644 case CP0_REGISTER_26:
9645 switch (sel) {
9646 case 0:
9647 gen_helper_mtc0_errctl(cpu_env, arg);
9648 ctx->base.is_jmp = DISAS_STOP;
9649 register_name = "ErrCtl";
9650 break;
9651 default:
9652 goto cp0_unimplemented;
9654 break;
9655 case CP0_REGISTER_27:
9656 switch (sel) {
9657 case 0:
9658 case 1:
9659 case 2:
9660 case 3:
9661 /* ignored */
9662 register_name = "CacheErr";
9663 break;
9664 default:
9665 goto cp0_unimplemented;
9667 break;
9668 case CP0_REGISTER_28:
9669 switch (sel) {
9670 case 0:
9671 case 2:
9672 case 4:
9673 case 6:
9674 gen_helper_mtc0_taglo(cpu_env, arg);
9675 register_name = "TagLo";
9676 break;
9677 case 1:
9678 case 3:
9679 case 5:
9680 case 7:
9681 gen_helper_mtc0_datalo(cpu_env, arg);
9682 register_name = "DataLo";
9683 break;
9684 default:
9685 goto cp0_unimplemented;
9687 break;
9688 case CP0_REGISTER_29:
9689 switch (sel) {
9690 case 0:
9691 case 2:
9692 case 4:
9693 case 6:
9694 gen_helper_mtc0_taghi(cpu_env, arg);
9695 register_name = "TagHi";
9696 break;
9697 case 1:
9698 case 3:
9699 case 5:
9700 case 7:
9701 gen_helper_mtc0_datahi(cpu_env, arg);
9702 register_name = "DataHi";
9703 break;
9704 default:
9705 register_name = "invalid sel";
9706 goto cp0_unimplemented;
9708 break;
9709 case CP0_REGISTER_30:
9710 switch (sel) {
9711 case 0:
9712 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9713 register_name = "ErrorEPC";
9714 break;
9715 default:
9716 goto cp0_unimplemented;
9718 break;
9719 case CP0_REGISTER_31:
9720 switch (sel) {
9721 case 0:
9722 /* EJTAG support */
9723 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9724 register_name = "DESAVE";
9725 break;
9726 case 2:
9727 case 3:
9728 case 4:
9729 case 5:
9730 case 6:
9731 case 7:
9732 CP0_CHECK(ctx->kscrexist & (1 << sel));
9733 tcg_gen_st_tl(arg, cpu_env,
9734 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
9735 register_name = "KScratch";
9736 break;
9737 default:
9738 goto cp0_unimplemented;
9740 break;
9741 default:
9742 goto cp0_unimplemented;
9744 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
9746 /* For simplicity assume that all writes can cause interrupts. */
9747 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9749 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9750 * translated code to check for pending interrupts.
9752 gen_save_pc(ctx->base.pc_next + 4);
9753 ctx->base.is_jmp = DISAS_EXIT;
9755 return;
9757 cp0_unimplemented:
9758 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
9759 register_name, reg, sel);
9761 #endif /* TARGET_MIPS64 */
9763 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
9764 int u, int sel, int h)
9766 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9767 TCGv t0 = tcg_temp_local_new();
9769 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9770 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9771 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
9772 tcg_gen_movi_tl(t0, -1);
9773 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9774 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
9775 tcg_gen_movi_tl(t0, -1);
9776 } else if (u == 0) {
9777 switch (rt) {
9778 case 1:
9779 switch (sel) {
9780 case 1:
9781 gen_helper_mftc0_vpecontrol(t0, cpu_env);
9782 break;
9783 case 2:
9784 gen_helper_mftc0_vpeconf0(t0, cpu_env);
9785 break;
9786 default:
9787 goto die;
9788 break;
9790 break;
9791 case 2:
9792 switch (sel) {
9793 case 1:
9794 gen_helper_mftc0_tcstatus(t0, cpu_env);
9795 break;
9796 case 2:
9797 gen_helper_mftc0_tcbind(t0, cpu_env);
9798 break;
9799 case 3:
9800 gen_helper_mftc0_tcrestart(t0, cpu_env);
9801 break;
9802 case 4:
9803 gen_helper_mftc0_tchalt(t0, cpu_env);
9804 break;
9805 case 5:
9806 gen_helper_mftc0_tccontext(t0, cpu_env);
9807 break;
9808 case 6:
9809 gen_helper_mftc0_tcschedule(t0, cpu_env);
9810 break;
9811 case 7:
9812 gen_helper_mftc0_tcschefback(t0, cpu_env);
9813 break;
9814 default:
9815 gen_mfc0(ctx, t0, rt, sel);
9816 break;
9818 break;
9819 case 10:
9820 switch (sel) {
9821 case 0:
9822 gen_helper_mftc0_entryhi(t0, cpu_env);
9823 break;
9824 default:
9825 gen_mfc0(ctx, t0, rt, sel);
9826 break;
9828 break;
9829 case 12:
9830 switch (sel) {
9831 case 0:
9832 gen_helper_mftc0_status(t0, cpu_env);
9833 break;
9834 default:
9835 gen_mfc0(ctx, t0, rt, sel);
9836 break;
9838 break;
9839 case 13:
9840 switch (sel) {
9841 case 0:
9842 gen_helper_mftc0_cause(t0, cpu_env);
9843 break;
9844 default:
9845 goto die;
9846 break;
9848 break;
9849 case 14:
9850 switch (sel) {
9851 case 0:
9852 gen_helper_mftc0_epc(t0, cpu_env);
9853 break;
9854 default:
9855 goto die;
9856 break;
9858 break;
9859 case 15:
9860 switch (sel) {
9861 case 1:
9862 gen_helper_mftc0_ebase(t0, cpu_env);
9863 break;
9864 default:
9865 goto die;
9866 break;
9868 break;
9869 case 16:
9870 switch (sel) {
9871 case 0:
9872 case 1:
9873 case 2:
9874 case 3:
9875 case 4:
9876 case 5:
9877 case 6:
9878 case 7:
9879 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
9880 break;
9881 default:
9882 goto die;
9883 break;
9885 break;
9886 case 23:
9887 switch (sel) {
9888 case 0:
9889 gen_helper_mftc0_debug(t0, cpu_env);
9890 break;
9891 default:
9892 gen_mfc0(ctx, t0, rt, sel);
9893 break;
9895 break;
9896 default:
9897 gen_mfc0(ctx, t0, rt, sel);
9899 } else {
9900 switch (sel) {
9901 /* GPR registers. */
9902 case 0:
9903 gen_helper_1e0i(mftgpr, t0, rt);
9904 break;
9905 /* Auxiliary CPU registers */
9906 case 1:
9907 switch (rt) {
9908 case 0:
9909 gen_helper_1e0i(mftlo, t0, 0);
9910 break;
9911 case 1:
9912 gen_helper_1e0i(mfthi, t0, 0);
9913 break;
9914 case 2:
9915 gen_helper_1e0i(mftacx, t0, 0);
9916 break;
9917 case 4:
9918 gen_helper_1e0i(mftlo, t0, 1);
9919 break;
9920 case 5:
9921 gen_helper_1e0i(mfthi, t0, 1);
9922 break;
9923 case 6:
9924 gen_helper_1e0i(mftacx, t0, 1);
9925 break;
9926 case 8:
9927 gen_helper_1e0i(mftlo, t0, 2);
9928 break;
9929 case 9:
9930 gen_helper_1e0i(mfthi, t0, 2);
9931 break;
9932 case 10:
9933 gen_helper_1e0i(mftacx, t0, 2);
9934 break;
9935 case 12:
9936 gen_helper_1e0i(mftlo, t0, 3);
9937 break;
9938 case 13:
9939 gen_helper_1e0i(mfthi, t0, 3);
9940 break;
9941 case 14:
9942 gen_helper_1e0i(mftacx, t0, 3);
9943 break;
9944 case 16:
9945 gen_helper_mftdsp(t0, cpu_env);
9946 break;
9947 default:
9948 goto die;
9950 break;
9951 /* Floating point (COP1). */
9952 case 2:
9953 /* XXX: For now we support only a single FPU context. */
9954 if (h == 0) {
9955 TCGv_i32 fp0 = tcg_temp_new_i32();
9957 gen_load_fpr32(ctx, fp0, rt);
9958 tcg_gen_ext_i32_tl(t0, fp0);
9959 tcg_temp_free_i32(fp0);
9960 } else {
9961 TCGv_i32 fp0 = tcg_temp_new_i32();
9963 gen_load_fpr32h(ctx, fp0, rt);
9964 tcg_gen_ext_i32_tl(t0, fp0);
9965 tcg_temp_free_i32(fp0);
9967 break;
9968 case 3:
9969 /* XXX: For now we support only a single FPU context. */
9970 gen_helper_1e0i(cfc1, t0, rt);
9971 break;
9972 /* COP2: Not implemented. */
9973 case 4:
9974 case 5:
9975 /* fall through */
9976 default:
9977 goto die;
9980 trace_mips_translate_tr("mftr", rt, u, sel, h);
9981 gen_store_gpr(t0, rd);
9982 tcg_temp_free(t0);
9983 return;
9985 die:
9986 tcg_temp_free(t0);
9987 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
9988 generate_exception_end(ctx, EXCP_RI);
9991 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
9992 int u, int sel, int h)
9994 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9995 TCGv t0 = tcg_temp_local_new();
9997 gen_load_gpr(t0, rt);
9998 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9999 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
10000 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
10001 /* NOP */
10003 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
10004 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
10005 /* NOP */
10007 } else if (u == 0) {
10008 switch (rd) {
10009 case 1:
10010 switch (sel) {
10011 case 1:
10012 gen_helper_mttc0_vpecontrol(cpu_env, t0);
10013 break;
10014 case 2:
10015 gen_helper_mttc0_vpeconf0(cpu_env, t0);
10016 break;
10017 default:
10018 goto die;
10019 break;
10021 break;
10022 case 2:
10023 switch (sel) {
10024 case 1:
10025 gen_helper_mttc0_tcstatus(cpu_env, t0);
10026 break;
10027 case 2:
10028 gen_helper_mttc0_tcbind(cpu_env, t0);
10029 break;
10030 case 3:
10031 gen_helper_mttc0_tcrestart(cpu_env, t0);
10032 break;
10033 case 4:
10034 gen_helper_mttc0_tchalt(cpu_env, t0);
10035 break;
10036 case 5:
10037 gen_helper_mttc0_tccontext(cpu_env, t0);
10038 break;
10039 case 6:
10040 gen_helper_mttc0_tcschedule(cpu_env, t0);
10041 break;
10042 case 7:
10043 gen_helper_mttc0_tcschefback(cpu_env, t0);
10044 break;
10045 default:
10046 gen_mtc0(ctx, t0, rd, sel);
10047 break;
10049 break;
10050 case 10:
10051 switch (sel) {
10052 case 0:
10053 gen_helper_mttc0_entryhi(cpu_env, t0);
10054 break;
10055 default:
10056 gen_mtc0(ctx, t0, rd, sel);
10057 break;
10059 break;
10060 case 12:
10061 switch (sel) {
10062 case 0:
10063 gen_helper_mttc0_status(cpu_env, t0);
10064 break;
10065 default:
10066 gen_mtc0(ctx, t0, rd, sel);
10067 break;
10069 break;
10070 case 13:
10071 switch (sel) {
10072 case 0:
10073 gen_helper_mttc0_cause(cpu_env, t0);
10074 break;
10075 default:
10076 goto die;
10077 break;
10079 break;
10080 case 15:
10081 switch (sel) {
10082 case 1:
10083 gen_helper_mttc0_ebase(cpu_env, t0);
10084 break;
10085 default:
10086 goto die;
10087 break;
10089 break;
10090 case 23:
10091 switch (sel) {
10092 case 0:
10093 gen_helper_mttc0_debug(cpu_env, t0);
10094 break;
10095 default:
10096 gen_mtc0(ctx, t0, rd, sel);
10097 break;
10099 break;
10100 default:
10101 gen_mtc0(ctx, t0, rd, sel);
10103 } else {
10104 switch (sel) {
10105 /* GPR registers. */
10106 case 0:
10107 gen_helper_0e1i(mttgpr, t0, rd);
10108 break;
10109 /* Auxiliary CPU registers */
10110 case 1:
10111 switch (rd) {
10112 case 0:
10113 gen_helper_0e1i(mttlo, t0, 0);
10114 break;
10115 case 1:
10116 gen_helper_0e1i(mtthi, t0, 0);
10117 break;
10118 case 2:
10119 gen_helper_0e1i(mttacx, t0, 0);
10120 break;
10121 case 4:
10122 gen_helper_0e1i(mttlo, t0, 1);
10123 break;
10124 case 5:
10125 gen_helper_0e1i(mtthi, t0, 1);
10126 break;
10127 case 6:
10128 gen_helper_0e1i(mttacx, t0, 1);
10129 break;
10130 case 8:
10131 gen_helper_0e1i(mttlo, t0, 2);
10132 break;
10133 case 9:
10134 gen_helper_0e1i(mtthi, t0, 2);
10135 break;
10136 case 10:
10137 gen_helper_0e1i(mttacx, t0, 2);
10138 break;
10139 case 12:
10140 gen_helper_0e1i(mttlo, t0, 3);
10141 break;
10142 case 13:
10143 gen_helper_0e1i(mtthi, t0, 3);
10144 break;
10145 case 14:
10146 gen_helper_0e1i(mttacx, t0, 3);
10147 break;
10148 case 16:
10149 gen_helper_mttdsp(cpu_env, t0);
10150 break;
10151 default:
10152 goto die;
10154 break;
10155 /* Floating point (COP1). */
10156 case 2:
10157 /* XXX: For now we support only a single FPU context. */
10158 if (h == 0) {
10159 TCGv_i32 fp0 = tcg_temp_new_i32();
10161 tcg_gen_trunc_tl_i32(fp0, t0);
10162 gen_store_fpr32(ctx, fp0, rd);
10163 tcg_temp_free_i32(fp0);
10164 } else {
10165 TCGv_i32 fp0 = tcg_temp_new_i32();
10167 tcg_gen_trunc_tl_i32(fp0, t0);
10168 gen_store_fpr32h(ctx, fp0, rd);
10169 tcg_temp_free_i32(fp0);
10171 break;
10172 case 3:
10173 /* XXX: For now we support only a single FPU context. */
10175 TCGv_i32 fs_tmp = tcg_const_i32(rd);
10177 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10178 tcg_temp_free_i32(fs_tmp);
10180 /* Stop translation as we may have changed hflags */
10181 ctx->base.is_jmp = DISAS_STOP;
10182 break;
10183 /* COP2: Not implemented. */
10184 case 4:
10185 case 5:
10186 /* fall through */
10187 default:
10188 goto die;
10191 trace_mips_translate_tr("mttr", rd, u, sel, h);
10192 tcg_temp_free(t0);
10193 return;
10195 die:
10196 tcg_temp_free(t0);
10197 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
10198 generate_exception_end(ctx, EXCP_RI);
10201 static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
10202 int rt, int rd)
10204 const char *opn = "ldst";
10206 check_cp0_enabled(ctx);
10207 switch (opc) {
10208 case OPC_MFC0:
10209 if (rt == 0) {
10210 /* Treat as NOP. */
10211 return;
10213 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10214 opn = "mfc0";
10215 break;
10216 case OPC_MTC0:
10218 TCGv t0 = tcg_temp_new();
10220 gen_load_gpr(t0, rt);
10221 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
10222 tcg_temp_free(t0);
10224 opn = "mtc0";
10225 break;
10226 #if defined(TARGET_MIPS64)
10227 case OPC_DMFC0:
10228 check_insn(ctx, ISA_MIPS3);
10229 if (rt == 0) {
10230 /* Treat as NOP. */
10231 return;
10233 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10234 opn = "dmfc0";
10235 break;
10236 case OPC_DMTC0:
10237 check_insn(ctx, ISA_MIPS3);
10239 TCGv t0 = tcg_temp_new();
10241 gen_load_gpr(t0, rt);
10242 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
10243 tcg_temp_free(t0);
10245 opn = "dmtc0";
10246 break;
10247 #endif
10248 case OPC_MFHC0:
10249 check_mvh(ctx);
10250 if (rt == 0) {
10251 /* Treat as NOP. */
10252 return;
10254 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10255 opn = "mfhc0";
10256 break;
10257 case OPC_MTHC0:
10258 check_mvh(ctx);
10260 TCGv t0 = tcg_temp_new();
10261 gen_load_gpr(t0, rt);
10262 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
10263 tcg_temp_free(t0);
10265 opn = "mthc0";
10266 break;
10267 case OPC_MFTR:
10268 check_cp0_enabled(ctx);
10269 if (rd == 0) {
10270 /* Treat as NOP. */
10271 return;
10273 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
10274 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10275 opn = "mftr";
10276 break;
10277 case OPC_MTTR:
10278 check_cp0_enabled(ctx);
10279 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
10280 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10281 opn = "mttr";
10282 break;
10283 case OPC_TLBWI:
10284 opn = "tlbwi";
10285 if (!env->tlb->helper_tlbwi) {
10286 goto die;
10288 gen_helper_tlbwi(cpu_env);
10289 break;
10290 case OPC_TLBINV:
10291 opn = "tlbinv";
10292 if (ctx->ie >= 2) {
10293 if (!env->tlb->helper_tlbinv) {
10294 goto die;
10296 gen_helper_tlbinv(cpu_env);
10297 } /* treat as nop if TLBINV not supported */
10298 break;
10299 case OPC_TLBINVF:
10300 opn = "tlbinvf";
10301 if (ctx->ie >= 2) {
10302 if (!env->tlb->helper_tlbinvf) {
10303 goto die;
10305 gen_helper_tlbinvf(cpu_env);
10306 } /* treat as nop if TLBINV not supported */
10307 break;
10308 case OPC_TLBWR:
10309 opn = "tlbwr";
10310 if (!env->tlb->helper_tlbwr) {
10311 goto die;
10313 gen_helper_tlbwr(cpu_env);
10314 break;
10315 case OPC_TLBP:
10316 opn = "tlbp";
10317 if (!env->tlb->helper_tlbp) {
10318 goto die;
10320 gen_helper_tlbp(cpu_env);
10321 break;
10322 case OPC_TLBR:
10323 opn = "tlbr";
10324 if (!env->tlb->helper_tlbr) {
10325 goto die;
10327 gen_helper_tlbr(cpu_env);
10328 break;
10329 case OPC_ERET: /* OPC_ERETNC */
10330 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10331 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10332 goto die;
10333 } else {
10334 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
10335 if (ctx->opcode & (1 << bit_shift)) {
10336 /* OPC_ERETNC */
10337 opn = "eretnc";
10338 check_insn(ctx, ISA_MIPS32R5);
10339 gen_helper_eretnc(cpu_env);
10340 } else {
10341 /* OPC_ERET */
10342 opn = "eret";
10343 check_insn(ctx, ISA_MIPS2);
10344 gen_helper_eret(cpu_env);
10346 ctx->base.is_jmp = DISAS_EXIT;
10348 break;
10349 case OPC_DERET:
10350 opn = "deret";
10351 check_insn(ctx, ISA_MIPS32);
10352 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10353 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10354 goto die;
10356 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10357 MIPS_INVAL(opn);
10358 generate_exception_end(ctx, EXCP_RI);
10359 } else {
10360 gen_helper_deret(cpu_env);
10361 ctx->base.is_jmp = DISAS_EXIT;
10363 break;
10364 case OPC_WAIT:
10365 opn = "wait";
10366 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
10367 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10368 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10369 goto die;
10371 /* If we get an exception, we want to restart at next instruction */
10372 ctx->base.pc_next += 4;
10373 save_cpu_state(ctx, 1);
10374 ctx->base.pc_next -= 4;
10375 gen_helper_wait(cpu_env);
10376 ctx->base.is_jmp = DISAS_NORETURN;
10377 break;
10378 default:
10379 die:
10380 MIPS_INVAL(opn);
10381 generate_exception_end(ctx, EXCP_RI);
10382 return;
10384 (void)opn; /* avoid a compiler warning */
10386 #endif /* !CONFIG_USER_ONLY */
10388 /* CP1 Branches (before delay slot) */
10389 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
10390 int32_t cc, int32_t offset)
10392 target_ulong btarget;
10393 TCGv_i32 t0 = tcg_temp_new_i32();
10395 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
10396 generate_exception_end(ctx, EXCP_RI);
10397 goto out;
10400 if (cc != 0) {
10401 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
10404 btarget = ctx->base.pc_next + 4 + offset;
10406 switch (op) {
10407 case OPC_BC1F:
10408 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10409 tcg_gen_not_i32(t0, t0);
10410 tcg_gen_andi_i32(t0, t0, 1);
10411 tcg_gen_extu_i32_tl(bcond, t0);
10412 goto not_likely;
10413 case OPC_BC1FL:
10414 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10415 tcg_gen_not_i32(t0, t0);
10416 tcg_gen_andi_i32(t0, t0, 1);
10417 tcg_gen_extu_i32_tl(bcond, t0);
10418 goto likely;
10419 case OPC_BC1T:
10420 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10421 tcg_gen_andi_i32(t0, t0, 1);
10422 tcg_gen_extu_i32_tl(bcond, t0);
10423 goto not_likely;
10424 case OPC_BC1TL:
10425 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10426 tcg_gen_andi_i32(t0, t0, 1);
10427 tcg_gen_extu_i32_tl(bcond, t0);
10428 likely:
10429 ctx->hflags |= MIPS_HFLAG_BL;
10430 break;
10431 case OPC_BC1FANY2:
10433 TCGv_i32 t1 = tcg_temp_new_i32();
10434 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10435 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10436 tcg_gen_nand_i32(t0, t0, t1);
10437 tcg_temp_free_i32(t1);
10438 tcg_gen_andi_i32(t0, t0, 1);
10439 tcg_gen_extu_i32_tl(bcond, t0);
10441 goto not_likely;
10442 case OPC_BC1TANY2:
10444 TCGv_i32 t1 = tcg_temp_new_i32();
10445 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10446 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10447 tcg_gen_or_i32(t0, t0, t1);
10448 tcg_temp_free_i32(t1);
10449 tcg_gen_andi_i32(t0, t0, 1);
10450 tcg_gen_extu_i32_tl(bcond, t0);
10452 goto not_likely;
10453 case OPC_BC1FANY4:
10455 TCGv_i32 t1 = tcg_temp_new_i32();
10456 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10457 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10458 tcg_gen_and_i32(t0, t0, t1);
10459 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
10460 tcg_gen_and_i32(t0, t0, t1);
10461 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
10462 tcg_gen_nand_i32(t0, t0, t1);
10463 tcg_temp_free_i32(t1);
10464 tcg_gen_andi_i32(t0, t0, 1);
10465 tcg_gen_extu_i32_tl(bcond, t0);
10467 goto not_likely;
10468 case OPC_BC1TANY4:
10470 TCGv_i32 t1 = tcg_temp_new_i32();
10471 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10472 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10473 tcg_gen_or_i32(t0, t0, t1);
10474 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
10475 tcg_gen_or_i32(t0, t0, t1);
10476 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
10477 tcg_gen_or_i32(t0, t0, t1);
10478 tcg_temp_free_i32(t1);
10479 tcg_gen_andi_i32(t0, t0, 1);
10480 tcg_gen_extu_i32_tl(bcond, t0);
10482 not_likely:
10483 ctx->hflags |= MIPS_HFLAG_BC;
10484 break;
10485 default:
10486 MIPS_INVAL("cp1 cond branch");
10487 generate_exception_end(ctx, EXCP_RI);
10488 goto out;
10490 ctx->btarget = btarget;
10491 ctx->hflags |= MIPS_HFLAG_BDS32;
10492 out:
10493 tcg_temp_free_i32(t0);
10496 /* R6 CP1 Branches */
10497 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
10498 int32_t ft, int32_t offset,
10499 int delayslot_size)
10501 target_ulong btarget;
10502 TCGv_i64 t0 = tcg_temp_new_i64();
10504 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10505 #ifdef MIPS_DEBUG_DISAS
10506 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
10507 "\n", ctx->base.pc_next);
10508 #endif
10509 generate_exception_end(ctx, EXCP_RI);
10510 goto out;
10513 gen_load_fpr64(ctx, t0, ft);
10514 tcg_gen_andi_i64(t0, t0, 1);
10516 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
10518 switch (op) {
10519 case OPC_BC1EQZ:
10520 tcg_gen_xori_i64(t0, t0, 1);
10521 ctx->hflags |= MIPS_HFLAG_BC;
10522 break;
10523 case OPC_BC1NEZ:
10524 /* t0 already set */
10525 ctx->hflags |= MIPS_HFLAG_BC;
10526 break;
10527 default:
10528 MIPS_INVAL("cp1 cond branch");
10529 generate_exception_end(ctx, EXCP_RI);
10530 goto out;
10533 tcg_gen_trunc_i64_tl(bcond, t0);
10535 ctx->btarget = btarget;
10537 switch (delayslot_size) {
10538 case 2:
10539 ctx->hflags |= MIPS_HFLAG_BDS16;
10540 break;
10541 case 4:
10542 ctx->hflags |= MIPS_HFLAG_BDS32;
10543 break;
10546 out:
10547 tcg_temp_free_i64(t0);
10550 /* Coprocessor 1 (FPU) */
10552 #define FOP(func, fmt) (((fmt) << 21) | (func))
10554 enum fopcode {
10555 OPC_ADD_S = FOP(0, FMT_S),
10556 OPC_SUB_S = FOP(1, FMT_S),
10557 OPC_MUL_S = FOP(2, FMT_S),
10558 OPC_DIV_S = FOP(3, FMT_S),
10559 OPC_SQRT_S = FOP(4, FMT_S),
10560 OPC_ABS_S = FOP(5, FMT_S),
10561 OPC_MOV_S = FOP(6, FMT_S),
10562 OPC_NEG_S = FOP(7, FMT_S),
10563 OPC_ROUND_L_S = FOP(8, FMT_S),
10564 OPC_TRUNC_L_S = FOP(9, FMT_S),
10565 OPC_CEIL_L_S = FOP(10, FMT_S),
10566 OPC_FLOOR_L_S = FOP(11, FMT_S),
10567 OPC_ROUND_W_S = FOP(12, FMT_S),
10568 OPC_TRUNC_W_S = FOP(13, FMT_S),
10569 OPC_CEIL_W_S = FOP(14, FMT_S),
10570 OPC_FLOOR_W_S = FOP(15, FMT_S),
10571 OPC_SEL_S = FOP(16, FMT_S),
10572 OPC_MOVCF_S = FOP(17, FMT_S),
10573 OPC_MOVZ_S = FOP(18, FMT_S),
10574 OPC_MOVN_S = FOP(19, FMT_S),
10575 OPC_SELEQZ_S = FOP(20, FMT_S),
10576 OPC_RECIP_S = FOP(21, FMT_S),
10577 OPC_RSQRT_S = FOP(22, FMT_S),
10578 OPC_SELNEZ_S = FOP(23, FMT_S),
10579 OPC_MADDF_S = FOP(24, FMT_S),
10580 OPC_MSUBF_S = FOP(25, FMT_S),
10581 OPC_RINT_S = FOP(26, FMT_S),
10582 OPC_CLASS_S = FOP(27, FMT_S),
10583 OPC_MIN_S = FOP(28, FMT_S),
10584 OPC_RECIP2_S = FOP(28, FMT_S),
10585 OPC_MINA_S = FOP(29, FMT_S),
10586 OPC_RECIP1_S = FOP(29, FMT_S),
10587 OPC_MAX_S = FOP(30, FMT_S),
10588 OPC_RSQRT1_S = FOP(30, FMT_S),
10589 OPC_MAXA_S = FOP(31, FMT_S),
10590 OPC_RSQRT2_S = FOP(31, FMT_S),
10591 OPC_CVT_D_S = FOP(33, FMT_S),
10592 OPC_CVT_W_S = FOP(36, FMT_S),
10593 OPC_CVT_L_S = FOP(37, FMT_S),
10594 OPC_CVT_PS_S = FOP(38, FMT_S),
10595 OPC_CMP_F_S = FOP(48, FMT_S),
10596 OPC_CMP_UN_S = FOP(49, FMT_S),
10597 OPC_CMP_EQ_S = FOP(50, FMT_S),
10598 OPC_CMP_UEQ_S = FOP(51, FMT_S),
10599 OPC_CMP_OLT_S = FOP(52, FMT_S),
10600 OPC_CMP_ULT_S = FOP(53, FMT_S),
10601 OPC_CMP_OLE_S = FOP(54, FMT_S),
10602 OPC_CMP_ULE_S = FOP(55, FMT_S),
10603 OPC_CMP_SF_S = FOP(56, FMT_S),
10604 OPC_CMP_NGLE_S = FOP(57, FMT_S),
10605 OPC_CMP_SEQ_S = FOP(58, FMT_S),
10606 OPC_CMP_NGL_S = FOP(59, FMT_S),
10607 OPC_CMP_LT_S = FOP(60, FMT_S),
10608 OPC_CMP_NGE_S = FOP(61, FMT_S),
10609 OPC_CMP_LE_S = FOP(62, FMT_S),
10610 OPC_CMP_NGT_S = FOP(63, FMT_S),
10612 OPC_ADD_D = FOP(0, FMT_D),
10613 OPC_SUB_D = FOP(1, FMT_D),
10614 OPC_MUL_D = FOP(2, FMT_D),
10615 OPC_DIV_D = FOP(3, FMT_D),
10616 OPC_SQRT_D = FOP(4, FMT_D),
10617 OPC_ABS_D = FOP(5, FMT_D),
10618 OPC_MOV_D = FOP(6, FMT_D),
10619 OPC_NEG_D = FOP(7, FMT_D),
10620 OPC_ROUND_L_D = FOP(8, FMT_D),
10621 OPC_TRUNC_L_D = FOP(9, FMT_D),
10622 OPC_CEIL_L_D = FOP(10, FMT_D),
10623 OPC_FLOOR_L_D = FOP(11, FMT_D),
10624 OPC_ROUND_W_D = FOP(12, FMT_D),
10625 OPC_TRUNC_W_D = FOP(13, FMT_D),
10626 OPC_CEIL_W_D = FOP(14, FMT_D),
10627 OPC_FLOOR_W_D = FOP(15, FMT_D),
10628 OPC_SEL_D = FOP(16, FMT_D),
10629 OPC_MOVCF_D = FOP(17, FMT_D),
10630 OPC_MOVZ_D = FOP(18, FMT_D),
10631 OPC_MOVN_D = FOP(19, FMT_D),
10632 OPC_SELEQZ_D = FOP(20, FMT_D),
10633 OPC_RECIP_D = FOP(21, FMT_D),
10634 OPC_RSQRT_D = FOP(22, FMT_D),
10635 OPC_SELNEZ_D = FOP(23, FMT_D),
10636 OPC_MADDF_D = FOP(24, FMT_D),
10637 OPC_MSUBF_D = FOP(25, FMT_D),
10638 OPC_RINT_D = FOP(26, FMT_D),
10639 OPC_CLASS_D = FOP(27, FMT_D),
10640 OPC_MIN_D = FOP(28, FMT_D),
10641 OPC_RECIP2_D = FOP(28, FMT_D),
10642 OPC_MINA_D = FOP(29, FMT_D),
10643 OPC_RECIP1_D = FOP(29, FMT_D),
10644 OPC_MAX_D = FOP(30, FMT_D),
10645 OPC_RSQRT1_D = FOP(30, FMT_D),
10646 OPC_MAXA_D = FOP(31, FMT_D),
10647 OPC_RSQRT2_D = FOP(31, FMT_D),
10648 OPC_CVT_S_D = FOP(32, FMT_D),
10649 OPC_CVT_W_D = FOP(36, FMT_D),
10650 OPC_CVT_L_D = FOP(37, FMT_D),
10651 OPC_CMP_F_D = FOP(48, FMT_D),
10652 OPC_CMP_UN_D = FOP(49, FMT_D),
10653 OPC_CMP_EQ_D = FOP(50, FMT_D),
10654 OPC_CMP_UEQ_D = FOP(51, FMT_D),
10655 OPC_CMP_OLT_D = FOP(52, FMT_D),
10656 OPC_CMP_ULT_D = FOP(53, FMT_D),
10657 OPC_CMP_OLE_D = FOP(54, FMT_D),
10658 OPC_CMP_ULE_D = FOP(55, FMT_D),
10659 OPC_CMP_SF_D = FOP(56, FMT_D),
10660 OPC_CMP_NGLE_D = FOP(57, FMT_D),
10661 OPC_CMP_SEQ_D = FOP(58, FMT_D),
10662 OPC_CMP_NGL_D = FOP(59, FMT_D),
10663 OPC_CMP_LT_D = FOP(60, FMT_D),
10664 OPC_CMP_NGE_D = FOP(61, FMT_D),
10665 OPC_CMP_LE_D = FOP(62, FMT_D),
10666 OPC_CMP_NGT_D = FOP(63, FMT_D),
10668 OPC_CVT_S_W = FOP(32, FMT_W),
10669 OPC_CVT_D_W = FOP(33, FMT_W),
10670 OPC_CVT_S_L = FOP(32, FMT_L),
10671 OPC_CVT_D_L = FOP(33, FMT_L),
10672 OPC_CVT_PS_PW = FOP(38, FMT_W),
10674 OPC_ADD_PS = FOP(0, FMT_PS),
10675 OPC_SUB_PS = FOP(1, FMT_PS),
10676 OPC_MUL_PS = FOP(2, FMT_PS),
10677 OPC_DIV_PS = FOP(3, FMT_PS),
10678 OPC_ABS_PS = FOP(5, FMT_PS),
10679 OPC_MOV_PS = FOP(6, FMT_PS),
10680 OPC_NEG_PS = FOP(7, FMT_PS),
10681 OPC_MOVCF_PS = FOP(17, FMT_PS),
10682 OPC_MOVZ_PS = FOP(18, FMT_PS),
10683 OPC_MOVN_PS = FOP(19, FMT_PS),
10684 OPC_ADDR_PS = FOP(24, FMT_PS),
10685 OPC_MULR_PS = FOP(26, FMT_PS),
10686 OPC_RECIP2_PS = FOP(28, FMT_PS),
10687 OPC_RECIP1_PS = FOP(29, FMT_PS),
10688 OPC_RSQRT1_PS = FOP(30, FMT_PS),
10689 OPC_RSQRT2_PS = FOP(31, FMT_PS),
10691 OPC_CVT_S_PU = FOP(32, FMT_PS),
10692 OPC_CVT_PW_PS = FOP(36, FMT_PS),
10693 OPC_CVT_S_PL = FOP(40, FMT_PS),
10694 OPC_PLL_PS = FOP(44, FMT_PS),
10695 OPC_PLU_PS = FOP(45, FMT_PS),
10696 OPC_PUL_PS = FOP(46, FMT_PS),
10697 OPC_PUU_PS = FOP(47, FMT_PS),
10698 OPC_CMP_F_PS = FOP(48, FMT_PS),
10699 OPC_CMP_UN_PS = FOP(49, FMT_PS),
10700 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
10701 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
10702 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
10703 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
10704 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
10705 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
10706 OPC_CMP_SF_PS = FOP(56, FMT_PS),
10707 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
10708 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
10709 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
10710 OPC_CMP_LT_PS = FOP(60, FMT_PS),
10711 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
10712 OPC_CMP_LE_PS = FOP(62, FMT_PS),
10713 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
10716 enum r6_f_cmp_op {
10717 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
10718 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
10719 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
10720 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
10721 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
10722 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
10723 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
10724 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
10725 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
10726 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
10727 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
10728 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
10729 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
10730 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
10731 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
10732 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
10733 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
10734 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
10735 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
10736 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
10737 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
10738 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
10740 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
10741 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
10742 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
10743 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
10744 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
10745 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
10746 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
10747 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
10748 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
10749 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
10750 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
10751 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
10752 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
10753 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
10754 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
10755 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
10756 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
10757 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
10758 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
10759 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
10760 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
10761 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
10764 static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
10766 TCGv t0 = tcg_temp_new();
10768 switch (opc) {
10769 case OPC_MFC1:
10771 TCGv_i32 fp0 = tcg_temp_new_i32();
10773 gen_load_fpr32(ctx, fp0, fs);
10774 tcg_gen_ext_i32_tl(t0, fp0);
10775 tcg_temp_free_i32(fp0);
10777 gen_store_gpr(t0, rt);
10778 break;
10779 case OPC_MTC1:
10780 gen_load_gpr(t0, rt);
10782 TCGv_i32 fp0 = tcg_temp_new_i32();
10784 tcg_gen_trunc_tl_i32(fp0, t0);
10785 gen_store_fpr32(ctx, fp0, fs);
10786 tcg_temp_free_i32(fp0);
10788 break;
10789 case OPC_CFC1:
10790 gen_helper_1e0i(cfc1, t0, fs);
10791 gen_store_gpr(t0, rt);
10792 break;
10793 case OPC_CTC1:
10794 gen_load_gpr(t0, rt);
10795 save_cpu_state(ctx, 0);
10797 TCGv_i32 fs_tmp = tcg_const_i32(fs);
10799 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10800 tcg_temp_free_i32(fs_tmp);
10802 /* Stop translation as we may have changed hflags */
10803 ctx->base.is_jmp = DISAS_STOP;
10804 break;
10805 #if defined(TARGET_MIPS64)
10806 case OPC_DMFC1:
10807 gen_load_fpr64(ctx, t0, fs);
10808 gen_store_gpr(t0, rt);
10809 break;
10810 case OPC_DMTC1:
10811 gen_load_gpr(t0, rt);
10812 gen_store_fpr64(ctx, t0, fs);
10813 break;
10814 #endif
10815 case OPC_MFHC1:
10817 TCGv_i32 fp0 = tcg_temp_new_i32();
10819 gen_load_fpr32h(ctx, fp0, fs);
10820 tcg_gen_ext_i32_tl(t0, fp0);
10821 tcg_temp_free_i32(fp0);
10823 gen_store_gpr(t0, rt);
10824 break;
10825 case OPC_MTHC1:
10826 gen_load_gpr(t0, rt);
10828 TCGv_i32 fp0 = tcg_temp_new_i32();
10830 tcg_gen_trunc_tl_i32(fp0, t0);
10831 gen_store_fpr32h(ctx, fp0, fs);
10832 tcg_temp_free_i32(fp0);
10834 break;
10835 default:
10836 MIPS_INVAL("cp1 move");
10837 generate_exception_end(ctx, EXCP_RI);
10838 goto out;
10841 out:
10842 tcg_temp_free(t0);
10845 static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
10847 TCGLabel *l1;
10848 TCGCond cond;
10849 TCGv_i32 t0;
10851 if (rd == 0) {
10852 /* Treat as NOP. */
10853 return;
10856 if (tf) {
10857 cond = TCG_COND_EQ;
10858 } else {
10859 cond = TCG_COND_NE;
10862 l1 = gen_new_label();
10863 t0 = tcg_temp_new_i32();
10864 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10865 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10866 tcg_temp_free_i32(t0);
10867 if (rs == 0) {
10868 tcg_gen_movi_tl(cpu_gpr[rd], 0);
10869 } else {
10870 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
10872 gen_set_label(l1);
10875 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
10876 int tf)
10878 int cond;
10879 TCGv_i32 t0 = tcg_temp_new_i32();
10880 TCGLabel *l1 = gen_new_label();
10882 if (tf) {
10883 cond = TCG_COND_EQ;
10884 } else {
10885 cond = TCG_COND_NE;
10888 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10889 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10890 gen_load_fpr32(ctx, t0, fs);
10891 gen_store_fpr32(ctx, t0, fd);
10892 gen_set_label(l1);
10893 tcg_temp_free_i32(t0);
10896 static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
10897 int tf)
10899 int cond;
10900 TCGv_i32 t0 = tcg_temp_new_i32();
10901 TCGv_i64 fp0;
10902 TCGLabel *l1 = gen_new_label();
10904 if (tf) {
10905 cond = TCG_COND_EQ;
10906 } else {
10907 cond = TCG_COND_NE;
10910 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10911 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10912 tcg_temp_free_i32(t0);
10913 fp0 = tcg_temp_new_i64();
10914 gen_load_fpr64(ctx, fp0, fs);
10915 gen_store_fpr64(ctx, fp0, fd);
10916 tcg_temp_free_i64(fp0);
10917 gen_set_label(l1);
10920 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
10921 int cc, int tf)
10923 int cond;
10924 TCGv_i32 t0 = tcg_temp_new_i32();
10925 TCGLabel *l1 = gen_new_label();
10926 TCGLabel *l2 = gen_new_label();
10928 if (tf) {
10929 cond = TCG_COND_EQ;
10930 } else {
10931 cond = TCG_COND_NE;
10934 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10935 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10936 gen_load_fpr32(ctx, t0, fs);
10937 gen_store_fpr32(ctx, t0, fd);
10938 gen_set_label(l1);
10940 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc + 1));
10941 tcg_gen_brcondi_i32(cond, t0, 0, l2);
10942 gen_load_fpr32h(ctx, t0, fs);
10943 gen_store_fpr32h(ctx, t0, fd);
10944 tcg_temp_free_i32(t0);
10945 gen_set_label(l2);
10948 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10949 int fs)
10951 TCGv_i32 t1 = tcg_const_i32(0);
10952 TCGv_i32 fp0 = tcg_temp_new_i32();
10953 TCGv_i32 fp1 = tcg_temp_new_i32();
10954 TCGv_i32 fp2 = tcg_temp_new_i32();
10955 gen_load_fpr32(ctx, fp0, fd);
10956 gen_load_fpr32(ctx, fp1, ft);
10957 gen_load_fpr32(ctx, fp2, fs);
10959 switch (op1) {
10960 case OPC_SEL_S:
10961 tcg_gen_andi_i32(fp0, fp0, 1);
10962 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10963 break;
10964 case OPC_SELEQZ_S:
10965 tcg_gen_andi_i32(fp1, fp1, 1);
10966 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10967 break;
10968 case OPC_SELNEZ_S:
10969 tcg_gen_andi_i32(fp1, fp1, 1);
10970 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10971 break;
10972 default:
10973 MIPS_INVAL("gen_sel_s");
10974 generate_exception_end(ctx, EXCP_RI);
10975 break;
10978 gen_store_fpr32(ctx, fp0, fd);
10979 tcg_temp_free_i32(fp2);
10980 tcg_temp_free_i32(fp1);
10981 tcg_temp_free_i32(fp0);
10982 tcg_temp_free_i32(t1);
10985 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10986 int fs)
10988 TCGv_i64 t1 = tcg_const_i64(0);
10989 TCGv_i64 fp0 = tcg_temp_new_i64();
10990 TCGv_i64 fp1 = tcg_temp_new_i64();
10991 TCGv_i64 fp2 = tcg_temp_new_i64();
10992 gen_load_fpr64(ctx, fp0, fd);
10993 gen_load_fpr64(ctx, fp1, ft);
10994 gen_load_fpr64(ctx, fp2, fs);
10996 switch (op1) {
10997 case OPC_SEL_D:
10998 tcg_gen_andi_i64(fp0, fp0, 1);
10999 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11000 break;
11001 case OPC_SELEQZ_D:
11002 tcg_gen_andi_i64(fp1, fp1, 1);
11003 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11004 break;
11005 case OPC_SELNEZ_D:
11006 tcg_gen_andi_i64(fp1, fp1, 1);
11007 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11008 break;
11009 default:
11010 MIPS_INVAL("gen_sel_d");
11011 generate_exception_end(ctx, EXCP_RI);
11012 break;
11015 gen_store_fpr64(ctx, fp0, fd);
11016 tcg_temp_free_i64(fp2);
11017 tcg_temp_free_i64(fp1);
11018 tcg_temp_free_i64(fp0);
11019 tcg_temp_free_i64(t1);
11022 static void gen_farith(DisasContext *ctx, enum fopcode op1,
11023 int ft, int fs, int fd, int cc)
11025 uint32_t func = ctx->opcode & 0x3f;
11026 switch (op1) {
11027 case OPC_ADD_S:
11029 TCGv_i32 fp0 = tcg_temp_new_i32();
11030 TCGv_i32 fp1 = tcg_temp_new_i32();
11032 gen_load_fpr32(ctx, fp0, fs);
11033 gen_load_fpr32(ctx, fp1, ft);
11034 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
11035 tcg_temp_free_i32(fp1);
11036 gen_store_fpr32(ctx, fp0, fd);
11037 tcg_temp_free_i32(fp0);
11039 break;
11040 case OPC_SUB_S:
11042 TCGv_i32 fp0 = tcg_temp_new_i32();
11043 TCGv_i32 fp1 = tcg_temp_new_i32();
11045 gen_load_fpr32(ctx, fp0, fs);
11046 gen_load_fpr32(ctx, fp1, ft);
11047 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
11048 tcg_temp_free_i32(fp1);
11049 gen_store_fpr32(ctx, fp0, fd);
11050 tcg_temp_free_i32(fp0);
11052 break;
11053 case OPC_MUL_S:
11055 TCGv_i32 fp0 = tcg_temp_new_i32();
11056 TCGv_i32 fp1 = tcg_temp_new_i32();
11058 gen_load_fpr32(ctx, fp0, fs);
11059 gen_load_fpr32(ctx, fp1, ft);
11060 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
11061 tcg_temp_free_i32(fp1);
11062 gen_store_fpr32(ctx, fp0, fd);
11063 tcg_temp_free_i32(fp0);
11065 break;
11066 case OPC_DIV_S:
11068 TCGv_i32 fp0 = tcg_temp_new_i32();
11069 TCGv_i32 fp1 = tcg_temp_new_i32();
11071 gen_load_fpr32(ctx, fp0, fs);
11072 gen_load_fpr32(ctx, fp1, ft);
11073 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
11074 tcg_temp_free_i32(fp1);
11075 gen_store_fpr32(ctx, fp0, fd);
11076 tcg_temp_free_i32(fp0);
11078 break;
11079 case OPC_SQRT_S:
11081 TCGv_i32 fp0 = tcg_temp_new_i32();
11083 gen_load_fpr32(ctx, fp0, fs);
11084 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
11085 gen_store_fpr32(ctx, fp0, fd);
11086 tcg_temp_free_i32(fp0);
11088 break;
11089 case OPC_ABS_S:
11091 TCGv_i32 fp0 = tcg_temp_new_i32();
11093 gen_load_fpr32(ctx, fp0, fs);
11094 if (ctx->abs2008) {
11095 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
11096 } else {
11097 gen_helper_float_abs_s(fp0, fp0);
11099 gen_store_fpr32(ctx, fp0, fd);
11100 tcg_temp_free_i32(fp0);
11102 break;
11103 case OPC_MOV_S:
11105 TCGv_i32 fp0 = tcg_temp_new_i32();
11107 gen_load_fpr32(ctx, fp0, fs);
11108 gen_store_fpr32(ctx, fp0, fd);
11109 tcg_temp_free_i32(fp0);
11111 break;
11112 case OPC_NEG_S:
11114 TCGv_i32 fp0 = tcg_temp_new_i32();
11116 gen_load_fpr32(ctx, fp0, fs);
11117 if (ctx->abs2008) {
11118 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
11119 } else {
11120 gen_helper_float_chs_s(fp0, fp0);
11122 gen_store_fpr32(ctx, fp0, fd);
11123 tcg_temp_free_i32(fp0);
11125 break;
11126 case OPC_ROUND_L_S:
11127 check_cp1_64bitmode(ctx);
11129 TCGv_i32 fp32 = tcg_temp_new_i32();
11130 TCGv_i64 fp64 = tcg_temp_new_i64();
11132 gen_load_fpr32(ctx, fp32, fs);
11133 if (ctx->nan2008) {
11134 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
11135 } else {
11136 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
11138 tcg_temp_free_i32(fp32);
11139 gen_store_fpr64(ctx, fp64, fd);
11140 tcg_temp_free_i64(fp64);
11142 break;
11143 case OPC_TRUNC_L_S:
11144 check_cp1_64bitmode(ctx);
11146 TCGv_i32 fp32 = tcg_temp_new_i32();
11147 TCGv_i64 fp64 = tcg_temp_new_i64();
11149 gen_load_fpr32(ctx, fp32, fs);
11150 if (ctx->nan2008) {
11151 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
11152 } else {
11153 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
11155 tcg_temp_free_i32(fp32);
11156 gen_store_fpr64(ctx, fp64, fd);
11157 tcg_temp_free_i64(fp64);
11159 break;
11160 case OPC_CEIL_L_S:
11161 check_cp1_64bitmode(ctx);
11163 TCGv_i32 fp32 = tcg_temp_new_i32();
11164 TCGv_i64 fp64 = tcg_temp_new_i64();
11166 gen_load_fpr32(ctx, fp32, fs);
11167 if (ctx->nan2008) {
11168 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
11169 } else {
11170 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
11172 tcg_temp_free_i32(fp32);
11173 gen_store_fpr64(ctx, fp64, fd);
11174 tcg_temp_free_i64(fp64);
11176 break;
11177 case OPC_FLOOR_L_S:
11178 check_cp1_64bitmode(ctx);
11180 TCGv_i32 fp32 = tcg_temp_new_i32();
11181 TCGv_i64 fp64 = tcg_temp_new_i64();
11183 gen_load_fpr32(ctx, fp32, fs);
11184 if (ctx->nan2008) {
11185 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
11186 } else {
11187 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
11189 tcg_temp_free_i32(fp32);
11190 gen_store_fpr64(ctx, fp64, fd);
11191 tcg_temp_free_i64(fp64);
11193 break;
11194 case OPC_ROUND_W_S:
11196 TCGv_i32 fp0 = tcg_temp_new_i32();
11198 gen_load_fpr32(ctx, fp0, fs);
11199 if (ctx->nan2008) {
11200 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
11201 } else {
11202 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
11204 gen_store_fpr32(ctx, fp0, fd);
11205 tcg_temp_free_i32(fp0);
11207 break;
11208 case OPC_TRUNC_W_S:
11210 TCGv_i32 fp0 = tcg_temp_new_i32();
11212 gen_load_fpr32(ctx, fp0, fs);
11213 if (ctx->nan2008) {
11214 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
11215 } else {
11216 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
11218 gen_store_fpr32(ctx, fp0, fd);
11219 tcg_temp_free_i32(fp0);
11221 break;
11222 case OPC_CEIL_W_S:
11224 TCGv_i32 fp0 = tcg_temp_new_i32();
11226 gen_load_fpr32(ctx, fp0, fs);
11227 if (ctx->nan2008) {
11228 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
11229 } else {
11230 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
11232 gen_store_fpr32(ctx, fp0, fd);
11233 tcg_temp_free_i32(fp0);
11235 break;
11236 case OPC_FLOOR_W_S:
11238 TCGv_i32 fp0 = tcg_temp_new_i32();
11240 gen_load_fpr32(ctx, fp0, fs);
11241 if (ctx->nan2008) {
11242 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
11243 } else {
11244 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
11246 gen_store_fpr32(ctx, fp0, fd);
11247 tcg_temp_free_i32(fp0);
11249 break;
11250 case OPC_SEL_S:
11251 check_insn(ctx, ISA_MIPS32R6);
11252 gen_sel_s(ctx, op1, fd, ft, fs);
11253 break;
11254 case OPC_SELEQZ_S:
11255 check_insn(ctx, ISA_MIPS32R6);
11256 gen_sel_s(ctx, op1, fd, ft, fs);
11257 break;
11258 case OPC_SELNEZ_S:
11259 check_insn(ctx, ISA_MIPS32R6);
11260 gen_sel_s(ctx, op1, fd, ft, fs);
11261 break;
11262 case OPC_MOVCF_S:
11263 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11264 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11265 break;
11266 case OPC_MOVZ_S:
11267 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11269 TCGLabel *l1 = gen_new_label();
11270 TCGv_i32 fp0;
11272 if (ft != 0) {
11273 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11275 fp0 = tcg_temp_new_i32();
11276 gen_load_fpr32(ctx, fp0, fs);
11277 gen_store_fpr32(ctx, fp0, fd);
11278 tcg_temp_free_i32(fp0);
11279 gen_set_label(l1);
11281 break;
11282 case OPC_MOVN_S:
11283 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11285 TCGLabel *l1 = gen_new_label();
11286 TCGv_i32 fp0;
11288 if (ft != 0) {
11289 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11290 fp0 = tcg_temp_new_i32();
11291 gen_load_fpr32(ctx, fp0, fs);
11292 gen_store_fpr32(ctx, fp0, fd);
11293 tcg_temp_free_i32(fp0);
11294 gen_set_label(l1);
11297 break;
11298 case OPC_RECIP_S:
11300 TCGv_i32 fp0 = tcg_temp_new_i32();
11302 gen_load_fpr32(ctx, fp0, fs);
11303 gen_helper_float_recip_s(fp0, cpu_env, fp0);
11304 gen_store_fpr32(ctx, fp0, fd);
11305 tcg_temp_free_i32(fp0);
11307 break;
11308 case OPC_RSQRT_S:
11310 TCGv_i32 fp0 = tcg_temp_new_i32();
11312 gen_load_fpr32(ctx, fp0, fs);
11313 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
11314 gen_store_fpr32(ctx, fp0, fd);
11315 tcg_temp_free_i32(fp0);
11317 break;
11318 case OPC_MADDF_S:
11319 check_insn(ctx, ISA_MIPS32R6);
11321 TCGv_i32 fp0 = tcg_temp_new_i32();
11322 TCGv_i32 fp1 = tcg_temp_new_i32();
11323 TCGv_i32 fp2 = tcg_temp_new_i32();
11324 gen_load_fpr32(ctx, fp0, fs);
11325 gen_load_fpr32(ctx, fp1, ft);
11326 gen_load_fpr32(ctx, fp2, fd);
11327 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
11328 gen_store_fpr32(ctx, fp2, fd);
11329 tcg_temp_free_i32(fp2);
11330 tcg_temp_free_i32(fp1);
11331 tcg_temp_free_i32(fp0);
11333 break;
11334 case OPC_MSUBF_S:
11335 check_insn(ctx, ISA_MIPS32R6);
11337 TCGv_i32 fp0 = tcg_temp_new_i32();
11338 TCGv_i32 fp1 = tcg_temp_new_i32();
11339 TCGv_i32 fp2 = tcg_temp_new_i32();
11340 gen_load_fpr32(ctx, fp0, fs);
11341 gen_load_fpr32(ctx, fp1, ft);
11342 gen_load_fpr32(ctx, fp2, fd);
11343 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
11344 gen_store_fpr32(ctx, fp2, fd);
11345 tcg_temp_free_i32(fp2);
11346 tcg_temp_free_i32(fp1);
11347 tcg_temp_free_i32(fp0);
11349 break;
11350 case OPC_RINT_S:
11351 check_insn(ctx, ISA_MIPS32R6);
11353 TCGv_i32 fp0 = tcg_temp_new_i32();
11354 gen_load_fpr32(ctx, fp0, fs);
11355 gen_helper_float_rint_s(fp0, cpu_env, fp0);
11356 gen_store_fpr32(ctx, fp0, fd);
11357 tcg_temp_free_i32(fp0);
11359 break;
11360 case OPC_CLASS_S:
11361 check_insn(ctx, ISA_MIPS32R6);
11363 TCGv_i32 fp0 = tcg_temp_new_i32();
11364 gen_load_fpr32(ctx, fp0, fs);
11365 gen_helper_float_class_s(fp0, cpu_env, fp0);
11366 gen_store_fpr32(ctx, fp0, fd);
11367 tcg_temp_free_i32(fp0);
11369 break;
11370 case OPC_MIN_S: /* OPC_RECIP2_S */
11371 if (ctx->insn_flags & ISA_MIPS32R6) {
11372 /* OPC_MIN_S */
11373 TCGv_i32 fp0 = tcg_temp_new_i32();
11374 TCGv_i32 fp1 = tcg_temp_new_i32();
11375 TCGv_i32 fp2 = tcg_temp_new_i32();
11376 gen_load_fpr32(ctx, fp0, fs);
11377 gen_load_fpr32(ctx, fp1, ft);
11378 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
11379 gen_store_fpr32(ctx, fp2, fd);
11380 tcg_temp_free_i32(fp2);
11381 tcg_temp_free_i32(fp1);
11382 tcg_temp_free_i32(fp0);
11383 } else {
11384 /* OPC_RECIP2_S */
11385 check_cp1_64bitmode(ctx);
11387 TCGv_i32 fp0 = tcg_temp_new_i32();
11388 TCGv_i32 fp1 = tcg_temp_new_i32();
11390 gen_load_fpr32(ctx, fp0, fs);
11391 gen_load_fpr32(ctx, fp1, ft);
11392 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
11393 tcg_temp_free_i32(fp1);
11394 gen_store_fpr32(ctx, fp0, fd);
11395 tcg_temp_free_i32(fp0);
11398 break;
11399 case OPC_MINA_S: /* OPC_RECIP1_S */
11400 if (ctx->insn_flags & ISA_MIPS32R6) {
11401 /* OPC_MINA_S */
11402 TCGv_i32 fp0 = tcg_temp_new_i32();
11403 TCGv_i32 fp1 = tcg_temp_new_i32();
11404 TCGv_i32 fp2 = tcg_temp_new_i32();
11405 gen_load_fpr32(ctx, fp0, fs);
11406 gen_load_fpr32(ctx, fp1, ft);
11407 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
11408 gen_store_fpr32(ctx, fp2, fd);
11409 tcg_temp_free_i32(fp2);
11410 tcg_temp_free_i32(fp1);
11411 tcg_temp_free_i32(fp0);
11412 } else {
11413 /* OPC_RECIP1_S */
11414 check_cp1_64bitmode(ctx);
11416 TCGv_i32 fp0 = tcg_temp_new_i32();
11418 gen_load_fpr32(ctx, fp0, fs);
11419 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
11420 gen_store_fpr32(ctx, fp0, fd);
11421 tcg_temp_free_i32(fp0);
11424 break;
11425 case OPC_MAX_S: /* OPC_RSQRT1_S */
11426 if (ctx->insn_flags & ISA_MIPS32R6) {
11427 /* OPC_MAX_S */
11428 TCGv_i32 fp0 = tcg_temp_new_i32();
11429 TCGv_i32 fp1 = tcg_temp_new_i32();
11430 gen_load_fpr32(ctx, fp0, fs);
11431 gen_load_fpr32(ctx, fp1, ft);
11432 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
11433 gen_store_fpr32(ctx, fp1, fd);
11434 tcg_temp_free_i32(fp1);
11435 tcg_temp_free_i32(fp0);
11436 } else {
11437 /* OPC_RSQRT1_S */
11438 check_cp1_64bitmode(ctx);
11440 TCGv_i32 fp0 = tcg_temp_new_i32();
11442 gen_load_fpr32(ctx, fp0, fs);
11443 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
11444 gen_store_fpr32(ctx, fp0, fd);
11445 tcg_temp_free_i32(fp0);
11448 break;
11449 case OPC_MAXA_S: /* OPC_RSQRT2_S */
11450 if (ctx->insn_flags & ISA_MIPS32R6) {
11451 /* OPC_MAXA_S */
11452 TCGv_i32 fp0 = tcg_temp_new_i32();
11453 TCGv_i32 fp1 = tcg_temp_new_i32();
11454 gen_load_fpr32(ctx, fp0, fs);
11455 gen_load_fpr32(ctx, fp1, ft);
11456 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
11457 gen_store_fpr32(ctx, fp1, fd);
11458 tcg_temp_free_i32(fp1);
11459 tcg_temp_free_i32(fp0);
11460 } else {
11461 /* OPC_RSQRT2_S */
11462 check_cp1_64bitmode(ctx);
11464 TCGv_i32 fp0 = tcg_temp_new_i32();
11465 TCGv_i32 fp1 = tcg_temp_new_i32();
11467 gen_load_fpr32(ctx, fp0, fs);
11468 gen_load_fpr32(ctx, fp1, ft);
11469 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
11470 tcg_temp_free_i32(fp1);
11471 gen_store_fpr32(ctx, fp0, fd);
11472 tcg_temp_free_i32(fp0);
11475 break;
11476 case OPC_CVT_D_S:
11477 check_cp1_registers(ctx, fd);
11479 TCGv_i32 fp32 = tcg_temp_new_i32();
11480 TCGv_i64 fp64 = tcg_temp_new_i64();
11482 gen_load_fpr32(ctx, fp32, fs);
11483 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
11484 tcg_temp_free_i32(fp32);
11485 gen_store_fpr64(ctx, fp64, fd);
11486 tcg_temp_free_i64(fp64);
11488 break;
11489 case OPC_CVT_W_S:
11491 TCGv_i32 fp0 = tcg_temp_new_i32();
11493 gen_load_fpr32(ctx, fp0, fs);
11494 if (ctx->nan2008) {
11495 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
11496 } else {
11497 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
11499 gen_store_fpr32(ctx, fp0, fd);
11500 tcg_temp_free_i32(fp0);
11502 break;
11503 case OPC_CVT_L_S:
11504 check_cp1_64bitmode(ctx);
11506 TCGv_i32 fp32 = tcg_temp_new_i32();
11507 TCGv_i64 fp64 = tcg_temp_new_i64();
11509 gen_load_fpr32(ctx, fp32, fs);
11510 if (ctx->nan2008) {
11511 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
11512 } else {
11513 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
11515 tcg_temp_free_i32(fp32);
11516 gen_store_fpr64(ctx, fp64, fd);
11517 tcg_temp_free_i64(fp64);
11519 break;
11520 case OPC_CVT_PS_S:
11521 check_ps(ctx);
11523 TCGv_i64 fp64 = tcg_temp_new_i64();
11524 TCGv_i32 fp32_0 = tcg_temp_new_i32();
11525 TCGv_i32 fp32_1 = tcg_temp_new_i32();
11527 gen_load_fpr32(ctx, fp32_0, fs);
11528 gen_load_fpr32(ctx, fp32_1, ft);
11529 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
11530 tcg_temp_free_i32(fp32_1);
11531 tcg_temp_free_i32(fp32_0);
11532 gen_store_fpr64(ctx, fp64, fd);
11533 tcg_temp_free_i64(fp64);
11535 break;
11536 case OPC_CMP_F_S:
11537 case OPC_CMP_UN_S:
11538 case OPC_CMP_EQ_S:
11539 case OPC_CMP_UEQ_S:
11540 case OPC_CMP_OLT_S:
11541 case OPC_CMP_ULT_S:
11542 case OPC_CMP_OLE_S:
11543 case OPC_CMP_ULE_S:
11544 case OPC_CMP_SF_S:
11545 case OPC_CMP_NGLE_S:
11546 case OPC_CMP_SEQ_S:
11547 case OPC_CMP_NGL_S:
11548 case OPC_CMP_LT_S:
11549 case OPC_CMP_NGE_S:
11550 case OPC_CMP_LE_S:
11551 case OPC_CMP_NGT_S:
11552 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11553 if (ctx->opcode & (1 << 6)) {
11554 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
11555 } else {
11556 gen_cmp_s(ctx, func - 48, ft, fs, cc);
11558 break;
11559 case OPC_ADD_D:
11560 check_cp1_registers(ctx, fs | ft | fd);
11562 TCGv_i64 fp0 = tcg_temp_new_i64();
11563 TCGv_i64 fp1 = tcg_temp_new_i64();
11565 gen_load_fpr64(ctx, fp0, fs);
11566 gen_load_fpr64(ctx, fp1, ft);
11567 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
11568 tcg_temp_free_i64(fp1);
11569 gen_store_fpr64(ctx, fp0, fd);
11570 tcg_temp_free_i64(fp0);
11572 break;
11573 case OPC_SUB_D:
11574 check_cp1_registers(ctx, fs | ft | fd);
11576 TCGv_i64 fp0 = tcg_temp_new_i64();
11577 TCGv_i64 fp1 = tcg_temp_new_i64();
11579 gen_load_fpr64(ctx, fp0, fs);
11580 gen_load_fpr64(ctx, fp1, ft);
11581 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
11582 tcg_temp_free_i64(fp1);
11583 gen_store_fpr64(ctx, fp0, fd);
11584 tcg_temp_free_i64(fp0);
11586 break;
11587 case OPC_MUL_D:
11588 check_cp1_registers(ctx, fs | ft | fd);
11590 TCGv_i64 fp0 = tcg_temp_new_i64();
11591 TCGv_i64 fp1 = tcg_temp_new_i64();
11593 gen_load_fpr64(ctx, fp0, fs);
11594 gen_load_fpr64(ctx, fp1, ft);
11595 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
11596 tcg_temp_free_i64(fp1);
11597 gen_store_fpr64(ctx, fp0, fd);
11598 tcg_temp_free_i64(fp0);
11600 break;
11601 case OPC_DIV_D:
11602 check_cp1_registers(ctx, fs | ft | fd);
11604 TCGv_i64 fp0 = tcg_temp_new_i64();
11605 TCGv_i64 fp1 = tcg_temp_new_i64();
11607 gen_load_fpr64(ctx, fp0, fs);
11608 gen_load_fpr64(ctx, fp1, ft);
11609 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
11610 tcg_temp_free_i64(fp1);
11611 gen_store_fpr64(ctx, fp0, fd);
11612 tcg_temp_free_i64(fp0);
11614 break;
11615 case OPC_SQRT_D:
11616 check_cp1_registers(ctx, fs | fd);
11618 TCGv_i64 fp0 = tcg_temp_new_i64();
11620 gen_load_fpr64(ctx, fp0, fs);
11621 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
11622 gen_store_fpr64(ctx, fp0, fd);
11623 tcg_temp_free_i64(fp0);
11625 break;
11626 case OPC_ABS_D:
11627 check_cp1_registers(ctx, fs | fd);
11629 TCGv_i64 fp0 = tcg_temp_new_i64();
11631 gen_load_fpr64(ctx, fp0, fs);
11632 if (ctx->abs2008) {
11633 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
11634 } else {
11635 gen_helper_float_abs_d(fp0, fp0);
11637 gen_store_fpr64(ctx, fp0, fd);
11638 tcg_temp_free_i64(fp0);
11640 break;
11641 case OPC_MOV_D:
11642 check_cp1_registers(ctx, fs | fd);
11644 TCGv_i64 fp0 = tcg_temp_new_i64();
11646 gen_load_fpr64(ctx, fp0, fs);
11647 gen_store_fpr64(ctx, fp0, fd);
11648 tcg_temp_free_i64(fp0);
11650 break;
11651 case OPC_NEG_D:
11652 check_cp1_registers(ctx, fs | fd);
11654 TCGv_i64 fp0 = tcg_temp_new_i64();
11656 gen_load_fpr64(ctx, fp0, fs);
11657 if (ctx->abs2008) {
11658 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
11659 } else {
11660 gen_helper_float_chs_d(fp0, fp0);
11662 gen_store_fpr64(ctx, fp0, fd);
11663 tcg_temp_free_i64(fp0);
11665 break;
11666 case OPC_ROUND_L_D:
11667 check_cp1_64bitmode(ctx);
11669 TCGv_i64 fp0 = tcg_temp_new_i64();
11671 gen_load_fpr64(ctx, fp0, fs);
11672 if (ctx->nan2008) {
11673 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
11674 } else {
11675 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
11677 gen_store_fpr64(ctx, fp0, fd);
11678 tcg_temp_free_i64(fp0);
11680 break;
11681 case OPC_TRUNC_L_D:
11682 check_cp1_64bitmode(ctx);
11684 TCGv_i64 fp0 = tcg_temp_new_i64();
11686 gen_load_fpr64(ctx, fp0, fs);
11687 if (ctx->nan2008) {
11688 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
11689 } else {
11690 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
11692 gen_store_fpr64(ctx, fp0, fd);
11693 tcg_temp_free_i64(fp0);
11695 break;
11696 case OPC_CEIL_L_D:
11697 check_cp1_64bitmode(ctx);
11699 TCGv_i64 fp0 = tcg_temp_new_i64();
11701 gen_load_fpr64(ctx, fp0, fs);
11702 if (ctx->nan2008) {
11703 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
11704 } else {
11705 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
11707 gen_store_fpr64(ctx, fp0, fd);
11708 tcg_temp_free_i64(fp0);
11710 break;
11711 case OPC_FLOOR_L_D:
11712 check_cp1_64bitmode(ctx);
11714 TCGv_i64 fp0 = tcg_temp_new_i64();
11716 gen_load_fpr64(ctx, fp0, fs);
11717 if (ctx->nan2008) {
11718 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
11719 } else {
11720 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
11722 gen_store_fpr64(ctx, fp0, fd);
11723 tcg_temp_free_i64(fp0);
11725 break;
11726 case OPC_ROUND_W_D:
11727 check_cp1_registers(ctx, fs);
11729 TCGv_i32 fp32 = tcg_temp_new_i32();
11730 TCGv_i64 fp64 = tcg_temp_new_i64();
11732 gen_load_fpr64(ctx, fp64, fs);
11733 if (ctx->nan2008) {
11734 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
11735 } else {
11736 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
11738 tcg_temp_free_i64(fp64);
11739 gen_store_fpr32(ctx, fp32, fd);
11740 tcg_temp_free_i32(fp32);
11742 break;
11743 case OPC_TRUNC_W_D:
11744 check_cp1_registers(ctx, fs);
11746 TCGv_i32 fp32 = tcg_temp_new_i32();
11747 TCGv_i64 fp64 = tcg_temp_new_i64();
11749 gen_load_fpr64(ctx, fp64, fs);
11750 if (ctx->nan2008) {
11751 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
11752 } else {
11753 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
11755 tcg_temp_free_i64(fp64);
11756 gen_store_fpr32(ctx, fp32, fd);
11757 tcg_temp_free_i32(fp32);
11759 break;
11760 case OPC_CEIL_W_D:
11761 check_cp1_registers(ctx, fs);
11763 TCGv_i32 fp32 = tcg_temp_new_i32();
11764 TCGv_i64 fp64 = tcg_temp_new_i64();
11766 gen_load_fpr64(ctx, fp64, fs);
11767 if (ctx->nan2008) {
11768 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
11769 } else {
11770 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
11772 tcg_temp_free_i64(fp64);
11773 gen_store_fpr32(ctx, fp32, fd);
11774 tcg_temp_free_i32(fp32);
11776 break;
11777 case OPC_FLOOR_W_D:
11778 check_cp1_registers(ctx, fs);
11780 TCGv_i32 fp32 = tcg_temp_new_i32();
11781 TCGv_i64 fp64 = tcg_temp_new_i64();
11783 gen_load_fpr64(ctx, fp64, fs);
11784 if (ctx->nan2008) {
11785 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
11786 } else {
11787 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
11789 tcg_temp_free_i64(fp64);
11790 gen_store_fpr32(ctx, fp32, fd);
11791 tcg_temp_free_i32(fp32);
11793 break;
11794 case OPC_SEL_D:
11795 check_insn(ctx, ISA_MIPS32R6);
11796 gen_sel_d(ctx, op1, fd, ft, fs);
11797 break;
11798 case OPC_SELEQZ_D:
11799 check_insn(ctx, ISA_MIPS32R6);
11800 gen_sel_d(ctx, op1, fd, ft, fs);
11801 break;
11802 case OPC_SELNEZ_D:
11803 check_insn(ctx, ISA_MIPS32R6);
11804 gen_sel_d(ctx, op1, fd, ft, fs);
11805 break;
11806 case OPC_MOVCF_D:
11807 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11808 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11809 break;
11810 case OPC_MOVZ_D:
11811 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11813 TCGLabel *l1 = gen_new_label();
11814 TCGv_i64 fp0;
11816 if (ft != 0) {
11817 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11819 fp0 = tcg_temp_new_i64();
11820 gen_load_fpr64(ctx, fp0, fs);
11821 gen_store_fpr64(ctx, fp0, fd);
11822 tcg_temp_free_i64(fp0);
11823 gen_set_label(l1);
11825 break;
11826 case OPC_MOVN_D:
11827 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11829 TCGLabel *l1 = gen_new_label();
11830 TCGv_i64 fp0;
11832 if (ft != 0) {
11833 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11834 fp0 = tcg_temp_new_i64();
11835 gen_load_fpr64(ctx, fp0, fs);
11836 gen_store_fpr64(ctx, fp0, fd);
11837 tcg_temp_free_i64(fp0);
11838 gen_set_label(l1);
11841 break;
11842 case OPC_RECIP_D:
11843 check_cp1_registers(ctx, fs | fd);
11845 TCGv_i64 fp0 = tcg_temp_new_i64();
11847 gen_load_fpr64(ctx, fp0, fs);
11848 gen_helper_float_recip_d(fp0, cpu_env, fp0);
11849 gen_store_fpr64(ctx, fp0, fd);
11850 tcg_temp_free_i64(fp0);
11852 break;
11853 case OPC_RSQRT_D:
11854 check_cp1_registers(ctx, fs | fd);
11856 TCGv_i64 fp0 = tcg_temp_new_i64();
11858 gen_load_fpr64(ctx, fp0, fs);
11859 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
11860 gen_store_fpr64(ctx, fp0, fd);
11861 tcg_temp_free_i64(fp0);
11863 break;
11864 case OPC_MADDF_D:
11865 check_insn(ctx, ISA_MIPS32R6);
11867 TCGv_i64 fp0 = tcg_temp_new_i64();
11868 TCGv_i64 fp1 = tcg_temp_new_i64();
11869 TCGv_i64 fp2 = tcg_temp_new_i64();
11870 gen_load_fpr64(ctx, fp0, fs);
11871 gen_load_fpr64(ctx, fp1, ft);
11872 gen_load_fpr64(ctx, fp2, fd);
11873 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
11874 gen_store_fpr64(ctx, fp2, fd);
11875 tcg_temp_free_i64(fp2);
11876 tcg_temp_free_i64(fp1);
11877 tcg_temp_free_i64(fp0);
11879 break;
11880 case OPC_MSUBF_D:
11881 check_insn(ctx, ISA_MIPS32R6);
11883 TCGv_i64 fp0 = tcg_temp_new_i64();
11884 TCGv_i64 fp1 = tcg_temp_new_i64();
11885 TCGv_i64 fp2 = tcg_temp_new_i64();
11886 gen_load_fpr64(ctx, fp0, fs);
11887 gen_load_fpr64(ctx, fp1, ft);
11888 gen_load_fpr64(ctx, fp2, fd);
11889 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
11890 gen_store_fpr64(ctx, fp2, fd);
11891 tcg_temp_free_i64(fp2);
11892 tcg_temp_free_i64(fp1);
11893 tcg_temp_free_i64(fp0);
11895 break;
11896 case OPC_RINT_D:
11897 check_insn(ctx, ISA_MIPS32R6);
11899 TCGv_i64 fp0 = tcg_temp_new_i64();
11900 gen_load_fpr64(ctx, fp0, fs);
11901 gen_helper_float_rint_d(fp0, cpu_env, fp0);
11902 gen_store_fpr64(ctx, fp0, fd);
11903 tcg_temp_free_i64(fp0);
11905 break;
11906 case OPC_CLASS_D:
11907 check_insn(ctx, ISA_MIPS32R6);
11909 TCGv_i64 fp0 = tcg_temp_new_i64();
11910 gen_load_fpr64(ctx, fp0, fs);
11911 gen_helper_float_class_d(fp0, cpu_env, fp0);
11912 gen_store_fpr64(ctx, fp0, fd);
11913 tcg_temp_free_i64(fp0);
11915 break;
11916 case OPC_MIN_D: /* OPC_RECIP2_D */
11917 if (ctx->insn_flags & ISA_MIPS32R6) {
11918 /* OPC_MIN_D */
11919 TCGv_i64 fp0 = tcg_temp_new_i64();
11920 TCGv_i64 fp1 = tcg_temp_new_i64();
11921 gen_load_fpr64(ctx, fp0, fs);
11922 gen_load_fpr64(ctx, fp1, ft);
11923 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
11924 gen_store_fpr64(ctx, fp1, fd);
11925 tcg_temp_free_i64(fp1);
11926 tcg_temp_free_i64(fp0);
11927 } else {
11928 /* OPC_RECIP2_D */
11929 check_cp1_64bitmode(ctx);
11931 TCGv_i64 fp0 = tcg_temp_new_i64();
11932 TCGv_i64 fp1 = tcg_temp_new_i64();
11934 gen_load_fpr64(ctx, fp0, fs);
11935 gen_load_fpr64(ctx, fp1, ft);
11936 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
11937 tcg_temp_free_i64(fp1);
11938 gen_store_fpr64(ctx, fp0, fd);
11939 tcg_temp_free_i64(fp0);
11942 break;
11943 case OPC_MINA_D: /* OPC_RECIP1_D */
11944 if (ctx->insn_flags & ISA_MIPS32R6) {
11945 /* OPC_MINA_D */
11946 TCGv_i64 fp0 = tcg_temp_new_i64();
11947 TCGv_i64 fp1 = tcg_temp_new_i64();
11948 gen_load_fpr64(ctx, fp0, fs);
11949 gen_load_fpr64(ctx, fp1, ft);
11950 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
11951 gen_store_fpr64(ctx, fp1, fd);
11952 tcg_temp_free_i64(fp1);
11953 tcg_temp_free_i64(fp0);
11954 } else {
11955 /* OPC_RECIP1_D */
11956 check_cp1_64bitmode(ctx);
11958 TCGv_i64 fp0 = tcg_temp_new_i64();
11960 gen_load_fpr64(ctx, fp0, fs);
11961 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
11962 gen_store_fpr64(ctx, fp0, fd);
11963 tcg_temp_free_i64(fp0);
11966 break;
11967 case OPC_MAX_D: /* OPC_RSQRT1_D */
11968 if (ctx->insn_flags & ISA_MIPS32R6) {
11969 /* OPC_MAX_D */
11970 TCGv_i64 fp0 = tcg_temp_new_i64();
11971 TCGv_i64 fp1 = tcg_temp_new_i64();
11972 gen_load_fpr64(ctx, fp0, fs);
11973 gen_load_fpr64(ctx, fp1, ft);
11974 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
11975 gen_store_fpr64(ctx, fp1, fd);
11976 tcg_temp_free_i64(fp1);
11977 tcg_temp_free_i64(fp0);
11978 } else {
11979 /* OPC_RSQRT1_D */
11980 check_cp1_64bitmode(ctx);
11982 TCGv_i64 fp0 = tcg_temp_new_i64();
11984 gen_load_fpr64(ctx, fp0, fs);
11985 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
11986 gen_store_fpr64(ctx, fp0, fd);
11987 tcg_temp_free_i64(fp0);
11990 break;
11991 case OPC_MAXA_D: /* OPC_RSQRT2_D */
11992 if (ctx->insn_flags & ISA_MIPS32R6) {
11993 /* OPC_MAXA_D */
11994 TCGv_i64 fp0 = tcg_temp_new_i64();
11995 TCGv_i64 fp1 = tcg_temp_new_i64();
11996 gen_load_fpr64(ctx, fp0, fs);
11997 gen_load_fpr64(ctx, fp1, ft);
11998 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
11999 gen_store_fpr64(ctx, fp1, fd);
12000 tcg_temp_free_i64(fp1);
12001 tcg_temp_free_i64(fp0);
12002 } else {
12003 /* OPC_RSQRT2_D */
12004 check_cp1_64bitmode(ctx);
12006 TCGv_i64 fp0 = tcg_temp_new_i64();
12007 TCGv_i64 fp1 = tcg_temp_new_i64();
12009 gen_load_fpr64(ctx, fp0, fs);
12010 gen_load_fpr64(ctx, fp1, ft);
12011 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
12012 tcg_temp_free_i64(fp1);
12013 gen_store_fpr64(ctx, fp0, fd);
12014 tcg_temp_free_i64(fp0);
12017 break;
12018 case OPC_CMP_F_D:
12019 case OPC_CMP_UN_D:
12020 case OPC_CMP_EQ_D:
12021 case OPC_CMP_UEQ_D:
12022 case OPC_CMP_OLT_D:
12023 case OPC_CMP_ULT_D:
12024 case OPC_CMP_OLE_D:
12025 case OPC_CMP_ULE_D:
12026 case OPC_CMP_SF_D:
12027 case OPC_CMP_NGLE_D:
12028 case OPC_CMP_SEQ_D:
12029 case OPC_CMP_NGL_D:
12030 case OPC_CMP_LT_D:
12031 case OPC_CMP_NGE_D:
12032 case OPC_CMP_LE_D:
12033 case OPC_CMP_NGT_D:
12034 check_insn_opc_removed(ctx, ISA_MIPS32R6);
12035 if (ctx->opcode & (1 << 6)) {
12036 gen_cmpabs_d(ctx, func - 48, ft, fs, cc);
12037 } else {
12038 gen_cmp_d(ctx, func - 48, ft, fs, cc);
12040 break;
12041 case OPC_CVT_S_D:
12042 check_cp1_registers(ctx, fs);
12044 TCGv_i32 fp32 = tcg_temp_new_i32();
12045 TCGv_i64 fp64 = tcg_temp_new_i64();
12047 gen_load_fpr64(ctx, fp64, fs);
12048 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
12049 tcg_temp_free_i64(fp64);
12050 gen_store_fpr32(ctx, fp32, fd);
12051 tcg_temp_free_i32(fp32);
12053 break;
12054 case OPC_CVT_W_D:
12055 check_cp1_registers(ctx, fs);
12057 TCGv_i32 fp32 = tcg_temp_new_i32();
12058 TCGv_i64 fp64 = tcg_temp_new_i64();
12060 gen_load_fpr64(ctx, fp64, fs);
12061 if (ctx->nan2008) {
12062 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
12063 } else {
12064 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
12066 tcg_temp_free_i64(fp64);
12067 gen_store_fpr32(ctx, fp32, fd);
12068 tcg_temp_free_i32(fp32);
12070 break;
12071 case OPC_CVT_L_D:
12072 check_cp1_64bitmode(ctx);
12074 TCGv_i64 fp0 = tcg_temp_new_i64();
12076 gen_load_fpr64(ctx, fp0, fs);
12077 if (ctx->nan2008) {
12078 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
12079 } else {
12080 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
12082 gen_store_fpr64(ctx, fp0, fd);
12083 tcg_temp_free_i64(fp0);
12085 break;
12086 case OPC_CVT_S_W:
12088 TCGv_i32 fp0 = tcg_temp_new_i32();
12090 gen_load_fpr32(ctx, fp0, fs);
12091 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
12092 gen_store_fpr32(ctx, fp0, fd);
12093 tcg_temp_free_i32(fp0);
12095 break;
12096 case OPC_CVT_D_W:
12097 check_cp1_registers(ctx, fd);
12099 TCGv_i32 fp32 = tcg_temp_new_i32();
12100 TCGv_i64 fp64 = tcg_temp_new_i64();
12102 gen_load_fpr32(ctx, fp32, fs);
12103 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
12104 tcg_temp_free_i32(fp32);
12105 gen_store_fpr64(ctx, fp64, fd);
12106 tcg_temp_free_i64(fp64);
12108 break;
12109 case OPC_CVT_S_L:
12110 check_cp1_64bitmode(ctx);
12112 TCGv_i32 fp32 = tcg_temp_new_i32();
12113 TCGv_i64 fp64 = tcg_temp_new_i64();
12115 gen_load_fpr64(ctx, fp64, fs);
12116 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
12117 tcg_temp_free_i64(fp64);
12118 gen_store_fpr32(ctx, fp32, fd);
12119 tcg_temp_free_i32(fp32);
12121 break;
12122 case OPC_CVT_D_L:
12123 check_cp1_64bitmode(ctx);
12125 TCGv_i64 fp0 = tcg_temp_new_i64();
12127 gen_load_fpr64(ctx, fp0, fs);
12128 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
12129 gen_store_fpr64(ctx, fp0, fd);
12130 tcg_temp_free_i64(fp0);
12132 break;
12133 case OPC_CVT_PS_PW:
12134 check_ps(ctx);
12136 TCGv_i64 fp0 = tcg_temp_new_i64();
12138 gen_load_fpr64(ctx, fp0, fs);
12139 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
12140 gen_store_fpr64(ctx, fp0, fd);
12141 tcg_temp_free_i64(fp0);
12143 break;
12144 case OPC_ADD_PS:
12145 check_ps(ctx);
12147 TCGv_i64 fp0 = tcg_temp_new_i64();
12148 TCGv_i64 fp1 = tcg_temp_new_i64();
12150 gen_load_fpr64(ctx, fp0, fs);
12151 gen_load_fpr64(ctx, fp1, ft);
12152 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
12153 tcg_temp_free_i64(fp1);
12154 gen_store_fpr64(ctx, fp0, fd);
12155 tcg_temp_free_i64(fp0);
12157 break;
12158 case OPC_SUB_PS:
12159 check_ps(ctx);
12161 TCGv_i64 fp0 = tcg_temp_new_i64();
12162 TCGv_i64 fp1 = tcg_temp_new_i64();
12164 gen_load_fpr64(ctx, fp0, fs);
12165 gen_load_fpr64(ctx, fp1, ft);
12166 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
12167 tcg_temp_free_i64(fp1);
12168 gen_store_fpr64(ctx, fp0, fd);
12169 tcg_temp_free_i64(fp0);
12171 break;
12172 case OPC_MUL_PS:
12173 check_ps(ctx);
12175 TCGv_i64 fp0 = tcg_temp_new_i64();
12176 TCGv_i64 fp1 = tcg_temp_new_i64();
12178 gen_load_fpr64(ctx, fp0, fs);
12179 gen_load_fpr64(ctx, fp1, ft);
12180 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
12181 tcg_temp_free_i64(fp1);
12182 gen_store_fpr64(ctx, fp0, fd);
12183 tcg_temp_free_i64(fp0);
12185 break;
12186 case OPC_ABS_PS:
12187 check_ps(ctx);
12189 TCGv_i64 fp0 = tcg_temp_new_i64();
12191 gen_load_fpr64(ctx, fp0, fs);
12192 gen_helper_float_abs_ps(fp0, fp0);
12193 gen_store_fpr64(ctx, fp0, fd);
12194 tcg_temp_free_i64(fp0);
12196 break;
12197 case OPC_MOV_PS:
12198 check_ps(ctx);
12200 TCGv_i64 fp0 = tcg_temp_new_i64();
12202 gen_load_fpr64(ctx, fp0, fs);
12203 gen_store_fpr64(ctx, fp0, fd);
12204 tcg_temp_free_i64(fp0);
12206 break;
12207 case OPC_NEG_PS:
12208 check_ps(ctx);
12210 TCGv_i64 fp0 = tcg_temp_new_i64();
12212 gen_load_fpr64(ctx, fp0, fs);
12213 gen_helper_float_chs_ps(fp0, fp0);
12214 gen_store_fpr64(ctx, fp0, fd);
12215 tcg_temp_free_i64(fp0);
12217 break;
12218 case OPC_MOVCF_PS:
12219 check_ps(ctx);
12220 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
12221 break;
12222 case OPC_MOVZ_PS:
12223 check_ps(ctx);
12225 TCGLabel *l1 = gen_new_label();
12226 TCGv_i64 fp0;
12228 if (ft != 0) {
12229 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
12231 fp0 = tcg_temp_new_i64();
12232 gen_load_fpr64(ctx, fp0, fs);
12233 gen_store_fpr64(ctx, fp0, fd);
12234 tcg_temp_free_i64(fp0);
12235 gen_set_label(l1);
12237 break;
12238 case OPC_MOVN_PS:
12239 check_ps(ctx);
12241 TCGLabel *l1 = gen_new_label();
12242 TCGv_i64 fp0;
12244 if (ft != 0) {
12245 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12246 fp0 = tcg_temp_new_i64();
12247 gen_load_fpr64(ctx, fp0, fs);
12248 gen_store_fpr64(ctx, fp0, fd);
12249 tcg_temp_free_i64(fp0);
12250 gen_set_label(l1);
12253 break;
12254 case OPC_ADDR_PS:
12255 check_ps(ctx);
12257 TCGv_i64 fp0 = tcg_temp_new_i64();
12258 TCGv_i64 fp1 = tcg_temp_new_i64();
12260 gen_load_fpr64(ctx, fp0, ft);
12261 gen_load_fpr64(ctx, fp1, fs);
12262 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
12263 tcg_temp_free_i64(fp1);
12264 gen_store_fpr64(ctx, fp0, fd);
12265 tcg_temp_free_i64(fp0);
12267 break;
12268 case OPC_MULR_PS:
12269 check_ps(ctx);
12271 TCGv_i64 fp0 = tcg_temp_new_i64();
12272 TCGv_i64 fp1 = tcg_temp_new_i64();
12274 gen_load_fpr64(ctx, fp0, ft);
12275 gen_load_fpr64(ctx, fp1, fs);
12276 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
12277 tcg_temp_free_i64(fp1);
12278 gen_store_fpr64(ctx, fp0, fd);
12279 tcg_temp_free_i64(fp0);
12281 break;
12282 case OPC_RECIP2_PS:
12283 check_ps(ctx);
12285 TCGv_i64 fp0 = tcg_temp_new_i64();
12286 TCGv_i64 fp1 = tcg_temp_new_i64();
12288 gen_load_fpr64(ctx, fp0, fs);
12289 gen_load_fpr64(ctx, fp1, ft);
12290 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
12291 tcg_temp_free_i64(fp1);
12292 gen_store_fpr64(ctx, fp0, fd);
12293 tcg_temp_free_i64(fp0);
12295 break;
12296 case OPC_RECIP1_PS:
12297 check_ps(ctx);
12299 TCGv_i64 fp0 = tcg_temp_new_i64();
12301 gen_load_fpr64(ctx, fp0, fs);
12302 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
12303 gen_store_fpr64(ctx, fp0, fd);
12304 tcg_temp_free_i64(fp0);
12306 break;
12307 case OPC_RSQRT1_PS:
12308 check_ps(ctx);
12310 TCGv_i64 fp0 = tcg_temp_new_i64();
12312 gen_load_fpr64(ctx, fp0, fs);
12313 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
12314 gen_store_fpr64(ctx, fp0, fd);
12315 tcg_temp_free_i64(fp0);
12317 break;
12318 case OPC_RSQRT2_PS:
12319 check_ps(ctx);
12321 TCGv_i64 fp0 = tcg_temp_new_i64();
12322 TCGv_i64 fp1 = tcg_temp_new_i64();
12324 gen_load_fpr64(ctx, fp0, fs);
12325 gen_load_fpr64(ctx, fp1, ft);
12326 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
12327 tcg_temp_free_i64(fp1);
12328 gen_store_fpr64(ctx, fp0, fd);
12329 tcg_temp_free_i64(fp0);
12331 break;
12332 case OPC_CVT_S_PU:
12333 check_cp1_64bitmode(ctx);
12335 TCGv_i32 fp0 = tcg_temp_new_i32();
12337 gen_load_fpr32h(ctx, fp0, fs);
12338 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
12339 gen_store_fpr32(ctx, fp0, fd);
12340 tcg_temp_free_i32(fp0);
12342 break;
12343 case OPC_CVT_PW_PS:
12344 check_ps(ctx);
12346 TCGv_i64 fp0 = tcg_temp_new_i64();
12348 gen_load_fpr64(ctx, fp0, fs);
12349 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
12350 gen_store_fpr64(ctx, fp0, fd);
12351 tcg_temp_free_i64(fp0);
12353 break;
12354 case OPC_CVT_S_PL:
12355 check_cp1_64bitmode(ctx);
12357 TCGv_i32 fp0 = tcg_temp_new_i32();
12359 gen_load_fpr32(ctx, fp0, fs);
12360 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
12361 gen_store_fpr32(ctx, fp0, fd);
12362 tcg_temp_free_i32(fp0);
12364 break;
12365 case OPC_PLL_PS:
12366 check_ps(ctx);
12368 TCGv_i32 fp0 = tcg_temp_new_i32();
12369 TCGv_i32 fp1 = tcg_temp_new_i32();
12371 gen_load_fpr32(ctx, fp0, fs);
12372 gen_load_fpr32(ctx, fp1, ft);
12373 gen_store_fpr32h(ctx, fp0, fd);
12374 gen_store_fpr32(ctx, fp1, fd);
12375 tcg_temp_free_i32(fp0);
12376 tcg_temp_free_i32(fp1);
12378 break;
12379 case OPC_PLU_PS:
12380 check_ps(ctx);
12382 TCGv_i32 fp0 = tcg_temp_new_i32();
12383 TCGv_i32 fp1 = tcg_temp_new_i32();
12385 gen_load_fpr32(ctx, fp0, fs);
12386 gen_load_fpr32h(ctx, fp1, ft);
12387 gen_store_fpr32(ctx, fp1, fd);
12388 gen_store_fpr32h(ctx, fp0, fd);
12389 tcg_temp_free_i32(fp0);
12390 tcg_temp_free_i32(fp1);
12392 break;
12393 case OPC_PUL_PS:
12394 check_ps(ctx);
12396 TCGv_i32 fp0 = tcg_temp_new_i32();
12397 TCGv_i32 fp1 = tcg_temp_new_i32();
12399 gen_load_fpr32h(ctx, fp0, fs);
12400 gen_load_fpr32(ctx, fp1, ft);
12401 gen_store_fpr32(ctx, fp1, fd);
12402 gen_store_fpr32h(ctx, fp0, fd);
12403 tcg_temp_free_i32(fp0);
12404 tcg_temp_free_i32(fp1);
12406 break;
12407 case OPC_PUU_PS:
12408 check_ps(ctx);
12410 TCGv_i32 fp0 = tcg_temp_new_i32();
12411 TCGv_i32 fp1 = tcg_temp_new_i32();
12413 gen_load_fpr32h(ctx, fp0, fs);
12414 gen_load_fpr32h(ctx, fp1, ft);
12415 gen_store_fpr32(ctx, fp1, fd);
12416 gen_store_fpr32h(ctx, fp0, fd);
12417 tcg_temp_free_i32(fp0);
12418 tcg_temp_free_i32(fp1);
12420 break;
12421 case OPC_CMP_F_PS:
12422 case OPC_CMP_UN_PS:
12423 case OPC_CMP_EQ_PS:
12424 case OPC_CMP_UEQ_PS:
12425 case OPC_CMP_OLT_PS:
12426 case OPC_CMP_ULT_PS:
12427 case OPC_CMP_OLE_PS:
12428 case OPC_CMP_ULE_PS:
12429 case OPC_CMP_SF_PS:
12430 case OPC_CMP_NGLE_PS:
12431 case OPC_CMP_SEQ_PS:
12432 case OPC_CMP_NGL_PS:
12433 case OPC_CMP_LT_PS:
12434 case OPC_CMP_NGE_PS:
12435 case OPC_CMP_LE_PS:
12436 case OPC_CMP_NGT_PS:
12437 if (ctx->opcode & (1 << 6)) {
12438 gen_cmpabs_ps(ctx, func - 48, ft, fs, cc);
12439 } else {
12440 gen_cmp_ps(ctx, func - 48, ft, fs, cc);
12442 break;
12443 default:
12444 MIPS_INVAL("farith");
12445 generate_exception_end(ctx, EXCP_RI);
12446 return;
12450 /* Coprocessor 3 (FPU) */
12451 static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
12452 int fd, int fs, int base, int index)
12454 TCGv t0 = tcg_temp_new();
12456 if (base == 0) {
12457 gen_load_gpr(t0, index);
12458 } else if (index == 0) {
12459 gen_load_gpr(t0, base);
12460 } else {
12461 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
12464 * Don't do NOP if destination is zero: we must perform the actual
12465 * memory access.
12467 switch (opc) {
12468 case OPC_LWXC1:
12469 check_cop1x(ctx);
12471 TCGv_i32 fp0 = tcg_temp_new_i32();
12473 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
12474 tcg_gen_trunc_tl_i32(fp0, t0);
12475 gen_store_fpr32(ctx, fp0, fd);
12476 tcg_temp_free_i32(fp0);
12478 break;
12479 case OPC_LDXC1:
12480 check_cop1x(ctx);
12481 check_cp1_registers(ctx, fd);
12483 TCGv_i64 fp0 = tcg_temp_new_i64();
12484 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12485 gen_store_fpr64(ctx, fp0, fd);
12486 tcg_temp_free_i64(fp0);
12488 break;
12489 case OPC_LUXC1:
12490 check_cp1_64bitmode(ctx);
12491 tcg_gen_andi_tl(t0, t0, ~0x7);
12493 TCGv_i64 fp0 = tcg_temp_new_i64();
12495 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12496 gen_store_fpr64(ctx, fp0, fd);
12497 tcg_temp_free_i64(fp0);
12499 break;
12500 case OPC_SWXC1:
12501 check_cop1x(ctx);
12503 TCGv_i32 fp0 = tcg_temp_new_i32();
12504 gen_load_fpr32(ctx, fp0, fs);
12505 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
12506 tcg_temp_free_i32(fp0);
12508 break;
12509 case OPC_SDXC1:
12510 check_cop1x(ctx);
12511 check_cp1_registers(ctx, fs);
12513 TCGv_i64 fp0 = tcg_temp_new_i64();
12514 gen_load_fpr64(ctx, fp0, fs);
12515 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12516 tcg_temp_free_i64(fp0);
12518 break;
12519 case OPC_SUXC1:
12520 check_cp1_64bitmode(ctx);
12521 tcg_gen_andi_tl(t0, t0, ~0x7);
12523 TCGv_i64 fp0 = tcg_temp_new_i64();
12524 gen_load_fpr64(ctx, fp0, fs);
12525 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12526 tcg_temp_free_i64(fp0);
12528 break;
12530 tcg_temp_free(t0);
12533 static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
12534 int fd, int fr, int fs, int ft)
12536 switch (opc) {
12537 case OPC_ALNV_PS:
12538 check_ps(ctx);
12540 TCGv t0 = tcg_temp_local_new();
12541 TCGv_i32 fp = tcg_temp_new_i32();
12542 TCGv_i32 fph = tcg_temp_new_i32();
12543 TCGLabel *l1 = gen_new_label();
12544 TCGLabel *l2 = gen_new_label();
12546 gen_load_gpr(t0, fr);
12547 tcg_gen_andi_tl(t0, t0, 0x7);
12549 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
12550 gen_load_fpr32(ctx, fp, fs);
12551 gen_load_fpr32h(ctx, fph, fs);
12552 gen_store_fpr32(ctx, fp, fd);
12553 gen_store_fpr32h(ctx, fph, fd);
12554 tcg_gen_br(l2);
12555 gen_set_label(l1);
12556 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
12557 tcg_temp_free(t0);
12558 #ifdef TARGET_WORDS_BIGENDIAN
12559 gen_load_fpr32(ctx, fp, fs);
12560 gen_load_fpr32h(ctx, fph, ft);
12561 gen_store_fpr32h(ctx, fp, fd);
12562 gen_store_fpr32(ctx, fph, fd);
12563 #else
12564 gen_load_fpr32h(ctx, fph, fs);
12565 gen_load_fpr32(ctx, fp, ft);
12566 gen_store_fpr32(ctx, fph, fd);
12567 gen_store_fpr32h(ctx, fp, fd);
12568 #endif
12569 gen_set_label(l2);
12570 tcg_temp_free_i32(fp);
12571 tcg_temp_free_i32(fph);
12573 break;
12574 case OPC_MADD_S:
12575 check_cop1x(ctx);
12577 TCGv_i32 fp0 = tcg_temp_new_i32();
12578 TCGv_i32 fp1 = tcg_temp_new_i32();
12579 TCGv_i32 fp2 = tcg_temp_new_i32();
12581 gen_load_fpr32(ctx, fp0, fs);
12582 gen_load_fpr32(ctx, fp1, ft);
12583 gen_load_fpr32(ctx, fp2, fr);
12584 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
12585 tcg_temp_free_i32(fp0);
12586 tcg_temp_free_i32(fp1);
12587 gen_store_fpr32(ctx, fp2, fd);
12588 tcg_temp_free_i32(fp2);
12590 break;
12591 case OPC_MADD_D:
12592 check_cop1x(ctx);
12593 check_cp1_registers(ctx, fd | fs | ft | fr);
12595 TCGv_i64 fp0 = tcg_temp_new_i64();
12596 TCGv_i64 fp1 = tcg_temp_new_i64();
12597 TCGv_i64 fp2 = tcg_temp_new_i64();
12599 gen_load_fpr64(ctx, fp0, fs);
12600 gen_load_fpr64(ctx, fp1, ft);
12601 gen_load_fpr64(ctx, fp2, fr);
12602 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
12603 tcg_temp_free_i64(fp0);
12604 tcg_temp_free_i64(fp1);
12605 gen_store_fpr64(ctx, fp2, fd);
12606 tcg_temp_free_i64(fp2);
12608 break;
12609 case OPC_MADD_PS:
12610 check_ps(ctx);
12612 TCGv_i64 fp0 = tcg_temp_new_i64();
12613 TCGv_i64 fp1 = tcg_temp_new_i64();
12614 TCGv_i64 fp2 = tcg_temp_new_i64();
12616 gen_load_fpr64(ctx, fp0, fs);
12617 gen_load_fpr64(ctx, fp1, ft);
12618 gen_load_fpr64(ctx, fp2, fr);
12619 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
12620 tcg_temp_free_i64(fp0);
12621 tcg_temp_free_i64(fp1);
12622 gen_store_fpr64(ctx, fp2, fd);
12623 tcg_temp_free_i64(fp2);
12625 break;
12626 case OPC_MSUB_S:
12627 check_cop1x(ctx);
12629 TCGv_i32 fp0 = tcg_temp_new_i32();
12630 TCGv_i32 fp1 = tcg_temp_new_i32();
12631 TCGv_i32 fp2 = tcg_temp_new_i32();
12633 gen_load_fpr32(ctx, fp0, fs);
12634 gen_load_fpr32(ctx, fp1, ft);
12635 gen_load_fpr32(ctx, fp2, fr);
12636 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
12637 tcg_temp_free_i32(fp0);
12638 tcg_temp_free_i32(fp1);
12639 gen_store_fpr32(ctx, fp2, fd);
12640 tcg_temp_free_i32(fp2);
12642 break;
12643 case OPC_MSUB_D:
12644 check_cop1x(ctx);
12645 check_cp1_registers(ctx, fd | fs | ft | fr);
12647 TCGv_i64 fp0 = tcg_temp_new_i64();
12648 TCGv_i64 fp1 = tcg_temp_new_i64();
12649 TCGv_i64 fp2 = tcg_temp_new_i64();
12651 gen_load_fpr64(ctx, fp0, fs);
12652 gen_load_fpr64(ctx, fp1, ft);
12653 gen_load_fpr64(ctx, fp2, fr);
12654 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
12655 tcg_temp_free_i64(fp0);
12656 tcg_temp_free_i64(fp1);
12657 gen_store_fpr64(ctx, fp2, fd);
12658 tcg_temp_free_i64(fp2);
12660 break;
12661 case OPC_MSUB_PS:
12662 check_ps(ctx);
12664 TCGv_i64 fp0 = tcg_temp_new_i64();
12665 TCGv_i64 fp1 = tcg_temp_new_i64();
12666 TCGv_i64 fp2 = tcg_temp_new_i64();
12668 gen_load_fpr64(ctx, fp0, fs);
12669 gen_load_fpr64(ctx, fp1, ft);
12670 gen_load_fpr64(ctx, fp2, fr);
12671 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
12672 tcg_temp_free_i64(fp0);
12673 tcg_temp_free_i64(fp1);
12674 gen_store_fpr64(ctx, fp2, fd);
12675 tcg_temp_free_i64(fp2);
12677 break;
12678 case OPC_NMADD_S:
12679 check_cop1x(ctx);
12681 TCGv_i32 fp0 = tcg_temp_new_i32();
12682 TCGv_i32 fp1 = tcg_temp_new_i32();
12683 TCGv_i32 fp2 = tcg_temp_new_i32();
12685 gen_load_fpr32(ctx, fp0, fs);
12686 gen_load_fpr32(ctx, fp1, ft);
12687 gen_load_fpr32(ctx, fp2, fr);
12688 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
12689 tcg_temp_free_i32(fp0);
12690 tcg_temp_free_i32(fp1);
12691 gen_store_fpr32(ctx, fp2, fd);
12692 tcg_temp_free_i32(fp2);
12694 break;
12695 case OPC_NMADD_D:
12696 check_cop1x(ctx);
12697 check_cp1_registers(ctx, fd | fs | ft | fr);
12699 TCGv_i64 fp0 = tcg_temp_new_i64();
12700 TCGv_i64 fp1 = tcg_temp_new_i64();
12701 TCGv_i64 fp2 = tcg_temp_new_i64();
12703 gen_load_fpr64(ctx, fp0, fs);
12704 gen_load_fpr64(ctx, fp1, ft);
12705 gen_load_fpr64(ctx, fp2, fr);
12706 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
12707 tcg_temp_free_i64(fp0);
12708 tcg_temp_free_i64(fp1);
12709 gen_store_fpr64(ctx, fp2, fd);
12710 tcg_temp_free_i64(fp2);
12712 break;
12713 case OPC_NMADD_PS:
12714 check_ps(ctx);
12716 TCGv_i64 fp0 = tcg_temp_new_i64();
12717 TCGv_i64 fp1 = tcg_temp_new_i64();
12718 TCGv_i64 fp2 = tcg_temp_new_i64();
12720 gen_load_fpr64(ctx, fp0, fs);
12721 gen_load_fpr64(ctx, fp1, ft);
12722 gen_load_fpr64(ctx, fp2, fr);
12723 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
12724 tcg_temp_free_i64(fp0);
12725 tcg_temp_free_i64(fp1);
12726 gen_store_fpr64(ctx, fp2, fd);
12727 tcg_temp_free_i64(fp2);
12729 break;
12730 case OPC_NMSUB_S:
12731 check_cop1x(ctx);
12733 TCGv_i32 fp0 = tcg_temp_new_i32();
12734 TCGv_i32 fp1 = tcg_temp_new_i32();
12735 TCGv_i32 fp2 = tcg_temp_new_i32();
12737 gen_load_fpr32(ctx, fp0, fs);
12738 gen_load_fpr32(ctx, fp1, ft);
12739 gen_load_fpr32(ctx, fp2, fr);
12740 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
12741 tcg_temp_free_i32(fp0);
12742 tcg_temp_free_i32(fp1);
12743 gen_store_fpr32(ctx, fp2, fd);
12744 tcg_temp_free_i32(fp2);
12746 break;
12747 case OPC_NMSUB_D:
12748 check_cop1x(ctx);
12749 check_cp1_registers(ctx, fd | fs | ft | fr);
12751 TCGv_i64 fp0 = tcg_temp_new_i64();
12752 TCGv_i64 fp1 = tcg_temp_new_i64();
12753 TCGv_i64 fp2 = tcg_temp_new_i64();
12755 gen_load_fpr64(ctx, fp0, fs);
12756 gen_load_fpr64(ctx, fp1, ft);
12757 gen_load_fpr64(ctx, fp2, fr);
12758 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
12759 tcg_temp_free_i64(fp0);
12760 tcg_temp_free_i64(fp1);
12761 gen_store_fpr64(ctx, fp2, fd);
12762 tcg_temp_free_i64(fp2);
12764 break;
12765 case OPC_NMSUB_PS:
12766 check_ps(ctx);
12768 TCGv_i64 fp0 = tcg_temp_new_i64();
12769 TCGv_i64 fp1 = tcg_temp_new_i64();
12770 TCGv_i64 fp2 = tcg_temp_new_i64();
12772 gen_load_fpr64(ctx, fp0, fs);
12773 gen_load_fpr64(ctx, fp1, ft);
12774 gen_load_fpr64(ctx, fp2, fr);
12775 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
12776 tcg_temp_free_i64(fp0);
12777 tcg_temp_free_i64(fp1);
12778 gen_store_fpr64(ctx, fp2, fd);
12779 tcg_temp_free_i64(fp2);
12781 break;
12782 default:
12783 MIPS_INVAL("flt3_arith");
12784 generate_exception_end(ctx, EXCP_RI);
12785 return;
12789 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
12791 TCGv t0;
12793 #if !defined(CONFIG_USER_ONLY)
12795 * The Linux kernel will emulate rdhwr if it's not supported natively.
12796 * Therefore only check the ISA in system mode.
12798 check_insn(ctx, ISA_MIPS32R2);
12799 #endif
12800 t0 = tcg_temp_new();
12802 switch (rd) {
12803 case 0:
12804 gen_helper_rdhwr_cpunum(t0, cpu_env);
12805 gen_store_gpr(t0, rt);
12806 break;
12807 case 1:
12808 gen_helper_rdhwr_synci_step(t0, cpu_env);
12809 gen_store_gpr(t0, rt);
12810 break;
12811 case 2:
12812 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12813 gen_io_start();
12815 gen_helper_rdhwr_cc(t0, cpu_env);
12816 gen_store_gpr(t0, rt);
12818 * Break the TB to be able to take timer interrupts immediately
12819 * after reading count. DISAS_STOP isn't sufficient, we need to ensure
12820 * we break completely out of translated code.
12822 gen_save_pc(ctx->base.pc_next + 4);
12823 ctx->base.is_jmp = DISAS_EXIT;
12824 break;
12825 case 3:
12826 gen_helper_rdhwr_ccres(t0, cpu_env);
12827 gen_store_gpr(t0, rt);
12828 break;
12829 case 4:
12830 check_insn(ctx, ISA_MIPS32R6);
12831 if (sel != 0) {
12833 * Performance counter registers are not implemented other than
12834 * control register 0.
12836 generate_exception(ctx, EXCP_RI);
12838 gen_helper_rdhwr_performance(t0, cpu_env);
12839 gen_store_gpr(t0, rt);
12840 break;
12841 case 5:
12842 check_insn(ctx, ISA_MIPS32R6);
12843 gen_helper_rdhwr_xnp(t0, cpu_env);
12844 gen_store_gpr(t0, rt);
12845 break;
12846 case 29:
12847 #if defined(CONFIG_USER_ONLY)
12848 tcg_gen_ld_tl(t0, cpu_env,
12849 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12850 gen_store_gpr(t0, rt);
12851 break;
12852 #else
12853 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
12854 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
12855 tcg_gen_ld_tl(t0, cpu_env,
12856 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12857 gen_store_gpr(t0, rt);
12858 } else {
12859 generate_exception_end(ctx, EXCP_RI);
12861 break;
12862 #endif
12863 default: /* Invalid */
12864 MIPS_INVAL("rdhwr");
12865 generate_exception_end(ctx, EXCP_RI);
12866 break;
12868 tcg_temp_free(t0);
12871 static inline void clear_branch_hflags(DisasContext *ctx)
12873 ctx->hflags &= ~MIPS_HFLAG_BMASK;
12874 if (ctx->base.is_jmp == DISAS_NEXT) {
12875 save_cpu_state(ctx, 0);
12876 } else {
12878 * It is not safe to save ctx->hflags as hflags may be changed
12879 * in execution time by the instruction in delay / forbidden slot.
12881 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
12885 static void gen_branch(DisasContext *ctx, int insn_bytes)
12887 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12888 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
12889 /* Branches completion */
12890 clear_branch_hflags(ctx);
12891 ctx->base.is_jmp = DISAS_NORETURN;
12892 /* FIXME: Need to clear can_do_io. */
12893 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
12894 case MIPS_HFLAG_FBNSLOT:
12895 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
12896 break;
12897 case MIPS_HFLAG_B:
12898 /* unconditional branch */
12899 if (proc_hflags & MIPS_HFLAG_BX) {
12900 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
12902 gen_goto_tb(ctx, 0, ctx->btarget);
12903 break;
12904 case MIPS_HFLAG_BL:
12905 /* blikely taken case */
12906 gen_goto_tb(ctx, 0, ctx->btarget);
12907 break;
12908 case MIPS_HFLAG_BC:
12909 /* Conditional branch */
12911 TCGLabel *l1 = gen_new_label();
12913 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
12914 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
12915 gen_set_label(l1);
12916 gen_goto_tb(ctx, 0, ctx->btarget);
12918 break;
12919 case MIPS_HFLAG_BR:
12920 /* unconditional branch to register */
12921 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
12922 TCGv t0 = tcg_temp_new();
12923 TCGv_i32 t1 = tcg_temp_new_i32();
12925 tcg_gen_andi_tl(t0, btarget, 0x1);
12926 tcg_gen_trunc_tl_i32(t1, t0);
12927 tcg_temp_free(t0);
12928 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
12929 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
12930 tcg_gen_or_i32(hflags, hflags, t1);
12931 tcg_temp_free_i32(t1);
12933 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
12934 } else {
12935 tcg_gen_mov_tl(cpu_PC, btarget);
12937 if (ctx->base.singlestep_enabled) {
12938 save_cpu_state(ctx, 0);
12939 gen_helper_raise_exception_debug(cpu_env);
12941 tcg_gen_lookup_and_goto_ptr();
12942 break;
12943 default:
12944 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
12945 abort();
12950 /* Compact Branches */
12951 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
12952 int rs, int rt, int32_t offset)
12954 int bcond_compute = 0;
12955 TCGv t0 = tcg_temp_new();
12956 TCGv t1 = tcg_temp_new();
12957 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
12959 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12960 #ifdef MIPS_DEBUG_DISAS
12961 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
12962 "\n", ctx->base.pc_next);
12963 #endif
12964 generate_exception_end(ctx, EXCP_RI);
12965 goto out;
12968 /* Load needed operands and calculate btarget */
12969 switch (opc) {
12970 /* compact branch */
12971 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12972 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12973 gen_load_gpr(t0, rs);
12974 gen_load_gpr(t1, rt);
12975 bcond_compute = 1;
12976 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12977 if (rs <= rt && rs == 0) {
12978 /* OPC_BEQZALC, OPC_BNEZALC */
12979 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12981 break;
12982 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12983 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12984 gen_load_gpr(t0, rs);
12985 gen_load_gpr(t1, rt);
12986 bcond_compute = 1;
12987 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12988 break;
12989 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12990 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12991 if (rs == 0 || rs == rt) {
12992 /* OPC_BLEZALC, OPC_BGEZALC */
12993 /* OPC_BGTZALC, OPC_BLTZALC */
12994 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12996 gen_load_gpr(t0, rs);
12997 gen_load_gpr(t1, rt);
12998 bcond_compute = 1;
12999 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13000 break;
13001 case OPC_BC:
13002 case OPC_BALC:
13003 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13004 break;
13005 case OPC_BEQZC:
13006 case OPC_BNEZC:
13007 if (rs != 0) {
13008 /* OPC_BEQZC, OPC_BNEZC */
13009 gen_load_gpr(t0, rs);
13010 bcond_compute = 1;
13011 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13012 } else {
13013 /* OPC_JIC, OPC_JIALC */
13014 TCGv tbase = tcg_temp_new();
13015 TCGv toffset = tcg_temp_new();
13017 gen_load_gpr(tbase, rt);
13018 tcg_gen_movi_tl(toffset, offset);
13019 gen_op_addr_add(ctx, btarget, tbase, toffset);
13020 tcg_temp_free(tbase);
13021 tcg_temp_free(toffset);
13023 break;
13024 default:
13025 MIPS_INVAL("Compact branch/jump");
13026 generate_exception_end(ctx, EXCP_RI);
13027 goto out;
13030 if (bcond_compute == 0) {
13031 /* Uncoditional compact branch */
13032 switch (opc) {
13033 case OPC_JIALC:
13034 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13035 /* Fallthrough */
13036 case OPC_JIC:
13037 ctx->hflags |= MIPS_HFLAG_BR;
13038 break;
13039 case OPC_BALC:
13040 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13041 /* Fallthrough */
13042 case OPC_BC:
13043 ctx->hflags |= MIPS_HFLAG_B;
13044 break;
13045 default:
13046 MIPS_INVAL("Compact branch/jump");
13047 generate_exception_end(ctx, EXCP_RI);
13048 goto out;
13051 /* Generating branch here as compact branches don't have delay slot */
13052 gen_branch(ctx, 4);
13053 } else {
13054 /* Conditional compact branch */
13055 TCGLabel *fs = gen_new_label();
13056 save_cpu_state(ctx, 0);
13058 switch (opc) {
13059 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13060 if (rs == 0 && rt != 0) {
13061 /* OPC_BLEZALC */
13062 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13063 } else if (rs != 0 && rt != 0 && rs == rt) {
13064 /* OPC_BGEZALC */
13065 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13066 } else {
13067 /* OPC_BGEUC */
13068 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
13070 break;
13071 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13072 if (rs == 0 && rt != 0) {
13073 /* OPC_BGTZALC */
13074 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13075 } else if (rs != 0 && rt != 0 && rs == rt) {
13076 /* OPC_BLTZALC */
13077 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13078 } else {
13079 /* OPC_BLTUC */
13080 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
13082 break;
13083 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13084 if (rs == 0 && rt != 0) {
13085 /* OPC_BLEZC */
13086 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13087 } else if (rs != 0 && rt != 0 && rs == rt) {
13088 /* OPC_BGEZC */
13089 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13090 } else {
13091 /* OPC_BGEC */
13092 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
13094 break;
13095 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13096 if (rs == 0 && rt != 0) {
13097 /* OPC_BGTZC */
13098 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13099 } else if (rs != 0 && rt != 0 && rs == rt) {
13100 /* OPC_BLTZC */
13101 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13102 } else {
13103 /* OPC_BLTC */
13104 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
13106 break;
13107 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13108 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13109 if (rs >= rt) {
13110 /* OPC_BOVC, OPC_BNVC */
13111 TCGv t2 = tcg_temp_new();
13112 TCGv t3 = tcg_temp_new();
13113 TCGv t4 = tcg_temp_new();
13114 TCGv input_overflow = tcg_temp_new();
13116 gen_load_gpr(t0, rs);
13117 gen_load_gpr(t1, rt);
13118 tcg_gen_ext32s_tl(t2, t0);
13119 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
13120 tcg_gen_ext32s_tl(t3, t1);
13121 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
13122 tcg_gen_or_tl(input_overflow, input_overflow, t4);
13124 tcg_gen_add_tl(t4, t2, t3);
13125 tcg_gen_ext32s_tl(t4, t4);
13126 tcg_gen_xor_tl(t2, t2, t3);
13127 tcg_gen_xor_tl(t3, t4, t3);
13128 tcg_gen_andc_tl(t2, t3, t2);
13129 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
13130 tcg_gen_or_tl(t4, t4, input_overflow);
13131 if (opc == OPC_BOVC) {
13132 /* OPC_BOVC */
13133 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
13134 } else {
13135 /* OPC_BNVC */
13136 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
13138 tcg_temp_free(input_overflow);
13139 tcg_temp_free(t4);
13140 tcg_temp_free(t3);
13141 tcg_temp_free(t2);
13142 } else if (rs < rt && rs == 0) {
13143 /* OPC_BEQZALC, OPC_BNEZALC */
13144 if (opc == OPC_BEQZALC) {
13145 /* OPC_BEQZALC */
13146 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
13147 } else {
13148 /* OPC_BNEZALC */
13149 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
13151 } else {
13152 /* OPC_BEQC, OPC_BNEC */
13153 if (opc == OPC_BEQC) {
13154 /* OPC_BEQC */
13155 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
13156 } else {
13157 /* OPC_BNEC */
13158 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
13161 break;
13162 case OPC_BEQZC:
13163 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
13164 break;
13165 case OPC_BNEZC:
13166 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
13167 break;
13168 default:
13169 MIPS_INVAL("Compact conditional branch/jump");
13170 generate_exception_end(ctx, EXCP_RI);
13171 goto out;
13174 /* Generating branch here as compact branches don't have delay slot */
13175 gen_goto_tb(ctx, 1, ctx->btarget);
13176 gen_set_label(fs);
13178 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
13181 out:
13182 tcg_temp_free(t0);
13183 tcg_temp_free(t1);
13186 /* ISA extensions (ASEs) */
13187 /* MIPS16 extension to MIPS32 */
13189 /* MIPS16 major opcodes */
13190 enum {
13191 M16_OPC_ADDIUSP = 0x00,
13192 M16_OPC_ADDIUPC = 0x01,
13193 M16_OPC_B = 0x02,
13194 M16_OPC_JAL = 0x03,
13195 M16_OPC_BEQZ = 0x04,
13196 M16_OPC_BNEQZ = 0x05,
13197 M16_OPC_SHIFT = 0x06,
13198 M16_OPC_LD = 0x07,
13199 M16_OPC_RRIA = 0x08,
13200 M16_OPC_ADDIU8 = 0x09,
13201 M16_OPC_SLTI = 0x0a,
13202 M16_OPC_SLTIU = 0x0b,
13203 M16_OPC_I8 = 0x0c,
13204 M16_OPC_LI = 0x0d,
13205 M16_OPC_CMPI = 0x0e,
13206 M16_OPC_SD = 0x0f,
13207 M16_OPC_LB = 0x10,
13208 M16_OPC_LH = 0x11,
13209 M16_OPC_LWSP = 0x12,
13210 M16_OPC_LW = 0x13,
13211 M16_OPC_LBU = 0x14,
13212 M16_OPC_LHU = 0x15,
13213 M16_OPC_LWPC = 0x16,
13214 M16_OPC_LWU = 0x17,
13215 M16_OPC_SB = 0x18,
13216 M16_OPC_SH = 0x19,
13217 M16_OPC_SWSP = 0x1a,
13218 M16_OPC_SW = 0x1b,
13219 M16_OPC_RRR = 0x1c,
13220 M16_OPC_RR = 0x1d,
13221 M16_OPC_EXTEND = 0x1e,
13222 M16_OPC_I64 = 0x1f
13225 /* I8 funct field */
13226 enum {
13227 I8_BTEQZ = 0x0,
13228 I8_BTNEZ = 0x1,
13229 I8_SWRASP = 0x2,
13230 I8_ADJSP = 0x3,
13231 I8_SVRS = 0x4,
13232 I8_MOV32R = 0x5,
13233 I8_MOVR32 = 0x7
13236 /* RRR f field */
13237 enum {
13238 RRR_DADDU = 0x0,
13239 RRR_ADDU = 0x1,
13240 RRR_DSUBU = 0x2,
13241 RRR_SUBU = 0x3
13244 /* RR funct field */
13245 enum {
13246 RR_JR = 0x00,
13247 RR_SDBBP = 0x01,
13248 RR_SLT = 0x02,
13249 RR_SLTU = 0x03,
13250 RR_SLLV = 0x04,
13251 RR_BREAK = 0x05,
13252 RR_SRLV = 0x06,
13253 RR_SRAV = 0x07,
13254 RR_DSRL = 0x08,
13255 RR_CMP = 0x0a,
13256 RR_NEG = 0x0b,
13257 RR_AND = 0x0c,
13258 RR_OR = 0x0d,
13259 RR_XOR = 0x0e,
13260 RR_NOT = 0x0f,
13261 RR_MFHI = 0x10,
13262 RR_CNVT = 0x11,
13263 RR_MFLO = 0x12,
13264 RR_DSRA = 0x13,
13265 RR_DSLLV = 0x14,
13266 RR_DSRLV = 0x16,
13267 RR_DSRAV = 0x17,
13268 RR_MULT = 0x18,
13269 RR_MULTU = 0x19,
13270 RR_DIV = 0x1a,
13271 RR_DIVU = 0x1b,
13272 RR_DMULT = 0x1c,
13273 RR_DMULTU = 0x1d,
13274 RR_DDIV = 0x1e,
13275 RR_DDIVU = 0x1f
13278 /* I64 funct field */
13279 enum {
13280 I64_LDSP = 0x0,
13281 I64_SDSP = 0x1,
13282 I64_SDRASP = 0x2,
13283 I64_DADJSP = 0x3,
13284 I64_LDPC = 0x4,
13285 I64_DADDIU5 = 0x5,
13286 I64_DADDIUPC = 0x6,
13287 I64_DADDIUSP = 0x7
13290 /* RR ry field for CNVT */
13291 enum {
13292 RR_RY_CNVT_ZEB = 0x0,
13293 RR_RY_CNVT_ZEH = 0x1,
13294 RR_RY_CNVT_ZEW = 0x2,
13295 RR_RY_CNVT_SEB = 0x4,
13296 RR_RY_CNVT_SEH = 0x5,
13297 RR_RY_CNVT_SEW = 0x6,
13300 static int xlat(int r)
13302 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
13304 return map[r];
13307 static void gen_mips16_save(DisasContext *ctx,
13308 int xsregs, int aregs,
13309 int do_ra, int do_s0, int do_s1,
13310 int framesize)
13312 TCGv t0 = tcg_temp_new();
13313 TCGv t1 = tcg_temp_new();
13314 TCGv t2 = tcg_temp_new();
13315 int args, astatic;
13317 switch (aregs) {
13318 case 0:
13319 case 1:
13320 case 2:
13321 case 3:
13322 case 11:
13323 args = 0;
13324 break;
13325 case 4:
13326 case 5:
13327 case 6:
13328 case 7:
13329 args = 1;
13330 break;
13331 case 8:
13332 case 9:
13333 case 10:
13334 args = 2;
13335 break;
13336 case 12:
13337 case 13:
13338 args = 3;
13339 break;
13340 case 14:
13341 args = 4;
13342 break;
13343 default:
13344 generate_exception_end(ctx, EXCP_RI);
13345 return;
13348 switch (args) {
13349 case 4:
13350 gen_base_offset_addr(ctx, t0, 29, 12);
13351 gen_load_gpr(t1, 7);
13352 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13353 /* Fall through */
13354 case 3:
13355 gen_base_offset_addr(ctx, t0, 29, 8);
13356 gen_load_gpr(t1, 6);
13357 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13358 /* Fall through */
13359 case 2:
13360 gen_base_offset_addr(ctx, t0, 29, 4);
13361 gen_load_gpr(t1, 5);
13362 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13363 /* Fall through */
13364 case 1:
13365 gen_base_offset_addr(ctx, t0, 29, 0);
13366 gen_load_gpr(t1, 4);
13367 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13370 gen_load_gpr(t0, 29);
13372 #define DECR_AND_STORE(reg) do { \
13373 tcg_gen_movi_tl(t2, -4); \
13374 gen_op_addr_add(ctx, t0, t0, t2); \
13375 gen_load_gpr(t1, reg); \
13376 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
13377 } while (0)
13379 if (do_ra) {
13380 DECR_AND_STORE(31);
13383 switch (xsregs) {
13384 case 7:
13385 DECR_AND_STORE(30);
13386 /* Fall through */
13387 case 6:
13388 DECR_AND_STORE(23);
13389 /* Fall through */
13390 case 5:
13391 DECR_AND_STORE(22);
13392 /* Fall through */
13393 case 4:
13394 DECR_AND_STORE(21);
13395 /* Fall through */
13396 case 3:
13397 DECR_AND_STORE(20);
13398 /* Fall through */
13399 case 2:
13400 DECR_AND_STORE(19);
13401 /* Fall through */
13402 case 1:
13403 DECR_AND_STORE(18);
13406 if (do_s1) {
13407 DECR_AND_STORE(17);
13409 if (do_s0) {
13410 DECR_AND_STORE(16);
13413 switch (aregs) {
13414 case 0:
13415 case 4:
13416 case 8:
13417 case 12:
13418 case 14:
13419 astatic = 0;
13420 break;
13421 case 1:
13422 case 5:
13423 case 9:
13424 case 13:
13425 astatic = 1;
13426 break;
13427 case 2:
13428 case 6:
13429 case 10:
13430 astatic = 2;
13431 break;
13432 case 3:
13433 case 7:
13434 astatic = 3;
13435 break;
13436 case 11:
13437 astatic = 4;
13438 break;
13439 default:
13440 generate_exception_end(ctx, EXCP_RI);
13441 return;
13444 if (astatic > 0) {
13445 DECR_AND_STORE(7);
13446 if (astatic > 1) {
13447 DECR_AND_STORE(6);
13448 if (astatic > 2) {
13449 DECR_AND_STORE(5);
13450 if (astatic > 3) {
13451 DECR_AND_STORE(4);
13456 #undef DECR_AND_STORE
13458 tcg_gen_movi_tl(t2, -framesize);
13459 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13460 tcg_temp_free(t0);
13461 tcg_temp_free(t1);
13462 tcg_temp_free(t2);
13465 static void gen_mips16_restore(DisasContext *ctx,
13466 int xsregs, int aregs,
13467 int do_ra, int do_s0, int do_s1,
13468 int framesize)
13470 int astatic;
13471 TCGv t0 = tcg_temp_new();
13472 TCGv t1 = tcg_temp_new();
13473 TCGv t2 = tcg_temp_new();
13475 tcg_gen_movi_tl(t2, framesize);
13476 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
13478 #define DECR_AND_LOAD(reg) do { \
13479 tcg_gen_movi_tl(t2, -4); \
13480 gen_op_addr_add(ctx, t0, t0, t2); \
13481 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
13482 gen_store_gpr(t1, reg); \
13483 } while (0)
13485 if (do_ra) {
13486 DECR_AND_LOAD(31);
13489 switch (xsregs) {
13490 case 7:
13491 DECR_AND_LOAD(30);
13492 /* Fall through */
13493 case 6:
13494 DECR_AND_LOAD(23);
13495 /* Fall through */
13496 case 5:
13497 DECR_AND_LOAD(22);
13498 /* Fall through */
13499 case 4:
13500 DECR_AND_LOAD(21);
13501 /* Fall through */
13502 case 3:
13503 DECR_AND_LOAD(20);
13504 /* Fall through */
13505 case 2:
13506 DECR_AND_LOAD(19);
13507 /* Fall through */
13508 case 1:
13509 DECR_AND_LOAD(18);
13512 if (do_s1) {
13513 DECR_AND_LOAD(17);
13515 if (do_s0) {
13516 DECR_AND_LOAD(16);
13519 switch (aregs) {
13520 case 0:
13521 case 4:
13522 case 8:
13523 case 12:
13524 case 14:
13525 astatic = 0;
13526 break;
13527 case 1:
13528 case 5:
13529 case 9:
13530 case 13:
13531 astatic = 1;
13532 break;
13533 case 2:
13534 case 6:
13535 case 10:
13536 astatic = 2;
13537 break;
13538 case 3:
13539 case 7:
13540 astatic = 3;
13541 break;
13542 case 11:
13543 astatic = 4;
13544 break;
13545 default:
13546 generate_exception_end(ctx, EXCP_RI);
13547 return;
13550 if (astatic > 0) {
13551 DECR_AND_LOAD(7);
13552 if (astatic > 1) {
13553 DECR_AND_LOAD(6);
13554 if (astatic > 2) {
13555 DECR_AND_LOAD(5);
13556 if (astatic > 3) {
13557 DECR_AND_LOAD(4);
13562 #undef DECR_AND_LOAD
13564 tcg_gen_movi_tl(t2, framesize);
13565 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13566 tcg_temp_free(t0);
13567 tcg_temp_free(t1);
13568 tcg_temp_free(t2);
13571 static void gen_addiupc(DisasContext *ctx, int rx, int imm,
13572 int is_64_bit, int extended)
13574 TCGv t0;
13576 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13577 generate_exception_end(ctx, EXCP_RI);
13578 return;
13581 t0 = tcg_temp_new();
13583 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
13584 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
13585 if (!is_64_bit) {
13586 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13589 tcg_temp_free(t0);
13592 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
13593 int16_t offset)
13595 TCGv_i32 t0 = tcg_const_i32(op);
13596 TCGv t1 = tcg_temp_new();
13597 gen_base_offset_addr(ctx, t1, base, offset);
13598 gen_helper_cache(cpu_env, t1, t0);
13601 #if defined(TARGET_MIPS64)
13602 static void decode_i64_mips16(DisasContext *ctx,
13603 int ry, int funct, int16_t offset,
13604 int extended)
13606 switch (funct) {
13607 case I64_LDSP:
13608 check_insn(ctx, ISA_MIPS3);
13609 check_mips_64(ctx);
13610 offset = extended ? offset : offset << 3;
13611 gen_ld(ctx, OPC_LD, ry, 29, offset);
13612 break;
13613 case I64_SDSP:
13614 check_insn(ctx, ISA_MIPS3);
13615 check_mips_64(ctx);
13616 offset = extended ? offset : offset << 3;
13617 gen_st(ctx, OPC_SD, ry, 29, offset);
13618 break;
13619 case I64_SDRASP:
13620 check_insn(ctx, ISA_MIPS3);
13621 check_mips_64(ctx);
13622 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
13623 gen_st(ctx, OPC_SD, 31, 29, offset);
13624 break;
13625 case I64_DADJSP:
13626 check_insn(ctx, ISA_MIPS3);
13627 check_mips_64(ctx);
13628 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
13629 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
13630 break;
13631 case I64_LDPC:
13632 check_insn(ctx, ISA_MIPS3);
13633 check_mips_64(ctx);
13634 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13635 generate_exception_end(ctx, EXCP_RI);
13636 } else {
13637 offset = extended ? offset : offset << 3;
13638 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
13640 break;
13641 case I64_DADDIU5:
13642 check_insn(ctx, ISA_MIPS3);
13643 check_mips_64(ctx);
13644 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
13645 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
13646 break;
13647 case I64_DADDIUPC:
13648 check_insn(ctx, ISA_MIPS3);
13649 check_mips_64(ctx);
13650 offset = extended ? offset : offset << 2;
13651 gen_addiupc(ctx, ry, offset, 1, extended);
13652 break;
13653 case I64_DADDIUSP:
13654 check_insn(ctx, ISA_MIPS3);
13655 check_mips_64(ctx);
13656 offset = extended ? offset : offset << 2;
13657 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
13658 break;
13661 #endif
13663 static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
13665 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
13666 int op, rx, ry, funct, sa;
13667 int16_t imm, offset;
13669 ctx->opcode = (ctx->opcode << 16) | extend;
13670 op = (ctx->opcode >> 11) & 0x1f;
13671 sa = (ctx->opcode >> 22) & 0x1f;
13672 funct = (ctx->opcode >> 8) & 0x7;
13673 rx = xlat((ctx->opcode >> 8) & 0x7);
13674 ry = xlat((ctx->opcode >> 5) & 0x7);
13675 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
13676 | ((ctx->opcode >> 21) & 0x3f) << 5
13677 | (ctx->opcode & 0x1f));
13680 * The extended opcodes cleverly reuse the opcodes from their 16-bit
13681 * counterparts.
13683 switch (op) {
13684 case M16_OPC_ADDIUSP:
13685 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13686 break;
13687 case M16_OPC_ADDIUPC:
13688 gen_addiupc(ctx, rx, imm, 0, 1);
13689 break;
13690 case M16_OPC_B:
13691 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
13692 /* No delay slot, so just process as a normal instruction */
13693 break;
13694 case M16_OPC_BEQZ:
13695 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
13696 /* No delay slot, so just process as a normal instruction */
13697 break;
13698 case M16_OPC_BNEQZ:
13699 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
13700 /* No delay slot, so just process as a normal instruction */
13701 break;
13702 case M16_OPC_SHIFT:
13703 switch (ctx->opcode & 0x3) {
13704 case 0x0:
13705 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13706 break;
13707 case 0x1:
13708 #if defined(TARGET_MIPS64)
13709 check_mips_64(ctx);
13710 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13711 #else
13712 generate_exception_end(ctx, EXCP_RI);
13713 #endif
13714 break;
13715 case 0x2:
13716 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13717 break;
13718 case 0x3:
13719 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13720 break;
13722 break;
13723 #if defined(TARGET_MIPS64)
13724 case M16_OPC_LD:
13725 check_insn(ctx, ISA_MIPS3);
13726 check_mips_64(ctx);
13727 gen_ld(ctx, OPC_LD, ry, rx, offset);
13728 break;
13729 #endif
13730 case M16_OPC_RRIA:
13731 imm = ctx->opcode & 0xf;
13732 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
13733 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
13734 imm = (int16_t) (imm << 1) >> 1;
13735 if ((ctx->opcode >> 4) & 0x1) {
13736 #if defined(TARGET_MIPS64)
13737 check_mips_64(ctx);
13738 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13739 #else
13740 generate_exception_end(ctx, EXCP_RI);
13741 #endif
13742 } else {
13743 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13745 break;
13746 case M16_OPC_ADDIU8:
13747 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13748 break;
13749 case M16_OPC_SLTI:
13750 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13751 break;
13752 case M16_OPC_SLTIU:
13753 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13754 break;
13755 case M16_OPC_I8:
13756 switch (funct) {
13757 case I8_BTEQZ:
13758 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
13759 break;
13760 case I8_BTNEZ:
13761 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
13762 break;
13763 case I8_SWRASP:
13764 gen_st(ctx, OPC_SW, 31, 29, imm);
13765 break;
13766 case I8_ADJSP:
13767 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
13768 break;
13769 case I8_SVRS:
13770 check_insn(ctx, ISA_MIPS32);
13772 int xsregs = (ctx->opcode >> 24) & 0x7;
13773 int aregs = (ctx->opcode >> 16) & 0xf;
13774 int do_ra = (ctx->opcode >> 6) & 0x1;
13775 int do_s0 = (ctx->opcode >> 5) & 0x1;
13776 int do_s1 = (ctx->opcode >> 4) & 0x1;
13777 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
13778 | (ctx->opcode & 0xf)) << 3;
13780 if (ctx->opcode & (1 << 7)) {
13781 gen_mips16_save(ctx, xsregs, aregs,
13782 do_ra, do_s0, do_s1,
13783 framesize);
13784 } else {
13785 gen_mips16_restore(ctx, xsregs, aregs,
13786 do_ra, do_s0, do_s1,
13787 framesize);
13790 break;
13791 default:
13792 generate_exception_end(ctx, EXCP_RI);
13793 break;
13795 break;
13796 case M16_OPC_LI:
13797 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
13798 break;
13799 case M16_OPC_CMPI:
13800 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
13801 break;
13802 #if defined(TARGET_MIPS64)
13803 case M16_OPC_SD:
13804 check_insn(ctx, ISA_MIPS3);
13805 check_mips_64(ctx);
13806 gen_st(ctx, OPC_SD, ry, rx, offset);
13807 break;
13808 #endif
13809 case M16_OPC_LB:
13810 gen_ld(ctx, OPC_LB, ry, rx, offset);
13811 break;
13812 case M16_OPC_LH:
13813 gen_ld(ctx, OPC_LH, ry, rx, offset);
13814 break;
13815 case M16_OPC_LWSP:
13816 gen_ld(ctx, OPC_LW, rx, 29, offset);
13817 break;
13818 case M16_OPC_LW:
13819 gen_ld(ctx, OPC_LW, ry, rx, offset);
13820 break;
13821 case M16_OPC_LBU:
13822 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13823 break;
13824 case M16_OPC_LHU:
13825 gen_ld(ctx, OPC_LHU, ry, rx, offset);
13826 break;
13827 case M16_OPC_LWPC:
13828 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
13829 break;
13830 #if defined(TARGET_MIPS64)
13831 case M16_OPC_LWU:
13832 check_insn(ctx, ISA_MIPS3);
13833 check_mips_64(ctx);
13834 gen_ld(ctx, OPC_LWU, ry, rx, offset);
13835 break;
13836 #endif
13837 case M16_OPC_SB:
13838 gen_st(ctx, OPC_SB, ry, rx, offset);
13839 break;
13840 case M16_OPC_SH:
13841 gen_st(ctx, OPC_SH, ry, rx, offset);
13842 break;
13843 case M16_OPC_SWSP:
13844 gen_st(ctx, OPC_SW, rx, 29, offset);
13845 break;
13846 case M16_OPC_SW:
13847 gen_st(ctx, OPC_SW, ry, rx, offset);
13848 break;
13849 #if defined(TARGET_MIPS64)
13850 case M16_OPC_I64:
13851 decode_i64_mips16(ctx, ry, funct, offset, 1);
13852 break;
13853 #endif
13854 default:
13855 generate_exception_end(ctx, EXCP_RI);
13856 break;
13859 return 4;
13862 static inline bool is_uhi(int sdbbp_code)
13864 #ifdef CONFIG_USER_ONLY
13865 return false;
13866 #else
13867 return semihosting_enabled() && sdbbp_code == 1;
13868 #endif
13871 #ifdef CONFIG_USER_ONLY
13872 /* The above should dead-code away any calls to this..*/
13873 static inline void gen_helper_do_semihosting(void *env)
13875 g_assert_not_reached();
13877 #endif
13879 static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
13881 int rx, ry;
13882 int sa;
13883 int op, cnvt_op, op1, offset;
13884 int funct;
13885 int n_bytes;
13887 op = (ctx->opcode >> 11) & 0x1f;
13888 sa = (ctx->opcode >> 2) & 0x7;
13889 sa = sa == 0 ? 8 : sa;
13890 rx = xlat((ctx->opcode >> 8) & 0x7);
13891 cnvt_op = (ctx->opcode >> 5) & 0x7;
13892 ry = xlat((ctx->opcode >> 5) & 0x7);
13893 op1 = offset = ctx->opcode & 0x1f;
13895 n_bytes = 2;
13897 switch (op) {
13898 case M16_OPC_ADDIUSP:
13900 int16_t imm = ((uint8_t) ctx->opcode) << 2;
13902 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13904 break;
13905 case M16_OPC_ADDIUPC:
13906 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
13907 break;
13908 case M16_OPC_B:
13909 offset = (ctx->opcode & 0x7ff) << 1;
13910 offset = (int16_t)(offset << 4) >> 4;
13911 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
13912 /* No delay slot, so just process as a normal instruction */
13913 break;
13914 case M16_OPC_JAL:
13915 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
13916 offset = (((ctx->opcode & 0x1f) << 21)
13917 | ((ctx->opcode >> 5) & 0x1f) << 16
13918 | offset) << 2;
13919 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
13920 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
13921 n_bytes = 4;
13922 break;
13923 case M16_OPC_BEQZ:
13924 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
13925 ((int8_t)ctx->opcode) << 1, 0);
13926 /* No delay slot, so just process as a normal instruction */
13927 break;
13928 case M16_OPC_BNEQZ:
13929 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
13930 ((int8_t)ctx->opcode) << 1, 0);
13931 /* No delay slot, so just process as a normal instruction */
13932 break;
13933 case M16_OPC_SHIFT:
13934 switch (ctx->opcode & 0x3) {
13935 case 0x0:
13936 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13937 break;
13938 case 0x1:
13939 #if defined(TARGET_MIPS64)
13940 check_insn(ctx, ISA_MIPS3);
13941 check_mips_64(ctx);
13942 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13943 #else
13944 generate_exception_end(ctx, EXCP_RI);
13945 #endif
13946 break;
13947 case 0x2:
13948 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13949 break;
13950 case 0x3:
13951 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13952 break;
13954 break;
13955 #if defined(TARGET_MIPS64)
13956 case M16_OPC_LD:
13957 check_insn(ctx, ISA_MIPS3);
13958 check_mips_64(ctx);
13959 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
13960 break;
13961 #endif
13962 case M16_OPC_RRIA:
13964 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
13966 if ((ctx->opcode >> 4) & 1) {
13967 #if defined(TARGET_MIPS64)
13968 check_insn(ctx, ISA_MIPS3);
13969 check_mips_64(ctx);
13970 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13971 #else
13972 generate_exception_end(ctx, EXCP_RI);
13973 #endif
13974 } else {
13975 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13978 break;
13979 case M16_OPC_ADDIU8:
13981 int16_t imm = (int8_t) ctx->opcode;
13983 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13985 break;
13986 case M16_OPC_SLTI:
13988 int16_t imm = (uint8_t) ctx->opcode;
13989 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13991 break;
13992 case M16_OPC_SLTIU:
13994 int16_t imm = (uint8_t) ctx->opcode;
13995 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13997 break;
13998 case M16_OPC_I8:
14000 int reg32;
14002 funct = (ctx->opcode >> 8) & 0x7;
14003 switch (funct) {
14004 case I8_BTEQZ:
14005 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
14006 ((int8_t)ctx->opcode) << 1, 0);
14007 break;
14008 case I8_BTNEZ:
14009 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
14010 ((int8_t)ctx->opcode) << 1, 0);
14011 break;
14012 case I8_SWRASP:
14013 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
14014 break;
14015 case I8_ADJSP:
14016 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
14017 ((int8_t)ctx->opcode) << 3);
14018 break;
14019 case I8_SVRS:
14020 check_insn(ctx, ISA_MIPS32);
14022 int do_ra = ctx->opcode & (1 << 6);
14023 int do_s0 = ctx->opcode & (1 << 5);
14024 int do_s1 = ctx->opcode & (1 << 4);
14025 int framesize = ctx->opcode & 0xf;
14027 if (framesize == 0) {
14028 framesize = 128;
14029 } else {
14030 framesize = framesize << 3;
14033 if (ctx->opcode & (1 << 7)) {
14034 gen_mips16_save(ctx, 0, 0,
14035 do_ra, do_s0, do_s1, framesize);
14036 } else {
14037 gen_mips16_restore(ctx, 0, 0,
14038 do_ra, do_s0, do_s1, framesize);
14041 break;
14042 case I8_MOV32R:
14044 int rz = xlat(ctx->opcode & 0x7);
14046 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
14047 ((ctx->opcode >> 5) & 0x7);
14048 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
14050 break;
14051 case I8_MOVR32:
14052 reg32 = ctx->opcode & 0x1f;
14053 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
14054 break;
14055 default:
14056 generate_exception_end(ctx, EXCP_RI);
14057 break;
14060 break;
14061 case M16_OPC_LI:
14063 int16_t imm = (uint8_t) ctx->opcode;
14065 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
14067 break;
14068 case M16_OPC_CMPI:
14070 int16_t imm = (uint8_t) ctx->opcode;
14071 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
14073 break;
14074 #if defined(TARGET_MIPS64)
14075 case M16_OPC_SD:
14076 check_insn(ctx, ISA_MIPS3);
14077 check_mips_64(ctx);
14078 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
14079 break;
14080 #endif
14081 case M16_OPC_LB:
14082 gen_ld(ctx, OPC_LB, ry, rx, offset);
14083 break;
14084 case M16_OPC_LH:
14085 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
14086 break;
14087 case M16_OPC_LWSP:
14088 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14089 break;
14090 case M16_OPC_LW:
14091 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
14092 break;
14093 case M16_OPC_LBU:
14094 gen_ld(ctx, OPC_LBU, ry, rx, offset);
14095 break;
14096 case M16_OPC_LHU:
14097 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
14098 break;
14099 case M16_OPC_LWPC:
14100 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
14101 break;
14102 #if defined(TARGET_MIPS64)
14103 case M16_OPC_LWU:
14104 check_insn(ctx, ISA_MIPS3);
14105 check_mips_64(ctx);
14106 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
14107 break;
14108 #endif
14109 case M16_OPC_SB:
14110 gen_st(ctx, OPC_SB, ry, rx, offset);
14111 break;
14112 case M16_OPC_SH:
14113 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
14114 break;
14115 case M16_OPC_SWSP:
14116 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14117 break;
14118 case M16_OPC_SW:
14119 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
14120 break;
14121 case M16_OPC_RRR:
14123 int rz = xlat((ctx->opcode >> 2) & 0x7);
14124 int mips32_op;
14126 switch (ctx->opcode & 0x3) {
14127 case RRR_ADDU:
14128 mips32_op = OPC_ADDU;
14129 break;
14130 case RRR_SUBU:
14131 mips32_op = OPC_SUBU;
14132 break;
14133 #if defined(TARGET_MIPS64)
14134 case RRR_DADDU:
14135 mips32_op = OPC_DADDU;
14136 check_insn(ctx, ISA_MIPS3);
14137 check_mips_64(ctx);
14138 break;
14139 case RRR_DSUBU:
14140 mips32_op = OPC_DSUBU;
14141 check_insn(ctx, ISA_MIPS3);
14142 check_mips_64(ctx);
14143 break;
14144 #endif
14145 default:
14146 generate_exception_end(ctx, EXCP_RI);
14147 goto done;
14150 gen_arith(ctx, mips32_op, rz, rx, ry);
14151 done:
14154 break;
14155 case M16_OPC_RR:
14156 switch (op1) {
14157 case RR_JR:
14159 int nd = (ctx->opcode >> 7) & 0x1;
14160 int link = (ctx->opcode >> 6) & 0x1;
14161 int ra = (ctx->opcode >> 5) & 0x1;
14163 if (nd) {
14164 check_insn(ctx, ISA_MIPS32);
14167 if (link) {
14168 op = OPC_JALR;
14169 } else {
14170 op = OPC_JR;
14173 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
14174 (nd ? 0 : 2));
14176 break;
14177 case RR_SDBBP:
14178 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
14179 gen_helper_do_semihosting(cpu_env);
14180 } else {
14182 * XXX: not clear which exception should be raised
14183 * when in debug mode...
14185 check_insn(ctx, ISA_MIPS32);
14186 generate_exception_end(ctx, EXCP_DBp);
14188 break;
14189 case RR_SLT:
14190 gen_slt(ctx, OPC_SLT, 24, rx, ry);
14191 break;
14192 case RR_SLTU:
14193 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
14194 break;
14195 case RR_BREAK:
14196 generate_exception_end(ctx, EXCP_BREAK);
14197 break;
14198 case RR_SLLV:
14199 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
14200 break;
14201 case RR_SRLV:
14202 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
14203 break;
14204 case RR_SRAV:
14205 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
14206 break;
14207 #if defined(TARGET_MIPS64)
14208 case RR_DSRL:
14209 check_insn(ctx, ISA_MIPS3);
14210 check_mips_64(ctx);
14211 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
14212 break;
14213 #endif
14214 case RR_CMP:
14215 gen_logic(ctx, OPC_XOR, 24, rx, ry);
14216 break;
14217 case RR_NEG:
14218 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
14219 break;
14220 case RR_AND:
14221 gen_logic(ctx, OPC_AND, rx, rx, ry);
14222 break;
14223 case RR_OR:
14224 gen_logic(ctx, OPC_OR, rx, rx, ry);
14225 break;
14226 case RR_XOR:
14227 gen_logic(ctx, OPC_XOR, rx, rx, ry);
14228 break;
14229 case RR_NOT:
14230 gen_logic(ctx, OPC_NOR, rx, ry, 0);
14231 break;
14232 case RR_MFHI:
14233 gen_HILO(ctx, OPC_MFHI, 0, rx);
14234 break;
14235 case RR_CNVT:
14236 check_insn(ctx, ISA_MIPS32);
14237 switch (cnvt_op) {
14238 case RR_RY_CNVT_ZEB:
14239 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14240 break;
14241 case RR_RY_CNVT_ZEH:
14242 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14243 break;
14244 case RR_RY_CNVT_SEB:
14245 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14246 break;
14247 case RR_RY_CNVT_SEH:
14248 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14249 break;
14250 #if defined(TARGET_MIPS64)
14251 case RR_RY_CNVT_ZEW:
14252 check_insn(ctx, ISA_MIPS64);
14253 check_mips_64(ctx);
14254 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14255 break;
14256 case RR_RY_CNVT_SEW:
14257 check_insn(ctx, ISA_MIPS64);
14258 check_mips_64(ctx);
14259 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14260 break;
14261 #endif
14262 default:
14263 generate_exception_end(ctx, EXCP_RI);
14264 break;
14266 break;
14267 case RR_MFLO:
14268 gen_HILO(ctx, OPC_MFLO, 0, rx);
14269 break;
14270 #if defined(TARGET_MIPS64)
14271 case RR_DSRA:
14272 check_insn(ctx, ISA_MIPS3);
14273 check_mips_64(ctx);
14274 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
14275 break;
14276 case RR_DSLLV:
14277 check_insn(ctx, ISA_MIPS3);
14278 check_mips_64(ctx);
14279 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
14280 break;
14281 case RR_DSRLV:
14282 check_insn(ctx, ISA_MIPS3);
14283 check_mips_64(ctx);
14284 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
14285 break;
14286 case RR_DSRAV:
14287 check_insn(ctx, ISA_MIPS3);
14288 check_mips_64(ctx);
14289 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
14290 break;
14291 #endif
14292 case RR_MULT:
14293 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
14294 break;
14295 case RR_MULTU:
14296 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
14297 break;
14298 case RR_DIV:
14299 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
14300 break;
14301 case RR_DIVU:
14302 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
14303 break;
14304 #if defined(TARGET_MIPS64)
14305 case RR_DMULT:
14306 check_insn(ctx, ISA_MIPS3);
14307 check_mips_64(ctx);
14308 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
14309 break;
14310 case RR_DMULTU:
14311 check_insn(ctx, ISA_MIPS3);
14312 check_mips_64(ctx);
14313 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
14314 break;
14315 case RR_DDIV:
14316 check_insn(ctx, ISA_MIPS3);
14317 check_mips_64(ctx);
14318 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
14319 break;
14320 case RR_DDIVU:
14321 check_insn(ctx, ISA_MIPS3);
14322 check_mips_64(ctx);
14323 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
14324 break;
14325 #endif
14326 default:
14327 generate_exception_end(ctx, EXCP_RI);
14328 break;
14330 break;
14331 case M16_OPC_EXTEND:
14332 decode_extended_mips16_opc(env, ctx);
14333 n_bytes = 4;
14334 break;
14335 #if defined(TARGET_MIPS64)
14336 case M16_OPC_I64:
14337 funct = (ctx->opcode >> 8) & 0x7;
14338 decode_i64_mips16(ctx, ry, funct, offset, 0);
14339 break;
14340 #endif
14341 default:
14342 generate_exception_end(ctx, EXCP_RI);
14343 break;
14346 return n_bytes;
14349 /* microMIPS extension to MIPS32/MIPS64 */
14352 * microMIPS32/microMIPS64 major opcodes
14354 * 1. MIPS Architecture for Programmers Volume II-B:
14355 * The microMIPS32 Instruction Set (Revision 3.05)
14357 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
14359 * 2. MIPS Architecture For Programmers Volume II-A:
14360 * The MIPS64 Instruction Set (Revision 3.51)
14363 enum {
14364 POOL32A = 0x00,
14365 POOL16A = 0x01,
14366 LBU16 = 0x02,
14367 MOVE16 = 0x03,
14368 ADDI32 = 0x04,
14369 R6_LUI = 0x04,
14370 AUI = 0x04,
14371 LBU32 = 0x05,
14372 SB32 = 0x06,
14373 LB32 = 0x07,
14375 POOL32B = 0x08,
14376 POOL16B = 0x09,
14377 LHU16 = 0x0a,
14378 ANDI16 = 0x0b,
14379 ADDIU32 = 0x0c,
14380 LHU32 = 0x0d,
14381 SH32 = 0x0e,
14382 LH32 = 0x0f,
14384 POOL32I = 0x10,
14385 POOL16C = 0x11,
14386 LWSP16 = 0x12,
14387 POOL16D = 0x13,
14388 ORI32 = 0x14,
14389 POOL32F = 0x15,
14390 POOL32S = 0x16, /* MIPS64 */
14391 DADDIU32 = 0x17, /* MIPS64 */
14393 POOL32C = 0x18,
14394 LWGP16 = 0x19,
14395 LW16 = 0x1a,
14396 POOL16E = 0x1b,
14397 XORI32 = 0x1c,
14398 JALS32 = 0x1d,
14399 BOVC = 0x1d,
14400 BEQC = 0x1d,
14401 BEQZALC = 0x1d,
14402 ADDIUPC = 0x1e,
14403 PCREL = 0x1e,
14404 BNVC = 0x1f,
14405 BNEC = 0x1f,
14406 BNEZALC = 0x1f,
14408 R6_BEQZC = 0x20,
14409 JIC = 0x20,
14410 POOL16F = 0x21,
14411 SB16 = 0x22,
14412 BEQZ16 = 0x23,
14413 BEQZC16 = 0x23,
14414 SLTI32 = 0x24,
14415 BEQ32 = 0x25,
14416 BC = 0x25,
14417 SWC132 = 0x26,
14418 LWC132 = 0x27,
14420 /* 0x29 is reserved */
14421 RES_29 = 0x29,
14422 R6_BNEZC = 0x28,
14423 JIALC = 0x28,
14424 SH16 = 0x2a,
14425 BNEZ16 = 0x2b,
14426 BNEZC16 = 0x2b,
14427 SLTIU32 = 0x2c,
14428 BNE32 = 0x2d,
14429 BALC = 0x2d,
14430 SDC132 = 0x2e,
14431 LDC132 = 0x2f,
14433 /* 0x31 is reserved */
14434 RES_31 = 0x31,
14435 BLEZALC = 0x30,
14436 BGEZALC = 0x30,
14437 BGEUC = 0x30,
14438 SWSP16 = 0x32,
14439 B16 = 0x33,
14440 BC16 = 0x33,
14441 ANDI32 = 0x34,
14442 J32 = 0x35,
14443 BGTZC = 0x35,
14444 BLTZC = 0x35,
14445 BLTC = 0x35,
14446 SD32 = 0x36, /* MIPS64 */
14447 LD32 = 0x37, /* MIPS64 */
14449 /* 0x39 is reserved */
14450 RES_39 = 0x39,
14451 BGTZALC = 0x38,
14452 BLTZALC = 0x38,
14453 BLTUC = 0x38,
14454 SW16 = 0x3a,
14455 LI16 = 0x3b,
14456 JALX32 = 0x3c,
14457 JAL32 = 0x3d,
14458 BLEZC = 0x3d,
14459 BGEZC = 0x3d,
14460 BGEC = 0x3d,
14461 SW32 = 0x3e,
14462 LW32 = 0x3f
14465 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
14466 enum {
14467 ADDIUPC_00 = 0x00,
14468 ADDIUPC_01 = 0x01,
14469 ADDIUPC_02 = 0x02,
14470 ADDIUPC_03 = 0x03,
14471 ADDIUPC_04 = 0x04,
14472 ADDIUPC_05 = 0x05,
14473 ADDIUPC_06 = 0x06,
14474 ADDIUPC_07 = 0x07,
14475 AUIPC = 0x1e,
14476 ALUIPC = 0x1f,
14477 LWPC_08 = 0x08,
14478 LWPC_09 = 0x09,
14479 LWPC_0A = 0x0A,
14480 LWPC_0B = 0x0B,
14481 LWPC_0C = 0x0C,
14482 LWPC_0D = 0x0D,
14483 LWPC_0E = 0x0E,
14484 LWPC_0F = 0x0F,
14487 /* POOL32A encoding of minor opcode field */
14489 enum {
14491 * These opcodes are distinguished only by bits 9..6; those bits are
14492 * what are recorded below.
14494 SLL32 = 0x0,
14495 SRL32 = 0x1,
14496 SRA = 0x2,
14497 ROTR = 0x3,
14498 SELEQZ = 0x5,
14499 SELNEZ = 0x6,
14500 R6_RDHWR = 0x7,
14502 SLLV = 0x0,
14503 SRLV = 0x1,
14504 SRAV = 0x2,
14505 ROTRV = 0x3,
14506 ADD = 0x4,
14507 ADDU32 = 0x5,
14508 SUB = 0x6,
14509 SUBU32 = 0x7,
14510 MUL = 0x8,
14511 AND = 0x9,
14512 OR32 = 0xa,
14513 NOR = 0xb,
14514 XOR32 = 0xc,
14515 SLT = 0xd,
14516 SLTU = 0xe,
14518 MOVN = 0x0,
14519 R6_MUL = 0x0,
14520 MOVZ = 0x1,
14521 MUH = 0x1,
14522 MULU = 0x2,
14523 MUHU = 0x3,
14524 LWXS = 0x4,
14525 R6_DIV = 0x4,
14526 MOD = 0x5,
14527 R6_DIVU = 0x6,
14528 MODU = 0x7,
14530 /* The following can be distinguished by their lower 6 bits. */
14531 BREAK32 = 0x07,
14532 INS = 0x0c,
14533 LSA = 0x0f,
14534 ALIGN = 0x1f,
14535 EXT = 0x2c,
14536 POOL32AXF = 0x3c,
14537 SIGRIE = 0x3f
14540 /* POOL32AXF encoding of minor opcode field extension */
14543 * 1. MIPS Architecture for Programmers Volume II-B:
14544 * The microMIPS32 Instruction Set (Revision 3.05)
14546 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
14548 * 2. MIPS Architecture for Programmers VolumeIV-e:
14549 * The MIPS DSP Application-Specific Extension
14550 * to the microMIPS32 Architecture (Revision 2.34)
14552 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
14555 enum {
14556 /* bits 11..6 */
14557 TEQ = 0x00,
14558 TGE = 0x08,
14559 TGEU = 0x10,
14560 TLT = 0x20,
14561 TLTU = 0x28,
14562 TNE = 0x30,
14564 MFC0 = 0x03,
14565 MTC0 = 0x0b,
14567 /* begin of microMIPS32 DSP */
14569 /* bits 13..12 for 0x01 */
14570 MFHI_ACC = 0x0,
14571 MFLO_ACC = 0x1,
14572 MTHI_ACC = 0x2,
14573 MTLO_ACC = 0x3,
14575 /* bits 13..12 for 0x2a */
14576 MADD_ACC = 0x0,
14577 MADDU_ACC = 0x1,
14578 MSUB_ACC = 0x2,
14579 MSUBU_ACC = 0x3,
14581 /* bits 13..12 for 0x32 */
14582 MULT_ACC = 0x0,
14583 MULTU_ACC = 0x1,
14585 /* end of microMIPS32 DSP */
14587 /* bits 15..12 for 0x2c */
14588 BITSWAP = 0x0,
14589 SEB = 0x2,
14590 SEH = 0x3,
14591 CLO = 0x4,
14592 CLZ = 0x5,
14593 RDHWR = 0x6,
14594 WSBH = 0x7,
14595 MULT = 0x8,
14596 MULTU = 0x9,
14597 DIV = 0xa,
14598 DIVU = 0xb,
14599 MADD = 0xc,
14600 MADDU = 0xd,
14601 MSUB = 0xe,
14602 MSUBU = 0xf,
14604 /* bits 15..12 for 0x34 */
14605 MFC2 = 0x4,
14606 MTC2 = 0x5,
14607 MFHC2 = 0x8,
14608 MTHC2 = 0x9,
14609 CFC2 = 0xc,
14610 CTC2 = 0xd,
14612 /* bits 15..12 for 0x3c */
14613 JALR = 0x0,
14614 JR = 0x0, /* alias */
14615 JALRC = 0x0,
14616 JRC = 0x0,
14617 JALR_HB = 0x1,
14618 JALRC_HB = 0x1,
14619 JALRS = 0x4,
14620 JALRS_HB = 0x5,
14622 /* bits 15..12 for 0x05 */
14623 RDPGPR = 0xe,
14624 WRPGPR = 0xf,
14626 /* bits 15..12 for 0x0d */
14627 TLBP = 0x0,
14628 TLBR = 0x1,
14629 TLBWI = 0x2,
14630 TLBWR = 0x3,
14631 TLBINV = 0x4,
14632 TLBINVF = 0x5,
14633 WAIT = 0x9,
14634 IRET = 0xd,
14635 DERET = 0xe,
14636 ERET = 0xf,
14638 /* bits 15..12 for 0x15 */
14639 DMT = 0x0,
14640 DVPE = 0x1,
14641 EMT = 0x2,
14642 EVPE = 0x3,
14644 /* bits 15..12 for 0x1d */
14645 DI = 0x4,
14646 EI = 0x5,
14648 /* bits 15..12 for 0x2d */
14649 SYNC = 0x6,
14650 SYSCALL = 0x8,
14651 SDBBP = 0xd,
14653 /* bits 15..12 for 0x35 */
14654 MFHI32 = 0x0,
14655 MFLO32 = 0x1,
14656 MTHI32 = 0x2,
14657 MTLO32 = 0x3,
14660 /* POOL32B encoding of minor opcode field (bits 15..12) */
14662 enum {
14663 LWC2 = 0x0,
14664 LWP = 0x1,
14665 LDP = 0x4,
14666 LWM32 = 0x5,
14667 CACHE = 0x6,
14668 LDM = 0x7,
14669 SWC2 = 0x8,
14670 SWP = 0x9,
14671 SDP = 0xc,
14672 SWM32 = 0xd,
14673 SDM = 0xf
14676 /* POOL32C encoding of minor opcode field (bits 15..12) */
14678 enum {
14679 LWL = 0x0,
14680 SWL = 0x8,
14681 LWR = 0x1,
14682 SWR = 0x9,
14683 PREF = 0x2,
14684 ST_EVA = 0xa,
14685 LL = 0x3,
14686 SC = 0xb,
14687 LDL = 0x4,
14688 SDL = 0xc,
14689 LDR = 0x5,
14690 SDR = 0xd,
14691 LD_EVA = 0x6,
14692 LWU = 0xe,
14693 LLD = 0x7,
14694 SCD = 0xf
14697 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
14699 enum {
14700 LBUE = 0x0,
14701 LHUE = 0x1,
14702 LWLE = 0x2,
14703 LWRE = 0x3,
14704 LBE = 0x4,
14705 LHE = 0x5,
14706 LLE = 0x6,
14707 LWE = 0x7,
14710 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
14712 enum {
14713 SWLE = 0x0,
14714 SWRE = 0x1,
14715 PREFE = 0x2,
14716 CACHEE = 0x3,
14717 SBE = 0x4,
14718 SHE = 0x5,
14719 SCE = 0x6,
14720 SWE = 0x7,
14723 /* POOL32F encoding of minor opcode field (bits 5..0) */
14725 enum {
14726 /* These are the bit 7..6 values */
14727 ADD_FMT = 0x0,
14729 SUB_FMT = 0x1,
14731 MUL_FMT = 0x2,
14733 DIV_FMT = 0x3,
14735 /* These are the bit 8..6 values */
14736 MOVN_FMT = 0x0,
14737 RSQRT2_FMT = 0x0,
14738 MOVF_FMT = 0x0,
14739 RINT_FMT = 0x0,
14740 SELNEZ_FMT = 0x0,
14742 MOVZ_FMT = 0x1,
14743 LWXC1 = 0x1,
14744 MOVT_FMT = 0x1,
14745 CLASS_FMT = 0x1,
14746 SELEQZ_FMT = 0x1,
14748 PLL_PS = 0x2,
14749 SWXC1 = 0x2,
14750 SEL_FMT = 0x2,
14752 PLU_PS = 0x3,
14753 LDXC1 = 0x3,
14755 MOVN_FMT_04 = 0x4,
14756 PUL_PS = 0x4,
14757 SDXC1 = 0x4,
14758 RECIP2_FMT = 0x4,
14760 MOVZ_FMT_05 = 0x05,
14761 PUU_PS = 0x5,
14762 LUXC1 = 0x5,
14764 CVT_PS_S = 0x6,
14765 SUXC1 = 0x6,
14766 ADDR_PS = 0x6,
14767 PREFX = 0x6,
14768 MADDF_FMT = 0x6,
14770 MULR_PS = 0x7,
14771 MSUBF_FMT = 0x7,
14773 MADD_S = 0x01,
14774 MADD_D = 0x09,
14775 MADD_PS = 0x11,
14776 ALNV_PS = 0x19,
14777 MSUB_S = 0x21,
14778 MSUB_D = 0x29,
14779 MSUB_PS = 0x31,
14781 NMADD_S = 0x02,
14782 NMADD_D = 0x0a,
14783 NMADD_PS = 0x12,
14784 NMSUB_S = 0x22,
14785 NMSUB_D = 0x2a,
14786 NMSUB_PS = 0x32,
14788 MIN_FMT = 0x3,
14789 MAX_FMT = 0xb,
14790 MINA_FMT = 0x23,
14791 MAXA_FMT = 0x2b,
14792 POOL32FXF = 0x3b,
14794 CABS_COND_FMT = 0x1c, /* MIPS3D */
14795 C_COND_FMT = 0x3c,
14797 CMP_CONDN_S = 0x5,
14798 CMP_CONDN_D = 0x15
14801 /* POOL32Fxf encoding of minor opcode extension field */
14803 enum {
14804 CVT_L = 0x04,
14805 RSQRT_FMT = 0x08,
14806 FLOOR_L = 0x0c,
14807 CVT_PW_PS = 0x1c,
14808 CVT_W = 0x24,
14809 SQRT_FMT = 0x28,
14810 FLOOR_W = 0x2c,
14811 CVT_PS_PW = 0x3c,
14812 CFC1 = 0x40,
14813 RECIP_FMT = 0x48,
14814 CEIL_L = 0x4c,
14815 CTC1 = 0x60,
14816 CEIL_W = 0x6c,
14817 MFC1 = 0x80,
14818 CVT_S_PL = 0x84,
14819 TRUNC_L = 0x8c,
14820 MTC1 = 0xa0,
14821 CVT_S_PU = 0xa4,
14822 TRUNC_W = 0xac,
14823 MFHC1 = 0xc0,
14824 ROUND_L = 0xcc,
14825 MTHC1 = 0xe0,
14826 ROUND_W = 0xec,
14828 MOV_FMT = 0x01,
14829 MOVF = 0x05,
14830 ABS_FMT = 0x0d,
14831 RSQRT1_FMT = 0x1d,
14832 MOVT = 0x25,
14833 NEG_FMT = 0x2d,
14834 CVT_D = 0x4d,
14835 RECIP1_FMT = 0x5d,
14836 CVT_S = 0x6d
14839 /* POOL32I encoding of minor opcode field (bits 25..21) */
14841 enum {
14842 BLTZ = 0x00,
14843 BLTZAL = 0x01,
14844 BGEZ = 0x02,
14845 BGEZAL = 0x03,
14846 BLEZ = 0x04,
14847 BNEZC = 0x05,
14848 BGTZ = 0x06,
14849 BEQZC = 0x07,
14850 TLTI = 0x08,
14851 BC1EQZC = 0x08,
14852 TGEI = 0x09,
14853 BC1NEZC = 0x09,
14854 TLTIU = 0x0a,
14855 BC2EQZC = 0x0a,
14856 TGEIU = 0x0b,
14857 BC2NEZC = 0x0a,
14858 TNEI = 0x0c,
14859 R6_SYNCI = 0x0c,
14860 LUI = 0x0d,
14861 TEQI = 0x0e,
14862 SYNCI = 0x10,
14863 BLTZALS = 0x11,
14864 BGEZALS = 0x13,
14865 BC2F = 0x14,
14866 BC2T = 0x15,
14867 BPOSGE64 = 0x1a,
14868 BPOSGE32 = 0x1b,
14869 /* These overlap and are distinguished by bit16 of the instruction */
14870 BC1F = 0x1c,
14871 BC1T = 0x1d,
14872 BC1ANY2F = 0x1c,
14873 BC1ANY2T = 0x1d,
14874 BC1ANY4F = 0x1e,
14875 BC1ANY4T = 0x1f
14878 /* POOL16A encoding of minor opcode field */
14880 enum {
14881 ADDU16 = 0x0,
14882 SUBU16 = 0x1
14885 /* POOL16B encoding of minor opcode field */
14887 enum {
14888 SLL16 = 0x0,
14889 SRL16 = 0x1
14892 /* POOL16C encoding of minor opcode field */
14894 enum {
14895 NOT16 = 0x00,
14896 XOR16 = 0x04,
14897 AND16 = 0x08,
14898 OR16 = 0x0c,
14899 LWM16 = 0x10,
14900 SWM16 = 0x14,
14901 JR16 = 0x18,
14902 JRC16 = 0x1a,
14903 JALR16 = 0x1c,
14904 JALR16S = 0x1e,
14905 MFHI16 = 0x20,
14906 MFLO16 = 0x24,
14907 BREAK16 = 0x28,
14908 SDBBP16 = 0x2c,
14909 JRADDIUSP = 0x30
14912 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
14914 enum {
14915 R6_NOT16 = 0x00,
14916 R6_AND16 = 0x01,
14917 R6_LWM16 = 0x02,
14918 R6_JRC16 = 0x03,
14919 MOVEP = 0x04,
14920 MOVEP_05 = 0x05,
14921 MOVEP_06 = 0x06,
14922 MOVEP_07 = 0x07,
14923 R6_XOR16 = 0x08,
14924 R6_OR16 = 0x09,
14925 R6_SWM16 = 0x0a,
14926 JALRC16 = 0x0b,
14927 MOVEP_0C = 0x0c,
14928 MOVEP_0D = 0x0d,
14929 MOVEP_0E = 0x0e,
14930 MOVEP_0F = 0x0f,
14931 JRCADDIUSP = 0x13,
14932 R6_BREAK16 = 0x1b,
14933 R6_SDBBP16 = 0x3b
14936 /* POOL16D encoding of minor opcode field */
14938 enum {
14939 ADDIUS5 = 0x0,
14940 ADDIUSP = 0x1
14943 /* POOL16E encoding of minor opcode field */
14945 enum {
14946 ADDIUR2 = 0x0,
14947 ADDIUR1SP = 0x1
14950 static int mmreg(int r)
14952 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
14954 return map[r];
14957 /* Used for 16-bit store instructions. */
14958 static int mmreg2(int r)
14960 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
14962 return map[r];
14965 #define uMIPS_RD(op) ((op >> 7) & 0x7)
14966 #define uMIPS_RS(op) ((op >> 4) & 0x7)
14967 #define uMIPS_RS2(op) uMIPS_RS(op)
14968 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
14969 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
14970 #define uMIPS_RS5(op) (op & 0x1f)
14972 /* Signed immediate */
14973 #define SIMM(op, start, width) \
14974 ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \
14975 << (32 - width)) \
14976 >> (32 - width))
14977 /* Zero-extended immediate */
14978 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width)))
14980 static void gen_addiur1sp(DisasContext *ctx)
14982 int rd = mmreg(uMIPS_RD(ctx->opcode));
14984 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
14987 static void gen_addiur2(DisasContext *ctx)
14989 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
14990 int rd = mmreg(uMIPS_RD(ctx->opcode));
14991 int rs = mmreg(uMIPS_RS(ctx->opcode));
14993 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
14996 static void gen_addiusp(DisasContext *ctx)
14998 int encoded = ZIMM(ctx->opcode, 1, 9);
14999 int decoded;
15001 if (encoded <= 1) {
15002 decoded = 256 + encoded;
15003 } else if (encoded <= 255) {
15004 decoded = encoded;
15005 } else if (encoded <= 509) {
15006 decoded = encoded - 512;
15007 } else {
15008 decoded = encoded - 768;
15011 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
15014 static void gen_addius5(DisasContext *ctx)
15016 int imm = SIMM(ctx->opcode, 1, 4);
15017 int rd = (ctx->opcode >> 5) & 0x1f;
15019 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
15022 static void gen_andi16(DisasContext *ctx)
15024 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
15025 31, 32, 63, 64, 255, 32768, 65535 };
15026 int rd = mmreg(uMIPS_RD(ctx->opcode));
15027 int rs = mmreg(uMIPS_RS(ctx->opcode));
15028 int encoded = ZIMM(ctx->opcode, 0, 4);
15030 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
15033 static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist,
15034 int base, int16_t offset)
15036 TCGv t0, t1;
15037 TCGv_i32 t2;
15039 if (ctx->hflags & MIPS_HFLAG_BMASK) {
15040 generate_exception_end(ctx, EXCP_RI);
15041 return;
15044 t0 = tcg_temp_new();
15046 gen_base_offset_addr(ctx, t0, base, offset);
15048 t1 = tcg_const_tl(reglist);
15049 t2 = tcg_const_i32(ctx->mem_idx);
15051 save_cpu_state(ctx, 1);
15052 switch (opc) {
15053 case LWM32:
15054 gen_helper_lwm(cpu_env, t0, t1, t2);
15055 break;
15056 case SWM32:
15057 gen_helper_swm(cpu_env, t0, t1, t2);
15058 break;
15059 #ifdef TARGET_MIPS64
15060 case LDM:
15061 gen_helper_ldm(cpu_env, t0, t1, t2);
15062 break;
15063 case SDM:
15064 gen_helper_sdm(cpu_env, t0, t1, t2);
15065 break;
15066 #endif
15068 tcg_temp_free(t0);
15069 tcg_temp_free(t1);
15070 tcg_temp_free_i32(t2);
15074 static void gen_pool16c_insn(DisasContext *ctx)
15076 int rd = mmreg((ctx->opcode >> 3) & 0x7);
15077 int rs = mmreg(ctx->opcode & 0x7);
15079 switch (((ctx->opcode) >> 4) & 0x3f) {
15080 case NOT16 + 0:
15081 case NOT16 + 1:
15082 case NOT16 + 2:
15083 case NOT16 + 3:
15084 gen_logic(ctx, OPC_NOR, rd, rs, 0);
15085 break;
15086 case XOR16 + 0:
15087 case XOR16 + 1:
15088 case XOR16 + 2:
15089 case XOR16 + 3:
15090 gen_logic(ctx, OPC_XOR, rd, rd, rs);
15091 break;
15092 case AND16 + 0:
15093 case AND16 + 1:
15094 case AND16 + 2:
15095 case AND16 + 3:
15096 gen_logic(ctx, OPC_AND, rd, rd, rs);
15097 break;
15098 case OR16 + 0:
15099 case OR16 + 1:
15100 case OR16 + 2:
15101 case OR16 + 3:
15102 gen_logic(ctx, OPC_OR, rd, rd, rs);
15103 break;
15104 case LWM16 + 0:
15105 case LWM16 + 1:
15106 case LWM16 + 2:
15107 case LWM16 + 3:
15109 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15110 int offset = ZIMM(ctx->opcode, 0, 4);
15112 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
15113 29, offset << 2);
15115 break;
15116 case SWM16 + 0:
15117 case SWM16 + 1:
15118 case SWM16 + 2:
15119 case SWM16 + 3:
15121 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15122 int offset = ZIMM(ctx->opcode, 0, 4);
15124 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
15125 29, offset << 2);
15127 break;
15128 case JR16 + 0:
15129 case JR16 + 1:
15131 int reg = ctx->opcode & 0x1f;
15133 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
15135 break;
15136 case JRC16 + 0:
15137 case JRC16 + 1:
15139 int reg = ctx->opcode & 0x1f;
15140 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
15142 * Let normal delay slot handling in our caller take us
15143 * to the branch target.
15146 break;
15147 case JALR16 + 0:
15148 case JALR16 + 1:
15149 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
15150 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15151 break;
15152 case JALR16S + 0:
15153 case JALR16S + 1:
15154 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
15155 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15156 break;
15157 case MFHI16 + 0:
15158 case MFHI16 + 1:
15159 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
15160 break;
15161 case MFLO16 + 0:
15162 case MFLO16 + 1:
15163 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
15164 break;
15165 case BREAK16:
15166 generate_exception_end(ctx, EXCP_BREAK);
15167 break;
15168 case SDBBP16:
15169 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
15170 gen_helper_do_semihosting(cpu_env);
15171 } else {
15173 * XXX: not clear which exception should be raised
15174 * when in debug mode...
15176 check_insn(ctx, ISA_MIPS32);
15177 generate_exception_end(ctx, EXCP_DBp);
15179 break;
15180 case JRADDIUSP + 0:
15181 case JRADDIUSP + 1:
15183 int imm = ZIMM(ctx->opcode, 0, 5);
15184 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15185 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15187 * Let normal delay slot handling in our caller take us
15188 * to the branch target.
15191 break;
15192 default:
15193 generate_exception_end(ctx, EXCP_RI);
15194 break;
15198 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
15199 int enc_rs)
15201 int rd, rs, re, rt;
15202 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
15203 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
15204 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
15205 rd = rd_enc[enc_dest];
15206 re = re_enc[enc_dest];
15207 rs = rs_rt_enc[enc_rs];
15208 rt = rs_rt_enc[enc_rt];
15209 if (rs) {
15210 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
15211 } else {
15212 tcg_gen_movi_tl(cpu_gpr[rd], 0);
15214 if (rt) {
15215 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
15216 } else {
15217 tcg_gen_movi_tl(cpu_gpr[re], 0);
15221 static void gen_pool16c_r6_insn(DisasContext *ctx)
15223 int rt = mmreg((ctx->opcode >> 7) & 0x7);
15224 int rs = mmreg((ctx->opcode >> 4) & 0x7);
15226 switch (ctx->opcode & 0xf) {
15227 case R6_NOT16:
15228 gen_logic(ctx, OPC_NOR, rt, rs, 0);
15229 break;
15230 case R6_AND16:
15231 gen_logic(ctx, OPC_AND, rt, rt, rs);
15232 break;
15233 case R6_LWM16:
15235 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15236 int offset = extract32(ctx->opcode, 4, 4);
15237 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
15239 break;
15240 case R6_JRC16: /* JRCADDIUSP */
15241 if ((ctx->opcode >> 4) & 1) {
15242 /* JRCADDIUSP */
15243 int imm = extract32(ctx->opcode, 5, 5);
15244 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15245 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15246 } else {
15247 /* JRC16 */
15248 rs = extract32(ctx->opcode, 5, 5);
15249 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
15251 break;
15252 case MOVEP:
15253 case MOVEP_05:
15254 case MOVEP_06:
15255 case MOVEP_07:
15256 case MOVEP_0C:
15257 case MOVEP_0D:
15258 case MOVEP_0E:
15259 case MOVEP_0F:
15261 int enc_dest = uMIPS_RD(ctx->opcode);
15262 int enc_rt = uMIPS_RS2(ctx->opcode);
15263 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
15264 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15266 break;
15267 case R6_XOR16:
15268 gen_logic(ctx, OPC_XOR, rt, rt, rs);
15269 break;
15270 case R6_OR16:
15271 gen_logic(ctx, OPC_OR, rt, rt, rs);
15272 break;
15273 case R6_SWM16:
15275 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15276 int offset = extract32(ctx->opcode, 4, 4);
15277 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
15279 break;
15280 case JALRC16: /* BREAK16, SDBBP16 */
15281 switch (ctx->opcode & 0x3f) {
15282 case JALRC16:
15283 case JALRC16 + 0x20:
15284 /* JALRC16 */
15285 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
15286 31, 0, 0);
15287 break;
15288 case R6_BREAK16:
15289 /* BREAK16 */
15290 generate_exception(ctx, EXCP_BREAK);
15291 break;
15292 case R6_SDBBP16:
15293 /* SDBBP16 */
15294 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
15295 gen_helper_do_semihosting(cpu_env);
15296 } else {
15297 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15298 generate_exception(ctx, EXCP_RI);
15299 } else {
15300 generate_exception(ctx, EXCP_DBp);
15303 break;
15305 break;
15306 default:
15307 generate_exception(ctx, EXCP_RI);
15308 break;
15312 static void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
15314 TCGv t0 = tcg_temp_new();
15315 TCGv t1 = tcg_temp_new();
15317 gen_load_gpr(t0, base);
15319 if (index != 0) {
15320 gen_load_gpr(t1, index);
15321 tcg_gen_shli_tl(t1, t1, 2);
15322 gen_op_addr_add(ctx, t0, t1, t0);
15325 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15326 gen_store_gpr(t1, rd);
15328 tcg_temp_free(t0);
15329 tcg_temp_free(t1);
15332 static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd,
15333 int base, int16_t offset)
15335 TCGv t0, t1;
15337 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
15338 generate_exception_end(ctx, EXCP_RI);
15339 return;
15342 t0 = tcg_temp_new();
15343 t1 = tcg_temp_new();
15345 gen_base_offset_addr(ctx, t0, base, offset);
15347 switch (opc) {
15348 case LWP:
15349 if (rd == base) {
15350 generate_exception_end(ctx, EXCP_RI);
15351 return;
15353 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15354 gen_store_gpr(t1, rd);
15355 tcg_gen_movi_tl(t1, 4);
15356 gen_op_addr_add(ctx, t0, t0, t1);
15357 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15358 gen_store_gpr(t1, rd + 1);
15359 break;
15360 case SWP:
15361 gen_load_gpr(t1, rd);
15362 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15363 tcg_gen_movi_tl(t1, 4);
15364 gen_op_addr_add(ctx, t0, t0, t1);
15365 gen_load_gpr(t1, rd + 1);
15366 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15367 break;
15368 #ifdef TARGET_MIPS64
15369 case LDP:
15370 if (rd == base) {
15371 generate_exception_end(ctx, EXCP_RI);
15372 return;
15374 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15375 gen_store_gpr(t1, rd);
15376 tcg_gen_movi_tl(t1, 8);
15377 gen_op_addr_add(ctx, t0, t0, t1);
15378 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15379 gen_store_gpr(t1, rd + 1);
15380 break;
15381 case SDP:
15382 gen_load_gpr(t1, rd);
15383 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15384 tcg_gen_movi_tl(t1, 8);
15385 gen_op_addr_add(ctx, t0, t0, t1);
15386 gen_load_gpr(t1, rd + 1);
15387 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15388 break;
15389 #endif
15391 tcg_temp_free(t0);
15392 tcg_temp_free(t1);
15395 static void gen_sync(int stype)
15397 TCGBar tcg_mo = TCG_BAR_SC;
15399 switch (stype) {
15400 case 0x4: /* SYNC_WMB */
15401 tcg_mo |= TCG_MO_ST_ST;
15402 break;
15403 case 0x10: /* SYNC_MB */
15404 tcg_mo |= TCG_MO_ALL;
15405 break;
15406 case 0x11: /* SYNC_ACQUIRE */
15407 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
15408 break;
15409 case 0x12: /* SYNC_RELEASE */
15410 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
15411 break;
15412 case 0x13: /* SYNC_RMB */
15413 tcg_mo |= TCG_MO_LD_LD;
15414 break;
15415 default:
15416 tcg_mo |= TCG_MO_ALL;
15417 break;
15420 tcg_gen_mb(tcg_mo);
15423 static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
15425 int extension = (ctx->opcode >> 6) & 0x3f;
15426 int minor = (ctx->opcode >> 12) & 0xf;
15427 uint32_t mips32_op;
15429 switch (extension) {
15430 case TEQ:
15431 mips32_op = OPC_TEQ;
15432 goto do_trap;
15433 case TGE:
15434 mips32_op = OPC_TGE;
15435 goto do_trap;
15436 case TGEU:
15437 mips32_op = OPC_TGEU;
15438 goto do_trap;
15439 case TLT:
15440 mips32_op = OPC_TLT;
15441 goto do_trap;
15442 case TLTU:
15443 mips32_op = OPC_TLTU;
15444 goto do_trap;
15445 case TNE:
15446 mips32_op = OPC_TNE;
15447 do_trap:
15448 gen_trap(ctx, mips32_op, rs, rt, -1);
15449 break;
15450 #ifndef CONFIG_USER_ONLY
15451 case MFC0:
15452 case MFC0 + 32:
15453 check_cp0_enabled(ctx);
15454 if (rt == 0) {
15455 /* Treat as NOP. */
15456 break;
15458 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
15459 break;
15460 case MTC0:
15461 case MTC0 + 32:
15462 check_cp0_enabled(ctx);
15464 TCGv t0 = tcg_temp_new();
15466 gen_load_gpr(t0, rt);
15467 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
15468 tcg_temp_free(t0);
15470 break;
15471 #endif
15472 case 0x2a:
15473 switch (minor & 3) {
15474 case MADD_ACC:
15475 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
15476 break;
15477 case MADDU_ACC:
15478 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
15479 break;
15480 case MSUB_ACC:
15481 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
15482 break;
15483 case MSUBU_ACC:
15484 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
15485 break;
15486 default:
15487 goto pool32axf_invalid;
15489 break;
15490 case 0x32:
15491 switch (minor & 3) {
15492 case MULT_ACC:
15493 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
15494 break;
15495 case MULTU_ACC:
15496 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
15497 break;
15498 default:
15499 goto pool32axf_invalid;
15501 break;
15502 case 0x2c:
15503 switch (minor) {
15504 case BITSWAP:
15505 check_insn(ctx, ISA_MIPS32R6);
15506 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
15507 break;
15508 case SEB:
15509 gen_bshfl(ctx, OPC_SEB, rs, rt);
15510 break;
15511 case SEH:
15512 gen_bshfl(ctx, OPC_SEH, rs, rt);
15513 break;
15514 case CLO:
15515 mips32_op = OPC_CLO;
15516 goto do_cl;
15517 case CLZ:
15518 mips32_op = OPC_CLZ;
15519 do_cl:
15520 check_insn(ctx, ISA_MIPS32);
15521 gen_cl(ctx, mips32_op, rt, rs);
15522 break;
15523 case RDHWR:
15524 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15525 gen_rdhwr(ctx, rt, rs, 0);
15526 break;
15527 case WSBH:
15528 gen_bshfl(ctx, OPC_WSBH, rs, rt);
15529 break;
15530 case MULT:
15531 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15532 mips32_op = OPC_MULT;
15533 goto do_mul;
15534 case MULTU:
15535 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15536 mips32_op = OPC_MULTU;
15537 goto do_mul;
15538 case DIV:
15539 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15540 mips32_op = OPC_DIV;
15541 goto do_div;
15542 case DIVU:
15543 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15544 mips32_op = OPC_DIVU;
15545 goto do_div;
15546 do_div:
15547 check_insn(ctx, ISA_MIPS32);
15548 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15549 break;
15550 case MADD:
15551 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15552 mips32_op = OPC_MADD;
15553 goto do_mul;
15554 case MADDU:
15555 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15556 mips32_op = OPC_MADDU;
15557 goto do_mul;
15558 case MSUB:
15559 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15560 mips32_op = OPC_MSUB;
15561 goto do_mul;
15562 case MSUBU:
15563 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15564 mips32_op = OPC_MSUBU;
15565 do_mul:
15566 check_insn(ctx, ISA_MIPS32);
15567 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15568 break;
15569 default:
15570 goto pool32axf_invalid;
15572 break;
15573 case 0x34:
15574 switch (minor) {
15575 case MFC2:
15576 case MTC2:
15577 case MFHC2:
15578 case MTHC2:
15579 case CFC2:
15580 case CTC2:
15581 generate_exception_err(ctx, EXCP_CpU, 2);
15582 break;
15583 default:
15584 goto pool32axf_invalid;
15586 break;
15587 case 0x3c:
15588 switch (minor) {
15589 case JALR: /* JALRC */
15590 case JALR_HB: /* JALRC_HB */
15591 if (ctx->insn_flags & ISA_MIPS32R6) {
15592 /* JALRC, JALRC_HB */
15593 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
15594 } else {
15595 /* JALR, JALR_HB */
15596 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
15597 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15599 break;
15600 case JALRS:
15601 case JALRS_HB:
15602 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15603 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
15604 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15605 break;
15606 default:
15607 goto pool32axf_invalid;
15609 break;
15610 case 0x05:
15611 switch (minor) {
15612 case RDPGPR:
15613 check_cp0_enabled(ctx);
15614 check_insn(ctx, ISA_MIPS32R2);
15615 gen_load_srsgpr(rs, rt);
15616 break;
15617 case WRPGPR:
15618 check_cp0_enabled(ctx);
15619 check_insn(ctx, ISA_MIPS32R2);
15620 gen_store_srsgpr(rs, rt);
15621 break;
15622 default:
15623 goto pool32axf_invalid;
15625 break;
15626 #ifndef CONFIG_USER_ONLY
15627 case 0x0d:
15628 switch (minor) {
15629 case TLBP:
15630 mips32_op = OPC_TLBP;
15631 goto do_cp0;
15632 case TLBR:
15633 mips32_op = OPC_TLBR;
15634 goto do_cp0;
15635 case TLBWI:
15636 mips32_op = OPC_TLBWI;
15637 goto do_cp0;
15638 case TLBWR:
15639 mips32_op = OPC_TLBWR;
15640 goto do_cp0;
15641 case TLBINV:
15642 mips32_op = OPC_TLBINV;
15643 goto do_cp0;
15644 case TLBINVF:
15645 mips32_op = OPC_TLBINVF;
15646 goto do_cp0;
15647 case WAIT:
15648 mips32_op = OPC_WAIT;
15649 goto do_cp0;
15650 case DERET:
15651 mips32_op = OPC_DERET;
15652 goto do_cp0;
15653 case ERET:
15654 mips32_op = OPC_ERET;
15655 do_cp0:
15656 gen_cp0(env, ctx, mips32_op, rt, rs);
15657 break;
15658 default:
15659 goto pool32axf_invalid;
15661 break;
15662 case 0x1d:
15663 switch (minor) {
15664 case DI:
15665 check_cp0_enabled(ctx);
15667 TCGv t0 = tcg_temp_new();
15669 save_cpu_state(ctx, 1);
15670 gen_helper_di(t0, cpu_env);
15671 gen_store_gpr(t0, rs);
15673 * Stop translation as we may have switched the execution
15674 * mode.
15676 ctx->base.is_jmp = DISAS_STOP;
15677 tcg_temp_free(t0);
15679 break;
15680 case EI:
15681 check_cp0_enabled(ctx);
15683 TCGv t0 = tcg_temp_new();
15685 save_cpu_state(ctx, 1);
15686 gen_helper_ei(t0, cpu_env);
15687 gen_store_gpr(t0, rs);
15689 * DISAS_STOP isn't sufficient, we need to ensure we break out
15690 * of translated code to check for pending interrupts.
15692 gen_save_pc(ctx->base.pc_next + 4);
15693 ctx->base.is_jmp = DISAS_EXIT;
15694 tcg_temp_free(t0);
15696 break;
15697 default:
15698 goto pool32axf_invalid;
15700 break;
15701 #endif
15702 case 0x2d:
15703 switch (minor) {
15704 case SYNC:
15705 gen_sync(extract32(ctx->opcode, 16, 5));
15706 break;
15707 case SYSCALL:
15708 generate_exception_end(ctx, EXCP_SYSCALL);
15709 break;
15710 case SDBBP:
15711 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
15712 gen_helper_do_semihosting(cpu_env);
15713 } else {
15714 check_insn(ctx, ISA_MIPS32);
15715 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15716 generate_exception_end(ctx, EXCP_RI);
15717 } else {
15718 generate_exception_end(ctx, EXCP_DBp);
15721 break;
15722 default:
15723 goto pool32axf_invalid;
15725 break;
15726 case 0x01:
15727 switch (minor & 3) {
15728 case MFHI_ACC:
15729 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
15730 break;
15731 case MFLO_ACC:
15732 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
15733 break;
15734 case MTHI_ACC:
15735 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
15736 break;
15737 case MTLO_ACC:
15738 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
15739 break;
15740 default:
15741 goto pool32axf_invalid;
15743 break;
15744 case 0x35:
15745 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15746 switch (minor) {
15747 case MFHI32:
15748 gen_HILO(ctx, OPC_MFHI, 0, rs);
15749 break;
15750 case MFLO32:
15751 gen_HILO(ctx, OPC_MFLO, 0, rs);
15752 break;
15753 case MTHI32:
15754 gen_HILO(ctx, OPC_MTHI, 0, rs);
15755 break;
15756 case MTLO32:
15757 gen_HILO(ctx, OPC_MTLO, 0, rs);
15758 break;
15759 default:
15760 goto pool32axf_invalid;
15762 break;
15763 default:
15764 pool32axf_invalid:
15765 MIPS_INVAL("pool32axf");
15766 generate_exception_end(ctx, EXCP_RI);
15767 break;
15772 * Values for microMIPS fmt field. Variable-width, depending on which
15773 * formats the instruction supports.
15775 enum {
15776 FMT_SD_S = 0,
15777 FMT_SD_D = 1,
15779 FMT_SDPS_S = 0,
15780 FMT_SDPS_D = 1,
15781 FMT_SDPS_PS = 2,
15783 FMT_SWL_S = 0,
15784 FMT_SWL_W = 1,
15785 FMT_SWL_L = 2,
15787 FMT_DWL_D = 0,
15788 FMT_DWL_W = 1,
15789 FMT_DWL_L = 2
15792 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
15794 int extension = (ctx->opcode >> 6) & 0x3ff;
15795 uint32_t mips32_op;
15797 #define FLOAT_1BIT_FMT(opc, fmt) ((fmt << 8) | opc)
15798 #define FLOAT_2BIT_FMT(opc, fmt) ((fmt << 7) | opc)
15799 #define COND_FLOAT_MOV(opc, cond) ((cond << 7) | opc)
15801 switch (extension) {
15802 case FLOAT_1BIT_FMT(CFC1, 0):
15803 mips32_op = OPC_CFC1;
15804 goto do_cp1;
15805 case FLOAT_1BIT_FMT(CTC1, 0):
15806 mips32_op = OPC_CTC1;
15807 goto do_cp1;
15808 case FLOAT_1BIT_FMT(MFC1, 0):
15809 mips32_op = OPC_MFC1;
15810 goto do_cp1;
15811 case FLOAT_1BIT_FMT(MTC1, 0):
15812 mips32_op = OPC_MTC1;
15813 goto do_cp1;
15814 case FLOAT_1BIT_FMT(MFHC1, 0):
15815 mips32_op = OPC_MFHC1;
15816 goto do_cp1;
15817 case FLOAT_1BIT_FMT(MTHC1, 0):
15818 mips32_op = OPC_MTHC1;
15819 do_cp1:
15820 gen_cp1(ctx, mips32_op, rt, rs);
15821 break;
15823 /* Reciprocal square root */
15824 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
15825 mips32_op = OPC_RSQRT_S;
15826 goto do_unaryfp;
15827 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
15828 mips32_op = OPC_RSQRT_D;
15829 goto do_unaryfp;
15831 /* Square root */
15832 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
15833 mips32_op = OPC_SQRT_S;
15834 goto do_unaryfp;
15835 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
15836 mips32_op = OPC_SQRT_D;
15837 goto do_unaryfp;
15839 /* Reciprocal */
15840 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
15841 mips32_op = OPC_RECIP_S;
15842 goto do_unaryfp;
15843 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
15844 mips32_op = OPC_RECIP_D;
15845 goto do_unaryfp;
15847 /* Floor */
15848 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
15849 mips32_op = OPC_FLOOR_L_S;
15850 goto do_unaryfp;
15851 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
15852 mips32_op = OPC_FLOOR_L_D;
15853 goto do_unaryfp;
15854 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
15855 mips32_op = OPC_FLOOR_W_S;
15856 goto do_unaryfp;
15857 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
15858 mips32_op = OPC_FLOOR_W_D;
15859 goto do_unaryfp;
15861 /* Ceiling */
15862 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
15863 mips32_op = OPC_CEIL_L_S;
15864 goto do_unaryfp;
15865 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
15866 mips32_op = OPC_CEIL_L_D;
15867 goto do_unaryfp;
15868 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
15869 mips32_op = OPC_CEIL_W_S;
15870 goto do_unaryfp;
15871 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
15872 mips32_op = OPC_CEIL_W_D;
15873 goto do_unaryfp;
15875 /* Truncation */
15876 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
15877 mips32_op = OPC_TRUNC_L_S;
15878 goto do_unaryfp;
15879 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
15880 mips32_op = OPC_TRUNC_L_D;
15881 goto do_unaryfp;
15882 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
15883 mips32_op = OPC_TRUNC_W_S;
15884 goto do_unaryfp;
15885 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
15886 mips32_op = OPC_TRUNC_W_D;
15887 goto do_unaryfp;
15889 /* Round */
15890 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
15891 mips32_op = OPC_ROUND_L_S;
15892 goto do_unaryfp;
15893 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
15894 mips32_op = OPC_ROUND_L_D;
15895 goto do_unaryfp;
15896 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
15897 mips32_op = OPC_ROUND_W_S;
15898 goto do_unaryfp;
15899 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
15900 mips32_op = OPC_ROUND_W_D;
15901 goto do_unaryfp;
15903 /* Integer to floating-point conversion */
15904 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
15905 mips32_op = OPC_CVT_L_S;
15906 goto do_unaryfp;
15907 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
15908 mips32_op = OPC_CVT_L_D;
15909 goto do_unaryfp;
15910 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
15911 mips32_op = OPC_CVT_W_S;
15912 goto do_unaryfp;
15913 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
15914 mips32_op = OPC_CVT_W_D;
15915 goto do_unaryfp;
15917 /* Paired-foo conversions */
15918 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
15919 mips32_op = OPC_CVT_S_PL;
15920 goto do_unaryfp;
15921 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
15922 mips32_op = OPC_CVT_S_PU;
15923 goto do_unaryfp;
15924 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
15925 mips32_op = OPC_CVT_PW_PS;
15926 goto do_unaryfp;
15927 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
15928 mips32_op = OPC_CVT_PS_PW;
15929 goto do_unaryfp;
15931 /* Floating-point moves */
15932 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
15933 mips32_op = OPC_MOV_S;
15934 goto do_unaryfp;
15935 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
15936 mips32_op = OPC_MOV_D;
15937 goto do_unaryfp;
15938 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
15939 mips32_op = OPC_MOV_PS;
15940 goto do_unaryfp;
15942 /* Absolute value */
15943 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
15944 mips32_op = OPC_ABS_S;
15945 goto do_unaryfp;
15946 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
15947 mips32_op = OPC_ABS_D;
15948 goto do_unaryfp;
15949 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
15950 mips32_op = OPC_ABS_PS;
15951 goto do_unaryfp;
15953 /* Negation */
15954 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
15955 mips32_op = OPC_NEG_S;
15956 goto do_unaryfp;
15957 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
15958 mips32_op = OPC_NEG_D;
15959 goto do_unaryfp;
15960 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
15961 mips32_op = OPC_NEG_PS;
15962 goto do_unaryfp;
15964 /* Reciprocal square root step */
15965 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
15966 mips32_op = OPC_RSQRT1_S;
15967 goto do_unaryfp;
15968 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
15969 mips32_op = OPC_RSQRT1_D;
15970 goto do_unaryfp;
15971 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
15972 mips32_op = OPC_RSQRT1_PS;
15973 goto do_unaryfp;
15975 /* Reciprocal step */
15976 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
15977 mips32_op = OPC_RECIP1_S;
15978 goto do_unaryfp;
15979 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
15980 mips32_op = OPC_RECIP1_S;
15981 goto do_unaryfp;
15982 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
15983 mips32_op = OPC_RECIP1_PS;
15984 goto do_unaryfp;
15986 /* Conversions from double */
15987 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
15988 mips32_op = OPC_CVT_D_S;
15989 goto do_unaryfp;
15990 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
15991 mips32_op = OPC_CVT_D_W;
15992 goto do_unaryfp;
15993 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
15994 mips32_op = OPC_CVT_D_L;
15995 goto do_unaryfp;
15997 /* Conversions from single */
15998 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
15999 mips32_op = OPC_CVT_S_D;
16000 goto do_unaryfp;
16001 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
16002 mips32_op = OPC_CVT_S_W;
16003 goto do_unaryfp;
16004 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
16005 mips32_op = OPC_CVT_S_L;
16006 do_unaryfp:
16007 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
16008 break;
16010 /* Conditional moves on floating-point codes */
16011 case COND_FLOAT_MOV(MOVT, 0):
16012 case COND_FLOAT_MOV(MOVT, 1):
16013 case COND_FLOAT_MOV(MOVT, 2):
16014 case COND_FLOAT_MOV(MOVT, 3):
16015 case COND_FLOAT_MOV(MOVT, 4):
16016 case COND_FLOAT_MOV(MOVT, 5):
16017 case COND_FLOAT_MOV(MOVT, 6):
16018 case COND_FLOAT_MOV(MOVT, 7):
16019 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16020 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
16021 break;
16022 case COND_FLOAT_MOV(MOVF, 0):
16023 case COND_FLOAT_MOV(MOVF, 1):
16024 case COND_FLOAT_MOV(MOVF, 2):
16025 case COND_FLOAT_MOV(MOVF, 3):
16026 case COND_FLOAT_MOV(MOVF, 4):
16027 case COND_FLOAT_MOV(MOVF, 5):
16028 case COND_FLOAT_MOV(MOVF, 6):
16029 case COND_FLOAT_MOV(MOVF, 7):
16030 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16031 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
16032 break;
16033 default:
16034 MIPS_INVAL("pool32fxf");
16035 generate_exception_end(ctx, EXCP_RI);
16036 break;
16040 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
16042 int32_t offset;
16043 uint16_t insn;
16044 int rt, rs, rd, rr;
16045 int16_t imm;
16046 uint32_t op, minor, minor2, mips32_op;
16047 uint32_t cond, fmt, cc;
16049 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
16050 ctx->opcode = (ctx->opcode << 16) | insn;
16052 rt = (ctx->opcode >> 21) & 0x1f;
16053 rs = (ctx->opcode >> 16) & 0x1f;
16054 rd = (ctx->opcode >> 11) & 0x1f;
16055 rr = (ctx->opcode >> 6) & 0x1f;
16056 imm = (int16_t) ctx->opcode;
16058 op = (ctx->opcode >> 26) & 0x3f;
16059 switch (op) {
16060 case POOL32A:
16061 minor = ctx->opcode & 0x3f;
16062 switch (minor) {
16063 case 0x00:
16064 minor = (ctx->opcode >> 6) & 0xf;
16065 switch (minor) {
16066 case SLL32:
16067 mips32_op = OPC_SLL;
16068 goto do_shifti;
16069 case SRA:
16070 mips32_op = OPC_SRA;
16071 goto do_shifti;
16072 case SRL32:
16073 mips32_op = OPC_SRL;
16074 goto do_shifti;
16075 case ROTR:
16076 mips32_op = OPC_ROTR;
16077 do_shifti:
16078 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
16079 break;
16080 case SELEQZ:
16081 check_insn(ctx, ISA_MIPS32R6);
16082 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
16083 break;
16084 case SELNEZ:
16085 check_insn(ctx, ISA_MIPS32R6);
16086 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
16087 break;
16088 case R6_RDHWR:
16089 check_insn(ctx, ISA_MIPS32R6);
16090 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
16091 break;
16092 default:
16093 goto pool32a_invalid;
16095 break;
16096 case 0x10:
16097 minor = (ctx->opcode >> 6) & 0xf;
16098 switch (minor) {
16099 /* Arithmetic */
16100 case ADD:
16101 mips32_op = OPC_ADD;
16102 goto do_arith;
16103 case ADDU32:
16104 mips32_op = OPC_ADDU;
16105 goto do_arith;
16106 case SUB:
16107 mips32_op = OPC_SUB;
16108 goto do_arith;
16109 case SUBU32:
16110 mips32_op = OPC_SUBU;
16111 goto do_arith;
16112 case MUL:
16113 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16114 mips32_op = OPC_MUL;
16115 do_arith:
16116 gen_arith(ctx, mips32_op, rd, rs, rt);
16117 break;
16118 /* Shifts */
16119 case SLLV:
16120 mips32_op = OPC_SLLV;
16121 goto do_shift;
16122 case SRLV:
16123 mips32_op = OPC_SRLV;
16124 goto do_shift;
16125 case SRAV:
16126 mips32_op = OPC_SRAV;
16127 goto do_shift;
16128 case ROTRV:
16129 mips32_op = OPC_ROTRV;
16130 do_shift:
16131 gen_shift(ctx, mips32_op, rd, rs, rt);
16132 break;
16133 /* Logical operations */
16134 case AND:
16135 mips32_op = OPC_AND;
16136 goto do_logic;
16137 case OR32:
16138 mips32_op = OPC_OR;
16139 goto do_logic;
16140 case NOR:
16141 mips32_op = OPC_NOR;
16142 goto do_logic;
16143 case XOR32:
16144 mips32_op = OPC_XOR;
16145 do_logic:
16146 gen_logic(ctx, mips32_op, rd, rs, rt);
16147 break;
16148 /* Set less than */
16149 case SLT:
16150 mips32_op = OPC_SLT;
16151 goto do_slt;
16152 case SLTU:
16153 mips32_op = OPC_SLTU;
16154 do_slt:
16155 gen_slt(ctx, mips32_op, rd, rs, rt);
16156 break;
16157 default:
16158 goto pool32a_invalid;
16160 break;
16161 case 0x18:
16162 minor = (ctx->opcode >> 6) & 0xf;
16163 switch (minor) {
16164 /* Conditional moves */
16165 case MOVN: /* MUL */
16166 if (ctx->insn_flags & ISA_MIPS32R6) {
16167 /* MUL */
16168 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
16169 } else {
16170 /* MOVN */
16171 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
16173 break;
16174 case MOVZ: /* MUH */
16175 if (ctx->insn_flags & ISA_MIPS32R6) {
16176 /* MUH */
16177 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
16178 } else {
16179 /* MOVZ */
16180 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
16182 break;
16183 case MULU:
16184 check_insn(ctx, ISA_MIPS32R6);
16185 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
16186 break;
16187 case MUHU:
16188 check_insn(ctx, ISA_MIPS32R6);
16189 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
16190 break;
16191 case LWXS: /* DIV */
16192 if (ctx->insn_flags & ISA_MIPS32R6) {
16193 /* DIV */
16194 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
16195 } else {
16196 /* LWXS */
16197 gen_ldxs(ctx, rs, rt, rd);
16199 break;
16200 case MOD:
16201 check_insn(ctx, ISA_MIPS32R6);
16202 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
16203 break;
16204 case R6_DIVU:
16205 check_insn(ctx, ISA_MIPS32R6);
16206 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
16207 break;
16208 case MODU:
16209 check_insn(ctx, ISA_MIPS32R6);
16210 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
16211 break;
16212 default:
16213 goto pool32a_invalid;
16215 break;
16216 case INS:
16217 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
16218 return;
16219 case LSA:
16220 check_insn(ctx, ISA_MIPS32R6);
16221 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
16222 extract32(ctx->opcode, 9, 2));
16223 break;
16224 case ALIGN:
16225 check_insn(ctx, ISA_MIPS32R6);
16226 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
16227 break;
16228 case EXT:
16229 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
16230 return;
16231 case POOL32AXF:
16232 gen_pool32axf(env, ctx, rt, rs);
16233 break;
16234 case BREAK32:
16235 generate_exception_end(ctx, EXCP_BREAK);
16236 break;
16237 case SIGRIE:
16238 check_insn(ctx, ISA_MIPS32R6);
16239 generate_exception_end(ctx, EXCP_RI);
16240 break;
16241 default:
16242 pool32a_invalid:
16243 MIPS_INVAL("pool32a");
16244 generate_exception_end(ctx, EXCP_RI);
16245 break;
16247 break;
16248 case POOL32B:
16249 minor = (ctx->opcode >> 12) & 0xf;
16250 switch (minor) {
16251 case CACHE:
16252 check_cp0_enabled(ctx);
16253 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16254 gen_cache_operation(ctx, rt, rs, imm);
16256 break;
16257 case LWC2:
16258 case SWC2:
16259 /* COP2: Not implemented. */
16260 generate_exception_err(ctx, EXCP_CpU, 2);
16261 break;
16262 #ifdef TARGET_MIPS64
16263 case LDP:
16264 case SDP:
16265 check_insn(ctx, ISA_MIPS3);
16266 check_mips_64(ctx);
16267 #endif
16268 /* fall through */
16269 case LWP:
16270 case SWP:
16271 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16272 break;
16273 #ifdef TARGET_MIPS64
16274 case LDM:
16275 case SDM:
16276 check_insn(ctx, ISA_MIPS3);
16277 check_mips_64(ctx);
16278 #endif
16279 /* fall through */
16280 case LWM32:
16281 case SWM32:
16282 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16283 break;
16284 default:
16285 MIPS_INVAL("pool32b");
16286 generate_exception_end(ctx, EXCP_RI);
16287 break;
16289 break;
16290 case POOL32F:
16291 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
16292 minor = ctx->opcode & 0x3f;
16293 check_cp1_enabled(ctx);
16294 switch (minor) {
16295 case ALNV_PS:
16296 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16297 mips32_op = OPC_ALNV_PS;
16298 goto do_madd;
16299 case MADD_S:
16300 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16301 mips32_op = OPC_MADD_S;
16302 goto do_madd;
16303 case MADD_D:
16304 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16305 mips32_op = OPC_MADD_D;
16306 goto do_madd;
16307 case MADD_PS:
16308 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16309 mips32_op = OPC_MADD_PS;
16310 goto do_madd;
16311 case MSUB_S:
16312 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16313 mips32_op = OPC_MSUB_S;
16314 goto do_madd;
16315 case MSUB_D:
16316 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16317 mips32_op = OPC_MSUB_D;
16318 goto do_madd;
16319 case MSUB_PS:
16320 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16321 mips32_op = OPC_MSUB_PS;
16322 goto do_madd;
16323 case NMADD_S:
16324 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16325 mips32_op = OPC_NMADD_S;
16326 goto do_madd;
16327 case NMADD_D:
16328 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16329 mips32_op = OPC_NMADD_D;
16330 goto do_madd;
16331 case NMADD_PS:
16332 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16333 mips32_op = OPC_NMADD_PS;
16334 goto do_madd;
16335 case NMSUB_S:
16336 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16337 mips32_op = OPC_NMSUB_S;
16338 goto do_madd;
16339 case NMSUB_D:
16340 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16341 mips32_op = OPC_NMSUB_D;
16342 goto do_madd;
16343 case NMSUB_PS:
16344 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16345 mips32_op = OPC_NMSUB_PS;
16346 do_madd:
16347 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
16348 break;
16349 case CABS_COND_FMT:
16350 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16351 cond = (ctx->opcode >> 6) & 0xf;
16352 cc = (ctx->opcode >> 13) & 0x7;
16353 fmt = (ctx->opcode >> 10) & 0x3;
16354 switch (fmt) {
16355 case 0x0:
16356 gen_cmpabs_s(ctx, cond, rt, rs, cc);
16357 break;
16358 case 0x1:
16359 gen_cmpabs_d(ctx, cond, rt, rs, cc);
16360 break;
16361 case 0x2:
16362 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
16363 break;
16364 default:
16365 goto pool32f_invalid;
16367 break;
16368 case C_COND_FMT:
16369 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16370 cond = (ctx->opcode >> 6) & 0xf;
16371 cc = (ctx->opcode >> 13) & 0x7;
16372 fmt = (ctx->opcode >> 10) & 0x3;
16373 switch (fmt) {
16374 case 0x0:
16375 gen_cmp_s(ctx, cond, rt, rs, cc);
16376 break;
16377 case 0x1:
16378 gen_cmp_d(ctx, cond, rt, rs, cc);
16379 break;
16380 case 0x2:
16381 gen_cmp_ps(ctx, cond, rt, rs, cc);
16382 break;
16383 default:
16384 goto pool32f_invalid;
16386 break;
16387 case CMP_CONDN_S:
16388 check_insn(ctx, ISA_MIPS32R6);
16389 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16390 break;
16391 case CMP_CONDN_D:
16392 check_insn(ctx, ISA_MIPS32R6);
16393 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16394 break;
16395 case POOL32FXF:
16396 gen_pool32fxf(ctx, rt, rs);
16397 break;
16398 case 0x00:
16399 /* PLL foo */
16400 switch ((ctx->opcode >> 6) & 0x7) {
16401 case PLL_PS:
16402 mips32_op = OPC_PLL_PS;
16403 goto do_ps;
16404 case PLU_PS:
16405 mips32_op = OPC_PLU_PS;
16406 goto do_ps;
16407 case PUL_PS:
16408 mips32_op = OPC_PUL_PS;
16409 goto do_ps;
16410 case PUU_PS:
16411 mips32_op = OPC_PUU_PS;
16412 goto do_ps;
16413 case CVT_PS_S:
16414 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16415 mips32_op = OPC_CVT_PS_S;
16416 do_ps:
16417 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16418 break;
16419 default:
16420 goto pool32f_invalid;
16422 break;
16423 case MIN_FMT:
16424 check_insn(ctx, ISA_MIPS32R6);
16425 switch ((ctx->opcode >> 9) & 0x3) {
16426 case FMT_SDPS_S:
16427 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
16428 break;
16429 case FMT_SDPS_D:
16430 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
16431 break;
16432 default:
16433 goto pool32f_invalid;
16435 break;
16436 case 0x08:
16437 /* [LS][WDU]XC1 */
16438 switch ((ctx->opcode >> 6) & 0x7) {
16439 case LWXC1:
16440 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16441 mips32_op = OPC_LWXC1;
16442 goto do_ldst_cp1;
16443 case SWXC1:
16444 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16445 mips32_op = OPC_SWXC1;
16446 goto do_ldst_cp1;
16447 case LDXC1:
16448 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16449 mips32_op = OPC_LDXC1;
16450 goto do_ldst_cp1;
16451 case SDXC1:
16452 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16453 mips32_op = OPC_SDXC1;
16454 goto do_ldst_cp1;
16455 case LUXC1:
16456 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16457 mips32_op = OPC_LUXC1;
16458 goto do_ldst_cp1;
16459 case SUXC1:
16460 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16461 mips32_op = OPC_SUXC1;
16462 do_ldst_cp1:
16463 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
16464 break;
16465 default:
16466 goto pool32f_invalid;
16468 break;
16469 case MAX_FMT:
16470 check_insn(ctx, ISA_MIPS32R6);
16471 switch ((ctx->opcode >> 9) & 0x3) {
16472 case FMT_SDPS_S:
16473 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
16474 break;
16475 case FMT_SDPS_D:
16476 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
16477 break;
16478 default:
16479 goto pool32f_invalid;
16481 break;
16482 case 0x18:
16483 /* 3D insns */
16484 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16485 fmt = (ctx->opcode >> 9) & 0x3;
16486 switch ((ctx->opcode >> 6) & 0x7) {
16487 case RSQRT2_FMT:
16488 switch (fmt) {
16489 case FMT_SDPS_S:
16490 mips32_op = OPC_RSQRT2_S;
16491 goto do_3d;
16492 case FMT_SDPS_D:
16493 mips32_op = OPC_RSQRT2_D;
16494 goto do_3d;
16495 case FMT_SDPS_PS:
16496 mips32_op = OPC_RSQRT2_PS;
16497 goto do_3d;
16498 default:
16499 goto pool32f_invalid;
16501 break;
16502 case RECIP2_FMT:
16503 switch (fmt) {
16504 case FMT_SDPS_S:
16505 mips32_op = OPC_RECIP2_S;
16506 goto do_3d;
16507 case FMT_SDPS_D:
16508 mips32_op = OPC_RECIP2_D;
16509 goto do_3d;
16510 case FMT_SDPS_PS:
16511 mips32_op = OPC_RECIP2_PS;
16512 goto do_3d;
16513 default:
16514 goto pool32f_invalid;
16516 break;
16517 case ADDR_PS:
16518 mips32_op = OPC_ADDR_PS;
16519 goto do_3d;
16520 case MULR_PS:
16521 mips32_op = OPC_MULR_PS;
16522 do_3d:
16523 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16524 break;
16525 default:
16526 goto pool32f_invalid;
16528 break;
16529 case 0x20:
16530 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
16531 cc = (ctx->opcode >> 13) & 0x7;
16532 fmt = (ctx->opcode >> 9) & 0x3;
16533 switch ((ctx->opcode >> 6) & 0x7) {
16534 case MOVF_FMT: /* RINT_FMT */
16535 if (ctx->insn_flags & ISA_MIPS32R6) {
16536 /* RINT_FMT */
16537 switch (fmt) {
16538 case FMT_SDPS_S:
16539 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
16540 break;
16541 case FMT_SDPS_D:
16542 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
16543 break;
16544 default:
16545 goto pool32f_invalid;
16547 } else {
16548 /* MOVF_FMT */
16549 switch (fmt) {
16550 case FMT_SDPS_S:
16551 gen_movcf_s(ctx, rs, rt, cc, 0);
16552 break;
16553 case FMT_SDPS_D:
16554 gen_movcf_d(ctx, rs, rt, cc, 0);
16555 break;
16556 case FMT_SDPS_PS:
16557 check_ps(ctx);
16558 gen_movcf_ps(ctx, rs, rt, cc, 0);
16559 break;
16560 default:
16561 goto pool32f_invalid;
16564 break;
16565 case MOVT_FMT: /* CLASS_FMT */
16566 if (ctx->insn_flags & ISA_MIPS32R6) {
16567 /* CLASS_FMT */
16568 switch (fmt) {
16569 case FMT_SDPS_S:
16570 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
16571 break;
16572 case FMT_SDPS_D:
16573 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
16574 break;
16575 default:
16576 goto pool32f_invalid;
16578 } else {
16579 /* MOVT_FMT */
16580 switch (fmt) {
16581 case FMT_SDPS_S:
16582 gen_movcf_s(ctx, rs, rt, cc, 1);
16583 break;
16584 case FMT_SDPS_D:
16585 gen_movcf_d(ctx, rs, rt, cc, 1);
16586 break;
16587 case FMT_SDPS_PS:
16588 check_ps(ctx);
16589 gen_movcf_ps(ctx, rs, rt, cc, 1);
16590 break;
16591 default:
16592 goto pool32f_invalid;
16595 break;
16596 case PREFX:
16597 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16598 break;
16599 default:
16600 goto pool32f_invalid;
16602 break;
16603 #define FINSN_3ARG_SDPS(prfx) \
16604 switch ((ctx->opcode >> 8) & 0x3) { \
16605 case FMT_SDPS_S: \
16606 mips32_op = OPC_##prfx##_S; \
16607 goto do_fpop; \
16608 case FMT_SDPS_D: \
16609 mips32_op = OPC_##prfx##_D; \
16610 goto do_fpop; \
16611 case FMT_SDPS_PS: \
16612 check_ps(ctx); \
16613 mips32_op = OPC_##prfx##_PS; \
16614 goto do_fpop; \
16615 default: \
16616 goto pool32f_invalid; \
16618 case MINA_FMT:
16619 check_insn(ctx, ISA_MIPS32R6);
16620 switch ((ctx->opcode >> 9) & 0x3) {
16621 case FMT_SDPS_S:
16622 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
16623 break;
16624 case FMT_SDPS_D:
16625 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
16626 break;
16627 default:
16628 goto pool32f_invalid;
16630 break;
16631 case MAXA_FMT:
16632 check_insn(ctx, ISA_MIPS32R6);
16633 switch ((ctx->opcode >> 9) & 0x3) {
16634 case FMT_SDPS_S:
16635 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
16636 break;
16637 case FMT_SDPS_D:
16638 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
16639 break;
16640 default:
16641 goto pool32f_invalid;
16643 break;
16644 case 0x30:
16645 /* regular FP ops */
16646 switch ((ctx->opcode >> 6) & 0x3) {
16647 case ADD_FMT:
16648 FINSN_3ARG_SDPS(ADD);
16649 break;
16650 case SUB_FMT:
16651 FINSN_3ARG_SDPS(SUB);
16652 break;
16653 case MUL_FMT:
16654 FINSN_3ARG_SDPS(MUL);
16655 break;
16656 case DIV_FMT:
16657 fmt = (ctx->opcode >> 8) & 0x3;
16658 if (fmt == 1) {
16659 mips32_op = OPC_DIV_D;
16660 } else if (fmt == 0) {
16661 mips32_op = OPC_DIV_S;
16662 } else {
16663 goto pool32f_invalid;
16665 goto do_fpop;
16666 default:
16667 goto pool32f_invalid;
16669 break;
16670 case 0x38:
16671 /* cmovs */
16672 switch ((ctx->opcode >> 6) & 0x7) {
16673 case MOVN_FMT: /* SELEQZ_FMT */
16674 if (ctx->insn_flags & ISA_MIPS32R6) {
16675 /* SELEQZ_FMT */
16676 switch ((ctx->opcode >> 9) & 0x3) {
16677 case FMT_SDPS_S:
16678 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
16679 break;
16680 case FMT_SDPS_D:
16681 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
16682 break;
16683 default:
16684 goto pool32f_invalid;
16686 } else {
16687 /* MOVN_FMT */
16688 FINSN_3ARG_SDPS(MOVN);
16690 break;
16691 case MOVN_FMT_04:
16692 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16693 FINSN_3ARG_SDPS(MOVN);
16694 break;
16695 case MOVZ_FMT: /* SELNEZ_FMT */
16696 if (ctx->insn_flags & ISA_MIPS32R6) {
16697 /* SELNEZ_FMT */
16698 switch ((ctx->opcode >> 9) & 0x3) {
16699 case FMT_SDPS_S:
16700 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
16701 break;
16702 case FMT_SDPS_D:
16703 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
16704 break;
16705 default:
16706 goto pool32f_invalid;
16708 } else {
16709 /* MOVZ_FMT */
16710 FINSN_3ARG_SDPS(MOVZ);
16712 break;
16713 case MOVZ_FMT_05:
16714 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16715 FINSN_3ARG_SDPS(MOVZ);
16716 break;
16717 case SEL_FMT:
16718 check_insn(ctx, ISA_MIPS32R6);
16719 switch ((ctx->opcode >> 9) & 0x3) {
16720 case FMT_SDPS_S:
16721 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
16722 break;
16723 case FMT_SDPS_D:
16724 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
16725 break;
16726 default:
16727 goto pool32f_invalid;
16729 break;
16730 case MADDF_FMT:
16731 check_insn(ctx, ISA_MIPS32R6);
16732 switch ((ctx->opcode >> 9) & 0x3) {
16733 case FMT_SDPS_S:
16734 mips32_op = OPC_MADDF_S;
16735 goto do_fpop;
16736 case FMT_SDPS_D:
16737 mips32_op = OPC_MADDF_D;
16738 goto do_fpop;
16739 default:
16740 goto pool32f_invalid;
16742 break;
16743 case MSUBF_FMT:
16744 check_insn(ctx, ISA_MIPS32R6);
16745 switch ((ctx->opcode >> 9) & 0x3) {
16746 case FMT_SDPS_S:
16747 mips32_op = OPC_MSUBF_S;
16748 goto do_fpop;
16749 case FMT_SDPS_D:
16750 mips32_op = OPC_MSUBF_D;
16751 goto do_fpop;
16752 default:
16753 goto pool32f_invalid;
16755 break;
16756 default:
16757 goto pool32f_invalid;
16759 break;
16760 do_fpop:
16761 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16762 break;
16763 default:
16764 pool32f_invalid:
16765 MIPS_INVAL("pool32f");
16766 generate_exception_end(ctx, EXCP_RI);
16767 break;
16769 } else {
16770 generate_exception_err(ctx, EXCP_CpU, 1);
16772 break;
16773 case POOL32I:
16774 minor = (ctx->opcode >> 21) & 0x1f;
16775 switch (minor) {
16776 case BLTZ:
16777 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16778 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
16779 break;
16780 case BLTZAL:
16781 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16782 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
16783 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16784 break;
16785 case BLTZALS:
16786 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16787 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
16788 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16789 break;
16790 case BGEZ:
16791 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16792 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
16793 break;
16794 case BGEZAL:
16795 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16796 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
16797 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16798 break;
16799 case BGEZALS:
16800 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16801 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
16802 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16803 break;
16804 case BLEZ:
16805 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16806 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
16807 break;
16808 case BGTZ:
16809 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16810 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
16811 break;
16813 /* Traps */
16814 case TLTI: /* BC1EQZC */
16815 if (ctx->insn_flags & ISA_MIPS32R6) {
16816 /* BC1EQZC */
16817 check_cp1_enabled(ctx);
16818 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
16819 } else {
16820 /* TLTI */
16821 mips32_op = OPC_TLTI;
16822 goto do_trapi;
16824 break;
16825 case TGEI: /* BC1NEZC */
16826 if (ctx->insn_flags & ISA_MIPS32R6) {
16827 /* BC1NEZC */
16828 check_cp1_enabled(ctx);
16829 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
16830 } else {
16831 /* TGEI */
16832 mips32_op = OPC_TGEI;
16833 goto do_trapi;
16835 break;
16836 case TLTIU:
16837 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16838 mips32_op = OPC_TLTIU;
16839 goto do_trapi;
16840 case TGEIU:
16841 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16842 mips32_op = OPC_TGEIU;
16843 goto do_trapi;
16844 case TNEI: /* SYNCI */
16845 if (ctx->insn_flags & ISA_MIPS32R6) {
16846 /* SYNCI */
16848 * Break the TB to be able to sync copied instructions
16849 * immediately.
16851 ctx->base.is_jmp = DISAS_STOP;
16852 } else {
16853 /* TNEI */
16854 mips32_op = OPC_TNEI;
16855 goto do_trapi;
16857 break;
16858 case TEQI:
16859 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16860 mips32_op = OPC_TEQI;
16861 do_trapi:
16862 gen_trap(ctx, mips32_op, rs, -1, imm);
16863 break;
16865 case BNEZC:
16866 case BEQZC:
16867 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16868 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
16869 4, rs, 0, imm << 1, 0);
16871 * Compact branches don't have a delay slot, so just let
16872 * the normal delay slot handling take us to the branch
16873 * target.
16875 break;
16876 case LUI:
16877 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16878 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
16879 break;
16880 case SYNCI:
16881 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16883 * Break the TB to be able to sync copied instructions
16884 * immediately.
16886 ctx->base.is_jmp = DISAS_STOP;
16887 break;
16888 case BC2F:
16889 case BC2T:
16890 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16891 /* COP2: Not implemented. */
16892 generate_exception_err(ctx, EXCP_CpU, 2);
16893 break;
16894 case BC1F:
16895 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16896 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
16897 goto do_cp1branch;
16898 case BC1T:
16899 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16900 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
16901 goto do_cp1branch;
16902 case BC1ANY4F:
16903 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16904 mips32_op = OPC_BC1FANY4;
16905 goto do_cp1mips3d;
16906 case BC1ANY4T:
16907 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16908 mips32_op = OPC_BC1TANY4;
16909 do_cp1mips3d:
16910 check_cop1x(ctx);
16911 check_insn(ctx, ASE_MIPS3D);
16912 /* Fall through */
16913 do_cp1branch:
16914 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16915 check_cp1_enabled(ctx);
16916 gen_compute_branch1(ctx, mips32_op,
16917 (ctx->opcode >> 18) & 0x7, imm << 1);
16918 } else {
16919 generate_exception_err(ctx, EXCP_CpU, 1);
16921 break;
16922 case BPOSGE64:
16923 case BPOSGE32:
16924 /* MIPS DSP: not implemented */
16925 /* Fall through */
16926 default:
16927 MIPS_INVAL("pool32i");
16928 generate_exception_end(ctx, EXCP_RI);
16929 break;
16931 break;
16932 case POOL32C:
16933 minor = (ctx->opcode >> 12) & 0xf;
16934 offset = sextract32(ctx->opcode, 0,
16935 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
16936 switch (minor) {
16937 case LWL:
16938 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16939 mips32_op = OPC_LWL;
16940 goto do_ld_lr;
16941 case SWL:
16942 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16943 mips32_op = OPC_SWL;
16944 goto do_st_lr;
16945 case LWR:
16946 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16947 mips32_op = OPC_LWR;
16948 goto do_ld_lr;
16949 case SWR:
16950 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16951 mips32_op = OPC_SWR;
16952 goto do_st_lr;
16953 #if defined(TARGET_MIPS64)
16954 case LDL:
16955 check_insn(ctx, ISA_MIPS3);
16956 check_mips_64(ctx);
16957 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16958 mips32_op = OPC_LDL;
16959 goto do_ld_lr;
16960 case SDL:
16961 check_insn(ctx, ISA_MIPS3);
16962 check_mips_64(ctx);
16963 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16964 mips32_op = OPC_SDL;
16965 goto do_st_lr;
16966 case LDR:
16967 check_insn(ctx, ISA_MIPS3);
16968 check_mips_64(ctx);
16969 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16970 mips32_op = OPC_LDR;
16971 goto do_ld_lr;
16972 case SDR:
16973 check_insn(ctx, ISA_MIPS3);
16974 check_mips_64(ctx);
16975 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16976 mips32_op = OPC_SDR;
16977 goto do_st_lr;
16978 case LWU:
16979 check_insn(ctx, ISA_MIPS3);
16980 check_mips_64(ctx);
16981 mips32_op = OPC_LWU;
16982 goto do_ld_lr;
16983 case LLD:
16984 check_insn(ctx, ISA_MIPS3);
16985 check_mips_64(ctx);
16986 mips32_op = OPC_LLD;
16987 goto do_ld_lr;
16988 #endif
16989 case LL:
16990 mips32_op = OPC_LL;
16991 goto do_ld_lr;
16992 do_ld_lr:
16993 gen_ld(ctx, mips32_op, rt, rs, offset);
16994 break;
16995 do_st_lr:
16996 gen_st(ctx, mips32_op, rt, rs, offset);
16997 break;
16998 case SC:
16999 gen_st_cond(ctx, rt, rs, offset, MO_TESL, false);
17000 break;
17001 #if defined(TARGET_MIPS64)
17002 case SCD:
17003 check_insn(ctx, ISA_MIPS3);
17004 check_mips_64(ctx);
17005 gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false);
17006 break;
17007 #endif
17008 case LD_EVA:
17009 if (!ctx->eva) {
17010 MIPS_INVAL("pool32c ld-eva");
17011 generate_exception_end(ctx, EXCP_RI);
17012 break;
17014 check_cp0_enabled(ctx);
17016 minor2 = (ctx->opcode >> 9) & 0x7;
17017 offset = sextract32(ctx->opcode, 0, 9);
17018 switch (minor2) {
17019 case LBUE:
17020 mips32_op = OPC_LBUE;
17021 goto do_ld_lr;
17022 case LHUE:
17023 mips32_op = OPC_LHUE;
17024 goto do_ld_lr;
17025 case LWLE:
17026 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17027 mips32_op = OPC_LWLE;
17028 goto do_ld_lr;
17029 case LWRE:
17030 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17031 mips32_op = OPC_LWRE;
17032 goto do_ld_lr;
17033 case LBE:
17034 mips32_op = OPC_LBE;
17035 goto do_ld_lr;
17036 case LHE:
17037 mips32_op = OPC_LHE;
17038 goto do_ld_lr;
17039 case LLE:
17040 mips32_op = OPC_LLE;
17041 goto do_ld_lr;
17042 case LWE:
17043 mips32_op = OPC_LWE;
17044 goto do_ld_lr;
17046 break;
17047 case ST_EVA:
17048 if (!ctx->eva) {
17049 MIPS_INVAL("pool32c st-eva");
17050 generate_exception_end(ctx, EXCP_RI);
17051 break;
17053 check_cp0_enabled(ctx);
17055 minor2 = (ctx->opcode >> 9) & 0x7;
17056 offset = sextract32(ctx->opcode, 0, 9);
17057 switch (minor2) {
17058 case SWLE:
17059 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17060 mips32_op = OPC_SWLE;
17061 goto do_st_lr;
17062 case SWRE:
17063 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17064 mips32_op = OPC_SWRE;
17065 goto do_st_lr;
17066 case PREFE:
17067 /* Treat as no-op */
17068 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
17069 /* hint codes 24-31 are reserved and signal RI */
17070 generate_exception(ctx, EXCP_RI);
17072 break;
17073 case CACHEE:
17074 /* Treat as no-op */
17075 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
17076 gen_cache_operation(ctx, rt, rs, offset);
17078 break;
17079 case SBE:
17080 mips32_op = OPC_SBE;
17081 goto do_st_lr;
17082 case SHE:
17083 mips32_op = OPC_SHE;
17084 goto do_st_lr;
17085 case SCE:
17086 gen_st_cond(ctx, rt, rs, offset, MO_TESL, true);
17087 break;
17088 case SWE:
17089 mips32_op = OPC_SWE;
17090 goto do_st_lr;
17092 break;
17093 case PREF:
17094 /* Treat as no-op */
17095 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
17096 /* hint codes 24-31 are reserved and signal RI */
17097 generate_exception(ctx, EXCP_RI);
17099 break;
17100 default:
17101 MIPS_INVAL("pool32c");
17102 generate_exception_end(ctx, EXCP_RI);
17103 break;
17105 break;
17106 case ADDI32: /* AUI, LUI */
17107 if (ctx->insn_flags & ISA_MIPS32R6) {
17108 /* AUI, LUI */
17109 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
17110 } else {
17111 /* ADDI32 */
17112 mips32_op = OPC_ADDI;
17113 goto do_addi;
17115 break;
17116 case ADDIU32:
17117 mips32_op = OPC_ADDIU;
17118 do_addi:
17119 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
17120 break;
17122 /* Logical operations */
17123 case ORI32:
17124 mips32_op = OPC_ORI;
17125 goto do_logici;
17126 case XORI32:
17127 mips32_op = OPC_XORI;
17128 goto do_logici;
17129 case ANDI32:
17130 mips32_op = OPC_ANDI;
17131 do_logici:
17132 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
17133 break;
17135 /* Set less than immediate */
17136 case SLTI32:
17137 mips32_op = OPC_SLTI;
17138 goto do_slti;
17139 case SLTIU32:
17140 mips32_op = OPC_SLTIU;
17141 do_slti:
17142 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
17143 break;
17144 case JALX32:
17145 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17146 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
17147 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
17148 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17149 break;
17150 case JALS32: /* BOVC, BEQC, BEQZALC */
17151 if (ctx->insn_flags & ISA_MIPS32R6) {
17152 if (rs >= rt) {
17153 /* BOVC */
17154 mips32_op = OPC_BOVC;
17155 } else if (rs < rt && rs == 0) {
17156 /* BEQZALC */
17157 mips32_op = OPC_BEQZALC;
17158 } else {
17159 /* BEQC */
17160 mips32_op = OPC_BEQC;
17162 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17163 } else {
17164 /* JALS32 */
17165 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
17166 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
17167 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17169 break;
17170 case BEQ32: /* BC */
17171 if (ctx->insn_flags & ISA_MIPS32R6) {
17172 /* BC */
17173 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
17174 sextract32(ctx->opcode << 1, 0, 27));
17175 } else {
17176 /* BEQ32 */
17177 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
17179 break;
17180 case BNE32: /* BALC */
17181 if (ctx->insn_flags & ISA_MIPS32R6) {
17182 /* BALC */
17183 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
17184 sextract32(ctx->opcode << 1, 0, 27));
17185 } else {
17186 /* BNE32 */
17187 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
17189 break;
17190 case J32: /* BGTZC, BLTZC, BLTC */
17191 if (ctx->insn_flags & ISA_MIPS32R6) {
17192 if (rs == 0 && rt != 0) {
17193 /* BGTZC */
17194 mips32_op = OPC_BGTZC;
17195 } else if (rs != 0 && rt != 0 && rs == rt) {
17196 /* BLTZC */
17197 mips32_op = OPC_BLTZC;
17198 } else {
17199 /* BLTC */
17200 mips32_op = OPC_BLTC;
17202 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17203 } else {
17204 /* J32 */
17205 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
17206 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17208 break;
17209 case JAL32: /* BLEZC, BGEZC, BGEC */
17210 if (ctx->insn_flags & ISA_MIPS32R6) {
17211 if (rs == 0 && rt != 0) {
17212 /* BLEZC */
17213 mips32_op = OPC_BLEZC;
17214 } else if (rs != 0 && rt != 0 && rs == rt) {
17215 /* BGEZC */
17216 mips32_op = OPC_BGEZC;
17217 } else {
17218 /* BGEC */
17219 mips32_op = OPC_BGEC;
17221 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17222 } else {
17223 /* JAL32 */
17224 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
17225 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17226 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17228 break;
17229 /* Floating point (COP1) */
17230 case LWC132:
17231 mips32_op = OPC_LWC1;
17232 goto do_cop1;
17233 case LDC132:
17234 mips32_op = OPC_LDC1;
17235 goto do_cop1;
17236 case SWC132:
17237 mips32_op = OPC_SWC1;
17238 goto do_cop1;
17239 case SDC132:
17240 mips32_op = OPC_SDC1;
17241 do_cop1:
17242 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
17243 break;
17244 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17245 if (ctx->insn_flags & ISA_MIPS32R6) {
17246 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17247 switch ((ctx->opcode >> 16) & 0x1f) {
17248 case ADDIUPC_00:
17249 case ADDIUPC_01:
17250 case ADDIUPC_02:
17251 case ADDIUPC_03:
17252 case ADDIUPC_04:
17253 case ADDIUPC_05:
17254 case ADDIUPC_06:
17255 case ADDIUPC_07:
17256 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
17257 break;
17258 case AUIPC:
17259 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
17260 break;
17261 case ALUIPC:
17262 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
17263 break;
17264 case LWPC_08:
17265 case LWPC_09:
17266 case LWPC_0A:
17267 case LWPC_0B:
17268 case LWPC_0C:
17269 case LWPC_0D:
17270 case LWPC_0E:
17271 case LWPC_0F:
17272 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
17273 break;
17274 default:
17275 generate_exception(ctx, EXCP_RI);
17276 break;
17278 } else {
17279 /* ADDIUPC */
17280 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
17281 offset = SIMM(ctx->opcode, 0, 23) << 2;
17283 gen_addiupc(ctx, reg, offset, 0, 0);
17285 break;
17286 case BNVC: /* BNEC, BNEZALC */
17287 check_insn(ctx, ISA_MIPS32R6);
17288 if (rs >= rt) {
17289 /* BNVC */
17290 mips32_op = OPC_BNVC;
17291 } else if (rs < rt && rs == 0) {
17292 /* BNEZALC */
17293 mips32_op = OPC_BNEZALC;
17294 } else {
17295 /* BNEC */
17296 mips32_op = OPC_BNEC;
17298 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17299 break;
17300 case R6_BNEZC: /* JIALC */
17301 check_insn(ctx, ISA_MIPS32R6);
17302 if (rt != 0) {
17303 /* BNEZC */
17304 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
17305 sextract32(ctx->opcode << 1, 0, 22));
17306 } else {
17307 /* JIALC */
17308 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
17310 break;
17311 case R6_BEQZC: /* JIC */
17312 check_insn(ctx, ISA_MIPS32R6);
17313 if (rt != 0) {
17314 /* BEQZC */
17315 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
17316 sextract32(ctx->opcode << 1, 0, 22));
17317 } else {
17318 /* JIC */
17319 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
17321 break;
17322 case BLEZALC: /* BGEZALC, BGEUC */
17323 check_insn(ctx, ISA_MIPS32R6);
17324 if (rs == 0 && rt != 0) {
17325 /* BLEZALC */
17326 mips32_op = OPC_BLEZALC;
17327 } else if (rs != 0 && rt != 0 && rs == rt) {
17328 /* BGEZALC */
17329 mips32_op = OPC_BGEZALC;
17330 } else {
17331 /* BGEUC */
17332 mips32_op = OPC_BGEUC;
17334 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17335 break;
17336 case BGTZALC: /* BLTZALC, BLTUC */
17337 check_insn(ctx, ISA_MIPS32R6);
17338 if (rs == 0 && rt != 0) {
17339 /* BGTZALC */
17340 mips32_op = OPC_BGTZALC;
17341 } else if (rs != 0 && rt != 0 && rs == rt) {
17342 /* BLTZALC */
17343 mips32_op = OPC_BLTZALC;
17344 } else {
17345 /* BLTUC */
17346 mips32_op = OPC_BLTUC;
17348 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17349 break;
17350 /* Loads and stores */
17351 case LB32:
17352 mips32_op = OPC_LB;
17353 goto do_ld;
17354 case LBU32:
17355 mips32_op = OPC_LBU;
17356 goto do_ld;
17357 case LH32:
17358 mips32_op = OPC_LH;
17359 goto do_ld;
17360 case LHU32:
17361 mips32_op = OPC_LHU;
17362 goto do_ld;
17363 case LW32:
17364 mips32_op = OPC_LW;
17365 goto do_ld;
17366 #ifdef TARGET_MIPS64
17367 case LD32:
17368 check_insn(ctx, ISA_MIPS3);
17369 check_mips_64(ctx);
17370 mips32_op = OPC_LD;
17371 goto do_ld;
17372 case SD32:
17373 check_insn(ctx, ISA_MIPS3);
17374 check_mips_64(ctx);
17375 mips32_op = OPC_SD;
17376 goto do_st;
17377 #endif
17378 case SB32:
17379 mips32_op = OPC_SB;
17380 goto do_st;
17381 case SH32:
17382 mips32_op = OPC_SH;
17383 goto do_st;
17384 case SW32:
17385 mips32_op = OPC_SW;
17386 goto do_st;
17387 do_ld:
17388 gen_ld(ctx, mips32_op, rt, rs, imm);
17389 break;
17390 do_st:
17391 gen_st(ctx, mips32_op, rt, rs, imm);
17392 break;
17393 default:
17394 generate_exception_end(ctx, EXCP_RI);
17395 break;
17399 static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx)
17401 uint32_t op;
17403 /* make sure instructions are on a halfword boundary */
17404 if (ctx->base.pc_next & 0x1) {
17405 env->CP0_BadVAddr = ctx->base.pc_next;
17406 generate_exception_end(ctx, EXCP_AdEL);
17407 return 2;
17410 op = (ctx->opcode >> 10) & 0x3f;
17411 /* Enforce properly-sized instructions in a delay slot */
17412 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
17413 switch (op & 0x7) { /* MSB-3..MSB-5 */
17414 case 0:
17415 /* POOL32A, POOL32B, POOL32I, POOL32C */
17416 case 4:
17417 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
17418 case 5:
17419 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
17420 case 6:
17421 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
17422 case 7:
17423 /* LB32, LH32, LWC132, LDC132, LW32 */
17424 if (ctx->hflags & MIPS_HFLAG_BDS16) {
17425 generate_exception_end(ctx, EXCP_RI);
17426 return 2;
17428 break;
17429 case 1:
17430 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
17431 case 2:
17432 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
17433 case 3:
17434 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
17435 if (ctx->hflags & MIPS_HFLAG_BDS32) {
17436 generate_exception_end(ctx, EXCP_RI);
17437 return 2;
17439 break;
17443 switch (op) {
17444 case POOL16A:
17446 int rd = mmreg(uMIPS_RD(ctx->opcode));
17447 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
17448 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
17449 uint32_t opc = 0;
17451 switch (ctx->opcode & 0x1) {
17452 case ADDU16:
17453 opc = OPC_ADDU;
17454 break;
17455 case SUBU16:
17456 opc = OPC_SUBU;
17457 break;
17459 if (ctx->insn_flags & ISA_MIPS32R6) {
17461 * In the Release 6, the register number location in
17462 * the instruction encoding has changed.
17464 gen_arith(ctx, opc, rs1, rd, rs2);
17465 } else {
17466 gen_arith(ctx, opc, rd, rs1, rs2);
17469 break;
17470 case POOL16B:
17472 int rd = mmreg(uMIPS_RD(ctx->opcode));
17473 int rs = mmreg(uMIPS_RS(ctx->opcode));
17474 int amount = (ctx->opcode >> 1) & 0x7;
17475 uint32_t opc = 0;
17476 amount = amount == 0 ? 8 : amount;
17478 switch (ctx->opcode & 0x1) {
17479 case SLL16:
17480 opc = OPC_SLL;
17481 break;
17482 case SRL16:
17483 opc = OPC_SRL;
17484 break;
17487 gen_shift_imm(ctx, opc, rd, rs, amount);
17489 break;
17490 case POOL16C:
17491 if (ctx->insn_flags & ISA_MIPS32R6) {
17492 gen_pool16c_r6_insn(ctx);
17493 } else {
17494 gen_pool16c_insn(ctx);
17496 break;
17497 case LWGP16:
17499 int rd = mmreg(uMIPS_RD(ctx->opcode));
17500 int rb = 28; /* GP */
17501 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
17503 gen_ld(ctx, OPC_LW, rd, rb, offset);
17505 break;
17506 case POOL16F:
17507 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17508 if (ctx->opcode & 1) {
17509 generate_exception_end(ctx, EXCP_RI);
17510 } else {
17511 /* MOVEP */
17512 int enc_dest = uMIPS_RD(ctx->opcode);
17513 int enc_rt = uMIPS_RS2(ctx->opcode);
17514 int enc_rs = uMIPS_RS1(ctx->opcode);
17515 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
17517 break;
17518 case LBU16:
17520 int rd = mmreg(uMIPS_RD(ctx->opcode));
17521 int rb = mmreg(uMIPS_RS(ctx->opcode));
17522 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17523 offset = (offset == 0xf ? -1 : offset);
17525 gen_ld(ctx, OPC_LBU, rd, rb, offset);
17527 break;
17528 case LHU16:
17530 int rd = mmreg(uMIPS_RD(ctx->opcode));
17531 int rb = mmreg(uMIPS_RS(ctx->opcode));
17532 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17534 gen_ld(ctx, OPC_LHU, rd, rb, offset);
17536 break;
17537 case LWSP16:
17539 int rd = (ctx->opcode >> 5) & 0x1f;
17540 int rb = 29; /* SP */
17541 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17543 gen_ld(ctx, OPC_LW, rd, rb, offset);
17545 break;
17546 case LW16:
17548 int rd = mmreg(uMIPS_RD(ctx->opcode));
17549 int rb = mmreg(uMIPS_RS(ctx->opcode));
17550 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17552 gen_ld(ctx, OPC_LW, rd, rb, offset);
17554 break;
17555 case SB16:
17557 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17558 int rb = mmreg(uMIPS_RS(ctx->opcode));
17559 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17561 gen_st(ctx, OPC_SB, rd, rb, offset);
17563 break;
17564 case SH16:
17566 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17567 int rb = mmreg(uMIPS_RS(ctx->opcode));
17568 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17570 gen_st(ctx, OPC_SH, rd, rb, offset);
17572 break;
17573 case SWSP16:
17575 int rd = (ctx->opcode >> 5) & 0x1f;
17576 int rb = 29; /* SP */
17577 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17579 gen_st(ctx, OPC_SW, rd, rb, offset);
17581 break;
17582 case SW16:
17584 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17585 int rb = mmreg(uMIPS_RS(ctx->opcode));
17586 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17588 gen_st(ctx, OPC_SW, rd, rb, offset);
17590 break;
17591 case MOVE16:
17593 int rd = uMIPS_RD5(ctx->opcode);
17594 int rs = uMIPS_RS5(ctx->opcode);
17596 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
17598 break;
17599 case ANDI16:
17600 gen_andi16(ctx);
17601 break;
17602 case POOL16D:
17603 switch (ctx->opcode & 0x1) {
17604 case ADDIUS5:
17605 gen_addius5(ctx);
17606 break;
17607 case ADDIUSP:
17608 gen_addiusp(ctx);
17609 break;
17611 break;
17612 case POOL16E:
17613 switch (ctx->opcode & 0x1) {
17614 case ADDIUR2:
17615 gen_addiur2(ctx);
17616 break;
17617 case ADDIUR1SP:
17618 gen_addiur1sp(ctx);
17619 break;
17621 break;
17622 case B16: /* BC16 */
17623 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
17624 sextract32(ctx->opcode, 0, 10) << 1,
17625 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17626 break;
17627 case BNEZ16: /* BNEZC16 */
17628 case BEQZ16: /* BEQZC16 */
17629 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
17630 mmreg(uMIPS_RD(ctx->opcode)),
17631 0, sextract32(ctx->opcode, 0, 7) << 1,
17632 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17634 break;
17635 case LI16:
17637 int reg = mmreg(uMIPS_RD(ctx->opcode));
17638 int imm = ZIMM(ctx->opcode, 0, 7);
17640 imm = (imm == 0x7f ? -1 : imm);
17641 tcg_gen_movi_tl(cpu_gpr[reg], imm);
17643 break;
17644 case RES_29:
17645 case RES_31:
17646 case RES_39:
17647 generate_exception_end(ctx, EXCP_RI);
17648 break;
17649 default:
17650 decode_micromips32_opc(env, ctx);
17651 return 4;
17654 return 2;
17659 * nanoMIPS opcodes
17663 /* MAJOR, P16, and P32 pools opcodes */
17664 enum {
17665 NM_P_ADDIU = 0x00,
17666 NM_ADDIUPC = 0x01,
17667 NM_MOVE_BALC = 0x02,
17668 NM_P16_MV = 0x04,
17669 NM_LW16 = 0x05,
17670 NM_BC16 = 0x06,
17671 NM_P16_SR = 0x07,
17673 NM_POOL32A = 0x08,
17674 NM_P_BAL = 0x0a,
17675 NM_P16_SHIFT = 0x0c,
17676 NM_LWSP16 = 0x0d,
17677 NM_BALC16 = 0x0e,
17678 NM_P16_4X4 = 0x0f,
17680 NM_P_GP_W = 0x10,
17681 NM_P_GP_BH = 0x11,
17682 NM_P_J = 0x12,
17683 NM_P16C = 0x14,
17684 NM_LWGP16 = 0x15,
17685 NM_P16_LB = 0x17,
17687 NM_P48I = 0x18,
17688 NM_P16_A1 = 0x1c,
17689 NM_LW4X4 = 0x1d,
17690 NM_P16_LH = 0x1f,
17692 NM_P_U12 = 0x20,
17693 NM_P_LS_U12 = 0x21,
17694 NM_P_BR1 = 0x22,
17695 NM_P16_A2 = 0x24,
17696 NM_SW16 = 0x25,
17697 NM_BEQZC16 = 0x26,
17699 NM_POOL32F = 0x28,
17700 NM_P_LS_S9 = 0x29,
17701 NM_P_BR2 = 0x2a,
17703 NM_P16_ADDU = 0x2c,
17704 NM_SWSP16 = 0x2d,
17705 NM_BNEZC16 = 0x2e,
17706 NM_MOVEP = 0x2f,
17708 NM_POOL32S = 0x30,
17709 NM_P_BRI = 0x32,
17710 NM_LI16 = 0x34,
17711 NM_SWGP16 = 0x35,
17712 NM_P16_BR = 0x36,
17714 NM_P_LUI = 0x38,
17715 NM_ANDI16 = 0x3c,
17716 NM_SW4X4 = 0x3d,
17717 NM_MOVEPREV = 0x3f,
17720 /* POOL32A instruction pool */
17721 enum {
17722 NM_POOL32A0 = 0x00,
17723 NM_SPECIAL2 = 0x01,
17724 NM_COP2_1 = 0x02,
17725 NM_UDI = 0x03,
17726 NM_POOL32A5 = 0x05,
17727 NM_POOL32A7 = 0x07,
17730 /* P.GP.W instruction pool */
17731 enum {
17732 NM_ADDIUGP_W = 0x00,
17733 NM_LWGP = 0x02,
17734 NM_SWGP = 0x03,
17737 /* P48I instruction pool */
17738 enum {
17739 NM_LI48 = 0x00,
17740 NM_ADDIU48 = 0x01,
17741 NM_ADDIUGP48 = 0x02,
17742 NM_ADDIUPC48 = 0x03,
17743 NM_LWPC48 = 0x0b,
17744 NM_SWPC48 = 0x0f,
17747 /* P.U12 instruction pool */
17748 enum {
17749 NM_ORI = 0x00,
17750 NM_XORI = 0x01,
17751 NM_ANDI = 0x02,
17752 NM_P_SR = 0x03,
17753 NM_SLTI = 0x04,
17754 NM_SLTIU = 0x05,
17755 NM_SEQI = 0x06,
17756 NM_ADDIUNEG = 0x08,
17757 NM_P_SHIFT = 0x0c,
17758 NM_P_ROTX = 0x0d,
17759 NM_P_INS = 0x0e,
17760 NM_P_EXT = 0x0f,
17763 /* POOL32F instruction pool */
17764 enum {
17765 NM_POOL32F_0 = 0x00,
17766 NM_POOL32F_3 = 0x03,
17767 NM_POOL32F_5 = 0x05,
17770 /* POOL32S instruction pool */
17771 enum {
17772 NM_POOL32S_0 = 0x00,
17773 NM_POOL32S_4 = 0x04,
17776 /* P.LUI instruction pool */
17777 enum {
17778 NM_LUI = 0x00,
17779 NM_ALUIPC = 0x01,
17782 /* P.GP.BH instruction pool */
17783 enum {
17784 NM_LBGP = 0x00,
17785 NM_SBGP = 0x01,
17786 NM_LBUGP = 0x02,
17787 NM_ADDIUGP_B = 0x03,
17788 NM_P_GP_LH = 0x04,
17789 NM_P_GP_SH = 0x05,
17790 NM_P_GP_CP1 = 0x06,
17793 /* P.LS.U12 instruction pool */
17794 enum {
17795 NM_LB = 0x00,
17796 NM_SB = 0x01,
17797 NM_LBU = 0x02,
17798 NM_P_PREFU12 = 0x03,
17799 NM_LH = 0x04,
17800 NM_SH = 0x05,
17801 NM_LHU = 0x06,
17802 NM_LWU = 0x07,
17803 NM_LW = 0x08,
17804 NM_SW = 0x09,
17805 NM_LWC1 = 0x0a,
17806 NM_SWC1 = 0x0b,
17807 NM_LDC1 = 0x0e,
17808 NM_SDC1 = 0x0f,
17811 /* P.LS.S9 instruction pool */
17812 enum {
17813 NM_P_LS_S0 = 0x00,
17814 NM_P_LS_S1 = 0x01,
17815 NM_P_LS_E0 = 0x02,
17816 NM_P_LS_WM = 0x04,
17817 NM_P_LS_UAWM = 0x05,
17820 /* P.BAL instruction pool */
17821 enum {
17822 NM_BC = 0x00,
17823 NM_BALC = 0x01,
17826 /* P.J instruction pool */
17827 enum {
17828 NM_JALRC = 0x00,
17829 NM_JALRC_HB = 0x01,
17830 NM_P_BALRSC = 0x08,
17833 /* P.BR1 instruction pool */
17834 enum {
17835 NM_BEQC = 0x00,
17836 NM_P_BR3A = 0x01,
17837 NM_BGEC = 0x02,
17838 NM_BGEUC = 0x03,
17841 /* P.BR2 instruction pool */
17842 enum {
17843 NM_BNEC = 0x00,
17844 NM_BLTC = 0x02,
17845 NM_BLTUC = 0x03,
17848 /* P.BRI instruction pool */
17849 enum {
17850 NM_BEQIC = 0x00,
17851 NM_BBEQZC = 0x01,
17852 NM_BGEIC = 0x02,
17853 NM_BGEIUC = 0x03,
17854 NM_BNEIC = 0x04,
17855 NM_BBNEZC = 0x05,
17856 NM_BLTIC = 0x06,
17857 NM_BLTIUC = 0x07,
17860 /* P16.SHIFT instruction pool */
17861 enum {
17862 NM_SLL16 = 0x00,
17863 NM_SRL16 = 0x01,
17866 /* POOL16C instruction pool */
17867 enum {
17868 NM_POOL16C_0 = 0x00,
17869 NM_LWXS16 = 0x01,
17872 /* P16.A1 instruction pool */
17873 enum {
17874 NM_ADDIUR1SP = 0x01,
17877 /* P16.A2 instruction pool */
17878 enum {
17879 NM_ADDIUR2 = 0x00,
17880 NM_P_ADDIURS5 = 0x01,
17883 /* P16.ADDU instruction pool */
17884 enum {
17885 NM_ADDU16 = 0x00,
17886 NM_SUBU16 = 0x01,
17889 /* P16.SR instruction pool */
17890 enum {
17891 NM_SAVE16 = 0x00,
17892 NM_RESTORE_JRC16 = 0x01,
17895 /* P16.4X4 instruction pool */
17896 enum {
17897 NM_ADDU4X4 = 0x00,
17898 NM_MUL4X4 = 0x01,
17901 /* P16.LB instruction pool */
17902 enum {
17903 NM_LB16 = 0x00,
17904 NM_SB16 = 0x01,
17905 NM_LBU16 = 0x02,
17908 /* P16.LH instruction pool */
17909 enum {
17910 NM_LH16 = 0x00,
17911 NM_SH16 = 0x01,
17912 NM_LHU16 = 0x02,
17915 /* P.RI instruction pool */
17916 enum {
17917 NM_SIGRIE = 0x00,
17918 NM_P_SYSCALL = 0x01,
17919 NM_BREAK = 0x02,
17920 NM_SDBBP = 0x03,
17923 /* POOL32A0 instruction pool */
17924 enum {
17925 NM_P_TRAP = 0x00,
17926 NM_SEB = 0x01,
17927 NM_SLLV = 0x02,
17928 NM_MUL = 0x03,
17929 NM_MFC0 = 0x06,
17930 NM_MFHC0 = 0x07,
17931 NM_SEH = 0x09,
17932 NM_SRLV = 0x0a,
17933 NM_MUH = 0x0b,
17934 NM_MTC0 = 0x0e,
17935 NM_MTHC0 = 0x0f,
17936 NM_SRAV = 0x12,
17937 NM_MULU = 0x13,
17938 NM_ROTRV = 0x1a,
17939 NM_MUHU = 0x1b,
17940 NM_ADD = 0x22,
17941 NM_DIV = 0x23,
17942 NM_ADDU = 0x2a,
17943 NM_MOD = 0x2b,
17944 NM_SUB = 0x32,
17945 NM_DIVU = 0x33,
17946 NM_RDHWR = 0x38,
17947 NM_SUBU = 0x3a,
17948 NM_MODU = 0x3b,
17949 NM_P_CMOVE = 0x42,
17950 NM_FORK = 0x45,
17951 NM_MFTR = 0x46,
17952 NM_MFHTR = 0x47,
17953 NM_AND = 0x4a,
17954 NM_YIELD = 0x4d,
17955 NM_MTTR = 0x4e,
17956 NM_MTHTR = 0x4f,
17957 NM_OR = 0x52,
17958 NM_D_E_MT_VPE = 0x56,
17959 NM_NOR = 0x5a,
17960 NM_XOR = 0x62,
17961 NM_SLT = 0x6a,
17962 NM_P_SLTU = 0x72,
17963 NM_SOV = 0x7a,
17966 /* CRC32 instruction pool */
17967 enum {
17968 NM_CRC32B = 0x00,
17969 NM_CRC32H = 0x01,
17970 NM_CRC32W = 0x02,
17971 NM_CRC32CB = 0x04,
17972 NM_CRC32CH = 0x05,
17973 NM_CRC32CW = 0x06,
17976 /* POOL32A5 instruction pool */
17977 enum {
17978 NM_CMP_EQ_PH = 0x00,
17979 NM_CMP_LT_PH = 0x08,
17980 NM_CMP_LE_PH = 0x10,
17981 NM_CMPGU_EQ_QB = 0x18,
17982 NM_CMPGU_LT_QB = 0x20,
17983 NM_CMPGU_LE_QB = 0x28,
17984 NM_CMPGDU_EQ_QB = 0x30,
17985 NM_CMPGDU_LT_QB = 0x38,
17986 NM_CMPGDU_LE_QB = 0x40,
17987 NM_CMPU_EQ_QB = 0x48,
17988 NM_CMPU_LT_QB = 0x50,
17989 NM_CMPU_LE_QB = 0x58,
17990 NM_ADDQ_S_W = 0x60,
17991 NM_SUBQ_S_W = 0x68,
17992 NM_ADDSC = 0x70,
17993 NM_ADDWC = 0x78,
17995 NM_ADDQ_S_PH = 0x01,
17996 NM_ADDQH_R_PH = 0x09,
17997 NM_ADDQH_R_W = 0x11,
17998 NM_ADDU_S_QB = 0x19,
17999 NM_ADDU_S_PH = 0x21,
18000 NM_ADDUH_R_QB = 0x29,
18001 NM_SHRAV_R_PH = 0x31,
18002 NM_SHRAV_R_QB = 0x39,
18003 NM_SUBQ_S_PH = 0x41,
18004 NM_SUBQH_R_PH = 0x49,
18005 NM_SUBQH_R_W = 0x51,
18006 NM_SUBU_S_QB = 0x59,
18007 NM_SUBU_S_PH = 0x61,
18008 NM_SUBUH_R_QB = 0x69,
18009 NM_SHLLV_S_PH = 0x71,
18010 NM_PRECR_SRA_R_PH_W = 0x79,
18012 NM_MULEU_S_PH_QBL = 0x12,
18013 NM_MULEU_S_PH_QBR = 0x1a,
18014 NM_MULQ_RS_PH = 0x22,
18015 NM_MULQ_S_PH = 0x2a,
18016 NM_MULQ_RS_W = 0x32,
18017 NM_MULQ_S_W = 0x3a,
18018 NM_APPEND = 0x42,
18019 NM_MODSUB = 0x52,
18020 NM_SHRAV_R_W = 0x5a,
18021 NM_SHRLV_PH = 0x62,
18022 NM_SHRLV_QB = 0x6a,
18023 NM_SHLLV_QB = 0x72,
18024 NM_SHLLV_S_W = 0x7a,
18026 NM_SHILO = 0x03,
18028 NM_MULEQ_S_W_PHL = 0x04,
18029 NM_MULEQ_S_W_PHR = 0x0c,
18031 NM_MUL_S_PH = 0x05,
18032 NM_PRECR_QB_PH = 0x0d,
18033 NM_PRECRQ_QB_PH = 0x15,
18034 NM_PRECRQ_PH_W = 0x1d,
18035 NM_PRECRQ_RS_PH_W = 0x25,
18036 NM_PRECRQU_S_QB_PH = 0x2d,
18037 NM_PACKRL_PH = 0x35,
18038 NM_PICK_QB = 0x3d,
18039 NM_PICK_PH = 0x45,
18041 NM_SHRA_R_W = 0x5e,
18042 NM_SHRA_R_PH = 0x66,
18043 NM_SHLL_S_PH = 0x76,
18044 NM_SHLL_S_W = 0x7e,
18046 NM_REPL_PH = 0x07
18049 /* POOL32A7 instruction pool */
18050 enum {
18051 NM_P_LSX = 0x00,
18052 NM_LSA = 0x01,
18053 NM_EXTW = 0x03,
18054 NM_POOL32AXF = 0x07,
18057 /* P.SR instruction pool */
18058 enum {
18059 NM_PP_SR = 0x00,
18060 NM_P_SR_F = 0x01,
18063 /* P.SHIFT instruction pool */
18064 enum {
18065 NM_P_SLL = 0x00,
18066 NM_SRL = 0x02,
18067 NM_SRA = 0x04,
18068 NM_ROTR = 0x06,
18071 /* P.ROTX instruction pool */
18072 enum {
18073 NM_ROTX = 0x00,
18076 /* P.INS instruction pool */
18077 enum {
18078 NM_INS = 0x00,
18081 /* P.EXT instruction pool */
18082 enum {
18083 NM_EXT = 0x00,
18086 /* POOL32F_0 (fmt) instruction pool */
18087 enum {
18088 NM_RINT_S = 0x04,
18089 NM_RINT_D = 0x44,
18090 NM_ADD_S = 0x06,
18091 NM_SELEQZ_S = 0x07,
18092 NM_SELEQZ_D = 0x47,
18093 NM_CLASS_S = 0x0c,
18094 NM_CLASS_D = 0x4c,
18095 NM_SUB_S = 0x0e,
18096 NM_SELNEZ_S = 0x0f,
18097 NM_SELNEZ_D = 0x4f,
18098 NM_MUL_S = 0x16,
18099 NM_SEL_S = 0x17,
18100 NM_SEL_D = 0x57,
18101 NM_DIV_S = 0x1e,
18102 NM_ADD_D = 0x26,
18103 NM_SUB_D = 0x2e,
18104 NM_MUL_D = 0x36,
18105 NM_MADDF_S = 0x37,
18106 NM_MADDF_D = 0x77,
18107 NM_DIV_D = 0x3e,
18108 NM_MSUBF_S = 0x3f,
18109 NM_MSUBF_D = 0x7f,
18112 /* POOL32F_3 instruction pool */
18113 enum {
18114 NM_MIN_FMT = 0x00,
18115 NM_MAX_FMT = 0x01,
18116 NM_MINA_FMT = 0x04,
18117 NM_MAXA_FMT = 0x05,
18118 NM_POOL32FXF = 0x07,
18121 /* POOL32F_5 instruction pool */
18122 enum {
18123 NM_CMP_CONDN_S = 0x00,
18124 NM_CMP_CONDN_D = 0x02,
18127 /* P.GP.LH instruction pool */
18128 enum {
18129 NM_LHGP = 0x00,
18130 NM_LHUGP = 0x01,
18133 /* P.GP.SH instruction pool */
18134 enum {
18135 NM_SHGP = 0x00,
18138 /* P.GP.CP1 instruction pool */
18139 enum {
18140 NM_LWC1GP = 0x00,
18141 NM_SWC1GP = 0x01,
18142 NM_LDC1GP = 0x02,
18143 NM_SDC1GP = 0x03,
18146 /* P.LS.S0 instruction pool */
18147 enum {
18148 NM_LBS9 = 0x00,
18149 NM_LHS9 = 0x04,
18150 NM_LWS9 = 0x08,
18151 NM_LDS9 = 0x0c,
18153 NM_SBS9 = 0x01,
18154 NM_SHS9 = 0x05,
18155 NM_SWS9 = 0x09,
18156 NM_SDS9 = 0x0d,
18158 NM_LBUS9 = 0x02,
18159 NM_LHUS9 = 0x06,
18160 NM_LWC1S9 = 0x0a,
18161 NM_LDC1S9 = 0x0e,
18163 NM_P_PREFS9 = 0x03,
18164 NM_LWUS9 = 0x07,
18165 NM_SWC1S9 = 0x0b,
18166 NM_SDC1S9 = 0x0f,
18169 /* P.LS.S1 instruction pool */
18170 enum {
18171 NM_ASET_ACLR = 0x02,
18172 NM_UALH = 0x04,
18173 NM_UASH = 0x05,
18174 NM_CACHE = 0x07,
18175 NM_P_LL = 0x0a,
18176 NM_P_SC = 0x0b,
18179 /* P.LS.E0 instruction pool */
18180 enum {
18181 NM_LBE = 0x00,
18182 NM_SBE = 0x01,
18183 NM_LBUE = 0x02,
18184 NM_P_PREFE = 0x03,
18185 NM_LHE = 0x04,
18186 NM_SHE = 0x05,
18187 NM_LHUE = 0x06,
18188 NM_CACHEE = 0x07,
18189 NM_LWE = 0x08,
18190 NM_SWE = 0x09,
18191 NM_P_LLE = 0x0a,
18192 NM_P_SCE = 0x0b,
18195 /* P.PREFE instruction pool */
18196 enum {
18197 NM_SYNCIE = 0x00,
18198 NM_PREFE = 0x01,
18201 /* P.LLE instruction pool */
18202 enum {
18203 NM_LLE = 0x00,
18204 NM_LLWPE = 0x01,
18207 /* P.SCE instruction pool */
18208 enum {
18209 NM_SCE = 0x00,
18210 NM_SCWPE = 0x01,
18213 /* P.LS.WM instruction pool */
18214 enum {
18215 NM_LWM = 0x00,
18216 NM_SWM = 0x01,
18219 /* P.LS.UAWM instruction pool */
18220 enum {
18221 NM_UALWM = 0x00,
18222 NM_UASWM = 0x01,
18225 /* P.BR3A instruction pool */
18226 enum {
18227 NM_BC1EQZC = 0x00,
18228 NM_BC1NEZC = 0x01,
18229 NM_BC2EQZC = 0x02,
18230 NM_BC2NEZC = 0x03,
18231 NM_BPOSGE32C = 0x04,
18234 /* P16.RI instruction pool */
18235 enum {
18236 NM_P16_SYSCALL = 0x01,
18237 NM_BREAK16 = 0x02,
18238 NM_SDBBP16 = 0x03,
18241 /* POOL16C_0 instruction pool */
18242 enum {
18243 NM_POOL16C_00 = 0x00,
18246 /* P16.JRC instruction pool */
18247 enum {
18248 NM_JRC = 0x00,
18249 NM_JALRC16 = 0x01,
18252 /* P.SYSCALL instruction pool */
18253 enum {
18254 NM_SYSCALL = 0x00,
18255 NM_HYPCALL = 0x01,
18258 /* P.TRAP instruction pool */
18259 enum {
18260 NM_TEQ = 0x00,
18261 NM_TNE = 0x01,
18264 /* P.CMOVE instruction pool */
18265 enum {
18266 NM_MOVZ = 0x00,
18267 NM_MOVN = 0x01,
18270 /* POOL32Axf instruction pool */
18271 enum {
18272 NM_POOL32AXF_1 = 0x01,
18273 NM_POOL32AXF_2 = 0x02,
18274 NM_POOL32AXF_4 = 0x04,
18275 NM_POOL32AXF_5 = 0x05,
18276 NM_POOL32AXF_7 = 0x07,
18279 /* POOL32Axf_1 instruction pool */
18280 enum {
18281 NM_POOL32AXF_1_0 = 0x00,
18282 NM_POOL32AXF_1_1 = 0x01,
18283 NM_POOL32AXF_1_3 = 0x03,
18284 NM_POOL32AXF_1_4 = 0x04,
18285 NM_POOL32AXF_1_5 = 0x05,
18286 NM_POOL32AXF_1_7 = 0x07,
18289 /* POOL32Axf_2 instruction pool */
18290 enum {
18291 NM_POOL32AXF_2_0_7 = 0x00,
18292 NM_POOL32AXF_2_8_15 = 0x01,
18293 NM_POOL32AXF_2_16_23 = 0x02,
18294 NM_POOL32AXF_2_24_31 = 0x03,
18297 /* POOL32Axf_7 instruction pool */
18298 enum {
18299 NM_SHRA_R_QB = 0x0,
18300 NM_SHRL_PH = 0x1,
18301 NM_REPL_QB = 0x2,
18304 /* POOL32Axf_1_0 instruction pool */
18305 enum {
18306 NM_MFHI = 0x0,
18307 NM_MFLO = 0x1,
18308 NM_MTHI = 0x2,
18309 NM_MTLO = 0x3,
18312 /* POOL32Axf_1_1 instruction pool */
18313 enum {
18314 NM_MTHLIP = 0x0,
18315 NM_SHILOV = 0x1,
18318 /* POOL32Axf_1_3 instruction pool */
18319 enum {
18320 NM_RDDSP = 0x0,
18321 NM_WRDSP = 0x1,
18322 NM_EXTP = 0x2,
18323 NM_EXTPDP = 0x3,
18326 /* POOL32Axf_1_4 instruction pool */
18327 enum {
18328 NM_SHLL_QB = 0x0,
18329 NM_SHRL_QB = 0x1,
18332 /* POOL32Axf_1_5 instruction pool */
18333 enum {
18334 NM_MAQ_S_W_PHR = 0x0,
18335 NM_MAQ_S_W_PHL = 0x1,
18336 NM_MAQ_SA_W_PHR = 0x2,
18337 NM_MAQ_SA_W_PHL = 0x3,
18340 /* POOL32Axf_1_7 instruction pool */
18341 enum {
18342 NM_EXTR_W = 0x0,
18343 NM_EXTR_R_W = 0x1,
18344 NM_EXTR_RS_W = 0x2,
18345 NM_EXTR_S_H = 0x3,
18348 /* POOL32Axf_2_0_7 instruction pool */
18349 enum {
18350 NM_DPA_W_PH = 0x0,
18351 NM_DPAQ_S_W_PH = 0x1,
18352 NM_DPS_W_PH = 0x2,
18353 NM_DPSQ_S_W_PH = 0x3,
18354 NM_BALIGN = 0x4,
18355 NM_MADD = 0x5,
18356 NM_MULT = 0x6,
18357 NM_EXTRV_W = 0x7,
18360 /* POOL32Axf_2_8_15 instruction pool */
18361 enum {
18362 NM_DPAX_W_PH = 0x0,
18363 NM_DPAQ_SA_L_W = 0x1,
18364 NM_DPSX_W_PH = 0x2,
18365 NM_DPSQ_SA_L_W = 0x3,
18366 NM_MADDU = 0x5,
18367 NM_MULTU = 0x6,
18368 NM_EXTRV_R_W = 0x7,
18371 /* POOL32Axf_2_16_23 instruction pool */
18372 enum {
18373 NM_DPAU_H_QBL = 0x0,
18374 NM_DPAQX_S_W_PH = 0x1,
18375 NM_DPSU_H_QBL = 0x2,
18376 NM_DPSQX_S_W_PH = 0x3,
18377 NM_EXTPV = 0x4,
18378 NM_MSUB = 0x5,
18379 NM_MULSA_W_PH = 0x6,
18380 NM_EXTRV_RS_W = 0x7,
18383 /* POOL32Axf_2_24_31 instruction pool */
18384 enum {
18385 NM_DPAU_H_QBR = 0x0,
18386 NM_DPAQX_SA_W_PH = 0x1,
18387 NM_DPSU_H_QBR = 0x2,
18388 NM_DPSQX_SA_W_PH = 0x3,
18389 NM_EXTPDPV = 0x4,
18390 NM_MSUBU = 0x5,
18391 NM_MULSAQ_S_W_PH = 0x6,
18392 NM_EXTRV_S_H = 0x7,
18395 /* POOL32Axf_{4, 5} instruction pool */
18396 enum {
18397 NM_CLO = 0x25,
18398 NM_CLZ = 0x2d,
18400 NM_TLBP = 0x01,
18401 NM_TLBR = 0x09,
18402 NM_TLBWI = 0x11,
18403 NM_TLBWR = 0x19,
18404 NM_TLBINV = 0x03,
18405 NM_TLBINVF = 0x0b,
18406 NM_DI = 0x23,
18407 NM_EI = 0x2b,
18408 NM_RDPGPR = 0x70,
18409 NM_WRPGPR = 0x78,
18410 NM_WAIT = 0x61,
18411 NM_DERET = 0x71,
18412 NM_ERETX = 0x79,
18414 /* nanoMIPS DSP instructions */
18415 NM_ABSQ_S_QB = 0x00,
18416 NM_ABSQ_S_PH = 0x08,
18417 NM_ABSQ_S_W = 0x10,
18418 NM_PRECEQ_W_PHL = 0x28,
18419 NM_PRECEQ_W_PHR = 0x30,
18420 NM_PRECEQU_PH_QBL = 0x38,
18421 NM_PRECEQU_PH_QBR = 0x48,
18422 NM_PRECEU_PH_QBL = 0x58,
18423 NM_PRECEU_PH_QBR = 0x68,
18424 NM_PRECEQU_PH_QBLA = 0x39,
18425 NM_PRECEQU_PH_QBRA = 0x49,
18426 NM_PRECEU_PH_QBLA = 0x59,
18427 NM_PRECEU_PH_QBRA = 0x69,
18428 NM_REPLV_PH = 0x01,
18429 NM_REPLV_QB = 0x09,
18430 NM_BITREV = 0x18,
18431 NM_INSV = 0x20,
18432 NM_RADDU_W_QB = 0x78,
18434 NM_BITSWAP = 0x05,
18435 NM_WSBH = 0x3d,
18438 /* PP.SR instruction pool */
18439 enum {
18440 NM_SAVE = 0x00,
18441 NM_RESTORE = 0x02,
18442 NM_RESTORE_JRC = 0x03,
18445 /* P.SR.F instruction pool */
18446 enum {
18447 NM_SAVEF = 0x00,
18448 NM_RESTOREF = 0x01,
18451 /* P16.SYSCALL instruction pool */
18452 enum {
18453 NM_SYSCALL16 = 0x00,
18454 NM_HYPCALL16 = 0x01,
18457 /* POOL16C_00 instruction pool */
18458 enum {
18459 NM_NOT16 = 0x00,
18460 NM_XOR16 = 0x01,
18461 NM_AND16 = 0x02,
18462 NM_OR16 = 0x03,
18465 /* PP.LSX and PP.LSXS instruction pool */
18466 enum {
18467 NM_LBX = 0x00,
18468 NM_LHX = 0x04,
18469 NM_LWX = 0x08,
18470 NM_LDX = 0x0c,
18472 NM_SBX = 0x01,
18473 NM_SHX = 0x05,
18474 NM_SWX = 0x09,
18475 NM_SDX = 0x0d,
18477 NM_LBUX = 0x02,
18478 NM_LHUX = 0x06,
18479 NM_LWC1X = 0x0a,
18480 NM_LDC1X = 0x0e,
18482 NM_LWUX = 0x07,
18483 NM_SWC1X = 0x0b,
18484 NM_SDC1X = 0x0f,
18486 NM_LHXS = 0x04,
18487 NM_LWXS = 0x08,
18488 NM_LDXS = 0x0c,
18490 NM_SHXS = 0x05,
18491 NM_SWXS = 0x09,
18492 NM_SDXS = 0x0d,
18494 NM_LHUXS = 0x06,
18495 NM_LWC1XS = 0x0a,
18496 NM_LDC1XS = 0x0e,
18498 NM_LWUXS = 0x07,
18499 NM_SWC1XS = 0x0b,
18500 NM_SDC1XS = 0x0f,
18503 /* ERETx instruction pool */
18504 enum {
18505 NM_ERET = 0x00,
18506 NM_ERETNC = 0x01,
18509 /* POOL32FxF_{0, 1} insturction pool */
18510 enum {
18511 NM_CFC1 = 0x40,
18512 NM_CTC1 = 0x60,
18513 NM_MFC1 = 0x80,
18514 NM_MTC1 = 0xa0,
18515 NM_MFHC1 = 0xc0,
18516 NM_MTHC1 = 0xe0,
18518 NM_CVT_S_PL = 0x84,
18519 NM_CVT_S_PU = 0xa4,
18521 NM_CVT_L_S = 0x004,
18522 NM_CVT_L_D = 0x104,
18523 NM_CVT_W_S = 0x024,
18524 NM_CVT_W_D = 0x124,
18526 NM_RSQRT_S = 0x008,
18527 NM_RSQRT_D = 0x108,
18529 NM_SQRT_S = 0x028,
18530 NM_SQRT_D = 0x128,
18532 NM_RECIP_S = 0x048,
18533 NM_RECIP_D = 0x148,
18535 NM_FLOOR_L_S = 0x00c,
18536 NM_FLOOR_L_D = 0x10c,
18538 NM_FLOOR_W_S = 0x02c,
18539 NM_FLOOR_W_D = 0x12c,
18541 NM_CEIL_L_S = 0x04c,
18542 NM_CEIL_L_D = 0x14c,
18543 NM_CEIL_W_S = 0x06c,
18544 NM_CEIL_W_D = 0x16c,
18545 NM_TRUNC_L_S = 0x08c,
18546 NM_TRUNC_L_D = 0x18c,
18547 NM_TRUNC_W_S = 0x0ac,
18548 NM_TRUNC_W_D = 0x1ac,
18549 NM_ROUND_L_S = 0x0cc,
18550 NM_ROUND_L_D = 0x1cc,
18551 NM_ROUND_W_S = 0x0ec,
18552 NM_ROUND_W_D = 0x1ec,
18554 NM_MOV_S = 0x01,
18555 NM_MOV_D = 0x81,
18556 NM_ABS_S = 0x0d,
18557 NM_ABS_D = 0x8d,
18558 NM_NEG_S = 0x2d,
18559 NM_NEG_D = 0xad,
18560 NM_CVT_D_S = 0x04d,
18561 NM_CVT_D_W = 0x0cd,
18562 NM_CVT_D_L = 0x14d,
18563 NM_CVT_S_D = 0x06d,
18564 NM_CVT_S_W = 0x0ed,
18565 NM_CVT_S_L = 0x16d,
18568 /* P.LL instruction pool */
18569 enum {
18570 NM_LL = 0x00,
18571 NM_LLWP = 0x01,
18574 /* P.SC instruction pool */
18575 enum {
18576 NM_SC = 0x00,
18577 NM_SCWP = 0x01,
18580 /* P.DVP instruction pool */
18581 enum {
18582 NM_DVP = 0x00,
18583 NM_EVP = 0x01,
18589 * nanoMIPS decoding engine
18594 /* extraction utilities */
18596 #define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7)
18597 #define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7)
18598 #define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7)
18599 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18600 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18602 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
18603 static inline int decode_gpr_gpr3(int r)
18605 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
18607 return map[r & 0x7];
18610 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
18611 static inline int decode_gpr_gpr3_src_store(int r)
18613 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
18615 return map[r & 0x7];
18618 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
18619 static inline int decode_gpr_gpr4(int r)
18621 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
18622 16, 17, 18, 19, 20, 21, 22, 23 };
18624 return map[r & 0xf];
18627 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
18628 static inline int decode_gpr_gpr4_zero(int r)
18630 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
18631 16, 17, 18, 19, 20, 21, 22, 23 };
18633 return map[r & 0xf];
18637 static void gen_adjust_sp(DisasContext *ctx, int u)
18639 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
18642 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
18643 uint8_t gp, uint16_t u)
18645 int counter = 0;
18646 TCGv va = tcg_temp_new();
18647 TCGv t0 = tcg_temp_new();
18649 while (counter != count) {
18650 bool use_gp = gp && (counter == count - 1);
18651 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18652 int this_offset = -((counter + 1) << 2);
18653 gen_base_offset_addr(ctx, va, 29, this_offset);
18654 gen_load_gpr(t0, this_rt);
18655 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
18656 (MO_TEUL | ctx->default_tcg_memop_mask));
18657 counter++;
18660 /* adjust stack pointer */
18661 gen_adjust_sp(ctx, -u);
18663 tcg_temp_free(t0);
18664 tcg_temp_free(va);
18667 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
18668 uint8_t gp, uint16_t u)
18670 int counter = 0;
18671 TCGv va = tcg_temp_new();
18672 TCGv t0 = tcg_temp_new();
18674 while (counter != count) {
18675 bool use_gp = gp && (counter == count - 1);
18676 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18677 int this_offset = u - ((counter + 1) << 2);
18678 gen_base_offset_addr(ctx, va, 29, this_offset);
18679 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
18680 ctx->default_tcg_memop_mask);
18681 tcg_gen_ext32s_tl(t0, t0);
18682 gen_store_gpr(t0, this_rt);
18683 counter++;
18686 /* adjust stack pointer */
18687 gen_adjust_sp(ctx, u);
18689 tcg_temp_free(t0);
18690 tcg_temp_free(va);
18693 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
18695 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
18696 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
18698 switch (extract32(ctx->opcode, 2, 2)) {
18699 case NM_NOT16:
18700 gen_logic(ctx, OPC_NOR, rt, rs, 0);
18701 break;
18702 case NM_AND16:
18703 gen_logic(ctx, OPC_AND, rt, rt, rs);
18704 break;
18705 case NM_XOR16:
18706 gen_logic(ctx, OPC_XOR, rt, rt, rs);
18707 break;
18708 case NM_OR16:
18709 gen_logic(ctx, OPC_OR, rt, rt, rs);
18710 break;
18714 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18716 int rt = extract32(ctx->opcode, 21, 5);
18717 int rs = extract32(ctx->opcode, 16, 5);
18718 int rd = extract32(ctx->opcode, 11, 5);
18720 switch (extract32(ctx->opcode, 3, 7)) {
18721 case NM_P_TRAP:
18722 switch (extract32(ctx->opcode, 10, 1)) {
18723 case NM_TEQ:
18724 check_nms(ctx);
18725 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
18726 break;
18727 case NM_TNE:
18728 check_nms(ctx);
18729 gen_trap(ctx, OPC_TNE, rs, rt, -1);
18730 break;
18732 break;
18733 case NM_RDHWR:
18734 check_nms(ctx);
18735 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
18736 break;
18737 case NM_SEB:
18738 check_nms(ctx);
18739 gen_bshfl(ctx, OPC_SEB, rs, rt);
18740 break;
18741 case NM_SEH:
18742 gen_bshfl(ctx, OPC_SEH, rs, rt);
18743 break;
18744 case NM_SLLV:
18745 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
18746 break;
18747 case NM_SRLV:
18748 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
18749 break;
18750 case NM_SRAV:
18751 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
18752 break;
18753 case NM_ROTRV:
18754 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
18755 break;
18756 case NM_ADD:
18757 gen_arith(ctx, OPC_ADD, rd, rs, rt);
18758 break;
18759 case NM_ADDU:
18760 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
18761 break;
18762 case NM_SUB:
18763 check_nms(ctx);
18764 gen_arith(ctx, OPC_SUB, rd, rs, rt);
18765 break;
18766 case NM_SUBU:
18767 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
18768 break;
18769 case NM_P_CMOVE:
18770 switch (extract32(ctx->opcode, 10, 1)) {
18771 case NM_MOVZ:
18772 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
18773 break;
18774 case NM_MOVN:
18775 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
18776 break;
18778 break;
18779 case NM_AND:
18780 gen_logic(ctx, OPC_AND, rd, rs, rt);
18781 break;
18782 case NM_OR:
18783 gen_logic(ctx, OPC_OR, rd, rs, rt);
18784 break;
18785 case NM_NOR:
18786 gen_logic(ctx, OPC_NOR, rd, rs, rt);
18787 break;
18788 case NM_XOR:
18789 gen_logic(ctx, OPC_XOR, rd, rs, rt);
18790 break;
18791 case NM_SLT:
18792 gen_slt(ctx, OPC_SLT, rd, rs, rt);
18793 break;
18794 case NM_P_SLTU:
18795 if (rd == 0) {
18796 /* P_DVP */
18797 #ifndef CONFIG_USER_ONLY
18798 TCGv t0 = tcg_temp_new();
18799 switch (extract32(ctx->opcode, 10, 1)) {
18800 case NM_DVP:
18801 if (ctx->vp) {
18802 check_cp0_enabled(ctx);
18803 gen_helper_dvp(t0, cpu_env);
18804 gen_store_gpr(t0, rt);
18806 break;
18807 case NM_EVP:
18808 if (ctx->vp) {
18809 check_cp0_enabled(ctx);
18810 gen_helper_evp(t0, cpu_env);
18811 gen_store_gpr(t0, rt);
18813 break;
18815 tcg_temp_free(t0);
18816 #endif
18817 } else {
18818 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
18820 break;
18821 case NM_SOV:
18823 TCGv t0 = tcg_temp_new();
18824 TCGv t1 = tcg_temp_new();
18825 TCGv t2 = tcg_temp_new();
18827 gen_load_gpr(t1, rs);
18828 gen_load_gpr(t2, rt);
18829 tcg_gen_add_tl(t0, t1, t2);
18830 tcg_gen_ext32s_tl(t0, t0);
18831 tcg_gen_xor_tl(t1, t1, t2);
18832 tcg_gen_xor_tl(t2, t0, t2);
18833 tcg_gen_andc_tl(t1, t2, t1);
18835 /* operands of same sign, result different sign */
18836 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
18837 gen_store_gpr(t0, rd);
18839 tcg_temp_free(t0);
18840 tcg_temp_free(t1);
18841 tcg_temp_free(t2);
18843 break;
18844 case NM_MUL:
18845 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
18846 break;
18847 case NM_MUH:
18848 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
18849 break;
18850 case NM_MULU:
18851 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
18852 break;
18853 case NM_MUHU:
18854 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
18855 break;
18856 case NM_DIV:
18857 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
18858 break;
18859 case NM_MOD:
18860 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
18861 break;
18862 case NM_DIVU:
18863 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
18864 break;
18865 case NM_MODU:
18866 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
18867 break;
18868 #ifndef CONFIG_USER_ONLY
18869 case NM_MFC0:
18870 check_cp0_enabled(ctx);
18871 if (rt == 0) {
18872 /* Treat as NOP. */
18873 break;
18875 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
18876 break;
18877 case NM_MTC0:
18878 check_cp0_enabled(ctx);
18880 TCGv t0 = tcg_temp_new();
18882 gen_load_gpr(t0, rt);
18883 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
18884 tcg_temp_free(t0);
18886 break;
18887 case NM_D_E_MT_VPE:
18889 uint8_t sc = extract32(ctx->opcode, 10, 1);
18890 TCGv t0 = tcg_temp_new();
18892 switch (sc) {
18893 case 0:
18894 if (rs == 1) {
18895 /* DMT */
18896 check_cp0_mt(ctx);
18897 gen_helper_dmt(t0);
18898 gen_store_gpr(t0, rt);
18899 } else if (rs == 0) {
18900 /* DVPE */
18901 check_cp0_mt(ctx);
18902 gen_helper_dvpe(t0, cpu_env);
18903 gen_store_gpr(t0, rt);
18904 } else {
18905 generate_exception_end(ctx, EXCP_RI);
18907 break;
18908 case 1:
18909 if (rs == 1) {
18910 /* EMT */
18911 check_cp0_mt(ctx);
18912 gen_helper_emt(t0);
18913 gen_store_gpr(t0, rt);
18914 } else if (rs == 0) {
18915 /* EVPE */
18916 check_cp0_mt(ctx);
18917 gen_helper_evpe(t0, cpu_env);
18918 gen_store_gpr(t0, rt);
18919 } else {
18920 generate_exception_end(ctx, EXCP_RI);
18922 break;
18925 tcg_temp_free(t0);
18927 break;
18928 case NM_FORK:
18929 check_mt(ctx);
18931 TCGv t0 = tcg_temp_new();
18932 TCGv t1 = tcg_temp_new();
18934 gen_load_gpr(t0, rt);
18935 gen_load_gpr(t1, rs);
18936 gen_helper_fork(t0, t1);
18937 tcg_temp_free(t0);
18938 tcg_temp_free(t1);
18940 break;
18941 case NM_MFTR:
18942 case NM_MFHTR:
18943 check_cp0_enabled(ctx);
18944 if (rd == 0) {
18945 /* Treat as NOP. */
18946 return;
18948 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18949 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18950 break;
18951 case NM_MTTR:
18952 case NM_MTHTR:
18953 check_cp0_enabled(ctx);
18954 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18955 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18956 break;
18957 case NM_YIELD:
18958 check_mt(ctx);
18960 TCGv t0 = tcg_temp_new();
18962 gen_load_gpr(t0, rs);
18963 gen_helper_yield(t0, cpu_env, t0);
18964 gen_store_gpr(t0, rt);
18965 tcg_temp_free(t0);
18967 break;
18968 #endif
18969 default:
18970 generate_exception_end(ctx, EXCP_RI);
18971 break;
18975 /* dsp */
18976 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
18977 int ret, int v1, int v2)
18979 TCGv_i32 t0;
18980 TCGv v0_t;
18981 TCGv v1_t;
18983 t0 = tcg_temp_new_i32();
18985 v0_t = tcg_temp_new();
18986 v1_t = tcg_temp_new();
18988 tcg_gen_movi_i32(t0, v2 >> 3);
18990 gen_load_gpr(v0_t, ret);
18991 gen_load_gpr(v1_t, v1);
18993 switch (opc) {
18994 case NM_MAQ_S_W_PHR:
18995 check_dsp(ctx);
18996 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
18997 break;
18998 case NM_MAQ_S_W_PHL:
18999 check_dsp(ctx);
19000 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
19001 break;
19002 case NM_MAQ_SA_W_PHR:
19003 check_dsp(ctx);
19004 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
19005 break;
19006 case NM_MAQ_SA_W_PHL:
19007 check_dsp(ctx);
19008 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
19009 break;
19010 default:
19011 generate_exception_end(ctx, EXCP_RI);
19012 break;
19015 tcg_temp_free_i32(t0);
19017 tcg_temp_free(v0_t);
19018 tcg_temp_free(v1_t);
19022 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
19023 int ret, int v1, int v2)
19025 int16_t imm;
19026 TCGv t0 = tcg_temp_new();
19027 TCGv t1 = tcg_temp_new();
19028 TCGv v0_t = tcg_temp_new();
19030 gen_load_gpr(v0_t, v1);
19032 switch (opc) {
19033 case NM_POOL32AXF_1_0:
19034 check_dsp(ctx);
19035 switch (extract32(ctx->opcode, 12, 2)) {
19036 case NM_MFHI:
19037 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
19038 break;
19039 case NM_MFLO:
19040 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
19041 break;
19042 case NM_MTHI:
19043 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
19044 break;
19045 case NM_MTLO:
19046 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
19047 break;
19049 break;
19050 case NM_POOL32AXF_1_1:
19051 check_dsp(ctx);
19052 switch (extract32(ctx->opcode, 12, 2)) {
19053 case NM_MTHLIP:
19054 tcg_gen_movi_tl(t0, v2);
19055 gen_helper_mthlip(t0, v0_t, cpu_env);
19056 break;
19057 case NM_SHILOV:
19058 tcg_gen_movi_tl(t0, v2 >> 3);
19059 gen_helper_shilo(t0, v0_t, cpu_env);
19060 break;
19061 default:
19062 generate_exception_end(ctx, EXCP_RI);
19063 break;
19065 break;
19066 case NM_POOL32AXF_1_3:
19067 check_dsp(ctx);
19068 imm = extract32(ctx->opcode, 14, 7);
19069 switch (extract32(ctx->opcode, 12, 2)) {
19070 case NM_RDDSP:
19071 tcg_gen_movi_tl(t0, imm);
19072 gen_helper_rddsp(t0, t0, cpu_env);
19073 gen_store_gpr(t0, ret);
19074 break;
19075 case NM_WRDSP:
19076 gen_load_gpr(t0, ret);
19077 tcg_gen_movi_tl(t1, imm);
19078 gen_helper_wrdsp(t0, t1, cpu_env);
19079 break;
19080 case NM_EXTP:
19081 tcg_gen_movi_tl(t0, v2 >> 3);
19082 tcg_gen_movi_tl(t1, v1);
19083 gen_helper_extp(t0, t0, t1, cpu_env);
19084 gen_store_gpr(t0, ret);
19085 break;
19086 case NM_EXTPDP:
19087 tcg_gen_movi_tl(t0, v2 >> 3);
19088 tcg_gen_movi_tl(t1, v1);
19089 gen_helper_extpdp(t0, t0, t1, cpu_env);
19090 gen_store_gpr(t0, ret);
19091 break;
19093 break;
19094 case NM_POOL32AXF_1_4:
19095 check_dsp(ctx);
19096 tcg_gen_movi_tl(t0, v2 >> 2);
19097 switch (extract32(ctx->opcode, 12, 1)) {
19098 case NM_SHLL_QB:
19099 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
19100 gen_store_gpr(t0, ret);
19101 break;
19102 case NM_SHRL_QB:
19103 gen_helper_shrl_qb(t0, t0, v0_t);
19104 gen_store_gpr(t0, ret);
19105 break;
19107 break;
19108 case NM_POOL32AXF_1_5:
19109 opc = extract32(ctx->opcode, 12, 2);
19110 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
19111 break;
19112 case NM_POOL32AXF_1_7:
19113 check_dsp(ctx);
19114 tcg_gen_movi_tl(t0, v2 >> 3);
19115 tcg_gen_movi_tl(t1, v1);
19116 switch (extract32(ctx->opcode, 12, 2)) {
19117 case NM_EXTR_W:
19118 gen_helper_extr_w(t0, t0, t1, cpu_env);
19119 gen_store_gpr(t0, ret);
19120 break;
19121 case NM_EXTR_R_W:
19122 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
19123 gen_store_gpr(t0, ret);
19124 break;
19125 case NM_EXTR_RS_W:
19126 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
19127 gen_store_gpr(t0, ret);
19128 break;
19129 case NM_EXTR_S_H:
19130 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
19131 gen_store_gpr(t0, ret);
19132 break;
19134 break;
19135 default:
19136 generate_exception_end(ctx, EXCP_RI);
19137 break;
19140 tcg_temp_free(t0);
19141 tcg_temp_free(t1);
19142 tcg_temp_free(v0_t);
19145 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
19146 TCGv v0, TCGv v1, int rd)
19148 TCGv_i32 t0;
19150 t0 = tcg_temp_new_i32();
19152 tcg_gen_movi_i32(t0, rd >> 3);
19154 switch (opc) {
19155 case NM_POOL32AXF_2_0_7:
19156 switch (extract32(ctx->opcode, 9, 3)) {
19157 case NM_DPA_W_PH:
19158 check_dsp_r2(ctx);
19159 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
19160 break;
19161 case NM_DPAQ_S_W_PH:
19162 check_dsp(ctx);
19163 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
19164 break;
19165 case NM_DPS_W_PH:
19166 check_dsp_r2(ctx);
19167 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
19168 break;
19169 case NM_DPSQ_S_W_PH:
19170 check_dsp(ctx);
19171 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
19172 break;
19173 default:
19174 generate_exception_end(ctx, EXCP_RI);
19175 break;
19177 break;
19178 case NM_POOL32AXF_2_8_15:
19179 switch (extract32(ctx->opcode, 9, 3)) {
19180 case NM_DPAX_W_PH:
19181 check_dsp_r2(ctx);
19182 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
19183 break;
19184 case NM_DPAQ_SA_L_W:
19185 check_dsp(ctx);
19186 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
19187 break;
19188 case NM_DPSX_W_PH:
19189 check_dsp_r2(ctx);
19190 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
19191 break;
19192 case NM_DPSQ_SA_L_W:
19193 check_dsp(ctx);
19194 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
19195 break;
19196 default:
19197 generate_exception_end(ctx, EXCP_RI);
19198 break;
19200 break;
19201 case NM_POOL32AXF_2_16_23:
19202 switch (extract32(ctx->opcode, 9, 3)) {
19203 case NM_DPAU_H_QBL:
19204 check_dsp(ctx);
19205 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
19206 break;
19207 case NM_DPAQX_S_W_PH:
19208 check_dsp_r2(ctx);
19209 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
19210 break;
19211 case NM_DPSU_H_QBL:
19212 check_dsp(ctx);
19213 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
19214 break;
19215 case NM_DPSQX_S_W_PH:
19216 check_dsp_r2(ctx);
19217 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
19218 break;
19219 case NM_MULSA_W_PH:
19220 check_dsp_r2(ctx);
19221 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
19222 break;
19223 default:
19224 generate_exception_end(ctx, EXCP_RI);
19225 break;
19227 break;
19228 case NM_POOL32AXF_2_24_31:
19229 switch (extract32(ctx->opcode, 9, 3)) {
19230 case NM_DPAU_H_QBR:
19231 check_dsp(ctx);
19232 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
19233 break;
19234 case NM_DPAQX_SA_W_PH:
19235 check_dsp_r2(ctx);
19236 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
19237 break;
19238 case NM_DPSU_H_QBR:
19239 check_dsp(ctx);
19240 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
19241 break;
19242 case NM_DPSQX_SA_W_PH:
19243 check_dsp_r2(ctx);
19244 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
19245 break;
19246 case NM_MULSAQ_S_W_PH:
19247 check_dsp(ctx);
19248 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
19249 break;
19250 default:
19251 generate_exception_end(ctx, EXCP_RI);
19252 break;
19254 break;
19255 default:
19256 generate_exception_end(ctx, EXCP_RI);
19257 break;
19260 tcg_temp_free_i32(t0);
19263 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
19264 int rt, int rs, int rd)
19266 int ret = rt;
19267 TCGv t0 = tcg_temp_new();
19268 TCGv t1 = tcg_temp_new();
19269 TCGv v0_t = tcg_temp_new();
19270 TCGv v1_t = tcg_temp_new();
19272 gen_load_gpr(v0_t, rt);
19273 gen_load_gpr(v1_t, rs);
19275 switch (opc) {
19276 case NM_POOL32AXF_2_0_7:
19277 switch (extract32(ctx->opcode, 9, 3)) {
19278 case NM_DPA_W_PH:
19279 case NM_DPAQ_S_W_PH:
19280 case NM_DPS_W_PH:
19281 case NM_DPSQ_S_W_PH:
19282 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19283 break;
19284 case NM_BALIGN:
19285 check_dsp_r2(ctx);
19286 if (rt != 0) {
19287 gen_load_gpr(t0, rs);
19288 rd &= 3;
19289 if (rd != 0 && rd != 2) {
19290 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
19291 tcg_gen_ext32u_tl(t0, t0);
19292 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
19293 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19295 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
19297 break;
19298 case NM_MADD:
19299 check_dsp(ctx);
19301 int acc = extract32(ctx->opcode, 14, 2);
19302 TCGv_i64 t2 = tcg_temp_new_i64();
19303 TCGv_i64 t3 = tcg_temp_new_i64();
19305 gen_load_gpr(t0, rt);
19306 gen_load_gpr(t1, rs);
19307 tcg_gen_ext_tl_i64(t2, t0);
19308 tcg_gen_ext_tl_i64(t3, t1);
19309 tcg_gen_mul_i64(t2, t2, t3);
19310 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19311 tcg_gen_add_i64(t2, t2, t3);
19312 tcg_temp_free_i64(t3);
19313 gen_move_low32(cpu_LO[acc], t2);
19314 gen_move_high32(cpu_HI[acc], t2);
19315 tcg_temp_free_i64(t2);
19317 break;
19318 case NM_MULT:
19319 check_dsp(ctx);
19321 int acc = extract32(ctx->opcode, 14, 2);
19322 TCGv_i32 t2 = tcg_temp_new_i32();
19323 TCGv_i32 t3 = tcg_temp_new_i32();
19325 gen_load_gpr(t0, rs);
19326 gen_load_gpr(t1, rt);
19327 tcg_gen_trunc_tl_i32(t2, t0);
19328 tcg_gen_trunc_tl_i32(t3, t1);
19329 tcg_gen_muls2_i32(t2, t3, t2, t3);
19330 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19331 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19332 tcg_temp_free_i32(t2);
19333 tcg_temp_free_i32(t3);
19335 break;
19336 case NM_EXTRV_W:
19337 check_dsp(ctx);
19338 gen_load_gpr(v1_t, rs);
19339 tcg_gen_movi_tl(t0, rd >> 3);
19340 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
19341 gen_store_gpr(t0, ret);
19342 break;
19344 break;
19345 case NM_POOL32AXF_2_8_15:
19346 switch (extract32(ctx->opcode, 9, 3)) {
19347 case NM_DPAX_W_PH:
19348 case NM_DPAQ_SA_L_W:
19349 case NM_DPSX_W_PH:
19350 case NM_DPSQ_SA_L_W:
19351 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19352 break;
19353 case NM_MADDU:
19354 check_dsp(ctx);
19356 int acc = extract32(ctx->opcode, 14, 2);
19357 TCGv_i64 t2 = tcg_temp_new_i64();
19358 TCGv_i64 t3 = tcg_temp_new_i64();
19360 gen_load_gpr(t0, rs);
19361 gen_load_gpr(t1, rt);
19362 tcg_gen_ext32u_tl(t0, t0);
19363 tcg_gen_ext32u_tl(t1, t1);
19364 tcg_gen_extu_tl_i64(t2, t0);
19365 tcg_gen_extu_tl_i64(t3, t1);
19366 tcg_gen_mul_i64(t2, t2, t3);
19367 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19368 tcg_gen_add_i64(t2, t2, t3);
19369 tcg_temp_free_i64(t3);
19370 gen_move_low32(cpu_LO[acc], t2);
19371 gen_move_high32(cpu_HI[acc], t2);
19372 tcg_temp_free_i64(t2);
19374 break;
19375 case NM_MULTU:
19376 check_dsp(ctx);
19378 int acc = extract32(ctx->opcode, 14, 2);
19379 TCGv_i32 t2 = tcg_temp_new_i32();
19380 TCGv_i32 t3 = tcg_temp_new_i32();
19382 gen_load_gpr(t0, rs);
19383 gen_load_gpr(t1, rt);
19384 tcg_gen_trunc_tl_i32(t2, t0);
19385 tcg_gen_trunc_tl_i32(t3, t1);
19386 tcg_gen_mulu2_i32(t2, t3, t2, t3);
19387 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19388 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19389 tcg_temp_free_i32(t2);
19390 tcg_temp_free_i32(t3);
19392 break;
19393 case NM_EXTRV_R_W:
19394 check_dsp(ctx);
19395 tcg_gen_movi_tl(t0, rd >> 3);
19396 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
19397 gen_store_gpr(t0, ret);
19398 break;
19399 default:
19400 generate_exception_end(ctx, EXCP_RI);
19401 break;
19403 break;
19404 case NM_POOL32AXF_2_16_23:
19405 switch (extract32(ctx->opcode, 9, 3)) {
19406 case NM_DPAU_H_QBL:
19407 case NM_DPAQX_S_W_PH:
19408 case NM_DPSU_H_QBL:
19409 case NM_DPSQX_S_W_PH:
19410 case NM_MULSA_W_PH:
19411 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19412 break;
19413 case NM_EXTPV:
19414 check_dsp(ctx);
19415 tcg_gen_movi_tl(t0, rd >> 3);
19416 gen_helper_extp(t0, t0, v1_t, cpu_env);
19417 gen_store_gpr(t0, ret);
19418 break;
19419 case NM_MSUB:
19420 check_dsp(ctx);
19422 int acc = extract32(ctx->opcode, 14, 2);
19423 TCGv_i64 t2 = tcg_temp_new_i64();
19424 TCGv_i64 t3 = tcg_temp_new_i64();
19426 gen_load_gpr(t0, rs);
19427 gen_load_gpr(t1, rt);
19428 tcg_gen_ext_tl_i64(t2, t0);
19429 tcg_gen_ext_tl_i64(t3, t1);
19430 tcg_gen_mul_i64(t2, t2, t3);
19431 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19432 tcg_gen_sub_i64(t2, t3, t2);
19433 tcg_temp_free_i64(t3);
19434 gen_move_low32(cpu_LO[acc], t2);
19435 gen_move_high32(cpu_HI[acc], t2);
19436 tcg_temp_free_i64(t2);
19438 break;
19439 case NM_EXTRV_RS_W:
19440 check_dsp(ctx);
19441 tcg_gen_movi_tl(t0, rd >> 3);
19442 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
19443 gen_store_gpr(t0, ret);
19444 break;
19446 break;
19447 case NM_POOL32AXF_2_24_31:
19448 switch (extract32(ctx->opcode, 9, 3)) {
19449 case NM_DPAU_H_QBR:
19450 case NM_DPAQX_SA_W_PH:
19451 case NM_DPSU_H_QBR:
19452 case NM_DPSQX_SA_W_PH:
19453 case NM_MULSAQ_S_W_PH:
19454 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19455 break;
19456 case NM_EXTPDPV:
19457 check_dsp(ctx);
19458 tcg_gen_movi_tl(t0, rd >> 3);
19459 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
19460 gen_store_gpr(t0, ret);
19461 break;
19462 case NM_MSUBU:
19463 check_dsp(ctx);
19465 int acc = extract32(ctx->opcode, 14, 2);
19466 TCGv_i64 t2 = tcg_temp_new_i64();
19467 TCGv_i64 t3 = tcg_temp_new_i64();
19469 gen_load_gpr(t0, rs);
19470 gen_load_gpr(t1, rt);
19471 tcg_gen_ext32u_tl(t0, t0);
19472 tcg_gen_ext32u_tl(t1, t1);
19473 tcg_gen_extu_tl_i64(t2, t0);
19474 tcg_gen_extu_tl_i64(t3, t1);
19475 tcg_gen_mul_i64(t2, t2, t3);
19476 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19477 tcg_gen_sub_i64(t2, t3, t2);
19478 tcg_temp_free_i64(t3);
19479 gen_move_low32(cpu_LO[acc], t2);
19480 gen_move_high32(cpu_HI[acc], t2);
19481 tcg_temp_free_i64(t2);
19483 break;
19484 case NM_EXTRV_S_H:
19485 check_dsp(ctx);
19486 tcg_gen_movi_tl(t0, rd >> 3);
19487 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
19488 gen_store_gpr(t0, ret);
19489 break;
19491 break;
19492 default:
19493 generate_exception_end(ctx, EXCP_RI);
19494 break;
19497 tcg_temp_free(t0);
19498 tcg_temp_free(t1);
19500 tcg_temp_free(v0_t);
19501 tcg_temp_free(v1_t);
19504 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
19505 int rt, int rs)
19507 int ret = rt;
19508 TCGv t0 = tcg_temp_new();
19509 TCGv v0_t = tcg_temp_new();
19511 gen_load_gpr(v0_t, rs);
19513 switch (opc) {
19514 case NM_ABSQ_S_QB:
19515 check_dsp_r2(ctx);
19516 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
19517 gen_store_gpr(v0_t, ret);
19518 break;
19519 case NM_ABSQ_S_PH:
19520 check_dsp(ctx);
19521 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
19522 gen_store_gpr(v0_t, ret);
19523 break;
19524 case NM_ABSQ_S_W:
19525 check_dsp(ctx);
19526 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
19527 gen_store_gpr(v0_t, ret);
19528 break;
19529 case NM_PRECEQ_W_PHL:
19530 check_dsp(ctx);
19531 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
19532 tcg_gen_ext32s_tl(v0_t, v0_t);
19533 gen_store_gpr(v0_t, ret);
19534 break;
19535 case NM_PRECEQ_W_PHR:
19536 check_dsp(ctx);
19537 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
19538 tcg_gen_shli_tl(v0_t, v0_t, 16);
19539 tcg_gen_ext32s_tl(v0_t, v0_t);
19540 gen_store_gpr(v0_t, ret);
19541 break;
19542 case NM_PRECEQU_PH_QBL:
19543 check_dsp(ctx);
19544 gen_helper_precequ_ph_qbl(v0_t, v0_t);
19545 gen_store_gpr(v0_t, ret);
19546 break;
19547 case NM_PRECEQU_PH_QBR:
19548 check_dsp(ctx);
19549 gen_helper_precequ_ph_qbr(v0_t, v0_t);
19550 gen_store_gpr(v0_t, ret);
19551 break;
19552 case NM_PRECEQU_PH_QBLA:
19553 check_dsp(ctx);
19554 gen_helper_precequ_ph_qbla(v0_t, v0_t);
19555 gen_store_gpr(v0_t, ret);
19556 break;
19557 case NM_PRECEQU_PH_QBRA:
19558 check_dsp(ctx);
19559 gen_helper_precequ_ph_qbra(v0_t, v0_t);
19560 gen_store_gpr(v0_t, ret);
19561 break;
19562 case NM_PRECEU_PH_QBL:
19563 check_dsp(ctx);
19564 gen_helper_preceu_ph_qbl(v0_t, v0_t);
19565 gen_store_gpr(v0_t, ret);
19566 break;
19567 case NM_PRECEU_PH_QBR:
19568 check_dsp(ctx);
19569 gen_helper_preceu_ph_qbr(v0_t, v0_t);
19570 gen_store_gpr(v0_t, ret);
19571 break;
19572 case NM_PRECEU_PH_QBLA:
19573 check_dsp(ctx);
19574 gen_helper_preceu_ph_qbla(v0_t, v0_t);
19575 gen_store_gpr(v0_t, ret);
19576 break;
19577 case NM_PRECEU_PH_QBRA:
19578 check_dsp(ctx);
19579 gen_helper_preceu_ph_qbra(v0_t, v0_t);
19580 gen_store_gpr(v0_t, ret);
19581 break;
19582 case NM_REPLV_PH:
19583 check_dsp(ctx);
19584 tcg_gen_ext16u_tl(v0_t, v0_t);
19585 tcg_gen_shli_tl(t0, v0_t, 16);
19586 tcg_gen_or_tl(v0_t, v0_t, t0);
19587 tcg_gen_ext32s_tl(v0_t, v0_t);
19588 gen_store_gpr(v0_t, ret);
19589 break;
19590 case NM_REPLV_QB:
19591 check_dsp(ctx);
19592 tcg_gen_ext8u_tl(v0_t, v0_t);
19593 tcg_gen_shli_tl(t0, v0_t, 8);
19594 tcg_gen_or_tl(v0_t, v0_t, t0);
19595 tcg_gen_shli_tl(t0, v0_t, 16);
19596 tcg_gen_or_tl(v0_t, v0_t, t0);
19597 tcg_gen_ext32s_tl(v0_t, v0_t);
19598 gen_store_gpr(v0_t, ret);
19599 break;
19600 case NM_BITREV:
19601 check_dsp(ctx);
19602 gen_helper_bitrev(v0_t, v0_t);
19603 gen_store_gpr(v0_t, ret);
19604 break;
19605 case NM_INSV:
19606 check_dsp(ctx);
19608 TCGv tv0 = tcg_temp_new();
19610 gen_load_gpr(tv0, rt);
19611 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
19612 gen_store_gpr(v0_t, ret);
19613 tcg_temp_free(tv0);
19615 break;
19616 case NM_RADDU_W_QB:
19617 check_dsp(ctx);
19618 gen_helper_raddu_w_qb(v0_t, v0_t);
19619 gen_store_gpr(v0_t, ret);
19620 break;
19621 case NM_BITSWAP:
19622 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
19623 break;
19624 case NM_CLO:
19625 check_nms(ctx);
19626 gen_cl(ctx, OPC_CLO, ret, rs);
19627 break;
19628 case NM_CLZ:
19629 check_nms(ctx);
19630 gen_cl(ctx, OPC_CLZ, ret, rs);
19631 break;
19632 case NM_WSBH:
19633 gen_bshfl(ctx, OPC_WSBH, ret, rs);
19634 break;
19635 default:
19636 generate_exception_end(ctx, EXCP_RI);
19637 break;
19640 tcg_temp_free(v0_t);
19641 tcg_temp_free(t0);
19644 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
19645 int rt, int rs, int rd)
19647 TCGv t0 = tcg_temp_new();
19648 TCGv rs_t = tcg_temp_new();
19650 gen_load_gpr(rs_t, rs);
19652 switch (opc) {
19653 case NM_SHRA_R_QB:
19654 check_dsp_r2(ctx);
19655 tcg_gen_movi_tl(t0, rd >> 2);
19656 switch (extract32(ctx->opcode, 12, 1)) {
19657 case 0:
19658 /* NM_SHRA_QB */
19659 gen_helper_shra_qb(t0, t0, rs_t);
19660 gen_store_gpr(t0, rt);
19661 break;
19662 case 1:
19663 /* NM_SHRA_R_QB */
19664 gen_helper_shra_r_qb(t0, t0, rs_t);
19665 gen_store_gpr(t0, rt);
19666 break;
19668 break;
19669 case NM_SHRL_PH:
19670 check_dsp_r2(ctx);
19671 tcg_gen_movi_tl(t0, rd >> 1);
19672 gen_helper_shrl_ph(t0, t0, rs_t);
19673 gen_store_gpr(t0, rt);
19674 break;
19675 case NM_REPL_QB:
19676 check_dsp(ctx);
19678 int16_t imm;
19679 target_long result;
19680 imm = extract32(ctx->opcode, 13, 8);
19681 result = (uint32_t)imm << 24 |
19682 (uint32_t)imm << 16 |
19683 (uint32_t)imm << 8 |
19684 (uint32_t)imm;
19685 result = (int32_t)result;
19686 tcg_gen_movi_tl(t0, result);
19687 gen_store_gpr(t0, rt);
19689 break;
19690 default:
19691 generate_exception_end(ctx, EXCP_RI);
19692 break;
19694 tcg_temp_free(t0);
19695 tcg_temp_free(rs_t);
19699 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19701 int rt = extract32(ctx->opcode, 21, 5);
19702 int rs = extract32(ctx->opcode, 16, 5);
19703 int rd = extract32(ctx->opcode, 11, 5);
19705 switch (extract32(ctx->opcode, 6, 3)) {
19706 case NM_POOL32AXF_1:
19708 int32_t op1 = extract32(ctx->opcode, 9, 3);
19709 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
19711 break;
19712 case NM_POOL32AXF_2:
19714 int32_t op1 = extract32(ctx->opcode, 12, 2);
19715 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
19717 break;
19718 case NM_POOL32AXF_4:
19720 int32_t op1 = extract32(ctx->opcode, 9, 7);
19721 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
19723 break;
19724 case NM_POOL32AXF_5:
19725 switch (extract32(ctx->opcode, 9, 7)) {
19726 #ifndef CONFIG_USER_ONLY
19727 case NM_TLBP:
19728 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
19729 break;
19730 case NM_TLBR:
19731 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
19732 break;
19733 case NM_TLBWI:
19734 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
19735 break;
19736 case NM_TLBWR:
19737 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
19738 break;
19739 case NM_TLBINV:
19740 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
19741 break;
19742 case NM_TLBINVF:
19743 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
19744 break;
19745 case NM_DI:
19746 check_cp0_enabled(ctx);
19748 TCGv t0 = tcg_temp_new();
19750 save_cpu_state(ctx, 1);
19751 gen_helper_di(t0, cpu_env);
19752 gen_store_gpr(t0, rt);
19753 /* Stop translation as we may have switched the execution mode */
19754 ctx->base.is_jmp = DISAS_STOP;
19755 tcg_temp_free(t0);
19757 break;
19758 case NM_EI:
19759 check_cp0_enabled(ctx);
19761 TCGv t0 = tcg_temp_new();
19763 save_cpu_state(ctx, 1);
19764 gen_helper_ei(t0, cpu_env);
19765 gen_store_gpr(t0, rt);
19766 /* Stop translation as we may have switched the execution mode */
19767 ctx->base.is_jmp = DISAS_STOP;
19768 tcg_temp_free(t0);
19770 break;
19771 case NM_RDPGPR:
19772 gen_load_srsgpr(rs, rt);
19773 break;
19774 case NM_WRPGPR:
19775 gen_store_srsgpr(rs, rt);
19776 break;
19777 case NM_WAIT:
19778 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
19779 break;
19780 case NM_DERET:
19781 gen_cp0(env, ctx, OPC_DERET, 0, 0);
19782 break;
19783 case NM_ERETX:
19784 gen_cp0(env, ctx, OPC_ERET, 0, 0);
19785 break;
19786 #endif
19787 default:
19788 generate_exception_end(ctx, EXCP_RI);
19789 break;
19791 break;
19792 case NM_POOL32AXF_7:
19794 int32_t op1 = extract32(ctx->opcode, 9, 3);
19795 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
19797 break;
19798 default:
19799 generate_exception_end(ctx, EXCP_RI);
19800 break;
19804 /* Immediate Value Compact Branches */
19805 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
19806 int rt, int32_t imm, int32_t offset)
19808 TCGCond cond;
19809 int bcond_compute = 0;
19810 TCGv t0 = tcg_temp_new();
19811 TCGv t1 = tcg_temp_new();
19813 gen_load_gpr(t0, rt);
19814 tcg_gen_movi_tl(t1, imm);
19815 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19817 /* Load needed operands and calculate btarget */
19818 switch (opc) {
19819 case NM_BEQIC:
19820 if (rt == 0 && imm == 0) {
19821 /* Unconditional branch */
19822 } else if (rt == 0 && imm != 0) {
19823 /* Treat as NOP */
19824 goto out;
19825 } else {
19826 bcond_compute = 1;
19827 cond = TCG_COND_EQ;
19829 break;
19830 case NM_BBEQZC:
19831 case NM_BBNEZC:
19832 check_nms(ctx);
19833 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
19834 generate_exception_end(ctx, EXCP_RI);
19835 goto out;
19836 } else if (rt == 0 && opc == NM_BBEQZC) {
19837 /* Unconditional branch */
19838 } else if (rt == 0 && opc == NM_BBNEZC) {
19839 /* Treat as NOP */
19840 goto out;
19841 } else {
19842 tcg_gen_shri_tl(t0, t0, imm);
19843 tcg_gen_andi_tl(t0, t0, 1);
19844 tcg_gen_movi_tl(t1, 0);
19845 bcond_compute = 1;
19846 if (opc == NM_BBEQZC) {
19847 cond = TCG_COND_EQ;
19848 } else {
19849 cond = TCG_COND_NE;
19852 break;
19853 case NM_BNEIC:
19854 if (rt == 0 && imm == 0) {
19855 /* Treat as NOP */
19856 goto out;
19857 } else if (rt == 0 && imm != 0) {
19858 /* Unconditional branch */
19859 } else {
19860 bcond_compute = 1;
19861 cond = TCG_COND_NE;
19863 break;
19864 case NM_BGEIC:
19865 if (rt == 0 && imm == 0) {
19866 /* Unconditional branch */
19867 } else {
19868 bcond_compute = 1;
19869 cond = TCG_COND_GE;
19871 break;
19872 case NM_BLTIC:
19873 bcond_compute = 1;
19874 cond = TCG_COND_LT;
19875 break;
19876 case NM_BGEIUC:
19877 if (rt == 0 && imm == 0) {
19878 /* Unconditional branch */
19879 } else {
19880 bcond_compute = 1;
19881 cond = TCG_COND_GEU;
19883 break;
19884 case NM_BLTIUC:
19885 bcond_compute = 1;
19886 cond = TCG_COND_LTU;
19887 break;
19888 default:
19889 MIPS_INVAL("Immediate Value Compact branch");
19890 generate_exception_end(ctx, EXCP_RI);
19891 goto out;
19894 /* branch completion */
19895 clear_branch_hflags(ctx);
19896 ctx->base.is_jmp = DISAS_NORETURN;
19898 if (bcond_compute == 0) {
19899 /* Uncoditional compact branch */
19900 gen_goto_tb(ctx, 0, ctx->btarget);
19901 } else {
19902 /* Conditional compact branch */
19903 TCGLabel *fs = gen_new_label();
19905 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
19907 gen_goto_tb(ctx, 1, ctx->btarget);
19908 gen_set_label(fs);
19910 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19913 out:
19914 tcg_temp_free(t0);
19915 tcg_temp_free(t1);
19918 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
19919 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
19920 int rt)
19922 TCGv t0 = tcg_temp_new();
19923 TCGv t1 = tcg_temp_new();
19925 /* load rs */
19926 gen_load_gpr(t0, rs);
19928 /* link */
19929 if (rt != 0) {
19930 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
19933 /* calculate btarget */
19934 tcg_gen_shli_tl(t0, t0, 1);
19935 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
19936 gen_op_addr_add(ctx, btarget, t1, t0);
19938 /* branch completion */
19939 clear_branch_hflags(ctx);
19940 ctx->base.is_jmp = DISAS_NORETURN;
19942 /* unconditional branch to register */
19943 tcg_gen_mov_tl(cpu_PC, btarget);
19944 tcg_gen_lookup_and_goto_ptr();
19946 tcg_temp_free(t0);
19947 tcg_temp_free(t1);
19950 /* nanoMIPS Branches */
19951 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
19952 int rs, int rt, int32_t offset)
19954 int bcond_compute = 0;
19955 TCGv t0 = tcg_temp_new();
19956 TCGv t1 = tcg_temp_new();
19958 /* Load needed operands and calculate btarget */
19959 switch (opc) {
19960 /* compact branch */
19961 case OPC_BGEC:
19962 case OPC_BLTC:
19963 gen_load_gpr(t0, rs);
19964 gen_load_gpr(t1, rt);
19965 bcond_compute = 1;
19966 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19967 break;
19968 case OPC_BGEUC:
19969 case OPC_BLTUC:
19970 if (rs == 0 || rs == rt) {
19971 /* OPC_BLEZALC, OPC_BGEZALC */
19972 /* OPC_BGTZALC, OPC_BLTZALC */
19973 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
19975 gen_load_gpr(t0, rs);
19976 gen_load_gpr(t1, rt);
19977 bcond_compute = 1;
19978 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19979 break;
19980 case OPC_BC:
19981 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19982 break;
19983 case OPC_BEQZC:
19984 if (rs != 0) {
19985 /* OPC_BEQZC, OPC_BNEZC */
19986 gen_load_gpr(t0, rs);
19987 bcond_compute = 1;
19988 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19989 } else {
19990 /* OPC_JIC, OPC_JIALC */
19991 TCGv tbase = tcg_temp_new();
19992 TCGv toffset = tcg_temp_new();
19994 gen_load_gpr(tbase, rt);
19995 tcg_gen_movi_tl(toffset, offset);
19996 gen_op_addr_add(ctx, btarget, tbase, toffset);
19997 tcg_temp_free(tbase);
19998 tcg_temp_free(toffset);
20000 break;
20001 default:
20002 MIPS_INVAL("Compact branch/jump");
20003 generate_exception_end(ctx, EXCP_RI);
20004 goto out;
20007 if (bcond_compute == 0) {
20008 /* Uncoditional compact branch */
20009 switch (opc) {
20010 case OPC_BC:
20011 gen_goto_tb(ctx, 0, ctx->btarget);
20012 break;
20013 default:
20014 MIPS_INVAL("Compact branch/jump");
20015 generate_exception_end(ctx, EXCP_RI);
20016 goto out;
20018 } else {
20019 /* Conditional compact branch */
20020 TCGLabel *fs = gen_new_label();
20022 switch (opc) {
20023 case OPC_BGEUC:
20024 if (rs == 0 && rt != 0) {
20025 /* OPC_BLEZALC */
20026 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20027 } else if (rs != 0 && rt != 0 && rs == rt) {
20028 /* OPC_BGEZALC */
20029 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20030 } else {
20031 /* OPC_BGEUC */
20032 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
20034 break;
20035 case OPC_BLTUC:
20036 if (rs == 0 && rt != 0) {
20037 /* OPC_BGTZALC */
20038 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20039 } else if (rs != 0 && rt != 0 && rs == rt) {
20040 /* OPC_BLTZALC */
20041 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20042 } else {
20043 /* OPC_BLTUC */
20044 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
20046 break;
20047 case OPC_BGEC:
20048 if (rs == 0 && rt != 0) {
20049 /* OPC_BLEZC */
20050 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20051 } else if (rs != 0 && rt != 0 && rs == rt) {
20052 /* OPC_BGEZC */
20053 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20054 } else {
20055 /* OPC_BGEC */
20056 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
20058 break;
20059 case OPC_BLTC:
20060 if (rs == 0 && rt != 0) {
20061 /* OPC_BGTZC */
20062 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20063 } else if (rs != 0 && rt != 0 && rs == rt) {
20064 /* OPC_BLTZC */
20065 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20066 } else {
20067 /* OPC_BLTC */
20068 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
20070 break;
20071 case OPC_BEQZC:
20072 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
20073 break;
20074 default:
20075 MIPS_INVAL("Compact conditional branch/jump");
20076 generate_exception_end(ctx, EXCP_RI);
20077 goto out;
20080 /* branch completion */
20081 clear_branch_hflags(ctx);
20082 ctx->base.is_jmp = DISAS_NORETURN;
20084 /* Generating branch here as compact branches don't have delay slot */
20085 gen_goto_tb(ctx, 1, ctx->btarget);
20086 gen_set_label(fs);
20088 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20091 out:
20092 tcg_temp_free(t0);
20093 tcg_temp_free(t1);
20097 /* nanoMIPS CP1 Branches */
20098 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
20099 int32_t ft, int32_t offset)
20101 target_ulong btarget;
20102 TCGv_i64 t0 = tcg_temp_new_i64();
20104 gen_load_fpr64(ctx, t0, ft);
20105 tcg_gen_andi_i64(t0, t0, 1);
20107 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20109 switch (op) {
20110 case NM_BC1EQZC:
20111 tcg_gen_xori_i64(t0, t0, 1);
20112 ctx->hflags |= MIPS_HFLAG_BC;
20113 break;
20114 case NM_BC1NEZC:
20115 /* t0 already set */
20116 ctx->hflags |= MIPS_HFLAG_BC;
20117 break;
20118 default:
20119 MIPS_INVAL("cp1 cond branch");
20120 generate_exception_end(ctx, EXCP_RI);
20121 goto out;
20124 tcg_gen_trunc_i64_tl(bcond, t0);
20126 ctx->btarget = btarget;
20128 out:
20129 tcg_temp_free_i64(t0);
20133 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
20135 TCGv t0, t1;
20136 t0 = tcg_temp_new();
20137 t1 = tcg_temp_new();
20139 gen_load_gpr(t0, rs);
20140 gen_load_gpr(t1, rt);
20142 if ((extract32(ctx->opcode, 6, 1)) == 1) {
20143 /* PP.LSXS instructions require shifting */
20144 switch (extract32(ctx->opcode, 7, 4)) {
20145 case NM_SHXS:
20146 check_nms(ctx);
20147 /* fall through */
20148 case NM_LHXS:
20149 case NM_LHUXS:
20150 tcg_gen_shli_tl(t0, t0, 1);
20151 break;
20152 case NM_SWXS:
20153 check_nms(ctx);
20154 /* fall through */
20155 case NM_LWXS:
20156 case NM_LWC1XS:
20157 case NM_SWC1XS:
20158 tcg_gen_shli_tl(t0, t0, 2);
20159 break;
20160 case NM_LDC1XS:
20161 case NM_SDC1XS:
20162 tcg_gen_shli_tl(t0, t0, 3);
20163 break;
20166 gen_op_addr_add(ctx, t0, t0, t1);
20168 switch (extract32(ctx->opcode, 7, 4)) {
20169 case NM_LBX:
20170 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20171 MO_SB);
20172 gen_store_gpr(t0, rd);
20173 break;
20174 case NM_LHX:
20175 /*case NM_LHXS:*/
20176 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20177 MO_TESW);
20178 gen_store_gpr(t0, rd);
20179 break;
20180 case NM_LWX:
20181 /*case NM_LWXS:*/
20182 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20183 MO_TESL);
20184 gen_store_gpr(t0, rd);
20185 break;
20186 case NM_LBUX:
20187 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20188 MO_UB);
20189 gen_store_gpr(t0, rd);
20190 break;
20191 case NM_LHUX:
20192 /*case NM_LHUXS:*/
20193 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20194 MO_TEUW);
20195 gen_store_gpr(t0, rd);
20196 break;
20197 case NM_SBX:
20198 check_nms(ctx);
20199 gen_load_gpr(t1, rd);
20200 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20201 MO_8);
20202 break;
20203 case NM_SHX:
20204 /*case NM_SHXS:*/
20205 check_nms(ctx);
20206 gen_load_gpr(t1, rd);
20207 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20208 MO_TEUW);
20209 break;
20210 case NM_SWX:
20211 /*case NM_SWXS:*/
20212 check_nms(ctx);
20213 gen_load_gpr(t1, rd);
20214 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20215 MO_TEUL);
20216 break;
20217 case NM_LWC1X:
20218 /*case NM_LWC1XS:*/
20219 case NM_LDC1X:
20220 /*case NM_LDC1XS:*/
20221 case NM_SWC1X:
20222 /*case NM_SWC1XS:*/
20223 case NM_SDC1X:
20224 /*case NM_SDC1XS:*/
20225 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
20226 check_cp1_enabled(ctx);
20227 switch (extract32(ctx->opcode, 7, 4)) {
20228 case NM_LWC1X:
20229 /*case NM_LWC1XS:*/
20230 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
20231 break;
20232 case NM_LDC1X:
20233 /*case NM_LDC1XS:*/
20234 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
20235 break;
20236 case NM_SWC1X:
20237 /*case NM_SWC1XS:*/
20238 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
20239 break;
20240 case NM_SDC1X:
20241 /*case NM_SDC1XS:*/
20242 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
20243 break;
20245 } else {
20246 generate_exception_err(ctx, EXCP_CpU, 1);
20248 break;
20249 default:
20250 generate_exception_end(ctx, EXCP_RI);
20251 break;
20254 tcg_temp_free(t0);
20255 tcg_temp_free(t1);
20258 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
20260 int rt, rs, rd;
20262 rt = extract32(ctx->opcode, 21, 5);
20263 rs = extract32(ctx->opcode, 16, 5);
20264 rd = extract32(ctx->opcode, 11, 5);
20266 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
20267 generate_exception_end(ctx, EXCP_RI);
20268 return;
20270 check_cp1_enabled(ctx);
20271 switch (extract32(ctx->opcode, 0, 3)) {
20272 case NM_POOL32F_0:
20273 switch (extract32(ctx->opcode, 3, 7)) {
20274 case NM_RINT_S:
20275 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
20276 break;
20277 case NM_RINT_D:
20278 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
20279 break;
20280 case NM_CLASS_S:
20281 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
20282 break;
20283 case NM_CLASS_D:
20284 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
20285 break;
20286 case NM_ADD_S:
20287 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
20288 break;
20289 case NM_ADD_D:
20290 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
20291 break;
20292 case NM_SUB_S:
20293 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
20294 break;
20295 case NM_SUB_D:
20296 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
20297 break;
20298 case NM_MUL_S:
20299 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
20300 break;
20301 case NM_MUL_D:
20302 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
20303 break;
20304 case NM_DIV_S:
20305 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
20306 break;
20307 case NM_DIV_D:
20308 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
20309 break;
20310 case NM_SELEQZ_S:
20311 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
20312 break;
20313 case NM_SELEQZ_D:
20314 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
20315 break;
20316 case NM_SELNEZ_S:
20317 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
20318 break;
20319 case NM_SELNEZ_D:
20320 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
20321 break;
20322 case NM_SEL_S:
20323 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
20324 break;
20325 case NM_SEL_D:
20326 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
20327 break;
20328 case NM_MADDF_S:
20329 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
20330 break;
20331 case NM_MADDF_D:
20332 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
20333 break;
20334 case NM_MSUBF_S:
20335 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
20336 break;
20337 case NM_MSUBF_D:
20338 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
20339 break;
20340 default:
20341 generate_exception_end(ctx, EXCP_RI);
20342 break;
20344 break;
20345 case NM_POOL32F_3:
20346 switch (extract32(ctx->opcode, 3, 3)) {
20347 case NM_MIN_FMT:
20348 switch (extract32(ctx->opcode, 9, 1)) {
20349 case FMT_SDPS_S:
20350 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
20351 break;
20352 case FMT_SDPS_D:
20353 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
20354 break;
20356 break;
20357 case NM_MAX_FMT:
20358 switch (extract32(ctx->opcode, 9, 1)) {
20359 case FMT_SDPS_S:
20360 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
20361 break;
20362 case FMT_SDPS_D:
20363 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
20364 break;
20366 break;
20367 case NM_MINA_FMT:
20368 switch (extract32(ctx->opcode, 9, 1)) {
20369 case FMT_SDPS_S:
20370 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
20371 break;
20372 case FMT_SDPS_D:
20373 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
20374 break;
20376 break;
20377 case NM_MAXA_FMT:
20378 switch (extract32(ctx->opcode, 9, 1)) {
20379 case FMT_SDPS_S:
20380 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
20381 break;
20382 case FMT_SDPS_D:
20383 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
20384 break;
20386 break;
20387 case NM_POOL32FXF:
20388 switch (extract32(ctx->opcode, 6, 8)) {
20389 case NM_CFC1:
20390 gen_cp1(ctx, OPC_CFC1, rt, rs);
20391 break;
20392 case NM_CTC1:
20393 gen_cp1(ctx, OPC_CTC1, rt, rs);
20394 break;
20395 case NM_MFC1:
20396 gen_cp1(ctx, OPC_MFC1, rt, rs);
20397 break;
20398 case NM_MTC1:
20399 gen_cp1(ctx, OPC_MTC1, rt, rs);
20400 break;
20401 case NM_MFHC1:
20402 gen_cp1(ctx, OPC_MFHC1, rt, rs);
20403 break;
20404 case NM_MTHC1:
20405 gen_cp1(ctx, OPC_MTHC1, rt, rs);
20406 break;
20407 case NM_CVT_S_PL:
20408 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
20409 break;
20410 case NM_CVT_S_PU:
20411 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
20412 break;
20413 default:
20414 switch (extract32(ctx->opcode, 6, 9)) {
20415 case NM_CVT_L_S:
20416 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
20417 break;
20418 case NM_CVT_L_D:
20419 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
20420 break;
20421 case NM_CVT_W_S:
20422 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
20423 break;
20424 case NM_CVT_W_D:
20425 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
20426 break;
20427 case NM_RSQRT_S:
20428 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
20429 break;
20430 case NM_RSQRT_D:
20431 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
20432 break;
20433 case NM_SQRT_S:
20434 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
20435 break;
20436 case NM_SQRT_D:
20437 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
20438 break;
20439 case NM_RECIP_S:
20440 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
20441 break;
20442 case NM_RECIP_D:
20443 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
20444 break;
20445 case NM_FLOOR_L_S:
20446 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
20447 break;
20448 case NM_FLOOR_L_D:
20449 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
20450 break;
20451 case NM_FLOOR_W_S:
20452 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
20453 break;
20454 case NM_FLOOR_W_D:
20455 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
20456 break;
20457 case NM_CEIL_L_S:
20458 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
20459 break;
20460 case NM_CEIL_L_D:
20461 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
20462 break;
20463 case NM_CEIL_W_S:
20464 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
20465 break;
20466 case NM_CEIL_W_D:
20467 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
20468 break;
20469 case NM_TRUNC_L_S:
20470 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
20471 break;
20472 case NM_TRUNC_L_D:
20473 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
20474 break;
20475 case NM_TRUNC_W_S:
20476 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
20477 break;
20478 case NM_TRUNC_W_D:
20479 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
20480 break;
20481 case NM_ROUND_L_S:
20482 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
20483 break;
20484 case NM_ROUND_L_D:
20485 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
20486 break;
20487 case NM_ROUND_W_S:
20488 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
20489 break;
20490 case NM_ROUND_W_D:
20491 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
20492 break;
20493 case NM_MOV_S:
20494 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
20495 break;
20496 case NM_MOV_D:
20497 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
20498 break;
20499 case NM_ABS_S:
20500 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
20501 break;
20502 case NM_ABS_D:
20503 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
20504 break;
20505 case NM_NEG_S:
20506 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
20507 break;
20508 case NM_NEG_D:
20509 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
20510 break;
20511 case NM_CVT_D_S:
20512 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
20513 break;
20514 case NM_CVT_D_W:
20515 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
20516 break;
20517 case NM_CVT_D_L:
20518 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
20519 break;
20520 case NM_CVT_S_D:
20521 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
20522 break;
20523 case NM_CVT_S_W:
20524 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
20525 break;
20526 case NM_CVT_S_L:
20527 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
20528 break;
20529 default:
20530 generate_exception_end(ctx, EXCP_RI);
20531 break;
20533 break;
20535 break;
20537 break;
20538 case NM_POOL32F_5:
20539 switch (extract32(ctx->opcode, 3, 3)) {
20540 case NM_CMP_CONDN_S:
20541 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20542 break;
20543 case NM_CMP_CONDN_D:
20544 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20545 break;
20546 default:
20547 generate_exception_end(ctx, EXCP_RI);
20548 break;
20550 break;
20551 default:
20552 generate_exception_end(ctx, EXCP_RI);
20553 break;
20557 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
20558 int rd, int rs, int rt)
20560 int ret = rd;
20561 TCGv t0 = tcg_temp_new();
20562 TCGv v1_t = tcg_temp_new();
20563 TCGv v2_t = tcg_temp_new();
20565 gen_load_gpr(v1_t, rs);
20566 gen_load_gpr(v2_t, rt);
20568 switch (opc) {
20569 case NM_CMP_EQ_PH:
20570 check_dsp(ctx);
20571 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
20572 break;
20573 case NM_CMP_LT_PH:
20574 check_dsp(ctx);
20575 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
20576 break;
20577 case NM_CMP_LE_PH:
20578 check_dsp(ctx);
20579 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
20580 break;
20581 case NM_CMPU_EQ_QB:
20582 check_dsp(ctx);
20583 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
20584 break;
20585 case NM_CMPU_LT_QB:
20586 check_dsp(ctx);
20587 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
20588 break;
20589 case NM_CMPU_LE_QB:
20590 check_dsp(ctx);
20591 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
20592 break;
20593 case NM_CMPGU_EQ_QB:
20594 check_dsp(ctx);
20595 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20596 gen_store_gpr(v1_t, ret);
20597 break;
20598 case NM_CMPGU_LT_QB:
20599 check_dsp(ctx);
20600 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20601 gen_store_gpr(v1_t, ret);
20602 break;
20603 case NM_CMPGU_LE_QB:
20604 check_dsp(ctx);
20605 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20606 gen_store_gpr(v1_t, ret);
20607 break;
20608 case NM_CMPGDU_EQ_QB:
20609 check_dsp_r2(ctx);
20610 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20611 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20612 gen_store_gpr(v1_t, ret);
20613 break;
20614 case NM_CMPGDU_LT_QB:
20615 check_dsp_r2(ctx);
20616 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20617 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20618 gen_store_gpr(v1_t, ret);
20619 break;
20620 case NM_CMPGDU_LE_QB:
20621 check_dsp_r2(ctx);
20622 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20623 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20624 gen_store_gpr(v1_t, ret);
20625 break;
20626 case NM_PACKRL_PH:
20627 check_dsp(ctx);
20628 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
20629 gen_store_gpr(v1_t, ret);
20630 break;
20631 case NM_PICK_QB:
20632 check_dsp(ctx);
20633 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
20634 gen_store_gpr(v1_t, ret);
20635 break;
20636 case NM_PICK_PH:
20637 check_dsp(ctx);
20638 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
20639 gen_store_gpr(v1_t, ret);
20640 break;
20641 case NM_ADDQ_S_W:
20642 check_dsp(ctx);
20643 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
20644 gen_store_gpr(v1_t, ret);
20645 break;
20646 case NM_SUBQ_S_W:
20647 check_dsp(ctx);
20648 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
20649 gen_store_gpr(v1_t, ret);
20650 break;
20651 case NM_ADDSC:
20652 check_dsp(ctx);
20653 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
20654 gen_store_gpr(v1_t, ret);
20655 break;
20656 case NM_ADDWC:
20657 check_dsp(ctx);
20658 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
20659 gen_store_gpr(v1_t, ret);
20660 break;
20661 case NM_ADDQ_S_PH:
20662 check_dsp(ctx);
20663 switch (extract32(ctx->opcode, 10, 1)) {
20664 case 0:
20665 /* ADDQ_PH */
20666 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
20667 gen_store_gpr(v1_t, ret);
20668 break;
20669 case 1:
20670 /* ADDQ_S_PH */
20671 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20672 gen_store_gpr(v1_t, ret);
20673 break;
20675 break;
20676 case NM_ADDQH_R_PH:
20677 check_dsp_r2(ctx);
20678 switch (extract32(ctx->opcode, 10, 1)) {
20679 case 0:
20680 /* ADDQH_PH */
20681 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
20682 gen_store_gpr(v1_t, ret);
20683 break;
20684 case 1:
20685 /* ADDQH_R_PH */
20686 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
20687 gen_store_gpr(v1_t, ret);
20688 break;
20690 break;
20691 case NM_ADDQH_R_W:
20692 check_dsp_r2(ctx);
20693 switch (extract32(ctx->opcode, 10, 1)) {
20694 case 0:
20695 /* ADDQH_W */
20696 gen_helper_addqh_w(v1_t, v1_t, v2_t);
20697 gen_store_gpr(v1_t, ret);
20698 break;
20699 case 1:
20700 /* ADDQH_R_W */
20701 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
20702 gen_store_gpr(v1_t, ret);
20703 break;
20705 break;
20706 case NM_ADDU_S_QB:
20707 check_dsp(ctx);
20708 switch (extract32(ctx->opcode, 10, 1)) {
20709 case 0:
20710 /* ADDU_QB */
20711 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
20712 gen_store_gpr(v1_t, ret);
20713 break;
20714 case 1:
20715 /* ADDU_S_QB */
20716 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20717 gen_store_gpr(v1_t, ret);
20718 break;
20720 break;
20721 case NM_ADDU_S_PH:
20722 check_dsp_r2(ctx);
20723 switch (extract32(ctx->opcode, 10, 1)) {
20724 case 0:
20725 /* ADDU_PH */
20726 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
20727 gen_store_gpr(v1_t, ret);
20728 break;
20729 case 1:
20730 /* ADDU_S_PH */
20731 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20732 gen_store_gpr(v1_t, ret);
20733 break;
20735 break;
20736 case NM_ADDUH_R_QB:
20737 check_dsp_r2(ctx);
20738 switch (extract32(ctx->opcode, 10, 1)) {
20739 case 0:
20740 /* ADDUH_QB */
20741 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
20742 gen_store_gpr(v1_t, ret);
20743 break;
20744 case 1:
20745 /* ADDUH_R_QB */
20746 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
20747 gen_store_gpr(v1_t, ret);
20748 break;
20750 break;
20751 case NM_SHRAV_R_PH:
20752 check_dsp(ctx);
20753 switch (extract32(ctx->opcode, 10, 1)) {
20754 case 0:
20755 /* SHRAV_PH */
20756 gen_helper_shra_ph(v1_t, v1_t, v2_t);
20757 gen_store_gpr(v1_t, ret);
20758 break;
20759 case 1:
20760 /* SHRAV_R_PH */
20761 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
20762 gen_store_gpr(v1_t, ret);
20763 break;
20765 break;
20766 case NM_SHRAV_R_QB:
20767 check_dsp_r2(ctx);
20768 switch (extract32(ctx->opcode, 10, 1)) {
20769 case 0:
20770 /* SHRAV_QB */
20771 gen_helper_shra_qb(v1_t, v1_t, v2_t);
20772 gen_store_gpr(v1_t, ret);
20773 break;
20774 case 1:
20775 /* SHRAV_R_QB */
20776 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
20777 gen_store_gpr(v1_t, ret);
20778 break;
20780 break;
20781 case NM_SUBQ_S_PH:
20782 check_dsp(ctx);
20783 switch (extract32(ctx->opcode, 10, 1)) {
20784 case 0:
20785 /* SUBQ_PH */
20786 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
20787 gen_store_gpr(v1_t, ret);
20788 break;
20789 case 1:
20790 /* SUBQ_S_PH */
20791 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20792 gen_store_gpr(v1_t, ret);
20793 break;
20795 break;
20796 case NM_SUBQH_R_PH:
20797 check_dsp_r2(ctx);
20798 switch (extract32(ctx->opcode, 10, 1)) {
20799 case 0:
20800 /* SUBQH_PH */
20801 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
20802 gen_store_gpr(v1_t, ret);
20803 break;
20804 case 1:
20805 /* SUBQH_R_PH */
20806 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
20807 gen_store_gpr(v1_t, ret);
20808 break;
20810 break;
20811 case NM_SUBQH_R_W:
20812 check_dsp_r2(ctx);
20813 switch (extract32(ctx->opcode, 10, 1)) {
20814 case 0:
20815 /* SUBQH_W */
20816 gen_helper_subqh_w(v1_t, v1_t, v2_t);
20817 gen_store_gpr(v1_t, ret);
20818 break;
20819 case 1:
20820 /* SUBQH_R_W */
20821 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
20822 gen_store_gpr(v1_t, ret);
20823 break;
20825 break;
20826 case NM_SUBU_S_QB:
20827 check_dsp(ctx);
20828 switch (extract32(ctx->opcode, 10, 1)) {
20829 case 0:
20830 /* SUBU_QB */
20831 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
20832 gen_store_gpr(v1_t, ret);
20833 break;
20834 case 1:
20835 /* SUBU_S_QB */
20836 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20837 gen_store_gpr(v1_t, ret);
20838 break;
20840 break;
20841 case NM_SUBU_S_PH:
20842 check_dsp_r2(ctx);
20843 switch (extract32(ctx->opcode, 10, 1)) {
20844 case 0:
20845 /* SUBU_PH */
20846 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
20847 gen_store_gpr(v1_t, ret);
20848 break;
20849 case 1:
20850 /* SUBU_S_PH */
20851 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20852 gen_store_gpr(v1_t, ret);
20853 break;
20855 break;
20856 case NM_SUBUH_R_QB:
20857 check_dsp_r2(ctx);
20858 switch (extract32(ctx->opcode, 10, 1)) {
20859 case 0:
20860 /* SUBUH_QB */
20861 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
20862 gen_store_gpr(v1_t, ret);
20863 break;
20864 case 1:
20865 /* SUBUH_R_QB */
20866 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
20867 gen_store_gpr(v1_t, ret);
20868 break;
20870 break;
20871 case NM_SHLLV_S_PH:
20872 check_dsp(ctx);
20873 switch (extract32(ctx->opcode, 10, 1)) {
20874 case 0:
20875 /* SHLLV_PH */
20876 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
20877 gen_store_gpr(v1_t, ret);
20878 break;
20879 case 1:
20880 /* SHLLV_S_PH */
20881 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
20882 gen_store_gpr(v1_t, ret);
20883 break;
20885 break;
20886 case NM_PRECR_SRA_R_PH_W:
20887 check_dsp_r2(ctx);
20888 switch (extract32(ctx->opcode, 10, 1)) {
20889 case 0:
20890 /* PRECR_SRA_PH_W */
20892 TCGv_i32 sa_t = tcg_const_i32(rd);
20893 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
20894 cpu_gpr[rt]);
20895 gen_store_gpr(v1_t, rt);
20896 tcg_temp_free_i32(sa_t);
20898 break;
20899 case 1:
20900 /* PRECR_SRA_R_PH_W */
20902 TCGv_i32 sa_t = tcg_const_i32(rd);
20903 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
20904 cpu_gpr[rt]);
20905 gen_store_gpr(v1_t, rt);
20906 tcg_temp_free_i32(sa_t);
20908 break;
20910 break;
20911 case NM_MULEU_S_PH_QBL:
20912 check_dsp(ctx);
20913 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
20914 gen_store_gpr(v1_t, ret);
20915 break;
20916 case NM_MULEU_S_PH_QBR:
20917 check_dsp(ctx);
20918 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
20919 gen_store_gpr(v1_t, ret);
20920 break;
20921 case NM_MULQ_RS_PH:
20922 check_dsp(ctx);
20923 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
20924 gen_store_gpr(v1_t, ret);
20925 break;
20926 case NM_MULQ_S_PH:
20927 check_dsp_r2(ctx);
20928 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20929 gen_store_gpr(v1_t, ret);
20930 break;
20931 case NM_MULQ_RS_W:
20932 check_dsp_r2(ctx);
20933 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
20934 gen_store_gpr(v1_t, ret);
20935 break;
20936 case NM_MULQ_S_W:
20937 check_dsp_r2(ctx);
20938 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
20939 gen_store_gpr(v1_t, ret);
20940 break;
20941 case NM_APPEND:
20942 check_dsp_r2(ctx);
20943 gen_load_gpr(t0, rs);
20944 if (rd != 0) {
20945 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
20947 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20948 break;
20949 case NM_MODSUB:
20950 check_dsp(ctx);
20951 gen_helper_modsub(v1_t, v1_t, v2_t);
20952 gen_store_gpr(v1_t, ret);
20953 break;
20954 case NM_SHRAV_R_W:
20955 check_dsp(ctx);
20956 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
20957 gen_store_gpr(v1_t, ret);
20958 break;
20959 case NM_SHRLV_PH:
20960 check_dsp_r2(ctx);
20961 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
20962 gen_store_gpr(v1_t, ret);
20963 break;
20964 case NM_SHRLV_QB:
20965 check_dsp(ctx);
20966 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
20967 gen_store_gpr(v1_t, ret);
20968 break;
20969 case NM_SHLLV_QB:
20970 check_dsp(ctx);
20971 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
20972 gen_store_gpr(v1_t, ret);
20973 break;
20974 case NM_SHLLV_S_W:
20975 check_dsp(ctx);
20976 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
20977 gen_store_gpr(v1_t, ret);
20978 break;
20979 case NM_SHILO:
20980 check_dsp(ctx);
20982 TCGv tv0 = tcg_temp_new();
20983 TCGv tv1 = tcg_temp_new();
20984 int16_t imm = extract32(ctx->opcode, 16, 7);
20986 tcg_gen_movi_tl(tv0, rd >> 3);
20987 tcg_gen_movi_tl(tv1, imm);
20988 gen_helper_shilo(tv0, tv1, cpu_env);
20990 break;
20991 case NM_MULEQ_S_W_PHL:
20992 check_dsp(ctx);
20993 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
20994 gen_store_gpr(v1_t, ret);
20995 break;
20996 case NM_MULEQ_S_W_PHR:
20997 check_dsp(ctx);
20998 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
20999 gen_store_gpr(v1_t, ret);
21000 break;
21001 case NM_MUL_S_PH:
21002 check_dsp_r2(ctx);
21003 switch (extract32(ctx->opcode, 10, 1)) {
21004 case 0:
21005 /* MUL_PH */
21006 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
21007 gen_store_gpr(v1_t, ret);
21008 break;
21009 case 1:
21010 /* MUL_S_PH */
21011 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
21012 gen_store_gpr(v1_t, ret);
21013 break;
21015 break;
21016 case NM_PRECR_QB_PH:
21017 check_dsp_r2(ctx);
21018 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
21019 gen_store_gpr(v1_t, ret);
21020 break;
21021 case NM_PRECRQ_QB_PH:
21022 check_dsp(ctx);
21023 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
21024 gen_store_gpr(v1_t, ret);
21025 break;
21026 case NM_PRECRQ_PH_W:
21027 check_dsp(ctx);
21028 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
21029 gen_store_gpr(v1_t, ret);
21030 break;
21031 case NM_PRECRQ_RS_PH_W:
21032 check_dsp(ctx);
21033 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
21034 gen_store_gpr(v1_t, ret);
21035 break;
21036 case NM_PRECRQU_S_QB_PH:
21037 check_dsp(ctx);
21038 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
21039 gen_store_gpr(v1_t, ret);
21040 break;
21041 case NM_SHRA_R_W:
21042 check_dsp(ctx);
21043 tcg_gen_movi_tl(t0, rd);
21044 gen_helper_shra_r_w(v1_t, t0, v1_t);
21045 gen_store_gpr(v1_t, rt);
21046 break;
21047 case NM_SHRA_R_PH:
21048 check_dsp(ctx);
21049 tcg_gen_movi_tl(t0, rd >> 1);
21050 switch (extract32(ctx->opcode, 10, 1)) {
21051 case 0:
21052 /* SHRA_PH */
21053 gen_helper_shra_ph(v1_t, t0, v1_t);
21054 gen_store_gpr(v1_t, rt);
21055 break;
21056 case 1:
21057 /* SHRA_R_PH */
21058 gen_helper_shra_r_ph(v1_t, t0, v1_t);
21059 gen_store_gpr(v1_t, rt);
21060 break;
21062 break;
21063 case NM_SHLL_S_PH:
21064 check_dsp(ctx);
21065 tcg_gen_movi_tl(t0, rd >> 1);
21066 switch (extract32(ctx->opcode, 10, 2)) {
21067 case 0:
21068 /* SHLL_PH */
21069 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
21070 gen_store_gpr(v1_t, rt);
21071 break;
21072 case 2:
21073 /* SHLL_S_PH */
21074 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
21075 gen_store_gpr(v1_t, rt);
21076 break;
21077 default:
21078 generate_exception_end(ctx, EXCP_RI);
21079 break;
21081 break;
21082 case NM_SHLL_S_W:
21083 check_dsp(ctx);
21084 tcg_gen_movi_tl(t0, rd);
21085 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
21086 gen_store_gpr(v1_t, rt);
21087 break;
21088 case NM_REPL_PH:
21089 check_dsp(ctx);
21091 int16_t imm;
21092 imm = sextract32(ctx->opcode, 11, 11);
21093 imm = (int16_t)(imm << 6) >> 6;
21094 if (rt != 0) {
21095 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
21098 break;
21099 default:
21100 generate_exception_end(ctx, EXCP_RI);
21101 break;
21105 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
21107 uint16_t insn;
21108 uint32_t op;
21109 int rt, rs, rd;
21110 int offset;
21111 int imm;
21113 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
21114 ctx->opcode = (ctx->opcode << 16) | insn;
21116 rt = extract32(ctx->opcode, 21, 5);
21117 rs = extract32(ctx->opcode, 16, 5);
21118 rd = extract32(ctx->opcode, 11, 5);
21120 op = extract32(ctx->opcode, 26, 6);
21121 switch (op) {
21122 case NM_P_ADDIU:
21123 if (rt == 0) {
21124 /* P.RI */
21125 switch (extract32(ctx->opcode, 19, 2)) {
21126 case NM_SIGRIE:
21127 default:
21128 generate_exception_end(ctx, EXCP_RI);
21129 break;
21130 case NM_P_SYSCALL:
21131 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
21132 generate_exception_end(ctx, EXCP_SYSCALL);
21133 } else {
21134 generate_exception_end(ctx, EXCP_RI);
21136 break;
21137 case NM_BREAK:
21138 generate_exception_end(ctx, EXCP_BREAK);
21139 break;
21140 case NM_SDBBP:
21141 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
21142 gen_helper_do_semihosting(cpu_env);
21143 } else {
21144 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21145 generate_exception_end(ctx, EXCP_RI);
21146 } else {
21147 generate_exception_end(ctx, EXCP_DBp);
21150 break;
21152 } else {
21153 /* NM_ADDIU */
21154 imm = extract32(ctx->opcode, 0, 16);
21155 if (rs != 0) {
21156 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
21157 } else {
21158 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21160 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21162 break;
21163 case NM_ADDIUPC:
21164 if (rt != 0) {
21165 offset = sextract32(ctx->opcode, 0, 1) << 21 |
21166 extract32(ctx->opcode, 1, 20) << 1;
21167 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
21168 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21170 break;
21171 case NM_POOL32A:
21172 switch (ctx->opcode & 0x07) {
21173 case NM_POOL32A0:
21174 gen_pool32a0_nanomips_insn(env, ctx);
21175 break;
21176 case NM_POOL32A5:
21178 int32_t op1 = extract32(ctx->opcode, 3, 7);
21179 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
21181 break;
21182 case NM_POOL32A7:
21183 switch (extract32(ctx->opcode, 3, 3)) {
21184 case NM_P_LSX:
21185 gen_p_lsx(ctx, rd, rs, rt);
21186 break;
21187 case NM_LSA:
21189 * In nanoMIPS, the shift field directly encodes the shift
21190 * amount, meaning that the supported shift values are in
21191 * the range 0 to 3 (instead of 1 to 4 in MIPSR6).
21193 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
21194 extract32(ctx->opcode, 9, 2) - 1);
21195 break;
21196 case NM_EXTW:
21197 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
21198 break;
21199 case NM_POOL32AXF:
21200 gen_pool32axf_nanomips_insn(env, ctx);
21201 break;
21202 default:
21203 generate_exception_end(ctx, EXCP_RI);
21204 break;
21206 break;
21207 default:
21208 generate_exception_end(ctx, EXCP_RI);
21209 break;
21211 break;
21212 case NM_P_GP_W:
21213 switch (ctx->opcode & 0x03) {
21214 case NM_ADDIUGP_W:
21215 if (rt != 0) {
21216 offset = extract32(ctx->opcode, 0, 21);
21217 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
21219 break;
21220 case NM_LWGP:
21221 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21222 break;
21223 case NM_SWGP:
21224 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21225 break;
21226 default:
21227 generate_exception_end(ctx, EXCP_RI);
21228 break;
21230 break;
21231 case NM_P48I:
21233 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
21234 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
21235 switch (extract32(ctx->opcode, 16, 5)) {
21236 case NM_LI48:
21237 check_nms(ctx);
21238 if (rt != 0) {
21239 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
21241 break;
21242 case NM_ADDIU48:
21243 check_nms(ctx);
21244 if (rt != 0) {
21245 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
21246 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21248 break;
21249 case NM_ADDIUGP48:
21250 check_nms(ctx);
21251 if (rt != 0) {
21252 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
21254 break;
21255 case NM_ADDIUPC48:
21256 check_nms(ctx);
21257 if (rt != 0) {
21258 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21259 addr_off);
21261 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21263 break;
21264 case NM_LWPC48:
21265 check_nms(ctx);
21266 if (rt != 0) {
21267 TCGv t0;
21268 t0 = tcg_temp_new();
21270 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21271 addr_off);
21273 tcg_gen_movi_tl(t0, addr);
21274 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
21275 tcg_temp_free(t0);
21277 break;
21278 case NM_SWPC48:
21279 check_nms(ctx);
21281 TCGv t0, t1;
21282 t0 = tcg_temp_new();
21283 t1 = tcg_temp_new();
21285 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21286 addr_off);
21288 tcg_gen_movi_tl(t0, addr);
21289 gen_load_gpr(t1, rt);
21291 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
21293 tcg_temp_free(t0);
21294 tcg_temp_free(t1);
21296 break;
21297 default:
21298 generate_exception_end(ctx, EXCP_RI);
21299 break;
21301 return 6;
21303 case NM_P_U12:
21304 switch (extract32(ctx->opcode, 12, 4)) {
21305 case NM_ORI:
21306 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
21307 break;
21308 case NM_XORI:
21309 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
21310 break;
21311 case NM_ANDI:
21312 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
21313 break;
21314 case NM_P_SR:
21315 switch (extract32(ctx->opcode, 20, 1)) {
21316 case NM_PP_SR:
21317 switch (ctx->opcode & 3) {
21318 case NM_SAVE:
21319 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
21320 extract32(ctx->opcode, 2, 1),
21321 extract32(ctx->opcode, 3, 9) << 3);
21322 break;
21323 case NM_RESTORE:
21324 case NM_RESTORE_JRC:
21325 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
21326 extract32(ctx->opcode, 2, 1),
21327 extract32(ctx->opcode, 3, 9) << 3);
21328 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
21329 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21331 break;
21332 default:
21333 generate_exception_end(ctx, EXCP_RI);
21334 break;
21336 break;
21337 case NM_P_SR_F:
21338 generate_exception_end(ctx, EXCP_RI);
21339 break;
21341 break;
21342 case NM_SLTI:
21343 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
21344 break;
21345 case NM_SLTIU:
21346 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
21347 break;
21348 case NM_SEQI:
21350 TCGv t0 = tcg_temp_new();
21352 imm = extract32(ctx->opcode, 0, 12);
21353 gen_load_gpr(t0, rs);
21354 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
21355 gen_store_gpr(t0, rt);
21357 tcg_temp_free(t0);
21359 break;
21360 case NM_ADDIUNEG:
21361 imm = (int16_t) extract32(ctx->opcode, 0, 12);
21362 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
21363 break;
21364 case NM_P_SHIFT:
21366 int shift = extract32(ctx->opcode, 0, 5);
21367 switch (extract32(ctx->opcode, 5, 4)) {
21368 case NM_P_SLL:
21369 if (rt == 0 && shift == 0) {
21370 /* NOP */
21371 } else if (rt == 0 && shift == 3) {
21372 /* EHB - treat as NOP */
21373 } else if (rt == 0 && shift == 5) {
21374 /* PAUSE - treat as NOP */
21375 } else if (rt == 0 && shift == 6) {
21376 /* SYNC */
21377 gen_sync(extract32(ctx->opcode, 16, 5));
21378 } else {
21379 /* SLL */
21380 gen_shift_imm(ctx, OPC_SLL, rt, rs,
21381 extract32(ctx->opcode, 0, 5));
21383 break;
21384 case NM_SRL:
21385 gen_shift_imm(ctx, OPC_SRL, rt, rs,
21386 extract32(ctx->opcode, 0, 5));
21387 break;
21388 case NM_SRA:
21389 gen_shift_imm(ctx, OPC_SRA, rt, rs,
21390 extract32(ctx->opcode, 0, 5));
21391 break;
21392 case NM_ROTR:
21393 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
21394 extract32(ctx->opcode, 0, 5));
21395 break;
21398 break;
21399 case NM_P_ROTX:
21400 check_nms(ctx);
21401 if (rt != 0) {
21402 TCGv t0 = tcg_temp_new();
21403 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
21404 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
21405 << 1);
21406 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
21408 gen_load_gpr(t0, rs);
21409 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
21410 tcg_temp_free(t0);
21412 tcg_temp_free_i32(shift);
21413 tcg_temp_free_i32(shiftx);
21414 tcg_temp_free_i32(stripe);
21416 break;
21417 case NM_P_INS:
21418 switch (((ctx->opcode >> 10) & 2) |
21419 (extract32(ctx->opcode, 5, 1))) {
21420 case NM_INS:
21421 check_nms(ctx);
21422 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
21423 extract32(ctx->opcode, 6, 5));
21424 break;
21425 default:
21426 generate_exception_end(ctx, EXCP_RI);
21427 break;
21429 break;
21430 case NM_P_EXT:
21431 switch (((ctx->opcode >> 10) & 2) |
21432 (extract32(ctx->opcode, 5, 1))) {
21433 case NM_EXT:
21434 check_nms(ctx);
21435 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
21436 extract32(ctx->opcode, 6, 5));
21437 break;
21438 default:
21439 generate_exception_end(ctx, EXCP_RI);
21440 break;
21442 break;
21443 default:
21444 generate_exception_end(ctx, EXCP_RI);
21445 break;
21447 break;
21448 case NM_POOL32F:
21449 gen_pool32f_nanomips_insn(ctx);
21450 break;
21451 case NM_POOL32S:
21452 break;
21453 case NM_P_LUI:
21454 switch (extract32(ctx->opcode, 1, 1)) {
21455 case NM_LUI:
21456 if (rt != 0) {
21457 tcg_gen_movi_tl(cpu_gpr[rt],
21458 sextract32(ctx->opcode, 0, 1) << 31 |
21459 extract32(ctx->opcode, 2, 10) << 21 |
21460 extract32(ctx->opcode, 12, 9) << 12);
21462 break;
21463 case NM_ALUIPC:
21464 if (rt != 0) {
21465 offset = sextract32(ctx->opcode, 0, 1) << 31 |
21466 extract32(ctx->opcode, 2, 10) << 21 |
21467 extract32(ctx->opcode, 12, 9) << 12;
21468 target_long addr;
21469 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
21470 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21472 break;
21474 break;
21475 case NM_P_GP_BH:
21477 uint32_t u = extract32(ctx->opcode, 0, 18);
21479 switch (extract32(ctx->opcode, 18, 3)) {
21480 case NM_LBGP:
21481 gen_ld(ctx, OPC_LB, rt, 28, u);
21482 break;
21483 case NM_SBGP:
21484 gen_st(ctx, OPC_SB, rt, 28, u);
21485 break;
21486 case NM_LBUGP:
21487 gen_ld(ctx, OPC_LBU, rt, 28, u);
21488 break;
21489 case NM_ADDIUGP_B:
21490 if (rt != 0) {
21491 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
21493 break;
21494 case NM_P_GP_LH:
21495 u &= ~1;
21496 switch (ctx->opcode & 1) {
21497 case NM_LHGP:
21498 gen_ld(ctx, OPC_LH, rt, 28, u);
21499 break;
21500 case NM_LHUGP:
21501 gen_ld(ctx, OPC_LHU, rt, 28, u);
21502 break;
21504 break;
21505 case NM_P_GP_SH:
21506 u &= ~1;
21507 switch (ctx->opcode & 1) {
21508 case NM_SHGP:
21509 gen_st(ctx, OPC_SH, rt, 28, u);
21510 break;
21511 default:
21512 generate_exception_end(ctx, EXCP_RI);
21513 break;
21515 break;
21516 case NM_P_GP_CP1:
21517 u &= ~0x3;
21518 switch (ctx->opcode & 0x3) {
21519 case NM_LWC1GP:
21520 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
21521 break;
21522 case NM_LDC1GP:
21523 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
21524 break;
21525 case NM_SWC1GP:
21526 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
21527 break;
21528 case NM_SDC1GP:
21529 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
21530 break;
21532 break;
21533 default:
21534 generate_exception_end(ctx, EXCP_RI);
21535 break;
21538 break;
21539 case NM_P_LS_U12:
21541 uint32_t u = extract32(ctx->opcode, 0, 12);
21543 switch (extract32(ctx->opcode, 12, 4)) {
21544 case NM_P_PREFU12:
21545 if (rt == 31) {
21546 /* SYNCI */
21548 * Break the TB to be able to sync copied instructions
21549 * immediately.
21551 ctx->base.is_jmp = DISAS_STOP;
21552 } else {
21553 /* PREF */
21554 /* Treat as NOP. */
21556 break;
21557 case NM_LB:
21558 gen_ld(ctx, OPC_LB, rt, rs, u);
21559 break;
21560 case NM_LH:
21561 gen_ld(ctx, OPC_LH, rt, rs, u);
21562 break;
21563 case NM_LW:
21564 gen_ld(ctx, OPC_LW, rt, rs, u);
21565 break;
21566 case NM_LBU:
21567 gen_ld(ctx, OPC_LBU, rt, rs, u);
21568 break;
21569 case NM_LHU:
21570 gen_ld(ctx, OPC_LHU, rt, rs, u);
21571 break;
21572 case NM_SB:
21573 gen_st(ctx, OPC_SB, rt, rs, u);
21574 break;
21575 case NM_SH:
21576 gen_st(ctx, OPC_SH, rt, rs, u);
21577 break;
21578 case NM_SW:
21579 gen_st(ctx, OPC_SW, rt, rs, u);
21580 break;
21581 case NM_LWC1:
21582 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
21583 break;
21584 case NM_LDC1:
21585 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
21586 break;
21587 case NM_SWC1:
21588 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
21589 break;
21590 case NM_SDC1:
21591 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
21592 break;
21593 default:
21594 generate_exception_end(ctx, EXCP_RI);
21595 break;
21598 break;
21599 case NM_P_LS_S9:
21601 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
21602 extract32(ctx->opcode, 0, 8);
21604 switch (extract32(ctx->opcode, 8, 3)) {
21605 case NM_P_LS_S0:
21606 switch (extract32(ctx->opcode, 11, 4)) {
21607 case NM_LBS9:
21608 gen_ld(ctx, OPC_LB, rt, rs, s);
21609 break;
21610 case NM_LHS9:
21611 gen_ld(ctx, OPC_LH, rt, rs, s);
21612 break;
21613 case NM_LWS9:
21614 gen_ld(ctx, OPC_LW, rt, rs, s);
21615 break;
21616 case NM_LBUS9:
21617 gen_ld(ctx, OPC_LBU, rt, rs, s);
21618 break;
21619 case NM_LHUS9:
21620 gen_ld(ctx, OPC_LHU, rt, rs, s);
21621 break;
21622 case NM_SBS9:
21623 gen_st(ctx, OPC_SB, rt, rs, s);
21624 break;
21625 case NM_SHS9:
21626 gen_st(ctx, OPC_SH, rt, rs, s);
21627 break;
21628 case NM_SWS9:
21629 gen_st(ctx, OPC_SW, rt, rs, s);
21630 break;
21631 case NM_LWC1S9:
21632 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
21633 break;
21634 case NM_LDC1S9:
21635 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
21636 break;
21637 case NM_SWC1S9:
21638 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
21639 break;
21640 case NM_SDC1S9:
21641 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
21642 break;
21643 case NM_P_PREFS9:
21644 if (rt == 31) {
21645 /* SYNCI */
21647 * Break the TB to be able to sync copied instructions
21648 * immediately.
21650 ctx->base.is_jmp = DISAS_STOP;
21651 } else {
21652 /* PREF */
21653 /* Treat as NOP. */
21655 break;
21656 default:
21657 generate_exception_end(ctx, EXCP_RI);
21658 break;
21660 break;
21661 case NM_P_LS_S1:
21662 switch (extract32(ctx->opcode, 11, 4)) {
21663 case NM_UALH:
21664 case NM_UASH:
21665 check_nms(ctx);
21667 TCGv t0 = tcg_temp_new();
21668 TCGv t1 = tcg_temp_new();
21670 gen_base_offset_addr(ctx, t0, rs, s);
21672 switch (extract32(ctx->opcode, 11, 4)) {
21673 case NM_UALH:
21674 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
21675 MO_UNALN);
21676 gen_store_gpr(t0, rt);
21677 break;
21678 case NM_UASH:
21679 gen_load_gpr(t1, rt);
21680 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
21681 MO_UNALN);
21682 break;
21684 tcg_temp_free(t0);
21685 tcg_temp_free(t1);
21687 break;
21688 case NM_P_LL:
21689 switch (ctx->opcode & 0x03) {
21690 case NM_LL:
21691 gen_ld(ctx, OPC_LL, rt, rs, s);
21692 break;
21693 case NM_LLWP:
21694 check_xnp(ctx);
21695 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21696 break;
21698 break;
21699 case NM_P_SC:
21700 switch (ctx->opcode & 0x03) {
21701 case NM_SC:
21702 gen_st_cond(ctx, rt, rs, s, MO_TESL, false);
21703 break;
21704 case NM_SCWP:
21705 check_xnp(ctx);
21706 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21707 false);
21708 break;
21710 break;
21711 case NM_CACHE:
21712 check_cp0_enabled(ctx);
21713 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
21714 gen_cache_operation(ctx, rt, rs, s);
21716 break;
21718 break;
21719 case NM_P_LS_E0:
21720 switch (extract32(ctx->opcode, 11, 4)) {
21721 case NM_LBE:
21722 check_eva(ctx);
21723 check_cp0_enabled(ctx);
21724 gen_ld(ctx, OPC_LBE, rt, rs, s);
21725 break;
21726 case NM_SBE:
21727 check_eva(ctx);
21728 check_cp0_enabled(ctx);
21729 gen_st(ctx, OPC_SBE, rt, rs, s);
21730 break;
21731 case NM_LBUE:
21732 check_eva(ctx);
21733 check_cp0_enabled(ctx);
21734 gen_ld(ctx, OPC_LBUE, rt, rs, s);
21735 break;
21736 case NM_P_PREFE:
21737 if (rt == 31) {
21738 /* case NM_SYNCIE */
21739 check_eva(ctx);
21740 check_cp0_enabled(ctx);
21742 * Break the TB to be able to sync copied instructions
21743 * immediately.
21745 ctx->base.is_jmp = DISAS_STOP;
21746 } else {
21747 /* case NM_PREFE */
21748 check_eva(ctx);
21749 check_cp0_enabled(ctx);
21750 /* Treat as NOP. */
21752 break;
21753 case NM_LHE:
21754 check_eva(ctx);
21755 check_cp0_enabled(ctx);
21756 gen_ld(ctx, OPC_LHE, rt, rs, s);
21757 break;
21758 case NM_SHE:
21759 check_eva(ctx);
21760 check_cp0_enabled(ctx);
21761 gen_st(ctx, OPC_SHE, rt, rs, s);
21762 break;
21763 case NM_LHUE:
21764 check_eva(ctx);
21765 check_cp0_enabled(ctx);
21766 gen_ld(ctx, OPC_LHUE, rt, rs, s);
21767 break;
21768 case NM_CACHEE:
21769 check_nms_dl_il_sl_tl_l2c(ctx);
21770 gen_cache_operation(ctx, rt, rs, s);
21771 break;
21772 case NM_LWE:
21773 check_eva(ctx);
21774 check_cp0_enabled(ctx);
21775 gen_ld(ctx, OPC_LWE, rt, rs, s);
21776 break;
21777 case NM_SWE:
21778 check_eva(ctx);
21779 check_cp0_enabled(ctx);
21780 gen_st(ctx, OPC_SWE, rt, rs, s);
21781 break;
21782 case NM_P_LLE:
21783 switch (extract32(ctx->opcode, 2, 2)) {
21784 case NM_LLE:
21785 check_xnp(ctx);
21786 check_eva(ctx);
21787 check_cp0_enabled(ctx);
21788 gen_ld(ctx, OPC_LLE, rt, rs, s);
21789 break;
21790 case NM_LLWPE:
21791 check_xnp(ctx);
21792 check_eva(ctx);
21793 check_cp0_enabled(ctx);
21794 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21795 break;
21796 default:
21797 generate_exception_end(ctx, EXCP_RI);
21798 break;
21800 break;
21801 case NM_P_SCE:
21802 switch (extract32(ctx->opcode, 2, 2)) {
21803 case NM_SCE:
21804 check_xnp(ctx);
21805 check_eva(ctx);
21806 check_cp0_enabled(ctx);
21807 gen_st_cond(ctx, rt, rs, s, MO_TESL, true);
21808 break;
21809 case NM_SCWPE:
21810 check_xnp(ctx);
21811 check_eva(ctx);
21812 check_cp0_enabled(ctx);
21813 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21814 true);
21815 break;
21816 default:
21817 generate_exception_end(ctx, EXCP_RI);
21818 break;
21820 break;
21822 break;
21823 case NM_P_LS_WM:
21824 case NM_P_LS_UAWM:
21825 check_nms(ctx);
21827 int count = extract32(ctx->opcode, 12, 3);
21828 int counter = 0;
21830 offset = sextract32(ctx->opcode, 15, 1) << 8 |
21831 extract32(ctx->opcode, 0, 8);
21832 TCGv va = tcg_temp_new();
21833 TCGv t1 = tcg_temp_new();
21834 TCGMemOp memop = (extract32(ctx->opcode, 8, 3)) ==
21835 NM_P_LS_UAWM ? MO_UNALN : 0;
21837 count = (count == 0) ? 8 : count;
21838 while (counter != count) {
21839 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
21840 int this_offset = offset + (counter << 2);
21842 gen_base_offset_addr(ctx, va, rs, this_offset);
21844 switch (extract32(ctx->opcode, 11, 1)) {
21845 case NM_LWM:
21846 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
21847 memop | MO_TESL);
21848 gen_store_gpr(t1, this_rt);
21849 if ((this_rt == rs) &&
21850 (counter != (count - 1))) {
21851 /* UNPREDICTABLE */
21853 break;
21854 case NM_SWM:
21855 this_rt = (rt == 0) ? 0 : this_rt;
21856 gen_load_gpr(t1, this_rt);
21857 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
21858 memop | MO_TEUL);
21859 break;
21861 counter++;
21863 tcg_temp_free(va);
21864 tcg_temp_free(t1);
21866 break;
21867 default:
21868 generate_exception_end(ctx, EXCP_RI);
21869 break;
21872 break;
21873 case NM_MOVE_BALC:
21874 check_nms(ctx);
21876 TCGv t0 = tcg_temp_new();
21877 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
21878 extract32(ctx->opcode, 1, 20) << 1;
21879 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
21880 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
21881 extract32(ctx->opcode, 21, 3));
21882 gen_load_gpr(t0, rt);
21883 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21884 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21885 tcg_temp_free(t0);
21887 break;
21888 case NM_P_BAL:
21890 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
21891 extract32(ctx->opcode, 1, 24) << 1;
21893 if ((extract32(ctx->opcode, 25, 1)) == 0) {
21894 /* BC */
21895 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
21896 } else {
21897 /* BALC */
21898 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21901 break;
21902 case NM_P_J:
21903 switch (extract32(ctx->opcode, 12, 4)) {
21904 case NM_JALRC:
21905 case NM_JALRC_HB:
21906 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
21907 break;
21908 case NM_P_BALRSC:
21909 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
21910 break;
21911 default:
21912 generate_exception_end(ctx, EXCP_RI);
21913 break;
21915 break;
21916 case NM_P_BR1:
21918 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21919 extract32(ctx->opcode, 1, 13) << 1;
21920 switch (extract32(ctx->opcode, 14, 2)) {
21921 case NM_BEQC:
21922 check_nms(ctx);
21923 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
21924 break;
21925 case NM_P_BR3A:
21926 s = sextract32(ctx->opcode, 0, 1) << 14 |
21927 extract32(ctx->opcode, 1, 13) << 1;
21928 check_cp1_enabled(ctx);
21929 switch (extract32(ctx->opcode, 16, 5)) {
21930 case NM_BC1EQZC:
21931 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
21932 break;
21933 case NM_BC1NEZC:
21934 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
21935 break;
21936 case NM_BPOSGE32C:
21937 check_dsp_r3(ctx);
21939 int32_t imm = extract32(ctx->opcode, 1, 13) |
21940 extract32(ctx->opcode, 0, 1) << 13;
21942 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
21943 imm);
21945 break;
21946 default:
21947 generate_exception_end(ctx, EXCP_RI);
21948 break;
21950 break;
21951 case NM_BGEC:
21952 if (rs == rt) {
21953 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
21954 } else {
21955 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
21957 break;
21958 case NM_BGEUC:
21959 if (rs == rt || rt == 0) {
21960 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
21961 } else if (rs == 0) {
21962 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
21963 } else {
21964 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
21966 break;
21969 break;
21970 case NM_P_BR2:
21972 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21973 extract32(ctx->opcode, 1, 13) << 1;
21974 switch (extract32(ctx->opcode, 14, 2)) {
21975 case NM_BNEC:
21976 check_nms(ctx);
21977 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
21978 break;
21979 case NM_BLTC:
21980 if (rs != 0 && rt != 0 && rs == rt) {
21981 /* NOP */
21982 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21983 } else {
21984 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
21986 break;
21987 case NM_BLTUC:
21988 if (rs == 0 || rs == rt) {
21989 /* NOP */
21990 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21991 } else {
21992 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
21994 break;
21995 default:
21996 generate_exception_end(ctx, EXCP_RI);
21997 break;
22000 break;
22001 case NM_P_BRI:
22003 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
22004 extract32(ctx->opcode, 1, 10) << 1;
22005 uint32_t u = extract32(ctx->opcode, 11, 7);
22007 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
22008 rt, u, s);
22010 break;
22011 default:
22012 generate_exception_end(ctx, EXCP_RI);
22013 break;
22015 return 4;
22018 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
22020 uint32_t op;
22021 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
22022 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22023 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode));
22024 int offset;
22025 int imm;
22027 /* make sure instructions are on a halfword boundary */
22028 if (ctx->base.pc_next & 0x1) {
22029 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
22030 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
22031 tcg_temp_free(tmp);
22032 generate_exception_end(ctx, EXCP_AdEL);
22033 return 2;
22036 op = extract32(ctx->opcode, 10, 6);
22037 switch (op) {
22038 case NM_P16_MV:
22039 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22040 if (rt != 0) {
22041 /* MOVE */
22042 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
22043 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
22044 } else {
22045 /* P16.RI */
22046 switch (extract32(ctx->opcode, 3, 2)) {
22047 case NM_P16_SYSCALL:
22048 if (extract32(ctx->opcode, 2, 1) == 0) {
22049 generate_exception_end(ctx, EXCP_SYSCALL);
22050 } else {
22051 generate_exception_end(ctx, EXCP_RI);
22053 break;
22054 case NM_BREAK16:
22055 generate_exception_end(ctx, EXCP_BREAK);
22056 break;
22057 case NM_SDBBP16:
22058 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
22059 gen_helper_do_semihosting(cpu_env);
22060 } else {
22061 if (ctx->hflags & MIPS_HFLAG_SBRI) {
22062 generate_exception_end(ctx, EXCP_RI);
22063 } else {
22064 generate_exception_end(ctx, EXCP_DBp);
22067 break;
22068 default:
22069 generate_exception_end(ctx, EXCP_RI);
22070 break;
22073 break;
22074 case NM_P16_SHIFT:
22076 int shift = extract32(ctx->opcode, 0, 3);
22077 uint32_t opc = 0;
22078 shift = (shift == 0) ? 8 : shift;
22080 switch (extract32(ctx->opcode, 3, 1)) {
22081 case NM_SLL16:
22082 opc = OPC_SLL;
22083 break;
22084 case NM_SRL16:
22085 opc = OPC_SRL;
22086 break;
22088 gen_shift_imm(ctx, opc, rt, rs, shift);
22090 break;
22091 case NM_P16C:
22092 switch (ctx->opcode & 1) {
22093 case NM_POOL16C_0:
22094 gen_pool16c_nanomips_insn(ctx);
22095 break;
22096 case NM_LWXS16:
22097 gen_ldxs(ctx, rt, rs, rd);
22098 break;
22100 break;
22101 case NM_P16_A1:
22102 switch (extract32(ctx->opcode, 6, 1)) {
22103 case NM_ADDIUR1SP:
22104 imm = extract32(ctx->opcode, 0, 6) << 2;
22105 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
22106 break;
22107 default:
22108 generate_exception_end(ctx, EXCP_RI);
22109 break;
22111 break;
22112 case NM_P16_A2:
22113 switch (extract32(ctx->opcode, 3, 1)) {
22114 case NM_ADDIUR2:
22115 imm = extract32(ctx->opcode, 0, 3) << 2;
22116 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
22117 break;
22118 case NM_P_ADDIURS5:
22119 rt = extract32(ctx->opcode, 5, 5);
22120 if (rt != 0) {
22121 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
22122 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
22123 (extract32(ctx->opcode, 0, 3));
22124 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
22126 break;
22128 break;
22129 case NM_P16_ADDU:
22130 switch (ctx->opcode & 0x1) {
22131 case NM_ADDU16:
22132 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
22133 break;
22134 case NM_SUBU16:
22135 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
22136 break;
22138 break;
22139 case NM_P16_4X4:
22140 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22141 extract32(ctx->opcode, 5, 3);
22142 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22143 extract32(ctx->opcode, 0, 3);
22144 rt = decode_gpr_gpr4(rt);
22145 rs = decode_gpr_gpr4(rs);
22146 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
22147 (extract32(ctx->opcode, 3, 1))) {
22148 case NM_ADDU4X4:
22149 check_nms(ctx);
22150 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
22151 break;
22152 case NM_MUL4X4:
22153 check_nms(ctx);
22154 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
22155 break;
22156 default:
22157 generate_exception_end(ctx, EXCP_RI);
22158 break;
22160 break;
22161 case NM_LI16:
22163 int imm = extract32(ctx->opcode, 0, 7);
22164 imm = (imm == 0x7f ? -1 : imm);
22165 if (rt != 0) {
22166 tcg_gen_movi_tl(cpu_gpr[rt], imm);
22169 break;
22170 case NM_ANDI16:
22172 uint32_t u = extract32(ctx->opcode, 0, 4);
22173 u = (u == 12) ? 0xff :
22174 (u == 13) ? 0xffff : u;
22175 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
22177 break;
22178 case NM_P16_LB:
22179 offset = extract32(ctx->opcode, 0, 2);
22180 switch (extract32(ctx->opcode, 2, 2)) {
22181 case NM_LB16:
22182 gen_ld(ctx, OPC_LB, rt, rs, offset);
22183 break;
22184 case NM_SB16:
22185 rt = decode_gpr_gpr3_src_store(
22186 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22187 gen_st(ctx, OPC_SB, rt, rs, offset);
22188 break;
22189 case NM_LBU16:
22190 gen_ld(ctx, OPC_LBU, rt, rs, offset);
22191 break;
22192 default:
22193 generate_exception_end(ctx, EXCP_RI);
22194 break;
22196 break;
22197 case NM_P16_LH:
22198 offset = extract32(ctx->opcode, 1, 2) << 1;
22199 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
22200 case NM_LH16:
22201 gen_ld(ctx, OPC_LH, rt, rs, offset);
22202 break;
22203 case NM_SH16:
22204 rt = decode_gpr_gpr3_src_store(
22205 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22206 gen_st(ctx, OPC_SH, rt, rs, offset);
22207 break;
22208 case NM_LHU16:
22209 gen_ld(ctx, OPC_LHU, rt, rs, offset);
22210 break;
22211 default:
22212 generate_exception_end(ctx, EXCP_RI);
22213 break;
22215 break;
22216 case NM_LW16:
22217 offset = extract32(ctx->opcode, 0, 4) << 2;
22218 gen_ld(ctx, OPC_LW, rt, rs, offset);
22219 break;
22220 case NM_LWSP16:
22221 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22222 offset = extract32(ctx->opcode, 0, 5) << 2;
22223 gen_ld(ctx, OPC_LW, rt, 29, offset);
22224 break;
22225 case NM_LW4X4:
22226 check_nms(ctx);
22227 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22228 extract32(ctx->opcode, 5, 3);
22229 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22230 extract32(ctx->opcode, 0, 3);
22231 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22232 (extract32(ctx->opcode, 8, 1) << 2);
22233 rt = decode_gpr_gpr4(rt);
22234 rs = decode_gpr_gpr4(rs);
22235 gen_ld(ctx, OPC_LW, rt, rs, offset);
22236 break;
22237 case NM_SW4X4:
22238 check_nms(ctx);
22239 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22240 extract32(ctx->opcode, 5, 3);
22241 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22242 extract32(ctx->opcode, 0, 3);
22243 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22244 (extract32(ctx->opcode, 8, 1) << 2);
22245 rt = decode_gpr_gpr4_zero(rt);
22246 rs = decode_gpr_gpr4(rs);
22247 gen_st(ctx, OPC_SW, rt, rs, offset);
22248 break;
22249 case NM_LWGP16:
22250 offset = extract32(ctx->opcode, 0, 7) << 2;
22251 gen_ld(ctx, OPC_LW, rt, 28, offset);
22252 break;
22253 case NM_SWSP16:
22254 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22255 offset = extract32(ctx->opcode, 0, 5) << 2;
22256 gen_st(ctx, OPC_SW, rt, 29, offset);
22257 break;
22258 case NM_SW16:
22259 rt = decode_gpr_gpr3_src_store(
22260 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22261 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22262 offset = extract32(ctx->opcode, 0, 4) << 2;
22263 gen_st(ctx, OPC_SW, rt, rs, offset);
22264 break;
22265 case NM_SWGP16:
22266 rt = decode_gpr_gpr3_src_store(
22267 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22268 offset = extract32(ctx->opcode, 0, 7) << 2;
22269 gen_st(ctx, OPC_SW, rt, 28, offset);
22270 break;
22271 case NM_BC16:
22272 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
22273 (sextract32(ctx->opcode, 0, 1) << 10) |
22274 (extract32(ctx->opcode, 1, 9) << 1));
22275 break;
22276 case NM_BALC16:
22277 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
22278 (sextract32(ctx->opcode, 0, 1) << 10) |
22279 (extract32(ctx->opcode, 1, 9) << 1));
22280 break;
22281 case NM_BEQZC16:
22282 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
22283 (sextract32(ctx->opcode, 0, 1) << 7) |
22284 (extract32(ctx->opcode, 1, 6) << 1));
22285 break;
22286 case NM_BNEZC16:
22287 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
22288 (sextract32(ctx->opcode, 0, 1) << 7) |
22289 (extract32(ctx->opcode, 1, 6) << 1));
22290 break;
22291 case NM_P16_BR:
22292 switch (ctx->opcode & 0xf) {
22293 case 0:
22294 /* P16.JRC */
22295 switch (extract32(ctx->opcode, 4, 1)) {
22296 case NM_JRC:
22297 gen_compute_branch_nm(ctx, OPC_JR, 2,
22298 extract32(ctx->opcode, 5, 5), 0, 0);
22299 break;
22300 case NM_JALRC16:
22301 gen_compute_branch_nm(ctx, OPC_JALR, 2,
22302 extract32(ctx->opcode, 5, 5), 31, 0);
22303 break;
22305 break;
22306 default:
22308 /* P16.BRI */
22309 uint32_t opc = extract32(ctx->opcode, 4, 3) <
22310 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
22311 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
22312 extract32(ctx->opcode, 0, 4) << 1);
22314 break;
22316 break;
22317 case NM_P16_SR:
22319 int count = extract32(ctx->opcode, 0, 4);
22320 int u = extract32(ctx->opcode, 4, 4) << 4;
22322 rt = 30 + extract32(ctx->opcode, 9, 1);
22323 switch (extract32(ctx->opcode, 8, 1)) {
22324 case NM_SAVE16:
22325 gen_save(ctx, rt, count, 0, u);
22326 break;
22327 case NM_RESTORE_JRC16:
22328 gen_restore(ctx, rt, count, 0, u);
22329 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
22330 break;
22333 break;
22334 case NM_MOVEP:
22335 case NM_MOVEPREV:
22336 check_nms(ctx);
22338 static const int gpr2reg1[] = {4, 5, 6, 7};
22339 static const int gpr2reg2[] = {5, 6, 7, 8};
22340 int re;
22341 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
22342 extract32(ctx->opcode, 8, 1);
22343 int r1 = gpr2reg1[rd2];
22344 int r2 = gpr2reg2[rd2];
22345 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
22346 extract32(ctx->opcode, 0, 3);
22347 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
22348 extract32(ctx->opcode, 5, 3);
22349 TCGv t0 = tcg_temp_new();
22350 TCGv t1 = tcg_temp_new();
22351 if (op == NM_MOVEP) {
22352 rd = r1;
22353 re = r2;
22354 rs = decode_gpr_gpr4_zero(r3);
22355 rt = decode_gpr_gpr4_zero(r4);
22356 } else {
22357 rd = decode_gpr_gpr4(r3);
22358 re = decode_gpr_gpr4(r4);
22359 rs = r1;
22360 rt = r2;
22362 gen_load_gpr(t0, rs);
22363 gen_load_gpr(t1, rt);
22364 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22365 tcg_gen_mov_tl(cpu_gpr[re], t1);
22366 tcg_temp_free(t0);
22367 tcg_temp_free(t1);
22369 break;
22370 default:
22371 return decode_nanomips_32_48_opc(env, ctx);
22374 return 2;
22378 /* SmartMIPS extension to MIPS32 */
22380 #if defined(TARGET_MIPS64)
22382 /* MDMX extension to MIPS64 */
22384 #endif
22386 /* MIPSDSP functions. */
22387 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
22388 int rd, int base, int offset)
22390 TCGv t0;
22392 check_dsp(ctx);
22393 t0 = tcg_temp_new();
22395 if (base == 0) {
22396 gen_load_gpr(t0, offset);
22397 } else if (offset == 0) {
22398 gen_load_gpr(t0, base);
22399 } else {
22400 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
22403 switch (opc) {
22404 case OPC_LBUX:
22405 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
22406 gen_store_gpr(t0, rd);
22407 break;
22408 case OPC_LHX:
22409 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
22410 gen_store_gpr(t0, rd);
22411 break;
22412 case OPC_LWX:
22413 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
22414 gen_store_gpr(t0, rd);
22415 break;
22416 #if defined(TARGET_MIPS64)
22417 case OPC_LDX:
22418 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
22419 gen_store_gpr(t0, rd);
22420 break;
22421 #endif
22423 tcg_temp_free(t0);
22426 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
22427 int ret, int v1, int v2)
22429 TCGv v1_t;
22430 TCGv v2_t;
22432 if (ret == 0) {
22433 /* Treat as NOP. */
22434 return;
22437 v1_t = tcg_temp_new();
22438 v2_t = tcg_temp_new();
22440 gen_load_gpr(v1_t, v1);
22441 gen_load_gpr(v2_t, v2);
22443 switch (op1) {
22444 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
22445 case OPC_MULT_G_2E:
22446 check_dsp_r2(ctx);
22447 switch (op2) {
22448 case OPC_ADDUH_QB:
22449 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
22450 break;
22451 case OPC_ADDUH_R_QB:
22452 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22453 break;
22454 case OPC_ADDQH_PH:
22455 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
22456 break;
22457 case OPC_ADDQH_R_PH:
22458 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22459 break;
22460 case OPC_ADDQH_W:
22461 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
22462 break;
22463 case OPC_ADDQH_R_W:
22464 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22465 break;
22466 case OPC_SUBUH_QB:
22467 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
22468 break;
22469 case OPC_SUBUH_R_QB:
22470 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22471 break;
22472 case OPC_SUBQH_PH:
22473 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
22474 break;
22475 case OPC_SUBQH_R_PH:
22476 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22477 break;
22478 case OPC_SUBQH_W:
22479 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
22480 break;
22481 case OPC_SUBQH_R_W:
22482 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22483 break;
22485 break;
22486 case OPC_ABSQ_S_PH_DSP:
22487 switch (op2) {
22488 case OPC_ABSQ_S_QB:
22489 check_dsp_r2(ctx);
22490 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
22491 break;
22492 case OPC_ABSQ_S_PH:
22493 check_dsp(ctx);
22494 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
22495 break;
22496 case OPC_ABSQ_S_W:
22497 check_dsp(ctx);
22498 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
22499 break;
22500 case OPC_PRECEQ_W_PHL:
22501 check_dsp(ctx);
22502 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
22503 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22504 break;
22505 case OPC_PRECEQ_W_PHR:
22506 check_dsp(ctx);
22507 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
22508 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
22509 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22510 break;
22511 case OPC_PRECEQU_PH_QBL:
22512 check_dsp(ctx);
22513 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
22514 break;
22515 case OPC_PRECEQU_PH_QBR:
22516 check_dsp(ctx);
22517 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
22518 break;
22519 case OPC_PRECEQU_PH_QBLA:
22520 check_dsp(ctx);
22521 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
22522 break;
22523 case OPC_PRECEQU_PH_QBRA:
22524 check_dsp(ctx);
22525 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
22526 break;
22527 case OPC_PRECEU_PH_QBL:
22528 check_dsp(ctx);
22529 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
22530 break;
22531 case OPC_PRECEU_PH_QBR:
22532 check_dsp(ctx);
22533 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
22534 break;
22535 case OPC_PRECEU_PH_QBLA:
22536 check_dsp(ctx);
22537 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
22538 break;
22539 case OPC_PRECEU_PH_QBRA:
22540 check_dsp(ctx);
22541 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
22542 break;
22544 break;
22545 case OPC_ADDU_QB_DSP:
22546 switch (op2) {
22547 case OPC_ADDQ_PH:
22548 check_dsp(ctx);
22549 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22550 break;
22551 case OPC_ADDQ_S_PH:
22552 check_dsp(ctx);
22553 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22554 break;
22555 case OPC_ADDQ_S_W:
22556 check_dsp(ctx);
22557 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22558 break;
22559 case OPC_ADDU_QB:
22560 check_dsp(ctx);
22561 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22562 break;
22563 case OPC_ADDU_S_QB:
22564 check_dsp(ctx);
22565 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22566 break;
22567 case OPC_ADDU_PH:
22568 check_dsp_r2(ctx);
22569 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22570 break;
22571 case OPC_ADDU_S_PH:
22572 check_dsp_r2(ctx);
22573 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22574 break;
22575 case OPC_SUBQ_PH:
22576 check_dsp(ctx);
22577 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22578 break;
22579 case OPC_SUBQ_S_PH:
22580 check_dsp(ctx);
22581 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22582 break;
22583 case OPC_SUBQ_S_W:
22584 check_dsp(ctx);
22585 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22586 break;
22587 case OPC_SUBU_QB:
22588 check_dsp(ctx);
22589 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22590 break;
22591 case OPC_SUBU_S_QB:
22592 check_dsp(ctx);
22593 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22594 break;
22595 case OPC_SUBU_PH:
22596 check_dsp_r2(ctx);
22597 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22598 break;
22599 case OPC_SUBU_S_PH:
22600 check_dsp_r2(ctx);
22601 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22602 break;
22603 case OPC_ADDSC:
22604 check_dsp(ctx);
22605 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22606 break;
22607 case OPC_ADDWC:
22608 check_dsp(ctx);
22609 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22610 break;
22611 case OPC_MODSUB:
22612 check_dsp(ctx);
22613 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
22614 break;
22615 case OPC_RADDU_W_QB:
22616 check_dsp(ctx);
22617 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
22618 break;
22620 break;
22621 case OPC_CMPU_EQ_QB_DSP:
22622 switch (op2) {
22623 case OPC_PRECR_QB_PH:
22624 check_dsp_r2(ctx);
22625 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22626 break;
22627 case OPC_PRECRQ_QB_PH:
22628 check_dsp(ctx);
22629 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22630 break;
22631 case OPC_PRECR_SRA_PH_W:
22632 check_dsp_r2(ctx);
22634 TCGv_i32 sa_t = tcg_const_i32(v2);
22635 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
22636 cpu_gpr[ret]);
22637 tcg_temp_free_i32(sa_t);
22638 break;
22640 case OPC_PRECR_SRA_R_PH_W:
22641 check_dsp_r2(ctx);
22643 TCGv_i32 sa_t = tcg_const_i32(v2);
22644 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
22645 cpu_gpr[ret]);
22646 tcg_temp_free_i32(sa_t);
22647 break;
22649 case OPC_PRECRQ_PH_W:
22650 check_dsp(ctx);
22651 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
22652 break;
22653 case OPC_PRECRQ_RS_PH_W:
22654 check_dsp(ctx);
22655 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22656 break;
22657 case OPC_PRECRQU_S_QB_PH:
22658 check_dsp(ctx);
22659 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22660 break;
22662 break;
22663 #ifdef TARGET_MIPS64
22664 case OPC_ABSQ_S_QH_DSP:
22665 switch (op2) {
22666 case OPC_PRECEQ_L_PWL:
22667 check_dsp(ctx);
22668 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
22669 break;
22670 case OPC_PRECEQ_L_PWR:
22671 check_dsp(ctx);
22672 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
22673 break;
22674 case OPC_PRECEQ_PW_QHL:
22675 check_dsp(ctx);
22676 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
22677 break;
22678 case OPC_PRECEQ_PW_QHR:
22679 check_dsp(ctx);
22680 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
22681 break;
22682 case OPC_PRECEQ_PW_QHLA:
22683 check_dsp(ctx);
22684 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
22685 break;
22686 case OPC_PRECEQ_PW_QHRA:
22687 check_dsp(ctx);
22688 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
22689 break;
22690 case OPC_PRECEQU_QH_OBL:
22691 check_dsp(ctx);
22692 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
22693 break;
22694 case OPC_PRECEQU_QH_OBR:
22695 check_dsp(ctx);
22696 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
22697 break;
22698 case OPC_PRECEQU_QH_OBLA:
22699 check_dsp(ctx);
22700 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
22701 break;
22702 case OPC_PRECEQU_QH_OBRA:
22703 check_dsp(ctx);
22704 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
22705 break;
22706 case OPC_PRECEU_QH_OBL:
22707 check_dsp(ctx);
22708 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
22709 break;
22710 case OPC_PRECEU_QH_OBR:
22711 check_dsp(ctx);
22712 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
22713 break;
22714 case OPC_PRECEU_QH_OBLA:
22715 check_dsp(ctx);
22716 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
22717 break;
22718 case OPC_PRECEU_QH_OBRA:
22719 check_dsp(ctx);
22720 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
22721 break;
22722 case OPC_ABSQ_S_OB:
22723 check_dsp_r2(ctx);
22724 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
22725 break;
22726 case OPC_ABSQ_S_PW:
22727 check_dsp(ctx);
22728 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
22729 break;
22730 case OPC_ABSQ_S_QH:
22731 check_dsp(ctx);
22732 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
22733 break;
22735 break;
22736 case OPC_ADDU_OB_DSP:
22737 switch (op2) {
22738 case OPC_RADDU_L_OB:
22739 check_dsp(ctx);
22740 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
22741 break;
22742 case OPC_SUBQ_PW:
22743 check_dsp(ctx);
22744 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22745 break;
22746 case OPC_SUBQ_S_PW:
22747 check_dsp(ctx);
22748 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22749 break;
22750 case OPC_SUBQ_QH:
22751 check_dsp(ctx);
22752 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22753 break;
22754 case OPC_SUBQ_S_QH:
22755 check_dsp(ctx);
22756 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22757 break;
22758 case OPC_SUBU_OB:
22759 check_dsp(ctx);
22760 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22761 break;
22762 case OPC_SUBU_S_OB:
22763 check_dsp(ctx);
22764 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22765 break;
22766 case OPC_SUBU_QH:
22767 check_dsp_r2(ctx);
22768 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22769 break;
22770 case OPC_SUBU_S_QH:
22771 check_dsp_r2(ctx);
22772 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22773 break;
22774 case OPC_SUBUH_OB:
22775 check_dsp_r2(ctx);
22776 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
22777 break;
22778 case OPC_SUBUH_R_OB:
22779 check_dsp_r2(ctx);
22780 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22781 break;
22782 case OPC_ADDQ_PW:
22783 check_dsp(ctx);
22784 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22785 break;
22786 case OPC_ADDQ_S_PW:
22787 check_dsp(ctx);
22788 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22789 break;
22790 case OPC_ADDQ_QH:
22791 check_dsp(ctx);
22792 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22793 break;
22794 case OPC_ADDQ_S_QH:
22795 check_dsp(ctx);
22796 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22797 break;
22798 case OPC_ADDU_OB:
22799 check_dsp(ctx);
22800 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22801 break;
22802 case OPC_ADDU_S_OB:
22803 check_dsp(ctx);
22804 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22805 break;
22806 case OPC_ADDU_QH:
22807 check_dsp_r2(ctx);
22808 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22809 break;
22810 case OPC_ADDU_S_QH:
22811 check_dsp_r2(ctx);
22812 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22813 break;
22814 case OPC_ADDUH_OB:
22815 check_dsp_r2(ctx);
22816 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
22817 break;
22818 case OPC_ADDUH_R_OB:
22819 check_dsp_r2(ctx);
22820 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22821 break;
22823 break;
22824 case OPC_CMPU_EQ_OB_DSP:
22825 switch (op2) {
22826 case OPC_PRECR_OB_QH:
22827 check_dsp_r2(ctx);
22828 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22829 break;
22830 case OPC_PRECR_SRA_QH_PW:
22831 check_dsp_r2(ctx);
22833 TCGv_i32 ret_t = tcg_const_i32(ret);
22834 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
22835 tcg_temp_free_i32(ret_t);
22836 break;
22838 case OPC_PRECR_SRA_R_QH_PW:
22839 check_dsp_r2(ctx);
22841 TCGv_i32 sa_v = tcg_const_i32(ret);
22842 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
22843 tcg_temp_free_i32(sa_v);
22844 break;
22846 case OPC_PRECRQ_OB_QH:
22847 check_dsp(ctx);
22848 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22849 break;
22850 case OPC_PRECRQ_PW_L:
22851 check_dsp(ctx);
22852 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
22853 break;
22854 case OPC_PRECRQ_QH_PW:
22855 check_dsp(ctx);
22856 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
22857 break;
22858 case OPC_PRECRQ_RS_QH_PW:
22859 check_dsp(ctx);
22860 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22861 break;
22862 case OPC_PRECRQU_S_OB_QH:
22863 check_dsp(ctx);
22864 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22865 break;
22867 break;
22868 #endif
22871 tcg_temp_free(v1_t);
22872 tcg_temp_free(v2_t);
22875 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
22876 int ret, int v1, int v2)
22878 uint32_t op2;
22879 TCGv t0;
22880 TCGv v1_t;
22881 TCGv v2_t;
22883 if (ret == 0) {
22884 /* Treat as NOP. */
22885 return;
22888 t0 = tcg_temp_new();
22889 v1_t = tcg_temp_new();
22890 v2_t = tcg_temp_new();
22892 tcg_gen_movi_tl(t0, v1);
22893 gen_load_gpr(v1_t, v1);
22894 gen_load_gpr(v2_t, v2);
22896 switch (opc) {
22897 case OPC_SHLL_QB_DSP:
22899 op2 = MASK_SHLL_QB(ctx->opcode);
22900 switch (op2) {
22901 case OPC_SHLL_QB:
22902 check_dsp(ctx);
22903 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
22904 break;
22905 case OPC_SHLLV_QB:
22906 check_dsp(ctx);
22907 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22908 break;
22909 case OPC_SHLL_PH:
22910 check_dsp(ctx);
22911 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22912 break;
22913 case OPC_SHLLV_PH:
22914 check_dsp(ctx);
22915 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22916 break;
22917 case OPC_SHLL_S_PH:
22918 check_dsp(ctx);
22919 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22920 break;
22921 case OPC_SHLLV_S_PH:
22922 check_dsp(ctx);
22923 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22924 break;
22925 case OPC_SHLL_S_W:
22926 check_dsp(ctx);
22927 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
22928 break;
22929 case OPC_SHLLV_S_W:
22930 check_dsp(ctx);
22931 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22932 break;
22933 case OPC_SHRL_QB:
22934 check_dsp(ctx);
22935 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
22936 break;
22937 case OPC_SHRLV_QB:
22938 check_dsp(ctx);
22939 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
22940 break;
22941 case OPC_SHRL_PH:
22942 check_dsp_r2(ctx);
22943 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
22944 break;
22945 case OPC_SHRLV_PH:
22946 check_dsp_r2(ctx);
22947 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
22948 break;
22949 case OPC_SHRA_QB:
22950 check_dsp_r2(ctx);
22951 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
22952 break;
22953 case OPC_SHRA_R_QB:
22954 check_dsp_r2(ctx);
22955 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
22956 break;
22957 case OPC_SHRAV_QB:
22958 check_dsp_r2(ctx);
22959 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
22960 break;
22961 case OPC_SHRAV_R_QB:
22962 check_dsp_r2(ctx);
22963 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
22964 break;
22965 case OPC_SHRA_PH:
22966 check_dsp(ctx);
22967 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
22968 break;
22969 case OPC_SHRA_R_PH:
22970 check_dsp(ctx);
22971 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
22972 break;
22973 case OPC_SHRAV_PH:
22974 check_dsp(ctx);
22975 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
22976 break;
22977 case OPC_SHRAV_R_PH:
22978 check_dsp(ctx);
22979 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
22980 break;
22981 case OPC_SHRA_R_W:
22982 check_dsp(ctx);
22983 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
22984 break;
22985 case OPC_SHRAV_R_W:
22986 check_dsp(ctx);
22987 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
22988 break;
22989 default: /* Invalid */
22990 MIPS_INVAL("MASK SHLL.QB");
22991 generate_exception_end(ctx, EXCP_RI);
22992 break;
22994 break;
22996 #ifdef TARGET_MIPS64
22997 case OPC_SHLL_OB_DSP:
22998 op2 = MASK_SHLL_OB(ctx->opcode);
22999 switch (op2) {
23000 case OPC_SHLL_PW:
23001 check_dsp(ctx);
23002 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23003 break;
23004 case OPC_SHLLV_PW:
23005 check_dsp(ctx);
23006 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23007 break;
23008 case OPC_SHLL_S_PW:
23009 check_dsp(ctx);
23010 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23011 break;
23012 case OPC_SHLLV_S_PW:
23013 check_dsp(ctx);
23014 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23015 break;
23016 case OPC_SHLL_OB:
23017 check_dsp(ctx);
23018 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
23019 break;
23020 case OPC_SHLLV_OB:
23021 check_dsp(ctx);
23022 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23023 break;
23024 case OPC_SHLL_QH:
23025 check_dsp(ctx);
23026 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23027 break;
23028 case OPC_SHLLV_QH:
23029 check_dsp(ctx);
23030 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23031 break;
23032 case OPC_SHLL_S_QH:
23033 check_dsp(ctx);
23034 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23035 break;
23036 case OPC_SHLLV_S_QH:
23037 check_dsp(ctx);
23038 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23039 break;
23040 case OPC_SHRA_OB:
23041 check_dsp_r2(ctx);
23042 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
23043 break;
23044 case OPC_SHRAV_OB:
23045 check_dsp_r2(ctx);
23046 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
23047 break;
23048 case OPC_SHRA_R_OB:
23049 check_dsp_r2(ctx);
23050 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
23051 break;
23052 case OPC_SHRAV_R_OB:
23053 check_dsp_r2(ctx);
23054 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
23055 break;
23056 case OPC_SHRA_PW:
23057 check_dsp(ctx);
23058 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
23059 break;
23060 case OPC_SHRAV_PW:
23061 check_dsp(ctx);
23062 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
23063 break;
23064 case OPC_SHRA_R_PW:
23065 check_dsp(ctx);
23066 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
23067 break;
23068 case OPC_SHRAV_R_PW:
23069 check_dsp(ctx);
23070 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
23071 break;
23072 case OPC_SHRA_QH:
23073 check_dsp(ctx);
23074 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
23075 break;
23076 case OPC_SHRAV_QH:
23077 check_dsp(ctx);
23078 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
23079 break;
23080 case OPC_SHRA_R_QH:
23081 check_dsp(ctx);
23082 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
23083 break;
23084 case OPC_SHRAV_R_QH:
23085 check_dsp(ctx);
23086 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
23087 break;
23088 case OPC_SHRL_OB:
23089 check_dsp(ctx);
23090 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
23091 break;
23092 case OPC_SHRLV_OB:
23093 check_dsp(ctx);
23094 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
23095 break;
23096 case OPC_SHRL_QH:
23097 check_dsp_r2(ctx);
23098 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
23099 break;
23100 case OPC_SHRLV_QH:
23101 check_dsp_r2(ctx);
23102 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
23103 break;
23104 default: /* Invalid */
23105 MIPS_INVAL("MASK SHLL.OB");
23106 generate_exception_end(ctx, EXCP_RI);
23107 break;
23109 break;
23110 #endif
23113 tcg_temp_free(t0);
23114 tcg_temp_free(v1_t);
23115 tcg_temp_free(v2_t);
23118 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
23119 int ret, int v1, int v2, int check_ret)
23121 TCGv_i32 t0;
23122 TCGv v1_t;
23123 TCGv v2_t;
23125 if ((ret == 0) && (check_ret == 1)) {
23126 /* Treat as NOP. */
23127 return;
23130 t0 = tcg_temp_new_i32();
23131 v1_t = tcg_temp_new();
23132 v2_t = tcg_temp_new();
23134 tcg_gen_movi_i32(t0, ret);
23135 gen_load_gpr(v1_t, v1);
23136 gen_load_gpr(v2_t, v2);
23138 switch (op1) {
23140 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
23141 * the same mask and op1.
23143 case OPC_MULT_G_2E:
23144 check_dsp_r2(ctx);
23145 switch (op2) {
23146 case OPC_MUL_PH:
23147 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23148 break;
23149 case OPC_MUL_S_PH:
23150 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23151 break;
23152 case OPC_MULQ_S_W:
23153 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23154 break;
23155 case OPC_MULQ_RS_W:
23156 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23157 break;
23159 break;
23160 case OPC_DPA_W_PH_DSP:
23161 switch (op2) {
23162 case OPC_DPAU_H_QBL:
23163 check_dsp(ctx);
23164 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
23165 break;
23166 case OPC_DPAU_H_QBR:
23167 check_dsp(ctx);
23168 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
23169 break;
23170 case OPC_DPSU_H_QBL:
23171 check_dsp(ctx);
23172 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
23173 break;
23174 case OPC_DPSU_H_QBR:
23175 check_dsp(ctx);
23176 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
23177 break;
23178 case OPC_DPA_W_PH:
23179 check_dsp_r2(ctx);
23180 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
23181 break;
23182 case OPC_DPAX_W_PH:
23183 check_dsp_r2(ctx);
23184 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
23185 break;
23186 case OPC_DPAQ_S_W_PH:
23187 check_dsp(ctx);
23188 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23189 break;
23190 case OPC_DPAQX_S_W_PH:
23191 check_dsp_r2(ctx);
23192 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23193 break;
23194 case OPC_DPAQX_SA_W_PH:
23195 check_dsp_r2(ctx);
23196 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23197 break;
23198 case OPC_DPS_W_PH:
23199 check_dsp_r2(ctx);
23200 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
23201 break;
23202 case OPC_DPSX_W_PH:
23203 check_dsp_r2(ctx);
23204 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
23205 break;
23206 case OPC_DPSQ_S_W_PH:
23207 check_dsp(ctx);
23208 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23209 break;
23210 case OPC_DPSQX_S_W_PH:
23211 check_dsp_r2(ctx);
23212 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23213 break;
23214 case OPC_DPSQX_SA_W_PH:
23215 check_dsp_r2(ctx);
23216 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23217 break;
23218 case OPC_MULSAQ_S_W_PH:
23219 check_dsp(ctx);
23220 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23221 break;
23222 case OPC_DPAQ_SA_L_W:
23223 check_dsp(ctx);
23224 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23225 break;
23226 case OPC_DPSQ_SA_L_W:
23227 check_dsp(ctx);
23228 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23229 break;
23230 case OPC_MAQ_S_W_PHL:
23231 check_dsp(ctx);
23232 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
23233 break;
23234 case OPC_MAQ_S_W_PHR:
23235 check_dsp(ctx);
23236 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
23237 break;
23238 case OPC_MAQ_SA_W_PHL:
23239 check_dsp(ctx);
23240 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
23241 break;
23242 case OPC_MAQ_SA_W_PHR:
23243 check_dsp(ctx);
23244 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
23245 break;
23246 case OPC_MULSA_W_PH:
23247 check_dsp_r2(ctx);
23248 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
23249 break;
23251 break;
23252 #ifdef TARGET_MIPS64
23253 case OPC_DPAQ_W_QH_DSP:
23255 int ac = ret & 0x03;
23256 tcg_gen_movi_i32(t0, ac);
23258 switch (op2) {
23259 case OPC_DMADD:
23260 check_dsp(ctx);
23261 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
23262 break;
23263 case OPC_DMADDU:
23264 check_dsp(ctx);
23265 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
23266 break;
23267 case OPC_DMSUB:
23268 check_dsp(ctx);
23269 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
23270 break;
23271 case OPC_DMSUBU:
23272 check_dsp(ctx);
23273 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
23274 break;
23275 case OPC_DPA_W_QH:
23276 check_dsp_r2(ctx);
23277 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
23278 break;
23279 case OPC_DPAQ_S_W_QH:
23280 check_dsp(ctx);
23281 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23282 break;
23283 case OPC_DPAQ_SA_L_PW:
23284 check_dsp(ctx);
23285 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23286 break;
23287 case OPC_DPAU_H_OBL:
23288 check_dsp(ctx);
23289 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
23290 break;
23291 case OPC_DPAU_H_OBR:
23292 check_dsp(ctx);
23293 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
23294 break;
23295 case OPC_DPS_W_QH:
23296 check_dsp_r2(ctx);
23297 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
23298 break;
23299 case OPC_DPSQ_S_W_QH:
23300 check_dsp(ctx);
23301 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23302 break;
23303 case OPC_DPSQ_SA_L_PW:
23304 check_dsp(ctx);
23305 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23306 break;
23307 case OPC_DPSU_H_OBL:
23308 check_dsp(ctx);
23309 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
23310 break;
23311 case OPC_DPSU_H_OBR:
23312 check_dsp(ctx);
23313 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
23314 break;
23315 case OPC_MAQ_S_L_PWL:
23316 check_dsp(ctx);
23317 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
23318 break;
23319 case OPC_MAQ_S_L_PWR:
23320 check_dsp(ctx);
23321 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
23322 break;
23323 case OPC_MAQ_S_W_QHLL:
23324 check_dsp(ctx);
23325 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
23326 break;
23327 case OPC_MAQ_SA_W_QHLL:
23328 check_dsp(ctx);
23329 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
23330 break;
23331 case OPC_MAQ_S_W_QHLR:
23332 check_dsp(ctx);
23333 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
23334 break;
23335 case OPC_MAQ_SA_W_QHLR:
23336 check_dsp(ctx);
23337 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
23338 break;
23339 case OPC_MAQ_S_W_QHRL:
23340 check_dsp(ctx);
23341 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
23342 break;
23343 case OPC_MAQ_SA_W_QHRL:
23344 check_dsp(ctx);
23345 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
23346 break;
23347 case OPC_MAQ_S_W_QHRR:
23348 check_dsp(ctx);
23349 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
23350 break;
23351 case OPC_MAQ_SA_W_QHRR:
23352 check_dsp(ctx);
23353 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
23354 break;
23355 case OPC_MULSAQ_S_L_PW:
23356 check_dsp(ctx);
23357 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
23358 break;
23359 case OPC_MULSAQ_S_W_QH:
23360 check_dsp(ctx);
23361 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23362 break;
23365 break;
23366 #endif
23367 case OPC_ADDU_QB_DSP:
23368 switch (op2) {
23369 case OPC_MULEU_S_PH_QBL:
23370 check_dsp(ctx);
23371 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23372 break;
23373 case OPC_MULEU_S_PH_QBR:
23374 check_dsp(ctx);
23375 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23376 break;
23377 case OPC_MULQ_RS_PH:
23378 check_dsp(ctx);
23379 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23380 break;
23381 case OPC_MULEQ_S_W_PHL:
23382 check_dsp(ctx);
23383 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23384 break;
23385 case OPC_MULEQ_S_W_PHR:
23386 check_dsp(ctx);
23387 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23388 break;
23389 case OPC_MULQ_S_PH:
23390 check_dsp_r2(ctx);
23391 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23392 break;
23394 break;
23395 #ifdef TARGET_MIPS64
23396 case OPC_ADDU_OB_DSP:
23397 switch (op2) {
23398 case OPC_MULEQ_S_PW_QHL:
23399 check_dsp(ctx);
23400 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23401 break;
23402 case OPC_MULEQ_S_PW_QHR:
23403 check_dsp(ctx);
23404 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23405 break;
23406 case OPC_MULEU_S_QH_OBL:
23407 check_dsp(ctx);
23408 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23409 break;
23410 case OPC_MULEU_S_QH_OBR:
23411 check_dsp(ctx);
23412 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23413 break;
23414 case OPC_MULQ_RS_QH:
23415 check_dsp(ctx);
23416 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23417 break;
23419 break;
23420 #endif
23423 tcg_temp_free_i32(t0);
23424 tcg_temp_free(v1_t);
23425 tcg_temp_free(v2_t);
23428 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23429 int ret, int val)
23431 int16_t imm;
23432 TCGv t0;
23433 TCGv val_t;
23435 if (ret == 0) {
23436 /* Treat as NOP. */
23437 return;
23440 t0 = tcg_temp_new();
23441 val_t = tcg_temp_new();
23442 gen_load_gpr(val_t, val);
23444 switch (op1) {
23445 case OPC_ABSQ_S_PH_DSP:
23446 switch (op2) {
23447 case OPC_BITREV:
23448 check_dsp(ctx);
23449 gen_helper_bitrev(cpu_gpr[ret], val_t);
23450 break;
23451 case OPC_REPL_QB:
23452 check_dsp(ctx);
23454 target_long result;
23455 imm = (ctx->opcode >> 16) & 0xFF;
23456 result = (uint32_t)imm << 24 |
23457 (uint32_t)imm << 16 |
23458 (uint32_t)imm << 8 |
23459 (uint32_t)imm;
23460 result = (int32_t)result;
23461 tcg_gen_movi_tl(cpu_gpr[ret], result);
23463 break;
23464 case OPC_REPLV_QB:
23465 check_dsp(ctx);
23466 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23467 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23468 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23469 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23470 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23471 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23472 break;
23473 case OPC_REPL_PH:
23474 check_dsp(ctx);
23476 imm = (ctx->opcode >> 16) & 0x03FF;
23477 imm = (int16_t)(imm << 6) >> 6;
23478 tcg_gen_movi_tl(cpu_gpr[ret], \
23479 (target_long)((int32_t)imm << 16 | \
23480 (uint16_t)imm));
23482 break;
23483 case OPC_REPLV_PH:
23484 check_dsp(ctx);
23485 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23486 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23487 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23488 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23489 break;
23491 break;
23492 #ifdef TARGET_MIPS64
23493 case OPC_ABSQ_S_QH_DSP:
23494 switch (op2) {
23495 case OPC_REPL_OB:
23496 check_dsp(ctx);
23498 target_long temp;
23500 imm = (ctx->opcode >> 16) & 0xFF;
23501 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
23502 temp = (temp << 16) | temp;
23503 temp = (temp << 32) | temp;
23504 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23505 break;
23507 case OPC_REPL_PW:
23508 check_dsp(ctx);
23510 target_long temp;
23512 imm = (ctx->opcode >> 16) & 0x03FF;
23513 imm = (int16_t)(imm << 6) >> 6;
23514 temp = ((target_long)imm << 32) \
23515 | ((target_long)imm & 0xFFFFFFFF);
23516 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23517 break;
23519 case OPC_REPL_QH:
23520 check_dsp(ctx);
23522 target_long temp;
23524 imm = (ctx->opcode >> 16) & 0x03FF;
23525 imm = (int16_t)(imm << 6) >> 6;
23527 temp = ((uint64_t)(uint16_t)imm << 48) |
23528 ((uint64_t)(uint16_t)imm << 32) |
23529 ((uint64_t)(uint16_t)imm << 16) |
23530 (uint64_t)(uint16_t)imm;
23531 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23532 break;
23534 case OPC_REPLV_OB:
23535 check_dsp(ctx);
23536 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23537 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23538 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23539 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23540 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23541 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23542 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23543 break;
23544 case OPC_REPLV_PW:
23545 check_dsp(ctx);
23546 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
23547 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23548 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23549 break;
23550 case OPC_REPLV_QH:
23551 check_dsp(ctx);
23552 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23553 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23554 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23555 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23556 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23557 break;
23559 break;
23560 #endif
23562 tcg_temp_free(t0);
23563 tcg_temp_free(val_t);
23566 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
23567 uint32_t op1, uint32_t op2,
23568 int ret, int v1, int v2, int check_ret)
23570 TCGv t1;
23571 TCGv v1_t;
23572 TCGv v2_t;
23574 if ((ret == 0) && (check_ret == 1)) {
23575 /* Treat as NOP. */
23576 return;
23579 t1 = tcg_temp_new();
23580 v1_t = tcg_temp_new();
23581 v2_t = tcg_temp_new();
23583 gen_load_gpr(v1_t, v1);
23584 gen_load_gpr(v2_t, v2);
23586 switch (op1) {
23587 case OPC_CMPU_EQ_QB_DSP:
23588 switch (op2) {
23589 case OPC_CMPU_EQ_QB:
23590 check_dsp(ctx);
23591 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
23592 break;
23593 case OPC_CMPU_LT_QB:
23594 check_dsp(ctx);
23595 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
23596 break;
23597 case OPC_CMPU_LE_QB:
23598 check_dsp(ctx);
23599 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
23600 break;
23601 case OPC_CMPGU_EQ_QB:
23602 check_dsp(ctx);
23603 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
23604 break;
23605 case OPC_CMPGU_LT_QB:
23606 check_dsp(ctx);
23607 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
23608 break;
23609 case OPC_CMPGU_LE_QB:
23610 check_dsp(ctx);
23611 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
23612 break;
23613 case OPC_CMPGDU_EQ_QB:
23614 check_dsp_r2(ctx);
23615 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
23616 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23617 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23618 tcg_gen_shli_tl(t1, t1, 24);
23619 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23620 break;
23621 case OPC_CMPGDU_LT_QB:
23622 check_dsp_r2(ctx);
23623 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
23624 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23625 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23626 tcg_gen_shli_tl(t1, t1, 24);
23627 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23628 break;
23629 case OPC_CMPGDU_LE_QB:
23630 check_dsp_r2(ctx);
23631 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
23632 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23633 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23634 tcg_gen_shli_tl(t1, t1, 24);
23635 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23636 break;
23637 case OPC_CMP_EQ_PH:
23638 check_dsp(ctx);
23639 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
23640 break;
23641 case OPC_CMP_LT_PH:
23642 check_dsp(ctx);
23643 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
23644 break;
23645 case OPC_CMP_LE_PH:
23646 check_dsp(ctx);
23647 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
23648 break;
23649 case OPC_PICK_QB:
23650 check_dsp(ctx);
23651 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23652 break;
23653 case OPC_PICK_PH:
23654 check_dsp(ctx);
23655 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23656 break;
23657 case OPC_PACKRL_PH:
23658 check_dsp(ctx);
23659 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
23660 break;
23662 break;
23663 #ifdef TARGET_MIPS64
23664 case OPC_CMPU_EQ_OB_DSP:
23665 switch (op2) {
23666 case OPC_CMP_EQ_PW:
23667 check_dsp(ctx);
23668 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
23669 break;
23670 case OPC_CMP_LT_PW:
23671 check_dsp(ctx);
23672 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
23673 break;
23674 case OPC_CMP_LE_PW:
23675 check_dsp(ctx);
23676 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
23677 break;
23678 case OPC_CMP_EQ_QH:
23679 check_dsp(ctx);
23680 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
23681 break;
23682 case OPC_CMP_LT_QH:
23683 check_dsp(ctx);
23684 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
23685 break;
23686 case OPC_CMP_LE_QH:
23687 check_dsp(ctx);
23688 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
23689 break;
23690 case OPC_CMPGDU_EQ_OB:
23691 check_dsp_r2(ctx);
23692 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23693 break;
23694 case OPC_CMPGDU_LT_OB:
23695 check_dsp_r2(ctx);
23696 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23697 break;
23698 case OPC_CMPGDU_LE_OB:
23699 check_dsp_r2(ctx);
23700 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23701 break;
23702 case OPC_CMPGU_EQ_OB:
23703 check_dsp(ctx);
23704 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
23705 break;
23706 case OPC_CMPGU_LT_OB:
23707 check_dsp(ctx);
23708 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
23709 break;
23710 case OPC_CMPGU_LE_OB:
23711 check_dsp(ctx);
23712 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
23713 break;
23714 case OPC_CMPU_EQ_OB:
23715 check_dsp(ctx);
23716 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
23717 break;
23718 case OPC_CMPU_LT_OB:
23719 check_dsp(ctx);
23720 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
23721 break;
23722 case OPC_CMPU_LE_OB:
23723 check_dsp(ctx);
23724 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
23725 break;
23726 case OPC_PACKRL_PW:
23727 check_dsp(ctx);
23728 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
23729 break;
23730 case OPC_PICK_OB:
23731 check_dsp(ctx);
23732 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23733 break;
23734 case OPC_PICK_PW:
23735 check_dsp(ctx);
23736 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23737 break;
23738 case OPC_PICK_QH:
23739 check_dsp(ctx);
23740 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23741 break;
23743 break;
23744 #endif
23747 tcg_temp_free(t1);
23748 tcg_temp_free(v1_t);
23749 tcg_temp_free(v2_t);
23752 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
23753 uint32_t op1, int rt, int rs, int sa)
23755 TCGv t0;
23757 check_dsp_r2(ctx);
23759 if (rt == 0) {
23760 /* Treat as NOP. */
23761 return;
23764 t0 = tcg_temp_new();
23765 gen_load_gpr(t0, rs);
23767 switch (op1) {
23768 case OPC_APPEND_DSP:
23769 switch (MASK_APPEND(ctx->opcode)) {
23770 case OPC_APPEND:
23771 if (sa != 0) {
23772 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
23774 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23775 break;
23776 case OPC_PREPEND:
23777 if (sa != 0) {
23778 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
23779 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23780 tcg_gen_shli_tl(t0, t0, 32 - sa);
23781 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23783 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23784 break;
23785 case OPC_BALIGN:
23786 sa &= 3;
23787 if (sa != 0 && sa != 2) {
23788 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23789 tcg_gen_ext32u_tl(t0, t0);
23790 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
23791 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23793 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23794 break;
23795 default: /* Invalid */
23796 MIPS_INVAL("MASK APPEND");
23797 generate_exception_end(ctx, EXCP_RI);
23798 break;
23800 break;
23801 #ifdef TARGET_MIPS64
23802 case OPC_DAPPEND_DSP:
23803 switch (MASK_DAPPEND(ctx->opcode)) {
23804 case OPC_DAPPEND:
23805 if (sa != 0) {
23806 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
23808 break;
23809 case OPC_PREPENDD:
23810 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
23811 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
23812 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
23813 break;
23814 case OPC_PREPENDW:
23815 if (sa != 0) {
23816 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23817 tcg_gen_shli_tl(t0, t0, 64 - sa);
23818 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23820 break;
23821 case OPC_DBALIGN:
23822 sa &= 7;
23823 if (sa != 0 && sa != 2 && sa != 4) {
23824 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23825 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
23826 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23828 break;
23829 default: /* Invalid */
23830 MIPS_INVAL("MASK DAPPEND");
23831 generate_exception_end(ctx, EXCP_RI);
23832 break;
23834 break;
23835 #endif
23837 tcg_temp_free(t0);
23840 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23841 int ret, int v1, int v2, int check_ret)
23844 TCGv t0;
23845 TCGv t1;
23846 TCGv v1_t;
23847 TCGv v2_t;
23848 int16_t imm;
23850 if ((ret == 0) && (check_ret == 1)) {
23851 /* Treat as NOP. */
23852 return;
23855 t0 = tcg_temp_new();
23856 t1 = tcg_temp_new();
23857 v1_t = tcg_temp_new();
23858 v2_t = tcg_temp_new();
23860 gen_load_gpr(v1_t, v1);
23861 gen_load_gpr(v2_t, v2);
23863 switch (op1) {
23864 case OPC_EXTR_W_DSP:
23865 check_dsp(ctx);
23866 switch (op2) {
23867 case OPC_EXTR_W:
23868 tcg_gen_movi_tl(t0, v2);
23869 tcg_gen_movi_tl(t1, v1);
23870 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
23871 break;
23872 case OPC_EXTR_R_W:
23873 tcg_gen_movi_tl(t0, v2);
23874 tcg_gen_movi_tl(t1, v1);
23875 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23876 break;
23877 case OPC_EXTR_RS_W:
23878 tcg_gen_movi_tl(t0, v2);
23879 tcg_gen_movi_tl(t1, v1);
23880 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23881 break;
23882 case OPC_EXTR_S_H:
23883 tcg_gen_movi_tl(t0, v2);
23884 tcg_gen_movi_tl(t1, v1);
23885 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23886 break;
23887 case OPC_EXTRV_S_H:
23888 tcg_gen_movi_tl(t0, v2);
23889 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
23890 break;
23891 case OPC_EXTRV_W:
23892 tcg_gen_movi_tl(t0, v2);
23893 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23894 break;
23895 case OPC_EXTRV_R_W:
23896 tcg_gen_movi_tl(t0, v2);
23897 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23898 break;
23899 case OPC_EXTRV_RS_W:
23900 tcg_gen_movi_tl(t0, v2);
23901 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23902 break;
23903 case OPC_EXTP:
23904 tcg_gen_movi_tl(t0, v2);
23905 tcg_gen_movi_tl(t1, v1);
23906 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
23907 break;
23908 case OPC_EXTPV:
23909 tcg_gen_movi_tl(t0, v2);
23910 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
23911 break;
23912 case OPC_EXTPDP:
23913 tcg_gen_movi_tl(t0, v2);
23914 tcg_gen_movi_tl(t1, v1);
23915 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
23916 break;
23917 case OPC_EXTPDPV:
23918 tcg_gen_movi_tl(t0, v2);
23919 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23920 break;
23921 case OPC_SHILO:
23922 imm = (ctx->opcode >> 20) & 0x3F;
23923 tcg_gen_movi_tl(t0, ret);
23924 tcg_gen_movi_tl(t1, imm);
23925 gen_helper_shilo(t0, t1, cpu_env);
23926 break;
23927 case OPC_SHILOV:
23928 tcg_gen_movi_tl(t0, ret);
23929 gen_helper_shilo(t0, v1_t, cpu_env);
23930 break;
23931 case OPC_MTHLIP:
23932 tcg_gen_movi_tl(t0, ret);
23933 gen_helper_mthlip(t0, v1_t, cpu_env);
23934 break;
23935 case OPC_WRDSP:
23936 imm = (ctx->opcode >> 11) & 0x3FF;
23937 tcg_gen_movi_tl(t0, imm);
23938 gen_helper_wrdsp(v1_t, t0, cpu_env);
23939 break;
23940 case OPC_RDDSP:
23941 imm = (ctx->opcode >> 16) & 0x03FF;
23942 tcg_gen_movi_tl(t0, imm);
23943 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
23944 break;
23946 break;
23947 #ifdef TARGET_MIPS64
23948 case OPC_DEXTR_W_DSP:
23949 check_dsp(ctx);
23950 switch (op2) {
23951 case OPC_DMTHLIP:
23952 tcg_gen_movi_tl(t0, ret);
23953 gen_helper_dmthlip(v1_t, t0, cpu_env);
23954 break;
23955 case OPC_DSHILO:
23957 int shift = (ctx->opcode >> 19) & 0x7F;
23958 int ac = (ctx->opcode >> 11) & 0x03;
23959 tcg_gen_movi_tl(t0, shift);
23960 tcg_gen_movi_tl(t1, ac);
23961 gen_helper_dshilo(t0, t1, cpu_env);
23962 break;
23964 case OPC_DSHILOV:
23966 int ac = (ctx->opcode >> 11) & 0x03;
23967 tcg_gen_movi_tl(t0, ac);
23968 gen_helper_dshilo(v1_t, t0, cpu_env);
23969 break;
23971 case OPC_DEXTP:
23972 tcg_gen_movi_tl(t0, v2);
23973 tcg_gen_movi_tl(t1, v1);
23975 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
23976 break;
23977 case OPC_DEXTPV:
23978 tcg_gen_movi_tl(t0, v2);
23979 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
23980 break;
23981 case OPC_DEXTPDP:
23982 tcg_gen_movi_tl(t0, v2);
23983 tcg_gen_movi_tl(t1, v1);
23984 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
23985 break;
23986 case OPC_DEXTPDPV:
23987 tcg_gen_movi_tl(t0, v2);
23988 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23989 break;
23990 case OPC_DEXTR_L:
23991 tcg_gen_movi_tl(t0, v2);
23992 tcg_gen_movi_tl(t1, v1);
23993 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
23994 break;
23995 case OPC_DEXTR_R_L:
23996 tcg_gen_movi_tl(t0, v2);
23997 tcg_gen_movi_tl(t1, v1);
23998 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
23999 break;
24000 case OPC_DEXTR_RS_L:
24001 tcg_gen_movi_tl(t0, v2);
24002 tcg_gen_movi_tl(t1, v1);
24003 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
24004 break;
24005 case OPC_DEXTR_W:
24006 tcg_gen_movi_tl(t0, v2);
24007 tcg_gen_movi_tl(t1, v1);
24008 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
24009 break;
24010 case OPC_DEXTR_R_W:
24011 tcg_gen_movi_tl(t0, v2);
24012 tcg_gen_movi_tl(t1, v1);
24013 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24014 break;
24015 case OPC_DEXTR_RS_W:
24016 tcg_gen_movi_tl(t0, v2);
24017 tcg_gen_movi_tl(t1, v1);
24018 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24019 break;
24020 case OPC_DEXTR_S_H:
24021 tcg_gen_movi_tl(t0, v2);
24022 tcg_gen_movi_tl(t1, v1);
24023 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24024 break;
24025 case OPC_DEXTRV_S_H:
24026 tcg_gen_movi_tl(t0, v2);
24027 tcg_gen_movi_tl(t1, v1);
24028 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24029 break;
24030 case OPC_DEXTRV_L:
24031 tcg_gen_movi_tl(t0, v2);
24032 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24033 break;
24034 case OPC_DEXTRV_R_L:
24035 tcg_gen_movi_tl(t0, v2);
24036 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24037 break;
24038 case OPC_DEXTRV_RS_L:
24039 tcg_gen_movi_tl(t0, v2);
24040 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24041 break;
24042 case OPC_DEXTRV_W:
24043 tcg_gen_movi_tl(t0, v2);
24044 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24045 break;
24046 case OPC_DEXTRV_R_W:
24047 tcg_gen_movi_tl(t0, v2);
24048 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24049 break;
24050 case OPC_DEXTRV_RS_W:
24051 tcg_gen_movi_tl(t0, v2);
24052 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24053 break;
24055 break;
24056 #endif
24059 tcg_temp_free(t0);
24060 tcg_temp_free(t1);
24061 tcg_temp_free(v1_t);
24062 tcg_temp_free(v2_t);
24065 /* End MIPSDSP functions. */
24067 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
24069 int rs, rt, rd, sa;
24070 uint32_t op1, op2;
24072 rs = (ctx->opcode >> 21) & 0x1f;
24073 rt = (ctx->opcode >> 16) & 0x1f;
24074 rd = (ctx->opcode >> 11) & 0x1f;
24075 sa = (ctx->opcode >> 6) & 0x1f;
24077 op1 = MASK_SPECIAL(ctx->opcode);
24078 switch (op1) {
24079 case OPC_LSA:
24080 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
24081 break;
24082 case OPC_MULT:
24083 case OPC_MULTU:
24084 case OPC_DIV:
24085 case OPC_DIVU:
24086 op2 = MASK_R6_MULDIV(ctx->opcode);
24087 switch (op2) {
24088 case R6_OPC_MUL:
24089 case R6_OPC_MUH:
24090 case R6_OPC_MULU:
24091 case R6_OPC_MUHU:
24092 case R6_OPC_DIV:
24093 case R6_OPC_MOD:
24094 case R6_OPC_DIVU:
24095 case R6_OPC_MODU:
24096 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24097 break;
24098 default:
24099 MIPS_INVAL("special_r6 muldiv");
24100 generate_exception_end(ctx, EXCP_RI);
24101 break;
24103 break;
24104 case OPC_SELEQZ:
24105 case OPC_SELNEZ:
24106 gen_cond_move(ctx, op1, rd, rs, rt);
24107 break;
24108 case R6_OPC_CLO:
24109 case R6_OPC_CLZ:
24110 if (rt == 0 && sa == 1) {
24112 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24113 * We need additionally to check other fields.
24115 gen_cl(ctx, op1, rd, rs);
24116 } else {
24117 generate_exception_end(ctx, EXCP_RI);
24119 break;
24120 case R6_OPC_SDBBP:
24121 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
24122 gen_helper_do_semihosting(cpu_env);
24123 } else {
24124 if (ctx->hflags & MIPS_HFLAG_SBRI) {
24125 generate_exception_end(ctx, EXCP_RI);
24126 } else {
24127 generate_exception_end(ctx, EXCP_DBp);
24130 break;
24131 #if defined(TARGET_MIPS64)
24132 case OPC_DLSA:
24133 check_mips_64(ctx);
24134 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
24135 break;
24136 case R6_OPC_DCLO:
24137 case R6_OPC_DCLZ:
24138 if (rt == 0 && sa == 1) {
24140 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24141 * We need additionally to check other fields.
24143 check_mips_64(ctx);
24144 gen_cl(ctx, op1, rd, rs);
24145 } else {
24146 generate_exception_end(ctx, EXCP_RI);
24148 break;
24149 case OPC_DMULT:
24150 case OPC_DMULTU:
24151 case OPC_DDIV:
24152 case OPC_DDIVU:
24154 op2 = MASK_R6_MULDIV(ctx->opcode);
24155 switch (op2) {
24156 case R6_OPC_DMUL:
24157 case R6_OPC_DMUH:
24158 case R6_OPC_DMULU:
24159 case R6_OPC_DMUHU:
24160 case R6_OPC_DDIV:
24161 case R6_OPC_DMOD:
24162 case R6_OPC_DDIVU:
24163 case R6_OPC_DMODU:
24164 check_mips_64(ctx);
24165 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24166 break;
24167 default:
24168 MIPS_INVAL("special_r6 muldiv");
24169 generate_exception_end(ctx, EXCP_RI);
24170 break;
24172 break;
24173 #endif
24174 default: /* Invalid */
24175 MIPS_INVAL("special_r6");
24176 generate_exception_end(ctx, EXCP_RI);
24177 break;
24181 static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
24183 int rs = extract32(ctx->opcode, 21, 5);
24184 int rt = extract32(ctx->opcode, 16, 5);
24185 int rd = extract32(ctx->opcode, 11, 5);
24186 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
24188 switch (op1) {
24189 case OPC_MOVN: /* Conditional move */
24190 case OPC_MOVZ:
24191 gen_cond_move(ctx, op1, rd, rs, rt);
24192 break;
24193 case OPC_MFHI: /* Move from HI/LO */
24194 case OPC_MFLO:
24195 gen_HILO(ctx, op1, 0, rd);
24196 break;
24197 case OPC_MTHI:
24198 case OPC_MTLO: /* Move to HI/LO */
24199 gen_HILO(ctx, op1, 0, rs);
24200 break;
24201 case OPC_MULT:
24202 case OPC_MULTU:
24203 gen_mul_txx9(ctx, op1, rd, rs, rt);
24204 break;
24205 case OPC_DIV:
24206 case OPC_DIVU:
24207 gen_muldiv(ctx, op1, 0, rs, rt);
24208 break;
24209 #if defined(TARGET_MIPS64)
24210 case OPC_DMULT:
24211 case OPC_DMULTU:
24212 case OPC_DDIV:
24213 case OPC_DDIVU:
24214 check_insn_opc_user_only(ctx, INSN_R5900);
24215 gen_muldiv(ctx, op1, 0, rs, rt);
24216 break;
24217 #endif
24218 case OPC_JR:
24219 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
24220 break;
24221 default: /* Invalid */
24222 MIPS_INVAL("special_tx79");
24223 generate_exception_end(ctx, EXCP_RI);
24224 break;
24228 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
24230 int rs, rt, rd, sa;
24231 uint32_t op1;
24233 rs = (ctx->opcode >> 21) & 0x1f;
24234 rt = (ctx->opcode >> 16) & 0x1f;
24235 rd = (ctx->opcode >> 11) & 0x1f;
24236 sa = (ctx->opcode >> 6) & 0x1f;
24238 op1 = MASK_SPECIAL(ctx->opcode);
24239 switch (op1) {
24240 case OPC_MOVN: /* Conditional move */
24241 case OPC_MOVZ:
24242 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
24243 INSN_LOONGSON2E | INSN_LOONGSON2F);
24244 gen_cond_move(ctx, op1, rd, rs, rt);
24245 break;
24246 case OPC_MFHI: /* Move from HI/LO */
24247 case OPC_MFLO:
24248 gen_HILO(ctx, op1, rs & 3, rd);
24249 break;
24250 case OPC_MTHI:
24251 case OPC_MTLO: /* Move to HI/LO */
24252 gen_HILO(ctx, op1, rd & 3, rs);
24253 break;
24254 case OPC_MOVCI:
24255 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
24256 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
24257 check_cp1_enabled(ctx);
24258 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
24259 (ctx->opcode >> 16) & 1);
24260 } else {
24261 generate_exception_err(ctx, EXCP_CpU, 1);
24263 break;
24264 case OPC_MULT:
24265 case OPC_MULTU:
24266 if (sa) {
24267 check_insn(ctx, INSN_VR54XX);
24268 op1 = MASK_MUL_VR54XX(ctx->opcode);
24269 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
24270 } else {
24271 gen_muldiv(ctx, op1, rd & 3, rs, rt);
24273 break;
24274 case OPC_DIV:
24275 case OPC_DIVU:
24276 gen_muldiv(ctx, op1, 0, rs, rt);
24277 break;
24278 #if defined(TARGET_MIPS64)
24279 case OPC_DMULT:
24280 case OPC_DMULTU:
24281 case OPC_DDIV:
24282 case OPC_DDIVU:
24283 check_insn(ctx, ISA_MIPS3);
24284 check_mips_64(ctx);
24285 gen_muldiv(ctx, op1, 0, rs, rt);
24286 break;
24287 #endif
24288 case OPC_JR:
24289 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24290 break;
24291 case OPC_SPIM:
24292 #ifdef MIPS_STRICT_STANDARD
24293 MIPS_INVAL("SPIM");
24294 generate_exception_end(ctx, EXCP_RI);
24295 #else
24296 /* Implemented as RI exception for now. */
24297 MIPS_INVAL("spim (unofficial)");
24298 generate_exception_end(ctx, EXCP_RI);
24299 #endif
24300 break;
24301 default: /* Invalid */
24302 MIPS_INVAL("special_legacy");
24303 generate_exception_end(ctx, EXCP_RI);
24304 break;
24308 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
24310 int rs, rt, rd, sa;
24311 uint32_t op1;
24313 rs = (ctx->opcode >> 21) & 0x1f;
24314 rt = (ctx->opcode >> 16) & 0x1f;
24315 rd = (ctx->opcode >> 11) & 0x1f;
24316 sa = (ctx->opcode >> 6) & 0x1f;
24318 op1 = MASK_SPECIAL(ctx->opcode);
24319 switch (op1) {
24320 case OPC_SLL: /* Shift with immediate */
24321 if (sa == 5 && rd == 0 &&
24322 rs == 0 && rt == 0) { /* PAUSE */
24323 if ((ctx->insn_flags & ISA_MIPS32R6) &&
24324 (ctx->hflags & MIPS_HFLAG_BMASK)) {
24325 generate_exception_end(ctx, EXCP_RI);
24326 break;
24329 /* Fallthrough */
24330 case OPC_SRA:
24331 gen_shift_imm(ctx, op1, rd, rt, sa);
24332 break;
24333 case OPC_SRL:
24334 switch ((ctx->opcode >> 21) & 0x1f) {
24335 case 1:
24336 /* rotr is decoded as srl on non-R2 CPUs */
24337 if (ctx->insn_flags & ISA_MIPS32R2) {
24338 op1 = OPC_ROTR;
24340 /* Fallthrough */
24341 case 0:
24342 gen_shift_imm(ctx, op1, rd, rt, sa);
24343 break;
24344 default:
24345 generate_exception_end(ctx, EXCP_RI);
24346 break;
24348 break;
24349 case OPC_ADD:
24350 case OPC_ADDU:
24351 case OPC_SUB:
24352 case OPC_SUBU:
24353 gen_arith(ctx, op1, rd, rs, rt);
24354 break;
24355 case OPC_SLLV: /* Shifts */
24356 case OPC_SRAV:
24357 gen_shift(ctx, op1, rd, rs, rt);
24358 break;
24359 case OPC_SRLV:
24360 switch ((ctx->opcode >> 6) & 0x1f) {
24361 case 1:
24362 /* rotrv is decoded as srlv on non-R2 CPUs */
24363 if (ctx->insn_flags & ISA_MIPS32R2) {
24364 op1 = OPC_ROTRV;
24366 /* Fallthrough */
24367 case 0:
24368 gen_shift(ctx, op1, rd, rs, rt);
24369 break;
24370 default:
24371 generate_exception_end(ctx, EXCP_RI);
24372 break;
24374 break;
24375 case OPC_SLT: /* Set on less than */
24376 case OPC_SLTU:
24377 gen_slt(ctx, op1, rd, rs, rt);
24378 break;
24379 case OPC_AND: /* Logic*/
24380 case OPC_OR:
24381 case OPC_NOR:
24382 case OPC_XOR:
24383 gen_logic(ctx, op1, rd, rs, rt);
24384 break;
24385 case OPC_JALR:
24386 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24387 break;
24388 case OPC_TGE: /* Traps */
24389 case OPC_TGEU:
24390 case OPC_TLT:
24391 case OPC_TLTU:
24392 case OPC_TEQ:
24393 case OPC_TNE:
24394 check_insn(ctx, ISA_MIPS2);
24395 gen_trap(ctx, op1, rs, rt, -1);
24396 break;
24397 case OPC_LSA: /* OPC_PMON */
24398 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24399 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
24400 decode_opc_special_r6(env, ctx);
24401 } else {
24402 /* Pmon entry point, also R4010 selsl */
24403 #ifdef MIPS_STRICT_STANDARD
24404 MIPS_INVAL("PMON / selsl");
24405 generate_exception_end(ctx, EXCP_RI);
24406 #else
24407 gen_helper_0e0i(pmon, sa);
24408 #endif
24410 break;
24411 case OPC_SYSCALL:
24412 generate_exception_end(ctx, EXCP_SYSCALL);
24413 break;
24414 case OPC_BREAK:
24415 generate_exception_end(ctx, EXCP_BREAK);
24416 break;
24417 case OPC_SYNC:
24418 check_insn(ctx, ISA_MIPS2);
24419 gen_sync(extract32(ctx->opcode, 6, 5));
24420 break;
24422 #if defined(TARGET_MIPS64)
24423 /* MIPS64 specific opcodes */
24424 case OPC_DSLL:
24425 case OPC_DSRA:
24426 case OPC_DSLL32:
24427 case OPC_DSRA32:
24428 check_insn(ctx, ISA_MIPS3);
24429 check_mips_64(ctx);
24430 gen_shift_imm(ctx, op1, rd, rt, sa);
24431 break;
24432 case OPC_DSRL:
24433 switch ((ctx->opcode >> 21) & 0x1f) {
24434 case 1:
24435 /* drotr is decoded as dsrl on non-R2 CPUs */
24436 if (ctx->insn_flags & ISA_MIPS32R2) {
24437 op1 = OPC_DROTR;
24439 /* Fallthrough */
24440 case 0:
24441 check_insn(ctx, ISA_MIPS3);
24442 check_mips_64(ctx);
24443 gen_shift_imm(ctx, op1, rd, rt, sa);
24444 break;
24445 default:
24446 generate_exception_end(ctx, EXCP_RI);
24447 break;
24449 break;
24450 case OPC_DSRL32:
24451 switch ((ctx->opcode >> 21) & 0x1f) {
24452 case 1:
24453 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
24454 if (ctx->insn_flags & ISA_MIPS32R2) {
24455 op1 = OPC_DROTR32;
24457 /* Fallthrough */
24458 case 0:
24459 check_insn(ctx, ISA_MIPS3);
24460 check_mips_64(ctx);
24461 gen_shift_imm(ctx, op1, rd, rt, sa);
24462 break;
24463 default:
24464 generate_exception_end(ctx, EXCP_RI);
24465 break;
24467 break;
24468 case OPC_DADD:
24469 case OPC_DADDU:
24470 case OPC_DSUB:
24471 case OPC_DSUBU:
24472 check_insn(ctx, ISA_MIPS3);
24473 check_mips_64(ctx);
24474 gen_arith(ctx, op1, rd, rs, rt);
24475 break;
24476 case OPC_DSLLV:
24477 case OPC_DSRAV:
24478 check_insn(ctx, ISA_MIPS3);
24479 check_mips_64(ctx);
24480 gen_shift(ctx, op1, rd, rs, rt);
24481 break;
24482 case OPC_DSRLV:
24483 switch ((ctx->opcode >> 6) & 0x1f) {
24484 case 1:
24485 /* drotrv is decoded as dsrlv on non-R2 CPUs */
24486 if (ctx->insn_flags & ISA_MIPS32R2) {
24487 op1 = OPC_DROTRV;
24489 /* Fallthrough */
24490 case 0:
24491 check_insn(ctx, ISA_MIPS3);
24492 check_mips_64(ctx);
24493 gen_shift(ctx, op1, rd, rs, rt);
24494 break;
24495 default:
24496 generate_exception_end(ctx, EXCP_RI);
24497 break;
24499 break;
24500 case OPC_DLSA:
24501 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24502 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
24503 decode_opc_special_r6(env, ctx);
24505 break;
24506 #endif
24507 default:
24508 if (ctx->insn_flags & ISA_MIPS32R6) {
24509 decode_opc_special_r6(env, ctx);
24510 } else if (ctx->insn_flags & INSN_R5900) {
24511 decode_opc_special_tx79(env, ctx);
24512 } else {
24513 decode_opc_special_legacy(env, ctx);
24519 #if defined(TARGET_MIPS64)
24523 * MMI (MultiMedia Interface) ASE instructions
24524 * ===========================================
24528 * MMI instructions category: data communication
24529 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24531 * PCPYH PEXCH PEXTLB PINTH PPACB PEXT5 PREVH
24532 * PCPYLD PEXCW PEXTLH PINTEH PPACH PPAC5 PROT3W
24533 * PCPYUD PEXEH PEXTLW PPACW
24534 * PEXEW PEXTUB
24535 * PEXTUH
24536 * PEXTUW
24540 * PCPYH rd, rt
24542 * Parallel Copy Halfword
24544 * 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
24545 * +-----------+---------+---------+---------+---------+-----------+
24546 * | MMI |0 0 0 0 0| rt | rd | PCPYH | MMI3 |
24547 * +-----------+---------+---------+---------+---------+-----------+
24549 static void gen_mmi_pcpyh(DisasContext *ctx)
24551 uint32_t pd, rt, rd;
24552 uint32_t opcode;
24554 opcode = ctx->opcode;
24556 pd = extract32(opcode, 21, 5);
24557 rt = extract32(opcode, 16, 5);
24558 rd = extract32(opcode, 11, 5);
24560 if (unlikely(pd != 0)) {
24561 generate_exception_end(ctx, EXCP_RI);
24562 } else if (rd == 0) {
24563 /* nop */
24564 } else if (rt == 0) {
24565 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24566 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24567 } else {
24568 TCGv_i64 t0 = tcg_temp_new();
24569 TCGv_i64 t1 = tcg_temp_new();
24570 uint64_t mask = (1ULL << 16) - 1;
24572 tcg_gen_andi_i64(t0, cpu_gpr[rt], mask);
24573 tcg_gen_movi_i64(t1, 0);
24574 tcg_gen_or_i64(t1, t0, t1);
24575 tcg_gen_shli_i64(t0, t0, 16);
24576 tcg_gen_or_i64(t1, t0, t1);
24577 tcg_gen_shli_i64(t0, t0, 16);
24578 tcg_gen_or_i64(t1, t0, t1);
24579 tcg_gen_shli_i64(t0, t0, 16);
24580 tcg_gen_or_i64(t1, t0, t1);
24582 tcg_gen_mov_i64(cpu_gpr[rd], t1);
24584 tcg_gen_andi_i64(t0, cpu_mmr[rt], mask);
24585 tcg_gen_movi_i64(t1, 0);
24586 tcg_gen_or_i64(t1, t0, t1);
24587 tcg_gen_shli_i64(t0, t0, 16);
24588 tcg_gen_or_i64(t1, t0, t1);
24589 tcg_gen_shli_i64(t0, t0, 16);
24590 tcg_gen_or_i64(t1, t0, t1);
24591 tcg_gen_shli_i64(t0, t0, 16);
24592 tcg_gen_or_i64(t1, t0, t1);
24594 tcg_gen_mov_i64(cpu_mmr[rd], t1);
24596 tcg_temp_free(t0);
24597 tcg_temp_free(t1);
24602 * PCPYLD rd, rs, rt
24604 * Parallel Copy Lower Doubleword
24606 * 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
24607 * +-----------+---------+---------+---------+---------+-----------+
24608 * | MMI | rs | rt | rd | PCPYLD | MMI2 |
24609 * +-----------+---------+---------+---------+---------+-----------+
24611 static void gen_mmi_pcpyld(DisasContext *ctx)
24613 uint32_t rs, rt, rd;
24614 uint32_t opcode;
24616 opcode = ctx->opcode;
24618 rs = extract32(opcode, 21, 5);
24619 rt = extract32(opcode, 16, 5);
24620 rd = extract32(opcode, 11, 5);
24622 if (rd == 0) {
24623 /* nop */
24624 } else {
24625 if (rs == 0) {
24626 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24627 } else {
24628 tcg_gen_mov_i64(cpu_mmr[rd], cpu_gpr[rs]);
24630 if (rt == 0) {
24631 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24632 } else {
24633 if (rd != rt) {
24634 tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr[rt]);
24641 * PCPYUD rd, rs, rt
24643 * Parallel Copy Upper Doubleword
24645 * 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
24646 * +-----------+---------+---------+---------+---------+-----------+
24647 * | MMI | rs | rt | rd | PCPYUD | MMI3 |
24648 * +-----------+---------+---------+---------+---------+-----------+
24650 static void gen_mmi_pcpyud(DisasContext *ctx)
24652 uint32_t rs, rt, rd;
24653 uint32_t opcode;
24655 opcode = ctx->opcode;
24657 rs = extract32(opcode, 21, 5);
24658 rt = extract32(opcode, 16, 5);
24659 rd = extract32(opcode, 11, 5);
24661 if (rd == 0) {
24662 /* nop */
24663 } else {
24664 if (rs == 0) {
24665 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24666 } else {
24667 tcg_gen_mov_i64(cpu_gpr[rd], cpu_mmr[rs]);
24669 if (rt == 0) {
24670 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24671 } else {
24672 if (rd != rt) {
24673 tcg_gen_mov_i64(cpu_mmr[rd], cpu_mmr[rt]);
24679 #endif
24682 #if !defined(TARGET_MIPS64)
24684 /* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
24685 #define MXU_APTN1_A 0
24686 #define MXU_APTN1_S 1
24688 /* MXU accumulate add/subtract 2-bit pattern 'aptn2' */
24689 #define MXU_APTN2_AA 0
24690 #define MXU_APTN2_AS 1
24691 #define MXU_APTN2_SA 2
24692 #define MXU_APTN2_SS 3
24694 /* MXU execute add/subtract 2-bit pattern 'eptn2' */
24695 #define MXU_EPTN2_AA 0
24696 #define MXU_EPTN2_AS 1
24697 #define MXU_EPTN2_SA 2
24698 #define MXU_EPTN2_SS 3
24700 /* MXU operand getting pattern 'optn2' */
24701 #define MXU_OPTN2_PTN0 0
24702 #define MXU_OPTN2_PTN1 1
24703 #define MXU_OPTN2_PTN2 2
24704 #define MXU_OPTN2_PTN3 3
24705 /* alternative naming scheme for 'optn2' */
24706 #define MXU_OPTN2_WW 0
24707 #define MXU_OPTN2_LW 1
24708 #define MXU_OPTN2_HW 2
24709 #define MXU_OPTN2_XW 3
24711 /* MXU operand getting pattern 'optn3' */
24712 #define MXU_OPTN3_PTN0 0
24713 #define MXU_OPTN3_PTN1 1
24714 #define MXU_OPTN3_PTN2 2
24715 #define MXU_OPTN3_PTN3 3
24716 #define MXU_OPTN3_PTN4 4
24717 #define MXU_OPTN3_PTN5 5
24718 #define MXU_OPTN3_PTN6 6
24719 #define MXU_OPTN3_PTN7 7
24723 * S32I2M XRa, rb - Register move from GRF to XRF
24725 static void gen_mxu_s32i2m(DisasContext *ctx)
24727 TCGv t0;
24728 uint32_t XRa, Rb;
24730 t0 = tcg_temp_new();
24732 XRa = extract32(ctx->opcode, 6, 5);
24733 Rb = extract32(ctx->opcode, 16, 5);
24735 gen_load_gpr(t0, Rb);
24736 if (XRa <= 15) {
24737 gen_store_mxu_gpr(t0, XRa);
24738 } else if (XRa == 16) {
24739 gen_store_mxu_cr(t0);
24742 tcg_temp_free(t0);
24746 * S32M2I XRa, rb - Register move from XRF to GRF
24748 static void gen_mxu_s32m2i(DisasContext *ctx)
24750 TCGv t0;
24751 uint32_t XRa, Rb;
24753 t0 = tcg_temp_new();
24755 XRa = extract32(ctx->opcode, 6, 5);
24756 Rb = extract32(ctx->opcode, 16, 5);
24758 if (XRa <= 15) {
24759 gen_load_mxu_gpr(t0, XRa);
24760 } else if (XRa == 16) {
24761 gen_load_mxu_cr(t0);
24764 gen_store_gpr(t0, Rb);
24766 tcg_temp_free(t0);
24770 * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF
24772 static void gen_mxu_s8ldd(DisasContext *ctx)
24774 TCGv t0, t1;
24775 uint32_t XRa, Rb, s8, optn3;
24777 t0 = tcg_temp_new();
24778 t1 = tcg_temp_new();
24780 XRa = extract32(ctx->opcode, 6, 4);
24781 s8 = extract32(ctx->opcode, 10, 8);
24782 optn3 = extract32(ctx->opcode, 18, 3);
24783 Rb = extract32(ctx->opcode, 21, 5);
24785 gen_load_gpr(t0, Rb);
24786 tcg_gen_addi_tl(t0, t0, (int8_t)s8);
24788 switch (optn3) {
24789 /* XRa[7:0] = tmp8 */
24790 case MXU_OPTN3_PTN0:
24791 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24792 gen_load_mxu_gpr(t0, XRa);
24793 tcg_gen_deposit_tl(t0, t0, t1, 0, 8);
24794 break;
24795 /* XRa[15:8] = tmp8 */
24796 case MXU_OPTN3_PTN1:
24797 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24798 gen_load_mxu_gpr(t0, XRa);
24799 tcg_gen_deposit_tl(t0, t0, t1, 8, 8);
24800 break;
24801 /* XRa[23:16] = tmp8 */
24802 case MXU_OPTN3_PTN2:
24803 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24804 gen_load_mxu_gpr(t0, XRa);
24805 tcg_gen_deposit_tl(t0, t0, t1, 16, 8);
24806 break;
24807 /* XRa[31:24] = tmp8 */
24808 case MXU_OPTN3_PTN3:
24809 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24810 gen_load_mxu_gpr(t0, XRa);
24811 tcg_gen_deposit_tl(t0, t0, t1, 24, 8);
24812 break;
24813 /* XRa = {8'b0, tmp8, 8'b0, tmp8} */
24814 case MXU_OPTN3_PTN4:
24815 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24816 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24817 break;
24818 /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */
24819 case MXU_OPTN3_PTN5:
24820 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24821 tcg_gen_shli_tl(t1, t1, 8);
24822 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24823 break;
24824 /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */
24825 case MXU_OPTN3_PTN6:
24826 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB);
24827 tcg_gen_mov_tl(t0, t1);
24828 tcg_gen_andi_tl(t0, t0, 0xFF00FFFF);
24829 tcg_gen_shli_tl(t1, t1, 16);
24830 tcg_gen_or_tl(t0, t0, t1);
24831 break;
24832 /* XRa = {tmp8, tmp8, tmp8, tmp8} */
24833 case MXU_OPTN3_PTN7:
24834 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24835 tcg_gen_deposit_tl(t1, t1, t1, 8, 8);
24836 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24837 break;
24840 gen_store_mxu_gpr(t0, XRa);
24842 tcg_temp_free(t0);
24843 tcg_temp_free(t1);
24847 * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication
24849 static void gen_mxu_d16mul(DisasContext *ctx)
24851 TCGv t0, t1, t2, t3;
24852 uint32_t XRa, XRb, XRc, XRd, optn2;
24854 t0 = tcg_temp_new();
24855 t1 = tcg_temp_new();
24856 t2 = tcg_temp_new();
24857 t3 = tcg_temp_new();
24859 XRa = extract32(ctx->opcode, 6, 4);
24860 XRb = extract32(ctx->opcode, 10, 4);
24861 XRc = extract32(ctx->opcode, 14, 4);
24862 XRd = extract32(ctx->opcode, 18, 4);
24863 optn2 = extract32(ctx->opcode, 22, 2);
24865 gen_load_mxu_gpr(t1, XRb);
24866 tcg_gen_sextract_tl(t0, t1, 0, 16);
24867 tcg_gen_sextract_tl(t1, t1, 16, 16);
24868 gen_load_mxu_gpr(t3, XRc);
24869 tcg_gen_sextract_tl(t2, t3, 0, 16);
24870 tcg_gen_sextract_tl(t3, t3, 16, 16);
24872 switch (optn2) {
24873 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
24874 tcg_gen_mul_tl(t3, t1, t3);
24875 tcg_gen_mul_tl(t2, t0, t2);
24876 break;
24877 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
24878 tcg_gen_mul_tl(t3, t0, t3);
24879 tcg_gen_mul_tl(t2, t0, t2);
24880 break;
24881 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
24882 tcg_gen_mul_tl(t3, t1, t3);
24883 tcg_gen_mul_tl(t2, t1, t2);
24884 break;
24885 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
24886 tcg_gen_mul_tl(t3, t0, t3);
24887 tcg_gen_mul_tl(t2, t1, t2);
24888 break;
24890 gen_store_mxu_gpr(t3, XRa);
24891 gen_store_mxu_gpr(t2, XRd);
24893 tcg_temp_free(t0);
24894 tcg_temp_free(t1);
24895 tcg_temp_free(t2);
24896 tcg_temp_free(t3);
24900 * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply
24901 * and accumulate
24903 static void gen_mxu_d16mac(DisasContext *ctx)
24905 TCGv t0, t1, t2, t3;
24906 uint32_t XRa, XRb, XRc, XRd, optn2, aptn2;
24908 t0 = tcg_temp_new();
24909 t1 = tcg_temp_new();
24910 t2 = tcg_temp_new();
24911 t3 = tcg_temp_new();
24913 XRa = extract32(ctx->opcode, 6, 4);
24914 XRb = extract32(ctx->opcode, 10, 4);
24915 XRc = extract32(ctx->opcode, 14, 4);
24916 XRd = extract32(ctx->opcode, 18, 4);
24917 optn2 = extract32(ctx->opcode, 22, 2);
24918 aptn2 = extract32(ctx->opcode, 24, 2);
24920 gen_load_mxu_gpr(t1, XRb);
24921 tcg_gen_sextract_tl(t0, t1, 0, 16);
24922 tcg_gen_sextract_tl(t1, t1, 16, 16);
24924 gen_load_mxu_gpr(t3, XRc);
24925 tcg_gen_sextract_tl(t2, t3, 0, 16);
24926 tcg_gen_sextract_tl(t3, t3, 16, 16);
24928 switch (optn2) {
24929 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
24930 tcg_gen_mul_tl(t3, t1, t3);
24931 tcg_gen_mul_tl(t2, t0, t2);
24932 break;
24933 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
24934 tcg_gen_mul_tl(t3, t0, t3);
24935 tcg_gen_mul_tl(t2, t0, t2);
24936 break;
24937 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
24938 tcg_gen_mul_tl(t3, t1, t3);
24939 tcg_gen_mul_tl(t2, t1, t2);
24940 break;
24941 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
24942 tcg_gen_mul_tl(t3, t0, t3);
24943 tcg_gen_mul_tl(t2, t1, t2);
24944 break;
24946 gen_load_mxu_gpr(t0, XRa);
24947 gen_load_mxu_gpr(t1, XRd);
24949 switch (aptn2) {
24950 case MXU_APTN2_AA:
24951 tcg_gen_add_tl(t3, t0, t3);
24952 tcg_gen_add_tl(t2, t1, t2);
24953 break;
24954 case MXU_APTN2_AS:
24955 tcg_gen_add_tl(t3, t0, t3);
24956 tcg_gen_sub_tl(t2, t1, t2);
24957 break;
24958 case MXU_APTN2_SA:
24959 tcg_gen_sub_tl(t3, t0, t3);
24960 tcg_gen_add_tl(t2, t1, t2);
24961 break;
24962 case MXU_APTN2_SS:
24963 tcg_gen_sub_tl(t3, t0, t3);
24964 tcg_gen_sub_tl(t2, t1, t2);
24965 break;
24967 gen_store_mxu_gpr(t3, XRa);
24968 gen_store_mxu_gpr(t2, XRd);
24970 tcg_temp_free(t0);
24971 tcg_temp_free(t1);
24972 tcg_temp_free(t2);
24973 tcg_temp_free(t3);
24977 * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply
24978 * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply
24980 static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx)
24982 TCGv t0, t1, t2, t3, t4, t5, t6, t7;
24983 uint32_t XRa, XRb, XRc, XRd, sel;
24985 t0 = tcg_temp_new();
24986 t1 = tcg_temp_new();
24987 t2 = tcg_temp_new();
24988 t3 = tcg_temp_new();
24989 t4 = tcg_temp_new();
24990 t5 = tcg_temp_new();
24991 t6 = tcg_temp_new();
24992 t7 = tcg_temp_new();
24994 XRa = extract32(ctx->opcode, 6, 4);
24995 XRb = extract32(ctx->opcode, 10, 4);
24996 XRc = extract32(ctx->opcode, 14, 4);
24997 XRd = extract32(ctx->opcode, 18, 4);
24998 sel = extract32(ctx->opcode, 22, 2);
25000 gen_load_mxu_gpr(t3, XRb);
25001 gen_load_mxu_gpr(t7, XRc);
25003 if (sel == 0x2) {
25004 /* Q8MULSU */
25005 tcg_gen_ext8s_tl(t0, t3);
25006 tcg_gen_shri_tl(t3, t3, 8);
25007 tcg_gen_ext8s_tl(t1, t3);
25008 tcg_gen_shri_tl(t3, t3, 8);
25009 tcg_gen_ext8s_tl(t2, t3);
25010 tcg_gen_shri_tl(t3, t3, 8);
25011 tcg_gen_ext8s_tl(t3, t3);
25012 } else {
25013 /* Q8MUL */
25014 tcg_gen_ext8u_tl(t0, t3);
25015 tcg_gen_shri_tl(t3, t3, 8);
25016 tcg_gen_ext8u_tl(t1, t3);
25017 tcg_gen_shri_tl(t3, t3, 8);
25018 tcg_gen_ext8u_tl(t2, t3);
25019 tcg_gen_shri_tl(t3, t3, 8);
25020 tcg_gen_ext8u_tl(t3, t3);
25023 tcg_gen_ext8u_tl(t4, t7);
25024 tcg_gen_shri_tl(t7, t7, 8);
25025 tcg_gen_ext8u_tl(t5, t7);
25026 tcg_gen_shri_tl(t7, t7, 8);
25027 tcg_gen_ext8u_tl(t6, t7);
25028 tcg_gen_shri_tl(t7, t7, 8);
25029 tcg_gen_ext8u_tl(t7, t7);
25031 tcg_gen_mul_tl(t0, t0, t4);
25032 tcg_gen_mul_tl(t1, t1, t5);
25033 tcg_gen_mul_tl(t2, t2, t6);
25034 tcg_gen_mul_tl(t3, t3, t7);
25036 tcg_gen_andi_tl(t0, t0, 0xFFFF);
25037 tcg_gen_andi_tl(t1, t1, 0xFFFF);
25038 tcg_gen_andi_tl(t2, t2, 0xFFFF);
25039 tcg_gen_andi_tl(t3, t3, 0xFFFF);
25041 tcg_gen_shli_tl(t1, t1, 16);
25042 tcg_gen_shli_tl(t3, t3, 16);
25044 tcg_gen_or_tl(t0, t0, t1);
25045 tcg_gen_or_tl(t1, t2, t3);
25047 gen_store_mxu_gpr(t0, XRd);
25048 gen_store_mxu_gpr(t1, XRa);
25050 tcg_temp_free(t0);
25051 tcg_temp_free(t1);
25052 tcg_temp_free(t2);
25053 tcg_temp_free(t3);
25054 tcg_temp_free(t4);
25055 tcg_temp_free(t5);
25056 tcg_temp_free(t6);
25057 tcg_temp_free(t7);
25061 * S32LDD XRa, Rb, S12 - Load a word from memory to XRF
25062 * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte seq.
25064 static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx)
25066 TCGv t0, t1;
25067 uint32_t XRa, Rb, s12, sel;
25069 t0 = tcg_temp_new();
25070 t1 = tcg_temp_new();
25072 XRa = extract32(ctx->opcode, 6, 4);
25073 s12 = extract32(ctx->opcode, 10, 10);
25074 sel = extract32(ctx->opcode, 20, 1);
25075 Rb = extract32(ctx->opcode, 21, 5);
25077 gen_load_gpr(t0, Rb);
25079 tcg_gen_movi_tl(t1, s12);
25080 tcg_gen_shli_tl(t1, t1, 2);
25081 if (s12 & 0x200) {
25082 tcg_gen_ori_tl(t1, t1, 0xFFFFF000);
25084 tcg_gen_add_tl(t1, t0, t1);
25085 tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL);
25087 if (sel == 1) {
25088 /* S32LDDR */
25089 tcg_gen_bswap32_tl(t1, t1);
25091 gen_store_mxu_gpr(t1, XRa);
25093 tcg_temp_free(t0);
25094 tcg_temp_free(t1);
25099 * MXU instruction category: logic
25100 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25102 * S32NOR S32AND S32OR S32XOR
25106 * S32NOR XRa, XRb, XRc
25107 * Update XRa with the result of logical bitwise 'nor' operation
25108 * applied to the content of XRb and XRc.
25110 * 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
25111 * +-----------+---------+-----+-------+-------+-------+-----------+
25112 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25113 * +-----------+---------+-----+-------+-------+-------+-----------+
25115 static void gen_mxu_S32NOR(DisasContext *ctx)
25117 uint32_t pad, XRc, XRb, XRa;
25119 pad = extract32(ctx->opcode, 21, 5);
25120 XRc = extract32(ctx->opcode, 14, 4);
25121 XRb = extract32(ctx->opcode, 10, 4);
25122 XRa = extract32(ctx->opcode, 6, 4);
25124 if (unlikely(pad != 0)) {
25125 /* opcode padding incorrect -> do nothing */
25126 } else if (unlikely(XRa == 0)) {
25127 /* destination is zero register -> do nothing */
25128 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25129 /* both operands zero registers -> just set destination to all 1s */
25130 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF);
25131 } else if (unlikely(XRb == 0)) {
25132 /* XRb zero register -> just set destination to the negation of XRc */
25133 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25134 } else if (unlikely(XRc == 0)) {
25135 /* XRa zero register -> just set destination to the negation of XRb */
25136 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25137 } else if (unlikely(XRb == XRc)) {
25138 /* both operands same -> just set destination to the negation of XRb */
25139 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25140 } else {
25141 /* the most general case */
25142 tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25147 * S32AND XRa, XRb, XRc
25148 * Update XRa with the result of logical bitwise 'and' operation
25149 * applied to the content of XRb and XRc.
25151 * 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
25152 * +-----------+---------+-----+-------+-------+-------+-----------+
25153 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25154 * +-----------+---------+-----+-------+-------+-------+-----------+
25156 static void gen_mxu_S32AND(DisasContext *ctx)
25158 uint32_t pad, XRc, XRb, XRa;
25160 pad = extract32(ctx->opcode, 21, 5);
25161 XRc = extract32(ctx->opcode, 14, 4);
25162 XRb = extract32(ctx->opcode, 10, 4);
25163 XRa = extract32(ctx->opcode, 6, 4);
25165 if (unlikely(pad != 0)) {
25166 /* opcode padding incorrect -> do nothing */
25167 } else if (unlikely(XRa == 0)) {
25168 /* destination is zero register -> do nothing */
25169 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25170 /* one of operands zero register -> just set destination to all 0s */
25171 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25172 } else if (unlikely(XRb == XRc)) {
25173 /* both operands same -> just set destination to one of them */
25174 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25175 } else {
25176 /* the most general case */
25177 tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25182 * S32OR XRa, XRb, XRc
25183 * Update XRa with the result of logical bitwise 'or' operation
25184 * applied to the content of XRb and XRc.
25186 * 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
25187 * +-----------+---------+-----+-------+-------+-------+-----------+
25188 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25189 * +-----------+---------+-----+-------+-------+-------+-----------+
25191 static void gen_mxu_S32OR(DisasContext *ctx)
25193 uint32_t pad, XRc, XRb, XRa;
25195 pad = extract32(ctx->opcode, 21, 5);
25196 XRc = extract32(ctx->opcode, 14, 4);
25197 XRb = extract32(ctx->opcode, 10, 4);
25198 XRa = extract32(ctx->opcode, 6, 4);
25200 if (unlikely(pad != 0)) {
25201 /* opcode padding incorrect -> do nothing */
25202 } else if (unlikely(XRa == 0)) {
25203 /* destination is zero register -> do nothing */
25204 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25205 /* both operands zero registers -> just set destination to all 0s */
25206 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25207 } else if (unlikely(XRb == 0)) {
25208 /* XRb zero register -> just set destination to the content of XRc */
25209 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25210 } else if (unlikely(XRc == 0)) {
25211 /* XRc zero register -> just set destination to the content of XRb */
25212 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25213 } else if (unlikely(XRb == XRc)) {
25214 /* both operands same -> just set destination to one of them */
25215 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25216 } else {
25217 /* the most general case */
25218 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25223 * S32XOR XRa, XRb, XRc
25224 * Update XRa with the result of logical bitwise 'xor' operation
25225 * applied to the content of XRb and XRc.
25227 * 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
25228 * +-----------+---------+-----+-------+-------+-------+-----------+
25229 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25230 * +-----------+---------+-----+-------+-------+-------+-----------+
25232 static void gen_mxu_S32XOR(DisasContext *ctx)
25234 uint32_t pad, XRc, XRb, XRa;
25236 pad = extract32(ctx->opcode, 21, 5);
25237 XRc = extract32(ctx->opcode, 14, 4);
25238 XRb = extract32(ctx->opcode, 10, 4);
25239 XRa = extract32(ctx->opcode, 6, 4);
25241 if (unlikely(pad != 0)) {
25242 /* opcode padding incorrect -> do nothing */
25243 } else if (unlikely(XRa == 0)) {
25244 /* destination is zero register -> do nothing */
25245 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25246 /* both operands zero registers -> just set destination to all 0s */
25247 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25248 } else if (unlikely(XRb == 0)) {
25249 /* XRb zero register -> just set destination to the content of XRc */
25250 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25251 } else if (unlikely(XRc == 0)) {
25252 /* XRc zero register -> just set destination to the content of XRb */
25253 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25254 } else if (unlikely(XRb == XRc)) {
25255 /* both operands same -> just set destination to all 0s */
25256 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25257 } else {
25258 /* the most general case */
25259 tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25265 * MXU instruction category max/min
25266 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25268 * S32MAX D16MAX Q8MAX
25269 * S32MIN D16MIN Q8MIN
25273 * S32MAX XRa, XRb, XRc
25274 * Update XRa with the maximum of signed 32-bit integers contained
25275 * in XRb and XRc.
25277 * S32MIN XRa, XRb, XRc
25278 * Update XRa with the minimum of signed 32-bit integers contained
25279 * in XRb and XRc.
25281 * 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
25282 * +-----------+---------+-----+-------+-------+-------+-----------+
25283 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25284 * +-----------+---------+-----+-------+-------+-------+-----------+
25286 static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx)
25288 uint32_t pad, opc, XRc, XRb, XRa;
25290 pad = extract32(ctx->opcode, 21, 5);
25291 opc = extract32(ctx->opcode, 18, 3);
25292 XRc = extract32(ctx->opcode, 14, 4);
25293 XRb = extract32(ctx->opcode, 10, 4);
25294 XRa = extract32(ctx->opcode, 6, 4);
25296 if (unlikely(pad != 0)) {
25297 /* opcode padding incorrect -> do nothing */
25298 } else if (unlikely(XRa == 0)) {
25299 /* destination is zero register -> do nothing */
25300 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25301 /* both operands zero registers -> just set destination to zero */
25302 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25303 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25304 /* exactly one operand is zero register - find which one is not...*/
25305 uint32_t XRx = XRb ? XRb : XRc;
25306 /* ...and do max/min operation with one operand 0 */
25307 if (opc == OPC_MXU_S32MAX) {
25308 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25309 } else {
25310 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25312 } else if (unlikely(XRb == XRc)) {
25313 /* both operands same -> just set destination to one of them */
25314 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25315 } else {
25316 /* the most general case */
25317 if (opc == OPC_MXU_S32MAX) {
25318 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25319 mxu_gpr[XRc - 1]);
25320 } else {
25321 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25322 mxu_gpr[XRc - 1]);
25328 * D16MAX
25329 * Update XRa with the 16-bit-wise maximums of signed integers
25330 * contained in XRb and XRc.
25332 * D16MIN
25333 * Update XRa with the 16-bit-wise minimums of signed integers
25334 * contained in 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__POOL00|
25339 * +-----------+---------+-----+-------+-------+-------+-----------+
25341 static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx)
25343 uint32_t pad, opc, XRc, XRb, XRa;
25345 pad = extract32(ctx->opcode, 21, 5);
25346 opc = extract32(ctx->opcode, 18, 3);
25347 XRc = extract32(ctx->opcode, 14, 4);
25348 XRb = extract32(ctx->opcode, 10, 4);
25349 XRa = extract32(ctx->opcode, 6, 4);
25351 if (unlikely(pad != 0)) {
25352 /* opcode padding incorrect -> do nothing */
25353 } else if (unlikely(XRc == 0)) {
25354 /* destination is zero register -> do nothing */
25355 } else if (unlikely((XRb == 0) && (XRa == 0))) {
25356 /* both operands zero registers -> just set destination to zero */
25357 tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0);
25358 } else if (unlikely((XRb == 0) || (XRa == 0))) {
25359 /* exactly one operand is zero register - find which one is not...*/
25360 uint32_t XRx = XRb ? XRb : XRc;
25361 /* ...and do half-word-wise max/min with one operand 0 */
25362 TCGv_i32 t0 = tcg_temp_new();
25363 TCGv_i32 t1 = tcg_const_i32(0);
25365 /* the left half-word first */
25366 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000);
25367 if (opc == OPC_MXU_D16MAX) {
25368 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25369 } else {
25370 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25373 /* the right half-word */
25374 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF);
25375 /* move half-words to the leftmost position */
25376 tcg_gen_shli_i32(t0, t0, 16);
25377 /* t0 will be max/min of t0 and t1 */
25378 if (opc == OPC_MXU_D16MAX) {
25379 tcg_gen_smax_i32(t0, t0, t1);
25380 } else {
25381 tcg_gen_smin_i32(t0, t0, t1);
25383 /* return resulting half-words to its original position */
25384 tcg_gen_shri_i32(t0, t0, 16);
25385 /* finaly update the destination */
25386 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25388 tcg_temp_free(t1);
25389 tcg_temp_free(t0);
25390 } else if (unlikely(XRb == XRc)) {
25391 /* both operands same -> just set destination to one of them */
25392 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25393 } else {
25394 /* the most general case */
25395 TCGv_i32 t0 = tcg_temp_new();
25396 TCGv_i32 t1 = tcg_temp_new();
25398 /* the left half-word first */
25399 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000);
25400 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25401 if (opc == OPC_MXU_D16MAX) {
25402 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25403 } else {
25404 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25407 /* the right half-word */
25408 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25409 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF);
25410 /* move half-words to the leftmost position */
25411 tcg_gen_shli_i32(t0, t0, 16);
25412 tcg_gen_shli_i32(t1, t1, 16);
25413 /* t0 will be max/min of t0 and t1 */
25414 if (opc == OPC_MXU_D16MAX) {
25415 tcg_gen_smax_i32(t0, t0, t1);
25416 } else {
25417 tcg_gen_smin_i32(t0, t0, t1);
25419 /* return resulting half-words to its original position */
25420 tcg_gen_shri_i32(t0, t0, 16);
25421 /* finaly update the destination */
25422 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25424 tcg_temp_free(t1);
25425 tcg_temp_free(t0);
25430 * Q8MAX
25431 * Update XRa with the 8-bit-wise maximums of signed integers
25432 * contained in XRb and XRc.
25434 * Q8MIN
25435 * Update XRa with the 8-bit-wise minimums of signed integers
25436 * contained in XRb and XRc.
25438 * 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
25439 * +-----------+---------+-----+-------+-------+-------+-----------+
25440 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25441 * +-----------+---------+-----+-------+-------+-------+-----------+
25443 static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx)
25445 uint32_t pad, opc, XRc, XRb, XRa;
25447 pad = extract32(ctx->opcode, 21, 5);
25448 opc = extract32(ctx->opcode, 18, 3);
25449 XRc = extract32(ctx->opcode, 14, 4);
25450 XRb = extract32(ctx->opcode, 10, 4);
25451 XRa = extract32(ctx->opcode, 6, 4);
25453 if (unlikely(pad != 0)) {
25454 /* opcode padding incorrect -> do nothing */
25455 } else if (unlikely(XRa == 0)) {
25456 /* destination is zero register -> do nothing */
25457 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25458 /* both operands zero registers -> just set destination to zero */
25459 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25460 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25461 /* exactly one operand is zero register - make it be the first...*/
25462 uint32_t XRx = XRb ? XRb : XRc;
25463 /* ...and do byte-wise max/min with one operand 0 */
25464 TCGv_i32 t0 = tcg_temp_new();
25465 TCGv_i32 t1 = tcg_const_i32(0);
25466 int32_t i;
25468 /* the leftmost byte (byte 3) first */
25469 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000);
25470 if (opc == OPC_MXU_Q8MAX) {
25471 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25472 } else {
25473 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25476 /* bytes 2, 1, 0 */
25477 for (i = 2; i >= 0; i--) {
25478 /* extract the byte */
25479 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i));
25480 /* move the byte to the leftmost position */
25481 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25482 /* t0 will be max/min of t0 and t1 */
25483 if (opc == OPC_MXU_Q8MAX) {
25484 tcg_gen_smax_i32(t0, t0, t1);
25485 } else {
25486 tcg_gen_smin_i32(t0, t0, t1);
25488 /* return resulting byte to its original position */
25489 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25490 /* finaly update the destination */
25491 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25494 tcg_temp_free(t1);
25495 tcg_temp_free(t0);
25496 } else if (unlikely(XRb == XRc)) {
25497 /* both operands same -> just set destination to one of them */
25498 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25499 } else {
25500 /* the most general case */
25501 TCGv_i32 t0 = tcg_temp_new();
25502 TCGv_i32 t1 = tcg_temp_new();
25503 int32_t i;
25505 /* the leftmost bytes (bytes 3) first */
25506 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000);
25507 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25508 if (opc == OPC_MXU_Q8MAX) {
25509 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25510 } else {
25511 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25514 /* bytes 2, 1, 0 */
25515 for (i = 2; i >= 0; i--) {
25516 /* extract corresponding bytes */
25517 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i));
25518 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i));
25519 /* move the bytes to the leftmost position */
25520 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25521 tcg_gen_shli_i32(t1, t1, 8 * (3 - i));
25522 /* t0 will be max/min of t0 and t1 */
25523 if (opc == OPC_MXU_Q8MAX) {
25524 tcg_gen_smax_i32(t0, t0, t1);
25525 } else {
25526 tcg_gen_smin_i32(t0, t0, t1);
25528 /* return resulting byte to its original position */
25529 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25530 /* finaly update the destination */
25531 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25534 tcg_temp_free(t1);
25535 tcg_temp_free(t0);
25541 * MXU instruction category: align
25542 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25544 * S32ALN S32ALNI
25548 * S32ALNI XRc, XRb, XRa, optn3
25549 * Arrange bytes from XRb and XRc according to one of five sets of
25550 * rules determined by optn3, and place the result in XRa.
25552 * 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
25553 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25554 * | SPECIAL2 |optn3|0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
25555 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25558 static void gen_mxu_S32ALNI(DisasContext *ctx)
25560 uint32_t optn3, pad, XRc, XRb, XRa;
25562 optn3 = extract32(ctx->opcode, 23, 3);
25563 pad = extract32(ctx->opcode, 21, 2);
25564 XRc = extract32(ctx->opcode, 14, 4);
25565 XRb = extract32(ctx->opcode, 10, 4);
25566 XRa = extract32(ctx->opcode, 6, 4);
25568 if (unlikely(pad != 0)) {
25569 /* opcode padding incorrect -> do nothing */
25570 } else if (unlikely(XRa == 0)) {
25571 /* destination is zero register -> do nothing */
25572 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25573 /* both operands zero registers -> just set destination to all 0s */
25574 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25575 } else if (unlikely(XRb == 0)) {
25576 /* XRb zero register -> just appropriatelly shift XRc into XRa */
25577 switch (optn3) {
25578 case MXU_OPTN3_PTN0:
25579 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25580 break;
25581 case MXU_OPTN3_PTN1:
25582 case MXU_OPTN3_PTN2:
25583 case MXU_OPTN3_PTN3:
25584 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1],
25585 8 * (4 - optn3));
25586 break;
25587 case MXU_OPTN3_PTN4:
25588 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25589 break;
25591 } else if (unlikely(XRc == 0)) {
25592 /* XRc zero register -> just appropriatelly shift XRb into XRa */
25593 switch (optn3) {
25594 case MXU_OPTN3_PTN0:
25595 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25596 break;
25597 case MXU_OPTN3_PTN1:
25598 case MXU_OPTN3_PTN2:
25599 case MXU_OPTN3_PTN3:
25600 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25601 break;
25602 case MXU_OPTN3_PTN4:
25603 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25604 break;
25606 } else if (unlikely(XRb == XRc)) {
25607 /* both operands same -> just rotation or moving from any of them */
25608 switch (optn3) {
25609 case MXU_OPTN3_PTN0:
25610 case MXU_OPTN3_PTN4:
25611 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25612 break;
25613 case MXU_OPTN3_PTN1:
25614 case MXU_OPTN3_PTN2:
25615 case MXU_OPTN3_PTN3:
25616 tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25617 break;
25619 } else {
25620 /* the most general case */
25621 switch (optn3) {
25622 case MXU_OPTN3_PTN0:
25624 /* */
25625 /* XRb XRc */
25626 /* +---------------+ */
25627 /* | A B C D | E F G H */
25628 /* +-------+-------+ */
25629 /* | */
25630 /* XRa */
25631 /* */
25633 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25635 break;
25636 case MXU_OPTN3_PTN1:
25638 /* */
25639 /* XRb XRc */
25640 /* +-------------------+ */
25641 /* A | B C D E | F G H */
25642 /* +---------+---------+ */
25643 /* | */
25644 /* XRa */
25645 /* */
25647 TCGv_i32 t0 = tcg_temp_new();
25648 TCGv_i32 t1 = tcg_temp_new();
25650 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF);
25651 tcg_gen_shli_i32(t0, t0, 8);
25653 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25654 tcg_gen_shri_i32(t1, t1, 24);
25656 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25658 tcg_temp_free(t1);
25659 tcg_temp_free(t0);
25661 break;
25662 case MXU_OPTN3_PTN2:
25664 /* */
25665 /* XRb XRc */
25666 /* +-------------------+ */
25667 /* A B | C D E F | G H */
25668 /* +---------+---------+ */
25669 /* | */
25670 /* XRa */
25671 /* */
25673 TCGv_i32 t0 = tcg_temp_new();
25674 TCGv_i32 t1 = tcg_temp_new();
25676 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25677 tcg_gen_shli_i32(t0, t0, 16);
25679 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25680 tcg_gen_shri_i32(t1, t1, 16);
25682 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25684 tcg_temp_free(t1);
25685 tcg_temp_free(t0);
25687 break;
25688 case MXU_OPTN3_PTN3:
25690 /* */
25691 /* XRb XRc */
25692 /* +-------------------+ */
25693 /* A B C | D E F G | H */
25694 /* +---------+---------+ */
25695 /* | */
25696 /* XRa */
25697 /* */
25699 TCGv_i32 t0 = tcg_temp_new();
25700 TCGv_i32 t1 = tcg_temp_new();
25702 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF);
25703 tcg_gen_shli_i32(t0, t0, 24);
25705 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00);
25706 tcg_gen_shri_i32(t1, t1, 8);
25708 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25710 tcg_temp_free(t1);
25711 tcg_temp_free(t0);
25713 break;
25714 case MXU_OPTN3_PTN4:
25716 /* */
25717 /* XRb XRc */
25718 /* +---------------+ */
25719 /* A B C D | E F G H | */
25720 /* +-------+-------+ */
25721 /* | */
25722 /* XRa */
25723 /* */
25725 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25727 break;
25734 * Decoding engine for MXU
25735 * =======================
25740 * Decode MXU pool00
25742 * 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
25743 * +-----------+---------+-----+-------+-------+-------+-----------+
25744 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL00|
25745 * +-----------+---------+-----+-------+-------+-------+-----------+
25748 static void decode_opc_mxu__pool00(CPUMIPSState *env, DisasContext *ctx)
25750 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25752 switch (opcode) {
25753 case OPC_MXU_S32MAX:
25754 case OPC_MXU_S32MIN:
25755 gen_mxu_S32MAX_S32MIN(ctx);
25756 break;
25757 case OPC_MXU_D16MAX:
25758 case OPC_MXU_D16MIN:
25759 gen_mxu_D16MAX_D16MIN(ctx);
25760 break;
25761 case OPC_MXU_Q8MAX:
25762 case OPC_MXU_Q8MIN:
25763 gen_mxu_Q8MAX_Q8MIN(ctx);
25764 break;
25765 case OPC_MXU_Q8SLT:
25766 /* TODO: Implement emulation of Q8SLT instruction. */
25767 MIPS_INVAL("OPC_MXU_Q8SLT");
25768 generate_exception_end(ctx, EXCP_RI);
25769 break;
25770 case OPC_MXU_Q8SLTU:
25771 /* TODO: Implement emulation of Q8SLTU instruction. */
25772 MIPS_INVAL("OPC_MXU_Q8SLTU");
25773 generate_exception_end(ctx, EXCP_RI);
25774 break;
25775 default:
25776 MIPS_INVAL("decode_opc_mxu");
25777 generate_exception_end(ctx, EXCP_RI);
25778 break;
25784 * Decode MXU pool01
25786 * S32SLT, D16SLT, D16AVG, D16AVGR, Q8AVG, Q8AVGR:
25787 * 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
25788 * +-----------+---------+-----+-------+-------+-------+-----------+
25789 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
25790 * +-----------+---------+-----+-------+-------+-------+-----------+
25792 * Q8ADD:
25793 * 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
25794 * +-----------+---+-----+-----+-------+-------+-------+-----------+
25795 * | SPECIAL2 |en2|0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
25796 * +-----------+---+-----+-----+-------+-------+-------+-----------+
25799 static void decode_opc_mxu__pool01(CPUMIPSState *env, DisasContext *ctx)
25801 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25803 switch (opcode) {
25804 case OPC_MXU_S32SLT:
25805 /* TODO: Implement emulation of S32SLT instruction. */
25806 MIPS_INVAL("OPC_MXU_S32SLT");
25807 generate_exception_end(ctx, EXCP_RI);
25808 break;
25809 case OPC_MXU_D16SLT:
25810 /* TODO: Implement emulation of D16SLT instruction. */
25811 MIPS_INVAL("OPC_MXU_D16SLT");
25812 generate_exception_end(ctx, EXCP_RI);
25813 break;
25814 case OPC_MXU_D16AVG:
25815 /* TODO: Implement emulation of D16AVG instruction. */
25816 MIPS_INVAL("OPC_MXU_D16AVG");
25817 generate_exception_end(ctx, EXCP_RI);
25818 break;
25819 case OPC_MXU_D16AVGR:
25820 /* TODO: Implement emulation of D16AVGR instruction. */
25821 MIPS_INVAL("OPC_MXU_D16AVGR");
25822 generate_exception_end(ctx, EXCP_RI);
25823 break;
25824 case OPC_MXU_Q8AVG:
25825 /* TODO: Implement emulation of Q8AVG instruction. */
25826 MIPS_INVAL("OPC_MXU_Q8AVG");
25827 generate_exception_end(ctx, EXCP_RI);
25828 break;
25829 case OPC_MXU_Q8AVGR:
25830 /* TODO: Implement emulation of Q8AVGR instruction. */
25831 MIPS_INVAL("OPC_MXU_Q8AVGR");
25832 generate_exception_end(ctx, EXCP_RI);
25833 break;
25834 case OPC_MXU_Q8ADD:
25835 /* TODO: Implement emulation of Q8ADD instruction. */
25836 MIPS_INVAL("OPC_MXU_Q8ADD");
25837 generate_exception_end(ctx, EXCP_RI);
25838 break;
25839 default:
25840 MIPS_INVAL("decode_opc_mxu");
25841 generate_exception_end(ctx, EXCP_RI);
25842 break;
25848 * Decode MXU pool02
25850 * 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
25851 * +-----------+---------+-----+-------+-------+-------+-----------+
25852 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL02|
25853 * +-----------+---------+-----+-------+-------+-------+-----------+
25856 static void decode_opc_mxu__pool02(CPUMIPSState *env, DisasContext *ctx)
25858 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25860 switch (opcode) {
25861 case OPC_MXU_S32CPS:
25862 /* TODO: Implement emulation of S32CPS instruction. */
25863 MIPS_INVAL("OPC_MXU_S32CPS");
25864 generate_exception_end(ctx, EXCP_RI);
25865 break;
25866 case OPC_MXU_D16CPS:
25867 /* TODO: Implement emulation of D16CPS instruction. */
25868 MIPS_INVAL("OPC_MXU_D16CPS");
25869 generate_exception_end(ctx, EXCP_RI);
25870 break;
25871 case OPC_MXU_Q8ABD:
25872 /* TODO: Implement emulation of Q8ABD instruction. */
25873 MIPS_INVAL("OPC_MXU_Q8ABD");
25874 generate_exception_end(ctx, EXCP_RI);
25875 break;
25876 case OPC_MXU_Q16SAT:
25877 /* TODO: Implement emulation of Q16SAT instruction. */
25878 MIPS_INVAL("OPC_MXU_Q16SAT");
25879 generate_exception_end(ctx, EXCP_RI);
25880 break;
25881 default:
25882 MIPS_INVAL("decode_opc_mxu");
25883 generate_exception_end(ctx, EXCP_RI);
25884 break;
25890 * Decode MXU pool03
25892 * D16MULF:
25893 * 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
25894 * +-----------+---+---+-------+-------+-------+-------+-----------+
25895 * | SPECIAL2 |x x|on2|0 0 0 0| XRc | XRb | XRa |MXU__POOL03|
25896 * +-----------+---+---+-------+-------+-------+-------+-----------+
25898 * D16MULE:
25899 * 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
25900 * +-----------+---+---+-------+-------+-------+-------+-----------+
25901 * | SPECIAL2 |x x|on2| Xd | XRc | XRb | XRa |MXU__POOL03|
25902 * +-----------+---+---+-------+-------+-------+-------+-----------+
25905 static void decode_opc_mxu__pool03(CPUMIPSState *env, DisasContext *ctx)
25907 uint32_t opcode = extract32(ctx->opcode, 24, 2);
25909 switch (opcode) {
25910 case OPC_MXU_D16MULF:
25911 /* TODO: Implement emulation of D16MULF instruction. */
25912 MIPS_INVAL("OPC_MXU_D16MULF");
25913 generate_exception_end(ctx, EXCP_RI);
25914 break;
25915 case OPC_MXU_D16MULE:
25916 /* TODO: Implement emulation of D16MULE instruction. */
25917 MIPS_INVAL("OPC_MXU_D16MULE");
25918 generate_exception_end(ctx, EXCP_RI);
25919 break;
25920 default:
25921 MIPS_INVAL("decode_opc_mxu");
25922 generate_exception_end(ctx, EXCP_RI);
25923 break;
25929 * Decode MXU pool04
25931 * 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
25932 * +-----------+---------+-+-------------------+-------+-----------+
25933 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL04|
25934 * +-----------+---------+-+-------------------+-------+-----------+
25937 static void decode_opc_mxu__pool04(CPUMIPSState *env, DisasContext *ctx)
25939 uint32_t opcode = extract32(ctx->opcode, 20, 1);
25941 switch (opcode) {
25942 case OPC_MXU_S32LDD:
25943 case OPC_MXU_S32LDDR:
25944 gen_mxu_s32ldd_s32lddr(ctx);
25945 break;
25946 default:
25947 MIPS_INVAL("decode_opc_mxu");
25948 generate_exception_end(ctx, EXCP_RI);
25949 break;
25955 * Decode MXU pool05
25957 * 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
25958 * +-----------+---------+-+-------------------+-------+-----------+
25959 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL05|
25960 * +-----------+---------+-+-------------------+-------+-----------+
25963 static void decode_opc_mxu__pool05(CPUMIPSState *env, DisasContext *ctx)
25965 uint32_t opcode = extract32(ctx->opcode, 20, 1);
25967 switch (opcode) {
25968 case OPC_MXU_S32STD:
25969 /* TODO: Implement emulation of S32STD instruction. */
25970 MIPS_INVAL("OPC_MXU_S32STD");
25971 generate_exception_end(ctx, EXCP_RI);
25972 break;
25973 case OPC_MXU_S32STDR:
25974 /* TODO: Implement emulation of S32STDR instruction. */
25975 MIPS_INVAL("OPC_MXU_S32STDR");
25976 generate_exception_end(ctx, EXCP_RI);
25977 break;
25978 default:
25979 MIPS_INVAL("decode_opc_mxu");
25980 generate_exception_end(ctx, EXCP_RI);
25981 break;
25987 * Decode MXU pool06
25989 * 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
25990 * +-----------+---------+---------+---+-------+-------+-----------+
25991 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL06|
25992 * +-----------+---------+---------+---+-------+-------+-----------+
25995 static void decode_opc_mxu__pool06(CPUMIPSState *env, DisasContext *ctx)
25997 uint32_t opcode = extract32(ctx->opcode, 10, 4);
25999 switch (opcode) {
26000 case OPC_MXU_S32LDDV:
26001 /* TODO: Implement emulation of S32LDDV instruction. */
26002 MIPS_INVAL("OPC_MXU_S32LDDV");
26003 generate_exception_end(ctx, EXCP_RI);
26004 break;
26005 case OPC_MXU_S32LDDVR:
26006 /* TODO: Implement emulation of S32LDDVR instruction. */
26007 MIPS_INVAL("OPC_MXU_S32LDDVR");
26008 generate_exception_end(ctx, EXCP_RI);
26009 break;
26010 default:
26011 MIPS_INVAL("decode_opc_mxu");
26012 generate_exception_end(ctx, EXCP_RI);
26013 break;
26019 * Decode MXU pool07
26021 * 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
26022 * +-----------+---------+---------+---+-------+-------+-----------+
26023 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL07|
26024 * +-----------+---------+---------+---+-------+-------+-----------+
26027 static void decode_opc_mxu__pool07(CPUMIPSState *env, DisasContext *ctx)
26029 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26031 switch (opcode) {
26032 case OPC_MXU_S32STDV:
26033 /* TODO: Implement emulation of S32TDV instruction. */
26034 MIPS_INVAL("OPC_MXU_S32TDV");
26035 generate_exception_end(ctx, EXCP_RI);
26036 break;
26037 case OPC_MXU_S32STDVR:
26038 /* TODO: Implement emulation of S32TDVR instruction. */
26039 MIPS_INVAL("OPC_MXU_S32TDVR");
26040 generate_exception_end(ctx, EXCP_RI);
26041 break;
26042 default:
26043 MIPS_INVAL("decode_opc_mxu");
26044 generate_exception_end(ctx, EXCP_RI);
26045 break;
26051 * Decode MXU pool08
26053 * 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
26054 * +-----------+---------+-+-------------------+-------+-----------+
26055 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL08|
26056 * +-----------+---------+-+-------------------+-------+-----------+
26059 static void decode_opc_mxu__pool08(CPUMIPSState *env, DisasContext *ctx)
26061 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26063 switch (opcode) {
26064 case OPC_MXU_S32LDI:
26065 /* TODO: Implement emulation of S32LDI instruction. */
26066 MIPS_INVAL("OPC_MXU_S32LDI");
26067 generate_exception_end(ctx, EXCP_RI);
26068 break;
26069 case OPC_MXU_S32LDIR:
26070 /* TODO: Implement emulation of S32LDIR instruction. */
26071 MIPS_INVAL("OPC_MXU_S32LDIR");
26072 generate_exception_end(ctx, EXCP_RI);
26073 break;
26074 default:
26075 MIPS_INVAL("decode_opc_mxu");
26076 generate_exception_end(ctx, EXCP_RI);
26077 break;
26083 * Decode MXU pool09
26085 * 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
26086 * +-----------+---------+-+-------------------+-------+-----------+
26087 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL09|
26088 * +-----------+---------+-+-------------------+-------+-----------+
26091 static void decode_opc_mxu__pool09(CPUMIPSState *env, DisasContext *ctx)
26093 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26095 switch (opcode) {
26096 case OPC_MXU_S32SDI:
26097 /* TODO: Implement emulation of S32SDI instruction. */
26098 MIPS_INVAL("OPC_MXU_S32SDI");
26099 generate_exception_end(ctx, EXCP_RI);
26100 break;
26101 case OPC_MXU_S32SDIR:
26102 /* TODO: Implement emulation of S32SDIR instruction. */
26103 MIPS_INVAL("OPC_MXU_S32SDIR");
26104 generate_exception_end(ctx, EXCP_RI);
26105 break;
26106 default:
26107 MIPS_INVAL("decode_opc_mxu");
26108 generate_exception_end(ctx, EXCP_RI);
26109 break;
26115 * Decode MXU pool10
26117 * 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
26118 * +-----------+---------+---------+---+-------+-------+-----------+
26119 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL10|
26120 * +-----------+---------+---------+---+-------+-------+-----------+
26123 static void decode_opc_mxu__pool10(CPUMIPSState *env, DisasContext *ctx)
26125 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26127 switch (opcode) {
26128 case OPC_MXU_S32LDIV:
26129 /* TODO: Implement emulation of S32LDIV instruction. */
26130 MIPS_INVAL("OPC_MXU_S32LDIV");
26131 generate_exception_end(ctx, EXCP_RI);
26132 break;
26133 case OPC_MXU_S32LDIVR:
26134 /* TODO: Implement emulation of S32LDIVR instruction. */
26135 MIPS_INVAL("OPC_MXU_S32LDIVR");
26136 generate_exception_end(ctx, EXCP_RI);
26137 break;
26138 default:
26139 MIPS_INVAL("decode_opc_mxu");
26140 generate_exception_end(ctx, EXCP_RI);
26141 break;
26147 * Decode MXU pool11
26149 * 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
26150 * +-----------+---------+---------+---+-------+-------+-----------+
26151 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL11|
26152 * +-----------+---------+---------+---+-------+-------+-----------+
26155 static void decode_opc_mxu__pool11(CPUMIPSState *env, DisasContext *ctx)
26157 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26159 switch (opcode) {
26160 case OPC_MXU_S32SDIV:
26161 /* TODO: Implement emulation of S32SDIV instruction. */
26162 MIPS_INVAL("OPC_MXU_S32SDIV");
26163 generate_exception_end(ctx, EXCP_RI);
26164 break;
26165 case OPC_MXU_S32SDIVR:
26166 /* TODO: Implement emulation of S32SDIVR instruction. */
26167 MIPS_INVAL("OPC_MXU_S32SDIVR");
26168 generate_exception_end(ctx, EXCP_RI);
26169 break;
26170 default:
26171 MIPS_INVAL("decode_opc_mxu");
26172 generate_exception_end(ctx, EXCP_RI);
26173 break;
26179 * Decode MXU pool12
26181 * 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
26182 * +-----------+---+---+-------+-------+-------+-------+-----------+
26183 * | SPECIAL2 |an2|x x| Xd | XRc | XRb | XRa |MXU__POOL12|
26184 * +-----------+---+---+-------+-------+-------+-------+-----------+
26187 static void decode_opc_mxu__pool12(CPUMIPSState *env, DisasContext *ctx)
26189 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26191 switch (opcode) {
26192 case OPC_MXU_D32ACC:
26193 /* TODO: Implement emulation of D32ACC instruction. */
26194 MIPS_INVAL("OPC_MXU_D32ACC");
26195 generate_exception_end(ctx, EXCP_RI);
26196 break;
26197 case OPC_MXU_D32ACCM:
26198 /* TODO: Implement emulation of D32ACCM instruction. */
26199 MIPS_INVAL("OPC_MXU_D32ACCM");
26200 generate_exception_end(ctx, EXCP_RI);
26201 break;
26202 case OPC_MXU_D32ASUM:
26203 /* TODO: Implement emulation of D32ASUM instruction. */
26204 MIPS_INVAL("OPC_MXU_D32ASUM");
26205 generate_exception_end(ctx, EXCP_RI);
26206 break;
26207 default:
26208 MIPS_INVAL("decode_opc_mxu");
26209 generate_exception_end(ctx, EXCP_RI);
26210 break;
26216 * Decode MXU pool13
26218 * 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
26219 * +-----------+---+---+-------+-------+-------+-------+-----------+
26220 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL13|
26221 * +-----------+---+---+-------+-------+-------+-------+-----------+
26224 static void decode_opc_mxu__pool13(CPUMIPSState *env, DisasContext *ctx)
26226 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26228 switch (opcode) {
26229 case OPC_MXU_Q16ACC:
26230 /* TODO: Implement emulation of Q16ACC instruction. */
26231 MIPS_INVAL("OPC_MXU_Q16ACC");
26232 generate_exception_end(ctx, EXCP_RI);
26233 break;
26234 case OPC_MXU_Q16ACCM:
26235 /* TODO: Implement emulation of Q16ACCM instruction. */
26236 MIPS_INVAL("OPC_MXU_Q16ACCM");
26237 generate_exception_end(ctx, EXCP_RI);
26238 break;
26239 case OPC_MXU_Q16ASUM:
26240 /* TODO: Implement emulation of Q16ASUM instruction. */
26241 MIPS_INVAL("OPC_MXU_Q16ASUM");
26242 generate_exception_end(ctx, EXCP_RI);
26243 break;
26244 default:
26245 MIPS_INVAL("decode_opc_mxu");
26246 generate_exception_end(ctx, EXCP_RI);
26247 break;
26253 * Decode MXU pool14
26255 * Q8ADDE, Q8ACCE:
26256 * 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
26257 * +-----------+---+---+-------+-------+-------+-------+-----------+
26258 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL14|
26259 * +-----------+---+---+-------+-------+-------+-------+-----------+
26261 * D8SUM, D8SUMC:
26262 * 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
26263 * +-----------+---+---+-------+-------+-------+-------+-----------+
26264 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL14|
26265 * +-----------+---+---+-------+-------+-------+-------+-----------+
26268 static void decode_opc_mxu__pool14(CPUMIPSState *env, DisasContext *ctx)
26270 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26272 switch (opcode) {
26273 case OPC_MXU_Q8ADDE:
26274 /* TODO: Implement emulation of Q8ADDE instruction. */
26275 MIPS_INVAL("OPC_MXU_Q8ADDE");
26276 generate_exception_end(ctx, EXCP_RI);
26277 break;
26278 case OPC_MXU_D8SUM:
26279 /* TODO: Implement emulation of D8SUM instruction. */
26280 MIPS_INVAL("OPC_MXU_D8SUM");
26281 generate_exception_end(ctx, EXCP_RI);
26282 break;
26283 case OPC_MXU_D8SUMC:
26284 /* TODO: Implement emulation of D8SUMC instruction. */
26285 MIPS_INVAL("OPC_MXU_D8SUMC");
26286 generate_exception_end(ctx, EXCP_RI);
26287 break;
26288 default:
26289 MIPS_INVAL("decode_opc_mxu");
26290 generate_exception_end(ctx, EXCP_RI);
26291 break;
26297 * Decode MXU pool15
26299 * S32MUL, S32MULU, S32EXTRV:
26300 * 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
26301 * +-----------+---------+---------+---+-------+-------+-----------+
26302 * | SPECIAL2 | rs | rt |x x| XRd | XRa |MXU__POOL15|
26303 * +-----------+---------+---------+---+-------+-------+-----------+
26305 * S32EXTR:
26306 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26307 * +-----------+---------+---------+---+-------+-------+-----------+
26308 * | SPECIAL2 | rb | sft5 |x x| XRd | XRa |MXU__POOL15|
26309 * +-----------+---------+---------+---+-------+-------+-----------+
26312 static void decode_opc_mxu__pool15(CPUMIPSState *env, DisasContext *ctx)
26314 uint32_t opcode = extract32(ctx->opcode, 14, 2);
26316 switch (opcode) {
26317 case OPC_MXU_S32MUL:
26318 /* TODO: Implement emulation of S32MUL instruction. */
26319 MIPS_INVAL("OPC_MXU_S32MUL");
26320 generate_exception_end(ctx, EXCP_RI);
26321 break;
26322 case OPC_MXU_S32MULU:
26323 /* TODO: Implement emulation of S32MULU instruction. */
26324 MIPS_INVAL("OPC_MXU_S32MULU");
26325 generate_exception_end(ctx, EXCP_RI);
26326 break;
26327 case OPC_MXU_S32EXTR:
26328 /* TODO: Implement emulation of S32EXTR instruction. */
26329 MIPS_INVAL("OPC_MXU_S32EXTR");
26330 generate_exception_end(ctx, EXCP_RI);
26331 break;
26332 case OPC_MXU_S32EXTRV:
26333 /* TODO: Implement emulation of S32EXTRV instruction. */
26334 MIPS_INVAL("OPC_MXU_S32EXTRV");
26335 generate_exception_end(ctx, EXCP_RI);
26336 break;
26337 default:
26338 MIPS_INVAL("decode_opc_mxu");
26339 generate_exception_end(ctx, EXCP_RI);
26340 break;
26346 * Decode MXU pool16
26348 * D32SARW:
26349 * 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
26350 * +-----------+---------+-----+-------+-------+-------+-----------+
26351 * | SPECIAL2 | rb |x x x| XRc | XRb | XRa |MXU__POOL16|
26352 * +-----------+---------+-----+-------+-------+-------+-----------+
26354 * S32ALN:
26355 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26356 * +-----------+---------+-----+-------+-------+-------+-----------+
26357 * | SPECIAL2 | rs |x x x| XRc | XRb | XRa |MXU__POOL16|
26358 * +-----------+---------+-----+-------+-------+-------+-----------+
26360 * S32ALNI:
26361 * 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
26362 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26363 * | SPECIAL2 | s3 |0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26364 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26366 * S32LUI:
26367 * 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
26368 * +-----------+-----+---+-----+-------+---------------+-----------+
26369 * | SPECIAL2 |optn3|0 0|x x x| XRc | s8 |MXU__POOL16|
26370 * +-----------+-----+---+-----+-------+---------------+-----------+
26372 * S32NOR, S32AND, S32OR, S32XOR:
26373 * 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
26374 * +-----------+---------+-----+-------+-------+-------+-----------+
26375 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26376 * +-----------+---------+-----+-------+-------+-------+-----------+
26379 static void decode_opc_mxu__pool16(CPUMIPSState *env, DisasContext *ctx)
26381 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26383 switch (opcode) {
26384 case OPC_MXU_D32SARW:
26385 /* TODO: Implement emulation of D32SARW instruction. */
26386 MIPS_INVAL("OPC_MXU_D32SARW");
26387 generate_exception_end(ctx, EXCP_RI);
26388 break;
26389 case OPC_MXU_S32ALN:
26390 /* TODO: Implement emulation of S32ALN instruction. */
26391 MIPS_INVAL("OPC_MXU_S32ALN");
26392 generate_exception_end(ctx, EXCP_RI);
26393 break;
26394 case OPC_MXU_S32ALNI:
26395 gen_mxu_S32ALNI(ctx);
26396 break;
26397 case OPC_MXU_S32LUI:
26398 /* TODO: Implement emulation of S32LUI instruction. */
26399 MIPS_INVAL("OPC_MXU_S32LUI");
26400 generate_exception_end(ctx, EXCP_RI);
26401 break;
26402 case OPC_MXU_S32NOR:
26403 gen_mxu_S32NOR(ctx);
26404 break;
26405 case OPC_MXU_S32AND:
26406 gen_mxu_S32AND(ctx);
26407 break;
26408 case OPC_MXU_S32OR:
26409 gen_mxu_S32OR(ctx);
26410 break;
26411 case OPC_MXU_S32XOR:
26412 gen_mxu_S32XOR(ctx);
26413 break;
26414 default:
26415 MIPS_INVAL("decode_opc_mxu");
26416 generate_exception_end(ctx, EXCP_RI);
26417 break;
26423 * Decode MXU pool17
26425 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26426 * +-----------+---------+---------+---+---------+-----+-----------+
26427 * | SPECIAL2 | rs | rt |0 0| rd |x x x|MXU__POOL15|
26428 * +-----------+---------+---------+---+---------+-----+-----------+
26431 static void decode_opc_mxu__pool17(CPUMIPSState *env, DisasContext *ctx)
26433 uint32_t opcode = extract32(ctx->opcode, 6, 2);
26435 switch (opcode) {
26436 case OPC_MXU_LXW:
26437 /* TODO: Implement emulation of LXW instruction. */
26438 MIPS_INVAL("OPC_MXU_LXW");
26439 generate_exception_end(ctx, EXCP_RI);
26440 break;
26441 case OPC_MXU_LXH:
26442 /* TODO: Implement emulation of LXH instruction. */
26443 MIPS_INVAL("OPC_MXU_LXH");
26444 generate_exception_end(ctx, EXCP_RI);
26445 break;
26446 case OPC_MXU_LXHU:
26447 /* TODO: Implement emulation of LXHU instruction. */
26448 MIPS_INVAL("OPC_MXU_LXHU");
26449 generate_exception_end(ctx, EXCP_RI);
26450 break;
26451 case OPC_MXU_LXB:
26452 /* TODO: Implement emulation of LXB instruction. */
26453 MIPS_INVAL("OPC_MXU_LXB");
26454 generate_exception_end(ctx, EXCP_RI);
26455 break;
26456 case OPC_MXU_LXBU:
26457 /* TODO: Implement emulation of LXBU instruction. */
26458 MIPS_INVAL("OPC_MXU_LXBU");
26459 generate_exception_end(ctx, EXCP_RI);
26460 break;
26461 default:
26462 MIPS_INVAL("decode_opc_mxu");
26463 generate_exception_end(ctx, EXCP_RI);
26464 break;
26469 * Decode MXU pool18
26471 * 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
26472 * +-----------+---------+-----+-------+-------+-------+-----------+
26473 * | SPECIAL2 | rb |x x x| XRd | XRa |0 0 0 0|MXU__POOL18|
26474 * +-----------+---------+-----+-------+-------+-------+-----------+
26477 static void decode_opc_mxu__pool18(CPUMIPSState *env, DisasContext *ctx)
26479 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26481 switch (opcode) {
26482 case OPC_MXU_D32SLLV:
26483 /* TODO: Implement emulation of D32SLLV instruction. */
26484 MIPS_INVAL("OPC_MXU_D32SLLV");
26485 generate_exception_end(ctx, EXCP_RI);
26486 break;
26487 case OPC_MXU_D32SLRV:
26488 /* TODO: Implement emulation of D32SLRV instruction. */
26489 MIPS_INVAL("OPC_MXU_D32SLRV");
26490 generate_exception_end(ctx, EXCP_RI);
26491 break;
26492 case OPC_MXU_D32SARV:
26493 /* TODO: Implement emulation of D32SARV instruction. */
26494 MIPS_INVAL("OPC_MXU_D32SARV");
26495 generate_exception_end(ctx, EXCP_RI);
26496 break;
26497 case OPC_MXU_Q16SLLV:
26498 /* TODO: Implement emulation of Q16SLLV instruction. */
26499 MIPS_INVAL("OPC_MXU_Q16SLLV");
26500 generate_exception_end(ctx, EXCP_RI);
26501 break;
26502 case OPC_MXU_Q16SLRV:
26503 /* TODO: Implement emulation of Q16SLRV instruction. */
26504 MIPS_INVAL("OPC_MXU_Q16SLRV");
26505 generate_exception_end(ctx, EXCP_RI);
26506 break;
26507 case OPC_MXU_Q16SARV:
26508 /* TODO: Implement emulation of Q16SARV instruction. */
26509 MIPS_INVAL("OPC_MXU_Q16SARV");
26510 generate_exception_end(ctx, EXCP_RI);
26511 break;
26512 default:
26513 MIPS_INVAL("decode_opc_mxu");
26514 generate_exception_end(ctx, EXCP_RI);
26515 break;
26521 * Decode MXU pool19
26523 * 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
26524 * +-----------+---+---+-------+-------+-------+-------+-----------+
26525 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL19|
26526 * +-----------+---+---+-------+-------+-------+-------+-----------+
26529 static void decode_opc_mxu__pool19(CPUMIPSState *env, DisasContext *ctx)
26531 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26533 switch (opcode) {
26534 case OPC_MXU_Q8MUL:
26535 case OPC_MXU_Q8MULSU:
26536 gen_mxu_q8mul_q8mulsu(ctx);
26537 break;
26538 default:
26539 MIPS_INVAL("decode_opc_mxu");
26540 generate_exception_end(ctx, EXCP_RI);
26541 break;
26547 * Decode MXU pool20
26549 * 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
26550 * +-----------+---------+-----+-------+-------+-------+-----------+
26551 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL20|
26552 * +-----------+---------+-----+-------+-------+-------+-----------+
26555 static void decode_opc_mxu__pool20(CPUMIPSState *env, DisasContext *ctx)
26557 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26559 switch (opcode) {
26560 case OPC_MXU_Q8MOVZ:
26561 /* TODO: Implement emulation of Q8MOVZ instruction. */
26562 MIPS_INVAL("OPC_MXU_Q8MOVZ");
26563 generate_exception_end(ctx, EXCP_RI);
26564 break;
26565 case OPC_MXU_Q8MOVN:
26566 /* TODO: Implement emulation of Q8MOVN instruction. */
26567 MIPS_INVAL("OPC_MXU_Q8MOVN");
26568 generate_exception_end(ctx, EXCP_RI);
26569 break;
26570 case OPC_MXU_D16MOVZ:
26571 /* TODO: Implement emulation of D16MOVZ instruction. */
26572 MIPS_INVAL("OPC_MXU_D16MOVZ");
26573 generate_exception_end(ctx, EXCP_RI);
26574 break;
26575 case OPC_MXU_D16MOVN:
26576 /* TODO: Implement emulation of D16MOVN instruction. */
26577 MIPS_INVAL("OPC_MXU_D16MOVN");
26578 generate_exception_end(ctx, EXCP_RI);
26579 break;
26580 case OPC_MXU_S32MOVZ:
26581 /* TODO: Implement emulation of S32MOVZ instruction. */
26582 MIPS_INVAL("OPC_MXU_S32MOVZ");
26583 generate_exception_end(ctx, EXCP_RI);
26584 break;
26585 case OPC_MXU_S32MOVN:
26586 /* TODO: Implement emulation of S32MOVN instruction. */
26587 MIPS_INVAL("OPC_MXU_S32MOVN");
26588 generate_exception_end(ctx, EXCP_RI);
26589 break;
26590 default:
26591 MIPS_INVAL("decode_opc_mxu");
26592 generate_exception_end(ctx, EXCP_RI);
26593 break;
26599 * Decode MXU pool21
26601 * 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
26602 * +-----------+---+---+-------+-------+-------+-------+-----------+
26603 * | SPECIAL2 |an2|x x| XRd | XRc | XRb | XRa |MXU__POOL21|
26604 * +-----------+---+---+-------+-------+-------+-------+-----------+
26607 static void decode_opc_mxu__pool21(CPUMIPSState *env, DisasContext *ctx)
26609 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26611 switch (opcode) {
26612 case OPC_MXU_Q8MAC:
26613 /* TODO: Implement emulation of Q8MAC instruction. */
26614 MIPS_INVAL("OPC_MXU_Q8MAC");
26615 generate_exception_end(ctx, EXCP_RI);
26616 break;
26617 case OPC_MXU_Q8MACSU:
26618 /* TODO: Implement emulation of Q8MACSU instruction. */
26619 MIPS_INVAL("OPC_MXU_Q8MACSU");
26620 generate_exception_end(ctx, EXCP_RI);
26621 break;
26622 default:
26623 MIPS_INVAL("decode_opc_mxu");
26624 generate_exception_end(ctx, EXCP_RI);
26625 break;
26631 * Main MXU decoding function
26633 * 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
26634 * +-----------+---------------------------------------+-----------+
26635 * | SPECIAL2 | |x x x x x x|
26636 * +-----------+---------------------------------------+-----------+
26639 static void decode_opc_mxu(CPUMIPSState *env, DisasContext *ctx)
26642 * TODO: Investigate necessity of including handling of
26643 * CLZ, CLO, SDBB in this function, as they belong to
26644 * SPECIAL2 opcode space for regular pre-R6 MIPS ISAs.
26646 uint32_t opcode = extract32(ctx->opcode, 0, 6);
26648 if (opcode == OPC__MXU_MUL) {
26649 uint32_t rs, rt, rd, op1;
26651 rs = extract32(ctx->opcode, 21, 5);
26652 rt = extract32(ctx->opcode, 16, 5);
26653 rd = extract32(ctx->opcode, 11, 5);
26654 op1 = MASK_SPECIAL2(ctx->opcode);
26656 gen_arith(ctx, op1, rd, rs, rt);
26658 return;
26661 if (opcode == OPC_MXU_S32M2I) {
26662 gen_mxu_s32m2i(ctx);
26663 return;
26666 if (opcode == OPC_MXU_S32I2M) {
26667 gen_mxu_s32i2m(ctx);
26668 return;
26672 TCGv t_mxu_cr = tcg_temp_new();
26673 TCGLabel *l_exit = gen_new_label();
26675 gen_load_mxu_cr(t_mxu_cr);
26676 tcg_gen_andi_tl(t_mxu_cr, t_mxu_cr, MXU_CR_MXU_EN);
26677 tcg_gen_brcondi_tl(TCG_COND_NE, t_mxu_cr, MXU_CR_MXU_EN, l_exit);
26679 switch (opcode) {
26680 case OPC_MXU_S32MADD:
26681 /* TODO: Implement emulation of S32MADD instruction. */
26682 MIPS_INVAL("OPC_MXU_S32MADD");
26683 generate_exception_end(ctx, EXCP_RI);
26684 break;
26685 case OPC_MXU_S32MADDU:
26686 /* TODO: Implement emulation of S32MADDU instruction. */
26687 MIPS_INVAL("OPC_MXU_S32MADDU");
26688 generate_exception_end(ctx, EXCP_RI);
26689 break;
26690 case OPC_MXU__POOL00:
26691 decode_opc_mxu__pool00(env, ctx);
26692 break;
26693 case OPC_MXU_S32MSUB:
26694 /* TODO: Implement emulation of S32MSUB instruction. */
26695 MIPS_INVAL("OPC_MXU_S32MSUB");
26696 generate_exception_end(ctx, EXCP_RI);
26697 break;
26698 case OPC_MXU_S32MSUBU:
26699 /* TODO: Implement emulation of S32MSUBU instruction. */
26700 MIPS_INVAL("OPC_MXU_S32MSUBU");
26701 generate_exception_end(ctx, EXCP_RI);
26702 break;
26703 case OPC_MXU__POOL01:
26704 decode_opc_mxu__pool01(env, ctx);
26705 break;
26706 case OPC_MXU__POOL02:
26707 decode_opc_mxu__pool02(env, ctx);
26708 break;
26709 case OPC_MXU_D16MUL:
26710 gen_mxu_d16mul(ctx);
26711 break;
26712 case OPC_MXU__POOL03:
26713 decode_opc_mxu__pool03(env, ctx);
26714 break;
26715 case OPC_MXU_D16MAC:
26716 gen_mxu_d16mac(ctx);
26717 break;
26718 case OPC_MXU_D16MACF:
26719 /* TODO: Implement emulation of D16MACF instruction. */
26720 MIPS_INVAL("OPC_MXU_D16MACF");
26721 generate_exception_end(ctx, EXCP_RI);
26722 break;
26723 case OPC_MXU_D16MADL:
26724 /* TODO: Implement emulation of D16MADL instruction. */
26725 MIPS_INVAL("OPC_MXU_D16MADL");
26726 generate_exception_end(ctx, EXCP_RI);
26727 break;
26728 case OPC_MXU_S16MAD:
26729 /* TODO: Implement emulation of S16MAD instruction. */
26730 MIPS_INVAL("OPC_MXU_S16MAD");
26731 generate_exception_end(ctx, EXCP_RI);
26732 break;
26733 case OPC_MXU_Q16ADD:
26734 /* TODO: Implement emulation of Q16ADD instruction. */
26735 MIPS_INVAL("OPC_MXU_Q16ADD");
26736 generate_exception_end(ctx, EXCP_RI);
26737 break;
26738 case OPC_MXU_D16MACE:
26739 /* TODO: Implement emulation of D16MACE instruction. */
26740 MIPS_INVAL("OPC_MXU_D16MACE");
26741 generate_exception_end(ctx, EXCP_RI);
26742 break;
26743 case OPC_MXU__POOL04:
26744 decode_opc_mxu__pool04(env, ctx);
26745 break;
26746 case OPC_MXU__POOL05:
26747 decode_opc_mxu__pool05(env, ctx);
26748 break;
26749 case OPC_MXU__POOL06:
26750 decode_opc_mxu__pool06(env, ctx);
26751 break;
26752 case OPC_MXU__POOL07:
26753 decode_opc_mxu__pool07(env, ctx);
26754 break;
26755 case OPC_MXU__POOL08:
26756 decode_opc_mxu__pool08(env, ctx);
26757 break;
26758 case OPC_MXU__POOL09:
26759 decode_opc_mxu__pool09(env, ctx);
26760 break;
26761 case OPC_MXU__POOL10:
26762 decode_opc_mxu__pool10(env, ctx);
26763 break;
26764 case OPC_MXU__POOL11:
26765 decode_opc_mxu__pool11(env, ctx);
26766 break;
26767 case OPC_MXU_D32ADD:
26768 /* TODO: Implement emulation of D32ADD instruction. */
26769 MIPS_INVAL("OPC_MXU_D32ADD");
26770 generate_exception_end(ctx, EXCP_RI);
26771 break;
26772 case OPC_MXU__POOL12:
26773 decode_opc_mxu__pool12(env, ctx);
26774 break;
26775 case OPC_MXU__POOL13:
26776 decode_opc_mxu__pool13(env, ctx);
26777 break;
26778 case OPC_MXU__POOL14:
26779 decode_opc_mxu__pool14(env, ctx);
26780 break;
26781 case OPC_MXU_Q8ACCE:
26782 /* TODO: Implement emulation of Q8ACCE instruction. */
26783 MIPS_INVAL("OPC_MXU_Q8ACCE");
26784 generate_exception_end(ctx, EXCP_RI);
26785 break;
26786 case OPC_MXU_S8LDD:
26787 gen_mxu_s8ldd(ctx);
26788 break;
26789 case OPC_MXU_S8STD:
26790 /* TODO: Implement emulation of S8STD instruction. */
26791 MIPS_INVAL("OPC_MXU_S8STD");
26792 generate_exception_end(ctx, EXCP_RI);
26793 break;
26794 case OPC_MXU_S8LDI:
26795 /* TODO: Implement emulation of S8LDI instruction. */
26796 MIPS_INVAL("OPC_MXU_S8LDI");
26797 generate_exception_end(ctx, EXCP_RI);
26798 break;
26799 case OPC_MXU_S8SDI:
26800 /* TODO: Implement emulation of S8SDI instruction. */
26801 MIPS_INVAL("OPC_MXU_S8SDI");
26802 generate_exception_end(ctx, EXCP_RI);
26803 break;
26804 case OPC_MXU__POOL15:
26805 decode_opc_mxu__pool15(env, ctx);
26806 break;
26807 case OPC_MXU__POOL16:
26808 decode_opc_mxu__pool16(env, ctx);
26809 break;
26810 case OPC_MXU__POOL17:
26811 decode_opc_mxu__pool17(env, ctx);
26812 break;
26813 case OPC_MXU_S16LDD:
26814 /* TODO: Implement emulation of S16LDD instruction. */
26815 MIPS_INVAL("OPC_MXU_S16LDD");
26816 generate_exception_end(ctx, EXCP_RI);
26817 break;
26818 case OPC_MXU_S16STD:
26819 /* TODO: Implement emulation of S16STD instruction. */
26820 MIPS_INVAL("OPC_MXU_S16STD");
26821 generate_exception_end(ctx, EXCP_RI);
26822 break;
26823 case OPC_MXU_S16LDI:
26824 /* TODO: Implement emulation of S16LDI instruction. */
26825 MIPS_INVAL("OPC_MXU_S16LDI");
26826 generate_exception_end(ctx, EXCP_RI);
26827 break;
26828 case OPC_MXU_S16SDI:
26829 /* TODO: Implement emulation of S16SDI instruction. */
26830 MIPS_INVAL("OPC_MXU_S16SDI");
26831 generate_exception_end(ctx, EXCP_RI);
26832 break;
26833 case OPC_MXU_D32SLL:
26834 /* TODO: Implement emulation of D32SLL instruction. */
26835 MIPS_INVAL("OPC_MXU_D32SLL");
26836 generate_exception_end(ctx, EXCP_RI);
26837 break;
26838 case OPC_MXU_D32SLR:
26839 /* TODO: Implement emulation of D32SLR instruction. */
26840 MIPS_INVAL("OPC_MXU_D32SLR");
26841 generate_exception_end(ctx, EXCP_RI);
26842 break;
26843 case OPC_MXU_D32SARL:
26844 /* TODO: Implement emulation of D32SARL instruction. */
26845 MIPS_INVAL("OPC_MXU_D32SARL");
26846 generate_exception_end(ctx, EXCP_RI);
26847 break;
26848 case OPC_MXU_D32SAR:
26849 /* TODO: Implement emulation of D32SAR instruction. */
26850 MIPS_INVAL("OPC_MXU_D32SAR");
26851 generate_exception_end(ctx, EXCP_RI);
26852 break;
26853 case OPC_MXU_Q16SLL:
26854 /* TODO: Implement emulation of Q16SLL instruction. */
26855 MIPS_INVAL("OPC_MXU_Q16SLL");
26856 generate_exception_end(ctx, EXCP_RI);
26857 break;
26858 case OPC_MXU_Q16SLR:
26859 /* TODO: Implement emulation of Q16SLR instruction. */
26860 MIPS_INVAL("OPC_MXU_Q16SLR");
26861 generate_exception_end(ctx, EXCP_RI);
26862 break;
26863 case OPC_MXU__POOL18:
26864 decode_opc_mxu__pool18(env, ctx);
26865 break;
26866 case OPC_MXU_Q16SAR:
26867 /* TODO: Implement emulation of Q16SAR instruction. */
26868 MIPS_INVAL("OPC_MXU_Q16SAR");
26869 generate_exception_end(ctx, EXCP_RI);
26870 break;
26871 case OPC_MXU__POOL19:
26872 decode_opc_mxu__pool19(env, ctx);
26873 break;
26874 case OPC_MXU__POOL20:
26875 decode_opc_mxu__pool20(env, ctx);
26876 break;
26877 case OPC_MXU__POOL21:
26878 decode_opc_mxu__pool21(env, ctx);
26879 break;
26880 case OPC_MXU_Q16SCOP:
26881 /* TODO: Implement emulation of Q16SCOP instruction. */
26882 MIPS_INVAL("OPC_MXU_Q16SCOP");
26883 generate_exception_end(ctx, EXCP_RI);
26884 break;
26885 case OPC_MXU_Q8MADL:
26886 /* TODO: Implement emulation of Q8MADL instruction. */
26887 MIPS_INVAL("OPC_MXU_Q8MADL");
26888 generate_exception_end(ctx, EXCP_RI);
26889 break;
26890 case OPC_MXU_S32SFL:
26891 /* TODO: Implement emulation of S32SFL instruction. */
26892 MIPS_INVAL("OPC_MXU_S32SFL");
26893 generate_exception_end(ctx, EXCP_RI);
26894 break;
26895 case OPC_MXU_Q8SAD:
26896 /* TODO: Implement emulation of Q8SAD instruction. */
26897 MIPS_INVAL("OPC_MXU_Q8SAD");
26898 generate_exception_end(ctx, EXCP_RI);
26899 break;
26900 default:
26901 MIPS_INVAL("decode_opc_mxu");
26902 generate_exception_end(ctx, EXCP_RI);
26905 gen_set_label(l_exit);
26906 tcg_temp_free(t_mxu_cr);
26910 #endif /* !defined(TARGET_MIPS64) */
26913 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
26915 int rs, rt, rd;
26916 uint32_t op1;
26918 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26920 rs = (ctx->opcode >> 21) & 0x1f;
26921 rt = (ctx->opcode >> 16) & 0x1f;
26922 rd = (ctx->opcode >> 11) & 0x1f;
26924 op1 = MASK_SPECIAL2(ctx->opcode);
26925 switch (op1) {
26926 case OPC_MADD: /* Multiply and add/sub */
26927 case OPC_MADDU:
26928 case OPC_MSUB:
26929 case OPC_MSUBU:
26930 check_insn(ctx, ISA_MIPS32);
26931 gen_muldiv(ctx, op1, rd & 3, rs, rt);
26932 break;
26933 case OPC_MUL:
26934 gen_arith(ctx, op1, rd, rs, rt);
26935 break;
26936 case OPC_DIV_G_2F:
26937 case OPC_DIVU_G_2F:
26938 case OPC_MULT_G_2F:
26939 case OPC_MULTU_G_2F:
26940 case OPC_MOD_G_2F:
26941 case OPC_MODU_G_2F:
26942 check_insn(ctx, INSN_LOONGSON2F);
26943 gen_loongson_integer(ctx, op1, rd, rs, rt);
26944 break;
26945 case OPC_CLO:
26946 case OPC_CLZ:
26947 check_insn(ctx, ISA_MIPS32);
26948 gen_cl(ctx, op1, rd, rs);
26949 break;
26950 case OPC_SDBBP:
26951 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
26952 gen_helper_do_semihosting(cpu_env);
26953 } else {
26955 * XXX: not clear which exception should be raised
26956 * when in debug mode...
26958 check_insn(ctx, ISA_MIPS32);
26959 generate_exception_end(ctx, EXCP_DBp);
26961 break;
26962 #if defined(TARGET_MIPS64)
26963 case OPC_DCLO:
26964 case OPC_DCLZ:
26965 check_insn(ctx, ISA_MIPS64);
26966 check_mips_64(ctx);
26967 gen_cl(ctx, op1, rd, rs);
26968 break;
26969 case OPC_DMULT_G_2F:
26970 case OPC_DMULTU_G_2F:
26971 case OPC_DDIV_G_2F:
26972 case OPC_DDIVU_G_2F:
26973 case OPC_DMOD_G_2F:
26974 case OPC_DMODU_G_2F:
26975 check_insn(ctx, INSN_LOONGSON2F);
26976 gen_loongson_integer(ctx, op1, rd, rs, rt);
26977 break;
26978 #endif
26979 default: /* Invalid */
26980 MIPS_INVAL("special2_legacy");
26981 generate_exception_end(ctx, EXCP_RI);
26982 break;
26986 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
26988 int rs, rt, rd, sa;
26989 uint32_t op1, op2;
26990 int16_t imm;
26992 rs = (ctx->opcode >> 21) & 0x1f;
26993 rt = (ctx->opcode >> 16) & 0x1f;
26994 rd = (ctx->opcode >> 11) & 0x1f;
26995 sa = (ctx->opcode >> 6) & 0x1f;
26996 imm = (int16_t)ctx->opcode >> 7;
26998 op1 = MASK_SPECIAL3(ctx->opcode);
26999 switch (op1) {
27000 case R6_OPC_PREF:
27001 if (rt >= 24) {
27002 /* hint codes 24-31 are reserved and signal RI */
27003 generate_exception_end(ctx, EXCP_RI);
27005 /* Treat as NOP. */
27006 break;
27007 case R6_OPC_CACHE:
27008 check_cp0_enabled(ctx);
27009 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
27010 gen_cache_operation(ctx, rt, rs, imm);
27012 break;
27013 case R6_OPC_SC:
27014 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
27015 break;
27016 case R6_OPC_LL:
27017 gen_ld(ctx, op1, rt, rs, imm);
27018 break;
27019 case OPC_BSHFL:
27021 if (rd == 0) {
27022 /* Treat as NOP. */
27023 break;
27025 op2 = MASK_BSHFL(ctx->opcode);
27026 switch (op2) {
27027 case OPC_ALIGN:
27028 case OPC_ALIGN_1:
27029 case OPC_ALIGN_2:
27030 case OPC_ALIGN_3:
27031 gen_align(ctx, 32, rd, rs, rt, sa & 3);
27032 break;
27033 case OPC_BITSWAP:
27034 gen_bitswap(ctx, op2, rd, rt);
27035 break;
27038 break;
27039 #if defined(TARGET_MIPS64)
27040 case R6_OPC_SCD:
27041 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
27042 break;
27043 case R6_OPC_LLD:
27044 gen_ld(ctx, op1, rt, rs, imm);
27045 break;
27046 case OPC_DBSHFL:
27047 check_mips_64(ctx);
27049 if (rd == 0) {
27050 /* Treat as NOP. */
27051 break;
27053 op2 = MASK_DBSHFL(ctx->opcode);
27054 switch (op2) {
27055 case OPC_DALIGN:
27056 case OPC_DALIGN_1:
27057 case OPC_DALIGN_2:
27058 case OPC_DALIGN_3:
27059 case OPC_DALIGN_4:
27060 case OPC_DALIGN_5:
27061 case OPC_DALIGN_6:
27062 case OPC_DALIGN_7:
27063 gen_align(ctx, 64, rd, rs, rt, sa & 7);
27064 break;
27065 case OPC_DBITSWAP:
27066 gen_bitswap(ctx, op2, rd, rt);
27067 break;
27071 break;
27072 #endif
27073 default: /* Invalid */
27074 MIPS_INVAL("special3_r6");
27075 generate_exception_end(ctx, EXCP_RI);
27076 break;
27080 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
27082 int rs, rt, rd;
27083 uint32_t op1, op2;
27085 rs = (ctx->opcode >> 21) & 0x1f;
27086 rt = (ctx->opcode >> 16) & 0x1f;
27087 rd = (ctx->opcode >> 11) & 0x1f;
27089 op1 = MASK_SPECIAL3(ctx->opcode);
27090 switch (op1) {
27091 case OPC_DIV_G_2E:
27092 case OPC_DIVU_G_2E:
27093 case OPC_MOD_G_2E:
27094 case OPC_MODU_G_2E:
27095 case OPC_MULT_G_2E:
27096 case OPC_MULTU_G_2E:
27098 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
27099 * the same mask and op1.
27101 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
27102 op2 = MASK_ADDUH_QB(ctx->opcode);
27103 switch (op2) {
27104 case OPC_ADDUH_QB:
27105 case OPC_ADDUH_R_QB:
27106 case OPC_ADDQH_PH:
27107 case OPC_ADDQH_R_PH:
27108 case OPC_ADDQH_W:
27109 case OPC_ADDQH_R_W:
27110 case OPC_SUBUH_QB:
27111 case OPC_SUBUH_R_QB:
27112 case OPC_SUBQH_PH:
27113 case OPC_SUBQH_R_PH:
27114 case OPC_SUBQH_W:
27115 case OPC_SUBQH_R_W:
27116 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27117 break;
27118 case OPC_MUL_PH:
27119 case OPC_MUL_S_PH:
27120 case OPC_MULQ_S_W:
27121 case OPC_MULQ_RS_W:
27122 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27123 break;
27124 default:
27125 MIPS_INVAL("MASK ADDUH.QB");
27126 generate_exception_end(ctx, EXCP_RI);
27127 break;
27129 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
27130 gen_loongson_integer(ctx, op1, rd, rs, rt);
27131 } else {
27132 generate_exception_end(ctx, EXCP_RI);
27134 break;
27135 case OPC_LX_DSP:
27136 op2 = MASK_LX(ctx->opcode);
27137 switch (op2) {
27138 #if defined(TARGET_MIPS64)
27139 case OPC_LDX:
27140 #endif
27141 case OPC_LBUX:
27142 case OPC_LHX:
27143 case OPC_LWX:
27144 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
27145 break;
27146 default: /* Invalid */
27147 MIPS_INVAL("MASK LX");
27148 generate_exception_end(ctx, EXCP_RI);
27149 break;
27151 break;
27152 case OPC_ABSQ_S_PH_DSP:
27153 op2 = MASK_ABSQ_S_PH(ctx->opcode);
27154 switch (op2) {
27155 case OPC_ABSQ_S_QB:
27156 case OPC_ABSQ_S_PH:
27157 case OPC_ABSQ_S_W:
27158 case OPC_PRECEQ_W_PHL:
27159 case OPC_PRECEQ_W_PHR:
27160 case OPC_PRECEQU_PH_QBL:
27161 case OPC_PRECEQU_PH_QBR:
27162 case OPC_PRECEQU_PH_QBLA:
27163 case OPC_PRECEQU_PH_QBRA:
27164 case OPC_PRECEU_PH_QBL:
27165 case OPC_PRECEU_PH_QBR:
27166 case OPC_PRECEU_PH_QBLA:
27167 case OPC_PRECEU_PH_QBRA:
27168 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27169 break;
27170 case OPC_BITREV:
27171 case OPC_REPL_QB:
27172 case OPC_REPLV_QB:
27173 case OPC_REPL_PH:
27174 case OPC_REPLV_PH:
27175 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27176 break;
27177 default:
27178 MIPS_INVAL("MASK ABSQ_S.PH");
27179 generate_exception_end(ctx, EXCP_RI);
27180 break;
27182 break;
27183 case OPC_ADDU_QB_DSP:
27184 op2 = MASK_ADDU_QB(ctx->opcode);
27185 switch (op2) {
27186 case OPC_ADDQ_PH:
27187 case OPC_ADDQ_S_PH:
27188 case OPC_ADDQ_S_W:
27189 case OPC_ADDU_QB:
27190 case OPC_ADDU_S_QB:
27191 case OPC_ADDU_PH:
27192 case OPC_ADDU_S_PH:
27193 case OPC_SUBQ_PH:
27194 case OPC_SUBQ_S_PH:
27195 case OPC_SUBQ_S_W:
27196 case OPC_SUBU_QB:
27197 case OPC_SUBU_S_QB:
27198 case OPC_SUBU_PH:
27199 case OPC_SUBU_S_PH:
27200 case OPC_ADDSC:
27201 case OPC_ADDWC:
27202 case OPC_MODSUB:
27203 case OPC_RADDU_W_QB:
27204 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27205 break;
27206 case OPC_MULEU_S_PH_QBL:
27207 case OPC_MULEU_S_PH_QBR:
27208 case OPC_MULQ_RS_PH:
27209 case OPC_MULEQ_S_W_PHL:
27210 case OPC_MULEQ_S_W_PHR:
27211 case OPC_MULQ_S_PH:
27212 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27213 break;
27214 default: /* Invalid */
27215 MIPS_INVAL("MASK ADDU.QB");
27216 generate_exception_end(ctx, EXCP_RI);
27217 break;
27220 break;
27221 case OPC_CMPU_EQ_QB_DSP:
27222 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
27223 switch (op2) {
27224 case OPC_PRECR_SRA_PH_W:
27225 case OPC_PRECR_SRA_R_PH_W:
27226 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
27227 break;
27228 case OPC_PRECR_QB_PH:
27229 case OPC_PRECRQ_QB_PH:
27230 case OPC_PRECRQ_PH_W:
27231 case OPC_PRECRQ_RS_PH_W:
27232 case OPC_PRECRQU_S_QB_PH:
27233 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27234 break;
27235 case OPC_CMPU_EQ_QB:
27236 case OPC_CMPU_LT_QB:
27237 case OPC_CMPU_LE_QB:
27238 case OPC_CMP_EQ_PH:
27239 case OPC_CMP_LT_PH:
27240 case OPC_CMP_LE_PH:
27241 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
27242 break;
27243 case OPC_CMPGU_EQ_QB:
27244 case OPC_CMPGU_LT_QB:
27245 case OPC_CMPGU_LE_QB:
27246 case OPC_CMPGDU_EQ_QB:
27247 case OPC_CMPGDU_LT_QB:
27248 case OPC_CMPGDU_LE_QB:
27249 case OPC_PICK_QB:
27250 case OPC_PICK_PH:
27251 case OPC_PACKRL_PH:
27252 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27253 break;
27254 default: /* Invalid */
27255 MIPS_INVAL("MASK CMPU.EQ.QB");
27256 generate_exception_end(ctx, EXCP_RI);
27257 break;
27259 break;
27260 case OPC_SHLL_QB_DSP:
27261 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27262 break;
27263 case OPC_DPA_W_PH_DSP:
27264 op2 = MASK_DPA_W_PH(ctx->opcode);
27265 switch (op2) {
27266 case OPC_DPAU_H_QBL:
27267 case OPC_DPAU_H_QBR:
27268 case OPC_DPSU_H_QBL:
27269 case OPC_DPSU_H_QBR:
27270 case OPC_DPA_W_PH:
27271 case OPC_DPAX_W_PH:
27272 case OPC_DPAQ_S_W_PH:
27273 case OPC_DPAQX_S_W_PH:
27274 case OPC_DPAQX_SA_W_PH:
27275 case OPC_DPS_W_PH:
27276 case OPC_DPSX_W_PH:
27277 case OPC_DPSQ_S_W_PH:
27278 case OPC_DPSQX_S_W_PH:
27279 case OPC_DPSQX_SA_W_PH:
27280 case OPC_MULSAQ_S_W_PH:
27281 case OPC_DPAQ_SA_L_W:
27282 case OPC_DPSQ_SA_L_W:
27283 case OPC_MAQ_S_W_PHL:
27284 case OPC_MAQ_S_W_PHR:
27285 case OPC_MAQ_SA_W_PHL:
27286 case OPC_MAQ_SA_W_PHR:
27287 case OPC_MULSA_W_PH:
27288 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27289 break;
27290 default: /* Invalid */
27291 MIPS_INVAL("MASK DPAW.PH");
27292 generate_exception_end(ctx, EXCP_RI);
27293 break;
27295 break;
27296 case OPC_INSV_DSP:
27297 op2 = MASK_INSV(ctx->opcode);
27298 switch (op2) {
27299 case OPC_INSV:
27300 check_dsp(ctx);
27302 TCGv t0, t1;
27304 if (rt == 0) {
27305 break;
27308 t0 = tcg_temp_new();
27309 t1 = tcg_temp_new();
27311 gen_load_gpr(t0, rt);
27312 gen_load_gpr(t1, rs);
27314 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
27316 tcg_temp_free(t0);
27317 tcg_temp_free(t1);
27318 break;
27320 default: /* Invalid */
27321 MIPS_INVAL("MASK INSV");
27322 generate_exception_end(ctx, EXCP_RI);
27323 break;
27325 break;
27326 case OPC_APPEND_DSP:
27327 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27328 break;
27329 case OPC_EXTR_W_DSP:
27330 op2 = MASK_EXTR_W(ctx->opcode);
27331 switch (op2) {
27332 case OPC_EXTR_W:
27333 case OPC_EXTR_R_W:
27334 case OPC_EXTR_RS_W:
27335 case OPC_EXTR_S_H:
27336 case OPC_EXTRV_S_H:
27337 case OPC_EXTRV_W:
27338 case OPC_EXTRV_R_W:
27339 case OPC_EXTRV_RS_W:
27340 case OPC_EXTP:
27341 case OPC_EXTPV:
27342 case OPC_EXTPDP:
27343 case OPC_EXTPDPV:
27344 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27345 break;
27346 case OPC_RDDSP:
27347 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
27348 break;
27349 case OPC_SHILO:
27350 case OPC_SHILOV:
27351 case OPC_MTHLIP:
27352 case OPC_WRDSP:
27353 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27354 break;
27355 default: /* Invalid */
27356 MIPS_INVAL("MASK EXTR.W");
27357 generate_exception_end(ctx, EXCP_RI);
27358 break;
27360 break;
27361 #if defined(TARGET_MIPS64)
27362 case OPC_DDIV_G_2E:
27363 case OPC_DDIVU_G_2E:
27364 case OPC_DMULT_G_2E:
27365 case OPC_DMULTU_G_2E:
27366 case OPC_DMOD_G_2E:
27367 case OPC_DMODU_G_2E:
27368 check_insn(ctx, INSN_LOONGSON2E);
27369 gen_loongson_integer(ctx, op1, rd, rs, rt);
27370 break;
27371 case OPC_ABSQ_S_QH_DSP:
27372 op2 = MASK_ABSQ_S_QH(ctx->opcode);
27373 switch (op2) {
27374 case OPC_PRECEQ_L_PWL:
27375 case OPC_PRECEQ_L_PWR:
27376 case OPC_PRECEQ_PW_QHL:
27377 case OPC_PRECEQ_PW_QHR:
27378 case OPC_PRECEQ_PW_QHLA:
27379 case OPC_PRECEQ_PW_QHRA:
27380 case OPC_PRECEQU_QH_OBL:
27381 case OPC_PRECEQU_QH_OBR:
27382 case OPC_PRECEQU_QH_OBLA:
27383 case OPC_PRECEQU_QH_OBRA:
27384 case OPC_PRECEU_QH_OBL:
27385 case OPC_PRECEU_QH_OBR:
27386 case OPC_PRECEU_QH_OBLA:
27387 case OPC_PRECEU_QH_OBRA:
27388 case OPC_ABSQ_S_OB:
27389 case OPC_ABSQ_S_PW:
27390 case OPC_ABSQ_S_QH:
27391 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27392 break;
27393 case OPC_REPL_OB:
27394 case OPC_REPL_PW:
27395 case OPC_REPL_QH:
27396 case OPC_REPLV_OB:
27397 case OPC_REPLV_PW:
27398 case OPC_REPLV_QH:
27399 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27400 break;
27401 default: /* Invalid */
27402 MIPS_INVAL("MASK ABSQ_S.QH");
27403 generate_exception_end(ctx, EXCP_RI);
27404 break;
27406 break;
27407 case OPC_ADDU_OB_DSP:
27408 op2 = MASK_ADDU_OB(ctx->opcode);
27409 switch (op2) {
27410 case OPC_RADDU_L_OB:
27411 case OPC_SUBQ_PW:
27412 case OPC_SUBQ_S_PW:
27413 case OPC_SUBQ_QH:
27414 case OPC_SUBQ_S_QH:
27415 case OPC_SUBU_OB:
27416 case OPC_SUBU_S_OB:
27417 case OPC_SUBU_QH:
27418 case OPC_SUBU_S_QH:
27419 case OPC_SUBUH_OB:
27420 case OPC_SUBUH_R_OB:
27421 case OPC_ADDQ_PW:
27422 case OPC_ADDQ_S_PW:
27423 case OPC_ADDQ_QH:
27424 case OPC_ADDQ_S_QH:
27425 case OPC_ADDU_OB:
27426 case OPC_ADDU_S_OB:
27427 case OPC_ADDU_QH:
27428 case OPC_ADDU_S_QH:
27429 case OPC_ADDUH_OB:
27430 case OPC_ADDUH_R_OB:
27431 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27432 break;
27433 case OPC_MULEQ_S_PW_QHL:
27434 case OPC_MULEQ_S_PW_QHR:
27435 case OPC_MULEU_S_QH_OBL:
27436 case OPC_MULEU_S_QH_OBR:
27437 case OPC_MULQ_RS_QH:
27438 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27439 break;
27440 default: /* Invalid */
27441 MIPS_INVAL("MASK ADDU.OB");
27442 generate_exception_end(ctx, EXCP_RI);
27443 break;
27445 break;
27446 case OPC_CMPU_EQ_OB_DSP:
27447 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
27448 switch (op2) {
27449 case OPC_PRECR_SRA_QH_PW:
27450 case OPC_PRECR_SRA_R_QH_PW:
27451 /* Return value is rt. */
27452 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
27453 break;
27454 case OPC_PRECR_OB_QH:
27455 case OPC_PRECRQ_OB_QH:
27456 case OPC_PRECRQ_PW_L:
27457 case OPC_PRECRQ_QH_PW:
27458 case OPC_PRECRQ_RS_QH_PW:
27459 case OPC_PRECRQU_S_OB_QH:
27460 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27461 break;
27462 case OPC_CMPU_EQ_OB:
27463 case OPC_CMPU_LT_OB:
27464 case OPC_CMPU_LE_OB:
27465 case OPC_CMP_EQ_QH:
27466 case OPC_CMP_LT_QH:
27467 case OPC_CMP_LE_QH:
27468 case OPC_CMP_EQ_PW:
27469 case OPC_CMP_LT_PW:
27470 case OPC_CMP_LE_PW:
27471 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
27472 break;
27473 case OPC_CMPGDU_EQ_OB:
27474 case OPC_CMPGDU_LT_OB:
27475 case OPC_CMPGDU_LE_OB:
27476 case OPC_CMPGU_EQ_OB:
27477 case OPC_CMPGU_LT_OB:
27478 case OPC_CMPGU_LE_OB:
27479 case OPC_PACKRL_PW:
27480 case OPC_PICK_OB:
27481 case OPC_PICK_PW:
27482 case OPC_PICK_QH:
27483 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27484 break;
27485 default: /* Invalid */
27486 MIPS_INVAL("MASK CMPU_EQ.OB");
27487 generate_exception_end(ctx, EXCP_RI);
27488 break;
27490 break;
27491 case OPC_DAPPEND_DSP:
27492 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27493 break;
27494 case OPC_DEXTR_W_DSP:
27495 op2 = MASK_DEXTR_W(ctx->opcode);
27496 switch (op2) {
27497 case OPC_DEXTP:
27498 case OPC_DEXTPDP:
27499 case OPC_DEXTPDPV:
27500 case OPC_DEXTPV:
27501 case OPC_DEXTR_L:
27502 case OPC_DEXTR_R_L:
27503 case OPC_DEXTR_RS_L:
27504 case OPC_DEXTR_W:
27505 case OPC_DEXTR_R_W:
27506 case OPC_DEXTR_RS_W:
27507 case OPC_DEXTR_S_H:
27508 case OPC_DEXTRV_L:
27509 case OPC_DEXTRV_R_L:
27510 case OPC_DEXTRV_RS_L:
27511 case OPC_DEXTRV_S_H:
27512 case OPC_DEXTRV_W:
27513 case OPC_DEXTRV_R_W:
27514 case OPC_DEXTRV_RS_W:
27515 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27516 break;
27517 case OPC_DMTHLIP:
27518 case OPC_DSHILO:
27519 case OPC_DSHILOV:
27520 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27521 break;
27522 default: /* Invalid */
27523 MIPS_INVAL("MASK EXTR.W");
27524 generate_exception_end(ctx, EXCP_RI);
27525 break;
27527 break;
27528 case OPC_DPAQ_W_QH_DSP:
27529 op2 = MASK_DPAQ_W_QH(ctx->opcode);
27530 switch (op2) {
27531 case OPC_DPAU_H_OBL:
27532 case OPC_DPAU_H_OBR:
27533 case OPC_DPSU_H_OBL:
27534 case OPC_DPSU_H_OBR:
27535 case OPC_DPA_W_QH:
27536 case OPC_DPAQ_S_W_QH:
27537 case OPC_DPS_W_QH:
27538 case OPC_DPSQ_S_W_QH:
27539 case OPC_MULSAQ_S_W_QH:
27540 case OPC_DPAQ_SA_L_PW:
27541 case OPC_DPSQ_SA_L_PW:
27542 case OPC_MULSAQ_S_L_PW:
27543 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27544 break;
27545 case OPC_MAQ_S_W_QHLL:
27546 case OPC_MAQ_S_W_QHLR:
27547 case OPC_MAQ_S_W_QHRL:
27548 case OPC_MAQ_S_W_QHRR:
27549 case OPC_MAQ_SA_W_QHLL:
27550 case OPC_MAQ_SA_W_QHLR:
27551 case OPC_MAQ_SA_W_QHRL:
27552 case OPC_MAQ_SA_W_QHRR:
27553 case OPC_MAQ_S_L_PWL:
27554 case OPC_MAQ_S_L_PWR:
27555 case OPC_DMADD:
27556 case OPC_DMADDU:
27557 case OPC_DMSUB:
27558 case OPC_DMSUBU:
27559 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27560 break;
27561 default: /* Invalid */
27562 MIPS_INVAL("MASK DPAQ.W.QH");
27563 generate_exception_end(ctx, EXCP_RI);
27564 break;
27566 break;
27567 case OPC_DINSV_DSP:
27568 op2 = MASK_INSV(ctx->opcode);
27569 switch (op2) {
27570 case OPC_DINSV:
27572 TCGv t0, t1;
27574 if (rt == 0) {
27575 break;
27577 check_dsp(ctx);
27579 t0 = tcg_temp_new();
27580 t1 = tcg_temp_new();
27582 gen_load_gpr(t0, rt);
27583 gen_load_gpr(t1, rs);
27585 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
27587 tcg_temp_free(t0);
27588 tcg_temp_free(t1);
27589 break;
27591 default: /* Invalid */
27592 MIPS_INVAL("MASK DINSV");
27593 generate_exception_end(ctx, EXCP_RI);
27594 break;
27596 break;
27597 case OPC_SHLL_OB_DSP:
27598 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27599 break;
27600 #endif
27601 default: /* Invalid */
27602 MIPS_INVAL("special3_legacy");
27603 generate_exception_end(ctx, EXCP_RI);
27604 break;
27609 #if defined(TARGET_MIPS64)
27611 static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx)
27613 uint32_t opc = MASK_MMI0(ctx->opcode);
27615 switch (opc) {
27616 case MMI_OPC_0_PADDW: /* TODO: MMI_OPC_0_PADDW */
27617 case MMI_OPC_0_PSUBW: /* TODO: MMI_OPC_0_PSUBW */
27618 case MMI_OPC_0_PCGTW: /* TODO: MMI_OPC_0_PCGTW */
27619 case MMI_OPC_0_PMAXW: /* TODO: MMI_OPC_0_PMAXW */
27620 case MMI_OPC_0_PADDH: /* TODO: MMI_OPC_0_PADDH */
27621 case MMI_OPC_0_PSUBH: /* TODO: MMI_OPC_0_PSUBH */
27622 case MMI_OPC_0_PCGTH: /* TODO: MMI_OPC_0_PCGTH */
27623 case MMI_OPC_0_PMAXH: /* TODO: MMI_OPC_0_PMAXH */
27624 case MMI_OPC_0_PADDB: /* TODO: MMI_OPC_0_PADDB */
27625 case MMI_OPC_0_PSUBB: /* TODO: MMI_OPC_0_PSUBB */
27626 case MMI_OPC_0_PCGTB: /* TODO: MMI_OPC_0_PCGTB */
27627 case MMI_OPC_0_PADDSW: /* TODO: MMI_OPC_0_PADDSW */
27628 case MMI_OPC_0_PSUBSW: /* TODO: MMI_OPC_0_PSUBSW */
27629 case MMI_OPC_0_PEXTLW: /* TODO: MMI_OPC_0_PEXTLW */
27630 case MMI_OPC_0_PPACW: /* TODO: MMI_OPC_0_PPACW */
27631 case MMI_OPC_0_PADDSH: /* TODO: MMI_OPC_0_PADDSH */
27632 case MMI_OPC_0_PSUBSH: /* TODO: MMI_OPC_0_PSUBSH */
27633 case MMI_OPC_0_PEXTLH: /* TODO: MMI_OPC_0_PEXTLH */
27634 case MMI_OPC_0_PPACH: /* TODO: MMI_OPC_0_PPACH */
27635 case MMI_OPC_0_PADDSB: /* TODO: MMI_OPC_0_PADDSB */
27636 case MMI_OPC_0_PSUBSB: /* TODO: MMI_OPC_0_PSUBSB */
27637 case MMI_OPC_0_PEXTLB: /* TODO: MMI_OPC_0_PEXTLB */
27638 case MMI_OPC_0_PPACB: /* TODO: MMI_OPC_0_PPACB */
27639 case MMI_OPC_0_PEXT5: /* TODO: MMI_OPC_0_PEXT5 */
27640 case MMI_OPC_0_PPAC5: /* TODO: MMI_OPC_0_PPAC5 */
27641 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI0 */
27642 break;
27643 default:
27644 MIPS_INVAL("TX79 MMI class MMI0");
27645 generate_exception_end(ctx, EXCP_RI);
27646 break;
27650 static void decode_mmi1(CPUMIPSState *env, DisasContext *ctx)
27652 uint32_t opc = MASK_MMI1(ctx->opcode);
27654 switch (opc) {
27655 case MMI_OPC_1_PABSW: /* TODO: MMI_OPC_1_PABSW */
27656 case MMI_OPC_1_PCEQW: /* TODO: MMI_OPC_1_PCEQW */
27657 case MMI_OPC_1_PMINW: /* TODO: MMI_OPC_1_PMINW */
27658 case MMI_OPC_1_PADSBH: /* TODO: MMI_OPC_1_PADSBH */
27659 case MMI_OPC_1_PABSH: /* TODO: MMI_OPC_1_PABSH */
27660 case MMI_OPC_1_PCEQH: /* TODO: MMI_OPC_1_PCEQH */
27661 case MMI_OPC_1_PMINH: /* TODO: MMI_OPC_1_PMINH */
27662 case MMI_OPC_1_PCEQB: /* TODO: MMI_OPC_1_PCEQB */
27663 case MMI_OPC_1_PADDUW: /* TODO: MMI_OPC_1_PADDUW */
27664 case MMI_OPC_1_PSUBUW: /* TODO: MMI_OPC_1_PSUBUW */
27665 case MMI_OPC_1_PEXTUW: /* TODO: MMI_OPC_1_PEXTUW */
27666 case MMI_OPC_1_PADDUH: /* TODO: MMI_OPC_1_PADDUH */
27667 case MMI_OPC_1_PSUBUH: /* TODO: MMI_OPC_1_PSUBUH */
27668 case MMI_OPC_1_PEXTUH: /* TODO: MMI_OPC_1_PEXTUH */
27669 case MMI_OPC_1_PADDUB: /* TODO: MMI_OPC_1_PADDUB */
27670 case MMI_OPC_1_PSUBUB: /* TODO: MMI_OPC_1_PSUBUB */
27671 case MMI_OPC_1_PEXTUB: /* TODO: MMI_OPC_1_PEXTUB */
27672 case MMI_OPC_1_QFSRV: /* TODO: MMI_OPC_1_QFSRV */
27673 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI1 */
27674 break;
27675 default:
27676 MIPS_INVAL("TX79 MMI class MMI1");
27677 generate_exception_end(ctx, EXCP_RI);
27678 break;
27682 static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx)
27684 uint32_t opc = MASK_MMI2(ctx->opcode);
27686 switch (opc) {
27687 case MMI_OPC_2_PMADDW: /* TODO: MMI_OPC_2_PMADDW */
27688 case MMI_OPC_2_PSLLVW: /* TODO: MMI_OPC_2_PSLLVW */
27689 case MMI_OPC_2_PSRLVW: /* TODO: MMI_OPC_2_PSRLVW */
27690 case MMI_OPC_2_PMSUBW: /* TODO: MMI_OPC_2_PMSUBW */
27691 case MMI_OPC_2_PMFHI: /* TODO: MMI_OPC_2_PMFHI */
27692 case MMI_OPC_2_PMFLO: /* TODO: MMI_OPC_2_PMFLO */
27693 case MMI_OPC_2_PINTH: /* TODO: MMI_OPC_2_PINTH */
27694 case MMI_OPC_2_PMULTW: /* TODO: MMI_OPC_2_PMULTW */
27695 case MMI_OPC_2_PDIVW: /* TODO: MMI_OPC_2_PDIVW */
27696 case MMI_OPC_2_PMADDH: /* TODO: MMI_OPC_2_PMADDH */
27697 case MMI_OPC_2_PHMADH: /* TODO: MMI_OPC_2_PHMADH */
27698 case MMI_OPC_2_PAND: /* TODO: MMI_OPC_2_PAND */
27699 case MMI_OPC_2_PXOR: /* TODO: MMI_OPC_2_PXOR */
27700 case MMI_OPC_2_PMSUBH: /* TODO: MMI_OPC_2_PMSUBH */
27701 case MMI_OPC_2_PHMSBH: /* TODO: MMI_OPC_2_PHMSBH */
27702 case MMI_OPC_2_PEXEH: /* TODO: MMI_OPC_2_PEXEH */
27703 case MMI_OPC_2_PREVH: /* TODO: MMI_OPC_2_PREVH */
27704 case MMI_OPC_2_PMULTH: /* TODO: MMI_OPC_2_PMULTH */
27705 case MMI_OPC_2_PDIVBW: /* TODO: MMI_OPC_2_PDIVBW */
27706 case MMI_OPC_2_PEXEW: /* TODO: MMI_OPC_2_PEXEW */
27707 case MMI_OPC_2_PROT3W: /* TODO: MMI_OPC_2_PROT3W */
27708 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI2 */
27709 break;
27710 case MMI_OPC_2_PCPYLD:
27711 gen_mmi_pcpyld(ctx);
27712 break;
27713 default:
27714 MIPS_INVAL("TX79 MMI class MMI2");
27715 generate_exception_end(ctx, EXCP_RI);
27716 break;
27720 static void decode_mmi3(CPUMIPSState *env, DisasContext *ctx)
27722 uint32_t opc = MASK_MMI3(ctx->opcode);
27724 switch (opc) {
27725 case MMI_OPC_3_PMADDUW: /* TODO: MMI_OPC_3_PMADDUW */
27726 case MMI_OPC_3_PSRAVW: /* TODO: MMI_OPC_3_PSRAVW */
27727 case MMI_OPC_3_PMTHI: /* TODO: MMI_OPC_3_PMTHI */
27728 case MMI_OPC_3_PMTLO: /* TODO: MMI_OPC_3_PMTLO */
27729 case MMI_OPC_3_PINTEH: /* TODO: MMI_OPC_3_PINTEH */
27730 case MMI_OPC_3_PMULTUW: /* TODO: MMI_OPC_3_PMULTUW */
27731 case MMI_OPC_3_PDIVUW: /* TODO: MMI_OPC_3_PDIVUW */
27732 case MMI_OPC_3_POR: /* TODO: MMI_OPC_3_POR */
27733 case MMI_OPC_3_PNOR: /* TODO: MMI_OPC_3_PNOR */
27734 case MMI_OPC_3_PEXCH: /* TODO: MMI_OPC_3_PEXCH */
27735 case MMI_OPC_3_PEXCW: /* TODO: MMI_OPC_3_PEXCW */
27736 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI3 */
27737 break;
27738 case MMI_OPC_3_PCPYH:
27739 gen_mmi_pcpyh(ctx);
27740 break;
27741 case MMI_OPC_3_PCPYUD:
27742 gen_mmi_pcpyud(ctx);
27743 break;
27744 default:
27745 MIPS_INVAL("TX79 MMI class MMI3");
27746 generate_exception_end(ctx, EXCP_RI);
27747 break;
27751 static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
27753 uint32_t opc = MASK_MMI(ctx->opcode);
27754 int rs = extract32(ctx->opcode, 21, 5);
27755 int rt = extract32(ctx->opcode, 16, 5);
27756 int rd = extract32(ctx->opcode, 11, 5);
27758 switch (opc) {
27759 case MMI_OPC_CLASS_MMI0:
27760 decode_mmi0(env, ctx);
27761 break;
27762 case MMI_OPC_CLASS_MMI1:
27763 decode_mmi1(env, ctx);
27764 break;
27765 case MMI_OPC_CLASS_MMI2:
27766 decode_mmi2(env, ctx);
27767 break;
27768 case MMI_OPC_CLASS_MMI3:
27769 decode_mmi3(env, ctx);
27770 break;
27771 case MMI_OPC_MULT1:
27772 case MMI_OPC_MULTU1:
27773 case MMI_OPC_MADD:
27774 case MMI_OPC_MADDU:
27775 case MMI_OPC_MADD1:
27776 case MMI_OPC_MADDU1:
27777 gen_mul_txx9(ctx, opc, rd, rs, rt);
27778 break;
27779 case MMI_OPC_DIV1:
27780 case MMI_OPC_DIVU1:
27781 gen_div1_tx79(ctx, opc, rs, rt);
27782 break;
27783 case MMI_OPC_MTLO1:
27784 case MMI_OPC_MTHI1:
27785 gen_HILO1_tx79(ctx, opc, rs);
27786 break;
27787 case MMI_OPC_MFLO1:
27788 case MMI_OPC_MFHI1:
27789 gen_HILO1_tx79(ctx, opc, rd);
27790 break;
27791 case MMI_OPC_PLZCW: /* TODO: MMI_OPC_PLZCW */
27792 case MMI_OPC_PMFHL: /* TODO: MMI_OPC_PMFHL */
27793 case MMI_OPC_PMTHL: /* TODO: MMI_OPC_PMTHL */
27794 case MMI_OPC_PSLLH: /* TODO: MMI_OPC_PSLLH */
27795 case MMI_OPC_PSRLH: /* TODO: MMI_OPC_PSRLH */
27796 case MMI_OPC_PSRAH: /* TODO: MMI_OPC_PSRAH */
27797 case MMI_OPC_PSLLW: /* TODO: MMI_OPC_PSLLW */
27798 case MMI_OPC_PSRLW: /* TODO: MMI_OPC_PSRLW */
27799 case MMI_OPC_PSRAW: /* TODO: MMI_OPC_PSRAW */
27800 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI */
27801 break;
27802 default:
27803 MIPS_INVAL("TX79 MMI class");
27804 generate_exception_end(ctx, EXCP_RI);
27805 break;
27809 static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
27811 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_LQ */
27814 static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
27816 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_SQ */
27820 * The TX79-specific instruction Store Quadword
27822 * +--------+-------+-------+------------------------+
27823 * | 011111 | base | rt | offset | SQ
27824 * +--------+-------+-------+------------------------+
27825 * 6 5 5 16
27827 * has the same opcode as the Read Hardware Register instruction
27829 * +--------+-------+-------+-------+-------+--------+
27830 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
27831 * +--------+-------+-------+-------+-------+--------+
27832 * 6 5 5 5 5 6
27834 * that is required, trapped and emulated by the Linux kernel. However, all
27835 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
27836 * offset is odd. Therefore all valid SQ instructions can execute normally.
27837 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
27838 * between SQ and RDHWR, as the Linux kernel does.
27840 static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
27842 int base = extract32(ctx->opcode, 21, 5);
27843 int rt = extract32(ctx->opcode, 16, 5);
27844 int offset = extract32(ctx->opcode, 0, 16);
27846 #ifdef CONFIG_USER_ONLY
27847 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
27848 uint32_t op2 = extract32(ctx->opcode, 6, 5);
27850 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
27851 int rd = extract32(ctx->opcode, 11, 5);
27853 gen_rdhwr(ctx, rt, rd, 0);
27854 return;
27856 #endif
27858 gen_mmi_sq(ctx, base, rt, offset);
27861 #endif
27863 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
27865 int rs, rt, rd, sa;
27866 uint32_t op1, op2;
27867 int16_t imm;
27869 rs = (ctx->opcode >> 21) & 0x1f;
27870 rt = (ctx->opcode >> 16) & 0x1f;
27871 rd = (ctx->opcode >> 11) & 0x1f;
27872 sa = (ctx->opcode >> 6) & 0x1f;
27873 imm = sextract32(ctx->opcode, 7, 9);
27875 op1 = MASK_SPECIAL3(ctx->opcode);
27878 * EVA loads and stores overlap Loongson 2E instructions decoded by
27879 * decode_opc_special3_legacy(), so be careful to allow their decoding when
27880 * EVA is absent.
27882 if (ctx->eva) {
27883 switch (op1) {
27884 case OPC_LWLE:
27885 case OPC_LWRE:
27886 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27887 /* fall through */
27888 case OPC_LBUE:
27889 case OPC_LHUE:
27890 case OPC_LBE:
27891 case OPC_LHE:
27892 case OPC_LLE:
27893 case OPC_LWE:
27894 check_cp0_enabled(ctx);
27895 gen_ld(ctx, op1, rt, rs, imm);
27896 return;
27897 case OPC_SWLE:
27898 case OPC_SWRE:
27899 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27900 /* fall through */
27901 case OPC_SBE:
27902 case OPC_SHE:
27903 case OPC_SWE:
27904 check_cp0_enabled(ctx);
27905 gen_st(ctx, op1, rt, rs, imm);
27906 return;
27907 case OPC_SCE:
27908 check_cp0_enabled(ctx);
27909 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
27910 return;
27911 case OPC_CACHEE:
27912 check_cp0_enabled(ctx);
27913 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
27914 gen_cache_operation(ctx, rt, rs, imm);
27916 /* Treat as NOP. */
27917 return;
27918 case OPC_PREFE:
27919 check_cp0_enabled(ctx);
27920 /* Treat as NOP. */
27921 return;
27925 switch (op1) {
27926 case OPC_EXT:
27927 case OPC_INS:
27928 check_insn(ctx, ISA_MIPS32R2);
27929 gen_bitops(ctx, op1, rt, rs, sa, rd);
27930 break;
27931 case OPC_BSHFL:
27932 op2 = MASK_BSHFL(ctx->opcode);
27933 switch (op2) {
27934 case OPC_ALIGN:
27935 case OPC_ALIGN_1:
27936 case OPC_ALIGN_2:
27937 case OPC_ALIGN_3:
27938 case OPC_BITSWAP:
27939 check_insn(ctx, ISA_MIPS32R6);
27940 decode_opc_special3_r6(env, ctx);
27941 break;
27942 default:
27943 check_insn(ctx, ISA_MIPS32R2);
27944 gen_bshfl(ctx, op2, rt, rd);
27945 break;
27947 break;
27948 #if defined(TARGET_MIPS64)
27949 case OPC_DEXTM:
27950 case OPC_DEXTU:
27951 case OPC_DEXT:
27952 case OPC_DINSM:
27953 case OPC_DINSU:
27954 case OPC_DINS:
27955 check_insn(ctx, ISA_MIPS64R2);
27956 check_mips_64(ctx);
27957 gen_bitops(ctx, op1, rt, rs, sa, rd);
27958 break;
27959 case OPC_DBSHFL:
27960 op2 = MASK_DBSHFL(ctx->opcode);
27961 switch (op2) {
27962 case OPC_DALIGN:
27963 case OPC_DALIGN_1:
27964 case OPC_DALIGN_2:
27965 case OPC_DALIGN_3:
27966 case OPC_DALIGN_4:
27967 case OPC_DALIGN_5:
27968 case OPC_DALIGN_6:
27969 case OPC_DALIGN_7:
27970 case OPC_DBITSWAP:
27971 check_insn(ctx, ISA_MIPS32R6);
27972 decode_opc_special3_r6(env, ctx);
27973 break;
27974 default:
27975 check_insn(ctx, ISA_MIPS64R2);
27976 check_mips_64(ctx);
27977 op2 = MASK_DBSHFL(ctx->opcode);
27978 gen_bshfl(ctx, op2, rt, rd);
27979 break;
27981 break;
27982 #endif
27983 case OPC_RDHWR:
27984 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
27985 break;
27986 case OPC_FORK:
27987 check_mt(ctx);
27989 TCGv t0 = tcg_temp_new();
27990 TCGv t1 = tcg_temp_new();
27992 gen_load_gpr(t0, rt);
27993 gen_load_gpr(t1, rs);
27994 gen_helper_fork(t0, t1);
27995 tcg_temp_free(t0);
27996 tcg_temp_free(t1);
27998 break;
27999 case OPC_YIELD:
28000 check_mt(ctx);
28002 TCGv t0 = tcg_temp_new();
28004 gen_load_gpr(t0, rs);
28005 gen_helper_yield(t0, cpu_env, t0);
28006 gen_store_gpr(t0, rd);
28007 tcg_temp_free(t0);
28009 break;
28010 default:
28011 if (ctx->insn_flags & ISA_MIPS32R6) {
28012 decode_opc_special3_r6(env, ctx);
28013 } else {
28014 decode_opc_special3_legacy(env, ctx);
28019 /* MIPS SIMD Architecture (MSA) */
28020 static inline int check_msa_access(DisasContext *ctx)
28022 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
28023 !(ctx->hflags & MIPS_HFLAG_F64))) {
28024 generate_exception_end(ctx, EXCP_RI);
28025 return 0;
28028 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
28029 if (ctx->insn_flags & ASE_MSA) {
28030 generate_exception_end(ctx, EXCP_MSADIS);
28031 return 0;
28032 } else {
28033 generate_exception_end(ctx, EXCP_RI);
28034 return 0;
28037 return 1;
28040 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
28042 /* generates tcg ops to check if any element is 0 */
28043 /* Note this function only works with MSA_WRLEN = 128 */
28044 uint64_t eval_zero_or_big = 0;
28045 uint64_t eval_big = 0;
28046 TCGv_i64 t0 = tcg_temp_new_i64();
28047 TCGv_i64 t1 = tcg_temp_new_i64();
28048 switch (df) {
28049 case DF_BYTE:
28050 eval_zero_or_big = 0x0101010101010101ULL;
28051 eval_big = 0x8080808080808080ULL;
28052 break;
28053 case DF_HALF:
28054 eval_zero_or_big = 0x0001000100010001ULL;
28055 eval_big = 0x8000800080008000ULL;
28056 break;
28057 case DF_WORD:
28058 eval_zero_or_big = 0x0000000100000001ULL;
28059 eval_big = 0x8000000080000000ULL;
28060 break;
28061 case DF_DOUBLE:
28062 eval_zero_or_big = 0x0000000000000001ULL;
28063 eval_big = 0x8000000000000000ULL;
28064 break;
28066 tcg_gen_subi_i64(t0, msa_wr_d[wt << 1], eval_zero_or_big);
28067 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt << 1]);
28068 tcg_gen_andi_i64(t0, t0, eval_big);
28069 tcg_gen_subi_i64(t1, msa_wr_d[(wt << 1) + 1], eval_zero_or_big);
28070 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt << 1) + 1]);
28071 tcg_gen_andi_i64(t1, t1, eval_big);
28072 tcg_gen_or_i64(t0, t0, t1);
28073 /* if all bits are zero then all elements are not zero */
28074 /* if some bit is non-zero then some element is zero */
28075 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
28076 tcg_gen_trunc_i64_tl(tresult, t0);
28077 tcg_temp_free_i64(t0);
28078 tcg_temp_free_i64(t1);
28081 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
28083 uint8_t df = (ctx->opcode >> 21) & 0x3;
28084 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28085 int64_t s16 = (int16_t)ctx->opcode;
28087 check_msa_access(ctx);
28089 if (ctx->hflags & MIPS_HFLAG_BMASK) {
28090 generate_exception_end(ctx, EXCP_RI);
28091 return;
28093 switch (op1) {
28094 case OPC_BZ_V:
28095 case OPC_BNZ_V:
28097 TCGv_i64 t0 = tcg_temp_new_i64();
28098 tcg_gen_or_i64(t0, msa_wr_d[wt << 1], msa_wr_d[(wt << 1) + 1]);
28099 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
28100 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
28101 tcg_gen_trunc_i64_tl(bcond, t0);
28102 tcg_temp_free_i64(t0);
28104 break;
28105 case OPC_BZ_B:
28106 case OPC_BZ_H:
28107 case OPC_BZ_W:
28108 case OPC_BZ_D:
28109 gen_check_zero_element(bcond, df, wt);
28110 break;
28111 case OPC_BNZ_B:
28112 case OPC_BNZ_H:
28113 case OPC_BNZ_W:
28114 case OPC_BNZ_D:
28115 gen_check_zero_element(bcond, df, wt);
28116 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
28117 break;
28120 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
28122 ctx->hflags |= MIPS_HFLAG_BC;
28123 ctx->hflags |= MIPS_HFLAG_BDS32;
28126 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
28128 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
28129 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
28130 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28131 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28133 TCGv_i32 twd = tcg_const_i32(wd);
28134 TCGv_i32 tws = tcg_const_i32(ws);
28135 TCGv_i32 ti8 = tcg_const_i32(i8);
28137 switch (MASK_MSA_I8(ctx->opcode)) {
28138 case OPC_ANDI_B:
28139 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
28140 break;
28141 case OPC_ORI_B:
28142 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
28143 break;
28144 case OPC_NORI_B:
28145 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
28146 break;
28147 case OPC_XORI_B:
28148 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
28149 break;
28150 case OPC_BMNZI_B:
28151 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
28152 break;
28153 case OPC_BMZI_B:
28154 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
28155 break;
28156 case OPC_BSELI_B:
28157 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
28158 break;
28159 case OPC_SHF_B:
28160 case OPC_SHF_H:
28161 case OPC_SHF_W:
28163 uint8_t df = (ctx->opcode >> 24) & 0x3;
28164 if (df == DF_DOUBLE) {
28165 generate_exception_end(ctx, EXCP_RI);
28166 } else {
28167 TCGv_i32 tdf = tcg_const_i32(df);
28168 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
28169 tcg_temp_free_i32(tdf);
28172 break;
28173 default:
28174 MIPS_INVAL("MSA instruction");
28175 generate_exception_end(ctx, EXCP_RI);
28176 break;
28179 tcg_temp_free_i32(twd);
28180 tcg_temp_free_i32(tws);
28181 tcg_temp_free_i32(ti8);
28184 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
28186 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28187 uint8_t df = (ctx->opcode >> 21) & 0x3;
28188 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
28189 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
28190 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28191 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28193 TCGv_i32 tdf = tcg_const_i32(df);
28194 TCGv_i32 twd = tcg_const_i32(wd);
28195 TCGv_i32 tws = tcg_const_i32(ws);
28196 TCGv_i32 timm = tcg_temp_new_i32();
28197 tcg_gen_movi_i32(timm, u5);
28199 switch (MASK_MSA_I5(ctx->opcode)) {
28200 case OPC_ADDVI_df:
28201 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
28202 break;
28203 case OPC_SUBVI_df:
28204 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
28205 break;
28206 case OPC_MAXI_S_df:
28207 tcg_gen_movi_i32(timm, s5);
28208 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
28209 break;
28210 case OPC_MAXI_U_df:
28211 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
28212 break;
28213 case OPC_MINI_S_df:
28214 tcg_gen_movi_i32(timm, s5);
28215 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
28216 break;
28217 case OPC_MINI_U_df:
28218 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
28219 break;
28220 case OPC_CEQI_df:
28221 tcg_gen_movi_i32(timm, s5);
28222 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
28223 break;
28224 case OPC_CLTI_S_df:
28225 tcg_gen_movi_i32(timm, s5);
28226 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
28227 break;
28228 case OPC_CLTI_U_df:
28229 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
28230 break;
28231 case OPC_CLEI_S_df:
28232 tcg_gen_movi_i32(timm, s5);
28233 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
28234 break;
28235 case OPC_CLEI_U_df:
28236 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
28237 break;
28238 case OPC_LDI_df:
28240 int32_t s10 = sextract32(ctx->opcode, 11, 10);
28241 tcg_gen_movi_i32(timm, s10);
28242 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
28244 break;
28245 default:
28246 MIPS_INVAL("MSA instruction");
28247 generate_exception_end(ctx, EXCP_RI);
28248 break;
28251 tcg_temp_free_i32(tdf);
28252 tcg_temp_free_i32(twd);
28253 tcg_temp_free_i32(tws);
28254 tcg_temp_free_i32(timm);
28257 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
28259 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28260 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
28261 uint32_t df = 0, m = 0;
28262 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28263 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28265 TCGv_i32 tdf;
28266 TCGv_i32 tm;
28267 TCGv_i32 twd;
28268 TCGv_i32 tws;
28270 if ((dfm & 0x40) == 0x00) {
28271 m = dfm & 0x3f;
28272 df = DF_DOUBLE;
28273 } else if ((dfm & 0x60) == 0x40) {
28274 m = dfm & 0x1f;
28275 df = DF_WORD;
28276 } else if ((dfm & 0x70) == 0x60) {
28277 m = dfm & 0x0f;
28278 df = DF_HALF;
28279 } else if ((dfm & 0x78) == 0x70) {
28280 m = dfm & 0x7;
28281 df = DF_BYTE;
28282 } else {
28283 generate_exception_end(ctx, EXCP_RI);
28284 return;
28287 tdf = tcg_const_i32(df);
28288 tm = tcg_const_i32(m);
28289 twd = tcg_const_i32(wd);
28290 tws = tcg_const_i32(ws);
28292 switch (MASK_MSA_BIT(ctx->opcode)) {
28293 case OPC_SLLI_df:
28294 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
28295 break;
28296 case OPC_SRAI_df:
28297 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
28298 break;
28299 case OPC_SRLI_df:
28300 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
28301 break;
28302 case OPC_BCLRI_df:
28303 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
28304 break;
28305 case OPC_BSETI_df:
28306 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
28307 break;
28308 case OPC_BNEGI_df:
28309 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
28310 break;
28311 case OPC_BINSLI_df:
28312 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
28313 break;
28314 case OPC_BINSRI_df:
28315 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
28316 break;
28317 case OPC_SAT_S_df:
28318 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
28319 break;
28320 case OPC_SAT_U_df:
28321 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
28322 break;
28323 case OPC_SRARI_df:
28324 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
28325 break;
28326 case OPC_SRLRI_df:
28327 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
28328 break;
28329 default:
28330 MIPS_INVAL("MSA instruction");
28331 generate_exception_end(ctx, EXCP_RI);
28332 break;
28335 tcg_temp_free_i32(tdf);
28336 tcg_temp_free_i32(tm);
28337 tcg_temp_free_i32(twd);
28338 tcg_temp_free_i32(tws);
28341 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
28343 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28344 uint8_t df = (ctx->opcode >> 21) & 0x3;
28345 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28346 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28347 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28349 TCGv_i32 tdf = tcg_const_i32(df);
28350 TCGv_i32 twd = tcg_const_i32(wd);
28351 TCGv_i32 tws = tcg_const_i32(ws);
28352 TCGv_i32 twt = tcg_const_i32(wt);
28354 switch (MASK_MSA_3R(ctx->opcode)) {
28355 case OPC_SLL_df:
28356 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
28357 break;
28358 case OPC_ADDV_df:
28359 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
28360 break;
28361 case OPC_CEQ_df:
28362 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
28363 break;
28364 case OPC_ADD_A_df:
28365 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
28366 break;
28367 case OPC_SUBS_S_df:
28368 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
28369 break;
28370 case OPC_MULV_df:
28371 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
28372 break;
28373 case OPC_SLD_df:
28374 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
28375 break;
28376 case OPC_VSHF_df:
28377 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
28378 break;
28379 case OPC_SRA_df:
28380 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
28381 break;
28382 case OPC_SUBV_df:
28383 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
28384 break;
28385 case OPC_ADDS_A_df:
28386 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
28387 break;
28388 case OPC_SUBS_U_df:
28389 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
28390 break;
28391 case OPC_MADDV_df:
28392 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
28393 break;
28394 case OPC_SPLAT_df:
28395 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
28396 break;
28397 case OPC_SRAR_df:
28398 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
28399 break;
28400 case OPC_SRL_df:
28401 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
28402 break;
28403 case OPC_MAX_S_df:
28404 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
28405 break;
28406 case OPC_CLT_S_df:
28407 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
28408 break;
28409 case OPC_ADDS_S_df:
28410 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
28411 break;
28412 case OPC_SUBSUS_U_df:
28413 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
28414 break;
28415 case OPC_MSUBV_df:
28416 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
28417 break;
28418 case OPC_PCKEV_df:
28419 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
28420 break;
28421 case OPC_SRLR_df:
28422 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
28423 break;
28424 case OPC_BCLR_df:
28425 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
28426 break;
28427 case OPC_MAX_U_df:
28428 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
28429 break;
28430 case OPC_CLT_U_df:
28431 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
28432 break;
28433 case OPC_ADDS_U_df:
28434 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
28435 break;
28436 case OPC_SUBSUU_S_df:
28437 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
28438 break;
28439 case OPC_PCKOD_df:
28440 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
28441 break;
28442 case OPC_BSET_df:
28443 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
28444 break;
28445 case OPC_MIN_S_df:
28446 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
28447 break;
28448 case OPC_CLE_S_df:
28449 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
28450 break;
28451 case OPC_AVE_S_df:
28452 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
28453 break;
28454 case OPC_ASUB_S_df:
28455 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
28456 break;
28457 case OPC_DIV_S_df:
28458 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
28459 break;
28460 case OPC_ILVL_df:
28461 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
28462 break;
28463 case OPC_BNEG_df:
28464 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
28465 break;
28466 case OPC_MIN_U_df:
28467 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
28468 break;
28469 case OPC_CLE_U_df:
28470 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
28471 break;
28472 case OPC_AVE_U_df:
28473 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
28474 break;
28475 case OPC_ASUB_U_df:
28476 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
28477 break;
28478 case OPC_DIV_U_df:
28479 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
28480 break;
28481 case OPC_ILVR_df:
28482 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
28483 break;
28484 case OPC_BINSL_df:
28485 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
28486 break;
28487 case OPC_MAX_A_df:
28488 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
28489 break;
28490 case OPC_AVER_S_df:
28491 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
28492 break;
28493 case OPC_MOD_S_df:
28494 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
28495 break;
28496 case OPC_ILVEV_df:
28497 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
28498 break;
28499 case OPC_BINSR_df:
28500 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
28501 break;
28502 case OPC_MIN_A_df:
28503 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
28504 break;
28505 case OPC_AVER_U_df:
28506 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
28507 break;
28508 case OPC_MOD_U_df:
28509 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
28510 break;
28511 case OPC_ILVOD_df:
28512 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
28513 break;
28515 case OPC_DOTP_S_df:
28516 case OPC_DOTP_U_df:
28517 case OPC_DPADD_S_df:
28518 case OPC_DPADD_U_df:
28519 case OPC_DPSUB_S_df:
28520 case OPC_HADD_S_df:
28521 case OPC_DPSUB_U_df:
28522 case OPC_HADD_U_df:
28523 case OPC_HSUB_S_df:
28524 case OPC_HSUB_U_df:
28525 if (df == DF_BYTE) {
28526 generate_exception_end(ctx, EXCP_RI);
28527 break;
28529 switch (MASK_MSA_3R(ctx->opcode)) {
28530 case OPC_DOTP_S_df:
28531 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
28532 break;
28533 case OPC_DOTP_U_df:
28534 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
28535 break;
28536 case OPC_DPADD_S_df:
28537 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
28538 break;
28539 case OPC_DPADD_U_df:
28540 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
28541 break;
28542 case OPC_DPSUB_S_df:
28543 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
28544 break;
28545 case OPC_HADD_S_df:
28546 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
28547 break;
28548 case OPC_DPSUB_U_df:
28549 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
28550 break;
28551 case OPC_HADD_U_df:
28552 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
28553 break;
28554 case OPC_HSUB_S_df:
28555 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
28556 break;
28557 case OPC_HSUB_U_df:
28558 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
28559 break;
28561 break;
28562 default:
28563 MIPS_INVAL("MSA instruction");
28564 generate_exception_end(ctx, EXCP_RI);
28565 break;
28567 tcg_temp_free_i32(twd);
28568 tcg_temp_free_i32(tws);
28569 tcg_temp_free_i32(twt);
28570 tcg_temp_free_i32(tdf);
28573 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
28575 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
28576 uint8_t source = (ctx->opcode >> 11) & 0x1f;
28577 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
28578 TCGv telm = tcg_temp_new();
28579 TCGv_i32 tsr = tcg_const_i32(source);
28580 TCGv_i32 tdt = tcg_const_i32(dest);
28582 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
28583 case OPC_CTCMSA:
28584 gen_load_gpr(telm, source);
28585 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
28586 break;
28587 case OPC_CFCMSA:
28588 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
28589 gen_store_gpr(telm, dest);
28590 break;
28591 case OPC_MOVE_V:
28592 gen_helper_msa_move_v(cpu_env, tdt, tsr);
28593 break;
28594 default:
28595 MIPS_INVAL("MSA instruction");
28596 generate_exception_end(ctx, EXCP_RI);
28597 break;
28600 tcg_temp_free(telm);
28601 tcg_temp_free_i32(tdt);
28602 tcg_temp_free_i32(tsr);
28605 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
28606 uint32_t n)
28608 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
28609 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28610 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28612 TCGv_i32 tws = tcg_const_i32(ws);
28613 TCGv_i32 twd = tcg_const_i32(wd);
28614 TCGv_i32 tn = tcg_const_i32(n);
28615 TCGv_i32 tdf = tcg_const_i32(df);
28617 switch (MASK_MSA_ELM(ctx->opcode)) {
28618 case OPC_SLDI_df:
28619 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
28620 break;
28621 case OPC_SPLATI_df:
28622 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
28623 break;
28624 case OPC_INSVE_df:
28625 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
28626 break;
28627 case OPC_COPY_S_df:
28628 case OPC_COPY_U_df:
28629 case OPC_INSERT_df:
28630 #if !defined(TARGET_MIPS64)
28631 /* Double format valid only for MIPS64 */
28632 if (df == DF_DOUBLE) {
28633 generate_exception_end(ctx, EXCP_RI);
28634 break;
28636 if ((MASK_MSA_ELM(ctx->opcode) == OPC_COPY_U_df) &&
28637 (df == DF_WORD)) {
28638 generate_exception_end(ctx, EXCP_RI);
28639 break;
28641 #endif
28642 switch (MASK_MSA_ELM(ctx->opcode)) {
28643 case OPC_COPY_S_df:
28644 if (likely(wd != 0)) {
28645 switch (df) {
28646 case DF_BYTE:
28647 gen_helper_msa_copy_s_b(cpu_env, twd, tws, tn);
28648 break;
28649 case DF_HALF:
28650 gen_helper_msa_copy_s_h(cpu_env, twd, tws, tn);
28651 break;
28652 case DF_WORD:
28653 gen_helper_msa_copy_s_w(cpu_env, twd, tws, tn);
28654 break;
28655 #if defined(TARGET_MIPS64)
28656 case DF_DOUBLE:
28657 gen_helper_msa_copy_s_d(cpu_env, twd, tws, tn);
28658 break;
28659 #endif
28660 default:
28661 assert(0);
28664 break;
28665 case OPC_COPY_U_df:
28666 if (likely(wd != 0)) {
28667 switch (df) {
28668 case DF_BYTE:
28669 gen_helper_msa_copy_u_b(cpu_env, twd, tws, tn);
28670 break;
28671 case DF_HALF:
28672 gen_helper_msa_copy_u_h(cpu_env, twd, tws, tn);
28673 break;
28674 #if defined(TARGET_MIPS64)
28675 case DF_WORD:
28676 gen_helper_msa_copy_u_w(cpu_env, twd, tws, tn);
28677 break;
28678 #endif
28679 default:
28680 assert(0);
28683 break;
28684 case OPC_INSERT_df:
28685 switch (df) {
28686 case DF_BYTE:
28687 gen_helper_msa_insert_b(cpu_env, twd, tws, tn);
28688 break;
28689 case DF_HALF:
28690 gen_helper_msa_insert_h(cpu_env, twd, tws, tn);
28691 break;
28692 case DF_WORD:
28693 gen_helper_msa_insert_w(cpu_env, twd, tws, tn);
28694 break;
28695 #if defined(TARGET_MIPS64)
28696 case DF_DOUBLE:
28697 gen_helper_msa_insert_d(cpu_env, twd, tws, tn);
28698 break;
28699 #endif
28700 default:
28701 assert(0);
28703 break;
28705 break;
28706 default:
28707 MIPS_INVAL("MSA instruction");
28708 generate_exception_end(ctx, EXCP_RI);
28710 tcg_temp_free_i32(twd);
28711 tcg_temp_free_i32(tws);
28712 tcg_temp_free_i32(tn);
28713 tcg_temp_free_i32(tdf);
28716 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
28718 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
28719 uint32_t df = 0, n = 0;
28721 if ((dfn & 0x30) == 0x00) {
28722 n = dfn & 0x0f;
28723 df = DF_BYTE;
28724 } else if ((dfn & 0x38) == 0x20) {
28725 n = dfn & 0x07;
28726 df = DF_HALF;
28727 } else if ((dfn & 0x3c) == 0x30) {
28728 n = dfn & 0x03;
28729 df = DF_WORD;
28730 } else if ((dfn & 0x3e) == 0x38) {
28731 n = dfn & 0x01;
28732 df = DF_DOUBLE;
28733 } else if (dfn == 0x3E) {
28734 /* CTCMSA, CFCMSA, MOVE.V */
28735 gen_msa_elm_3e(env, ctx);
28736 return;
28737 } else {
28738 generate_exception_end(ctx, EXCP_RI);
28739 return;
28742 gen_msa_elm_df(env, ctx, df, n);
28745 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
28747 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
28748 uint8_t df = (ctx->opcode >> 21) & 0x1;
28749 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28750 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28751 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28753 TCGv_i32 twd = tcg_const_i32(wd);
28754 TCGv_i32 tws = tcg_const_i32(ws);
28755 TCGv_i32 twt = tcg_const_i32(wt);
28756 TCGv_i32 tdf = tcg_temp_new_i32();
28758 /* adjust df value for floating-point instruction */
28759 tcg_gen_movi_i32(tdf, df + 2);
28761 switch (MASK_MSA_3RF(ctx->opcode)) {
28762 case OPC_FCAF_df:
28763 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
28764 break;
28765 case OPC_FADD_df:
28766 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
28767 break;
28768 case OPC_FCUN_df:
28769 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
28770 break;
28771 case OPC_FSUB_df:
28772 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
28773 break;
28774 case OPC_FCOR_df:
28775 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
28776 break;
28777 case OPC_FCEQ_df:
28778 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
28779 break;
28780 case OPC_FMUL_df:
28781 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
28782 break;
28783 case OPC_FCUNE_df:
28784 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
28785 break;
28786 case OPC_FCUEQ_df:
28787 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
28788 break;
28789 case OPC_FDIV_df:
28790 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
28791 break;
28792 case OPC_FCNE_df:
28793 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
28794 break;
28795 case OPC_FCLT_df:
28796 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
28797 break;
28798 case OPC_FMADD_df:
28799 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
28800 break;
28801 case OPC_MUL_Q_df:
28802 tcg_gen_movi_i32(tdf, df + 1);
28803 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
28804 break;
28805 case OPC_FCULT_df:
28806 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
28807 break;
28808 case OPC_FMSUB_df:
28809 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
28810 break;
28811 case OPC_MADD_Q_df:
28812 tcg_gen_movi_i32(tdf, df + 1);
28813 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
28814 break;
28815 case OPC_FCLE_df:
28816 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
28817 break;
28818 case OPC_MSUB_Q_df:
28819 tcg_gen_movi_i32(tdf, df + 1);
28820 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
28821 break;
28822 case OPC_FCULE_df:
28823 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
28824 break;
28825 case OPC_FEXP2_df:
28826 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
28827 break;
28828 case OPC_FSAF_df:
28829 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
28830 break;
28831 case OPC_FEXDO_df:
28832 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
28833 break;
28834 case OPC_FSUN_df:
28835 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
28836 break;
28837 case OPC_FSOR_df:
28838 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
28839 break;
28840 case OPC_FSEQ_df:
28841 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
28842 break;
28843 case OPC_FTQ_df:
28844 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
28845 break;
28846 case OPC_FSUNE_df:
28847 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
28848 break;
28849 case OPC_FSUEQ_df:
28850 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
28851 break;
28852 case OPC_FSNE_df:
28853 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
28854 break;
28855 case OPC_FSLT_df:
28856 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
28857 break;
28858 case OPC_FMIN_df:
28859 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
28860 break;
28861 case OPC_MULR_Q_df:
28862 tcg_gen_movi_i32(tdf, df + 1);
28863 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
28864 break;
28865 case OPC_FSULT_df:
28866 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
28867 break;
28868 case OPC_FMIN_A_df:
28869 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
28870 break;
28871 case OPC_MADDR_Q_df:
28872 tcg_gen_movi_i32(tdf, df + 1);
28873 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
28874 break;
28875 case OPC_FSLE_df:
28876 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
28877 break;
28878 case OPC_FMAX_df:
28879 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
28880 break;
28881 case OPC_MSUBR_Q_df:
28882 tcg_gen_movi_i32(tdf, df + 1);
28883 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
28884 break;
28885 case OPC_FSULE_df:
28886 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
28887 break;
28888 case OPC_FMAX_A_df:
28889 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
28890 break;
28891 default:
28892 MIPS_INVAL("MSA instruction");
28893 generate_exception_end(ctx, EXCP_RI);
28894 break;
28897 tcg_temp_free_i32(twd);
28898 tcg_temp_free_i32(tws);
28899 tcg_temp_free_i32(twt);
28900 tcg_temp_free_i32(tdf);
28903 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
28905 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
28906 (op & (0x7 << 18)))
28907 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28908 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28909 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28910 uint8_t df = (ctx->opcode >> 16) & 0x3;
28911 TCGv_i32 twd = tcg_const_i32(wd);
28912 TCGv_i32 tws = tcg_const_i32(ws);
28913 TCGv_i32 twt = tcg_const_i32(wt);
28914 TCGv_i32 tdf = tcg_const_i32(df);
28916 switch (MASK_MSA_2R(ctx->opcode)) {
28917 case OPC_FILL_df:
28918 #if !defined(TARGET_MIPS64)
28919 /* Double format valid only for MIPS64 */
28920 if (df == DF_DOUBLE) {
28921 generate_exception_end(ctx, EXCP_RI);
28922 break;
28924 #endif
28925 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
28926 break;
28927 case OPC_PCNT_df:
28928 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
28929 break;
28930 case OPC_NLOC_df:
28931 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
28932 break;
28933 case OPC_NLZC_df:
28934 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
28935 break;
28936 default:
28937 MIPS_INVAL("MSA instruction");
28938 generate_exception_end(ctx, EXCP_RI);
28939 break;
28942 tcg_temp_free_i32(twd);
28943 tcg_temp_free_i32(tws);
28944 tcg_temp_free_i32(twt);
28945 tcg_temp_free_i32(tdf);
28948 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
28950 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
28951 (op & (0xf << 17)))
28952 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28953 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28954 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28955 uint8_t df = (ctx->opcode >> 16) & 0x1;
28956 TCGv_i32 twd = tcg_const_i32(wd);
28957 TCGv_i32 tws = tcg_const_i32(ws);
28958 TCGv_i32 twt = tcg_const_i32(wt);
28959 /* adjust df value for floating-point instruction */
28960 TCGv_i32 tdf = tcg_const_i32(df + 2);
28962 switch (MASK_MSA_2RF(ctx->opcode)) {
28963 case OPC_FCLASS_df:
28964 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
28965 break;
28966 case OPC_FTRUNC_S_df:
28967 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
28968 break;
28969 case OPC_FTRUNC_U_df:
28970 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
28971 break;
28972 case OPC_FSQRT_df:
28973 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
28974 break;
28975 case OPC_FRSQRT_df:
28976 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
28977 break;
28978 case OPC_FRCP_df:
28979 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
28980 break;
28981 case OPC_FRINT_df:
28982 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
28983 break;
28984 case OPC_FLOG2_df:
28985 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
28986 break;
28987 case OPC_FEXUPL_df:
28988 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
28989 break;
28990 case OPC_FEXUPR_df:
28991 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
28992 break;
28993 case OPC_FFQL_df:
28994 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
28995 break;
28996 case OPC_FFQR_df:
28997 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
28998 break;
28999 case OPC_FTINT_S_df:
29000 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
29001 break;
29002 case OPC_FTINT_U_df:
29003 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
29004 break;
29005 case OPC_FFINT_S_df:
29006 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
29007 break;
29008 case OPC_FFINT_U_df:
29009 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
29010 break;
29013 tcg_temp_free_i32(twd);
29014 tcg_temp_free_i32(tws);
29015 tcg_temp_free_i32(twt);
29016 tcg_temp_free_i32(tdf);
29019 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
29021 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
29022 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
29023 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29024 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29025 TCGv_i32 twd = tcg_const_i32(wd);
29026 TCGv_i32 tws = tcg_const_i32(ws);
29027 TCGv_i32 twt = tcg_const_i32(wt);
29029 switch (MASK_MSA_VEC(ctx->opcode)) {
29030 case OPC_AND_V:
29031 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
29032 break;
29033 case OPC_OR_V:
29034 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
29035 break;
29036 case OPC_NOR_V:
29037 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
29038 break;
29039 case OPC_XOR_V:
29040 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
29041 break;
29042 case OPC_BMNZ_V:
29043 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
29044 break;
29045 case OPC_BMZ_V:
29046 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
29047 break;
29048 case OPC_BSEL_V:
29049 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
29050 break;
29051 default:
29052 MIPS_INVAL("MSA instruction");
29053 generate_exception_end(ctx, EXCP_RI);
29054 break;
29057 tcg_temp_free_i32(twd);
29058 tcg_temp_free_i32(tws);
29059 tcg_temp_free_i32(twt);
29062 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
29064 switch (MASK_MSA_VEC(ctx->opcode)) {
29065 case OPC_AND_V:
29066 case OPC_OR_V:
29067 case OPC_NOR_V:
29068 case OPC_XOR_V:
29069 case OPC_BMNZ_V:
29070 case OPC_BMZ_V:
29071 case OPC_BSEL_V:
29072 gen_msa_vec_v(env, ctx);
29073 break;
29074 case OPC_MSA_2R:
29075 gen_msa_2r(env, ctx);
29076 break;
29077 case OPC_MSA_2RF:
29078 gen_msa_2rf(env, ctx);
29079 break;
29080 default:
29081 MIPS_INVAL("MSA instruction");
29082 generate_exception_end(ctx, EXCP_RI);
29083 break;
29087 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
29089 uint32_t opcode = ctx->opcode;
29090 check_insn(ctx, ASE_MSA);
29091 check_msa_access(ctx);
29093 switch (MASK_MSA_MINOR(opcode)) {
29094 case OPC_MSA_I8_00:
29095 case OPC_MSA_I8_01:
29096 case OPC_MSA_I8_02:
29097 gen_msa_i8(env, ctx);
29098 break;
29099 case OPC_MSA_I5_06:
29100 case OPC_MSA_I5_07:
29101 gen_msa_i5(env, ctx);
29102 break;
29103 case OPC_MSA_BIT_09:
29104 case OPC_MSA_BIT_0A:
29105 gen_msa_bit(env, ctx);
29106 break;
29107 case OPC_MSA_3R_0D:
29108 case OPC_MSA_3R_0E:
29109 case OPC_MSA_3R_0F:
29110 case OPC_MSA_3R_10:
29111 case OPC_MSA_3R_11:
29112 case OPC_MSA_3R_12:
29113 case OPC_MSA_3R_13:
29114 case OPC_MSA_3R_14:
29115 case OPC_MSA_3R_15:
29116 gen_msa_3r(env, ctx);
29117 break;
29118 case OPC_MSA_ELM:
29119 gen_msa_elm(env, ctx);
29120 break;
29121 case OPC_MSA_3RF_1A:
29122 case OPC_MSA_3RF_1B:
29123 case OPC_MSA_3RF_1C:
29124 gen_msa_3rf(env, ctx);
29125 break;
29126 case OPC_MSA_VEC:
29127 gen_msa_vec(env, ctx);
29128 break;
29129 case OPC_LD_B:
29130 case OPC_LD_H:
29131 case OPC_LD_W:
29132 case OPC_LD_D:
29133 case OPC_ST_B:
29134 case OPC_ST_H:
29135 case OPC_ST_W:
29136 case OPC_ST_D:
29138 int32_t s10 = sextract32(ctx->opcode, 16, 10);
29139 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
29140 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29141 uint8_t df = (ctx->opcode >> 0) & 0x3;
29143 TCGv_i32 twd = tcg_const_i32(wd);
29144 TCGv taddr = tcg_temp_new();
29145 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
29147 switch (MASK_MSA_MINOR(opcode)) {
29148 case OPC_LD_B:
29149 gen_helper_msa_ld_b(cpu_env, twd, taddr);
29150 break;
29151 case OPC_LD_H:
29152 gen_helper_msa_ld_h(cpu_env, twd, taddr);
29153 break;
29154 case OPC_LD_W:
29155 gen_helper_msa_ld_w(cpu_env, twd, taddr);
29156 break;
29157 case OPC_LD_D:
29158 gen_helper_msa_ld_d(cpu_env, twd, taddr);
29159 break;
29160 case OPC_ST_B:
29161 gen_helper_msa_st_b(cpu_env, twd, taddr);
29162 break;
29163 case OPC_ST_H:
29164 gen_helper_msa_st_h(cpu_env, twd, taddr);
29165 break;
29166 case OPC_ST_W:
29167 gen_helper_msa_st_w(cpu_env, twd, taddr);
29168 break;
29169 case OPC_ST_D:
29170 gen_helper_msa_st_d(cpu_env, twd, taddr);
29171 break;
29174 tcg_temp_free_i32(twd);
29175 tcg_temp_free(taddr);
29177 break;
29178 default:
29179 MIPS_INVAL("MSA instruction");
29180 generate_exception_end(ctx, EXCP_RI);
29181 break;
29186 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
29188 int32_t offset;
29189 int rs, rt, rd, sa;
29190 uint32_t op, op1;
29191 int16_t imm;
29193 /* make sure instructions are on a word boundary */
29194 if (ctx->base.pc_next & 0x3) {
29195 env->CP0_BadVAddr = ctx->base.pc_next;
29196 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
29197 return;
29200 /* Handle blikely not taken case */
29201 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
29202 TCGLabel *l1 = gen_new_label();
29204 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
29205 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
29206 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
29207 gen_set_label(l1);
29210 op = MASK_OP_MAJOR(ctx->opcode);
29211 rs = (ctx->opcode >> 21) & 0x1f;
29212 rt = (ctx->opcode >> 16) & 0x1f;
29213 rd = (ctx->opcode >> 11) & 0x1f;
29214 sa = (ctx->opcode >> 6) & 0x1f;
29215 imm = (int16_t)ctx->opcode;
29216 switch (op) {
29217 case OPC_SPECIAL:
29218 decode_opc_special(env, ctx);
29219 break;
29220 case OPC_SPECIAL2:
29221 #if defined(TARGET_MIPS64)
29222 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
29223 decode_mmi(env, ctx);
29224 #else
29225 if (ctx->insn_flags & ASE_MXU) {
29226 decode_opc_mxu(env, ctx);
29227 #endif
29228 } else {
29229 decode_opc_special2_legacy(env, ctx);
29231 break;
29232 case OPC_SPECIAL3:
29233 #if defined(TARGET_MIPS64)
29234 if (ctx->insn_flags & INSN_R5900) {
29235 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
29236 } else {
29237 decode_opc_special3(env, ctx);
29239 #else
29240 decode_opc_special3(env, ctx);
29241 #endif
29242 break;
29243 case OPC_REGIMM:
29244 op1 = MASK_REGIMM(ctx->opcode);
29245 switch (op1) {
29246 case OPC_BLTZL: /* REGIMM branches */
29247 case OPC_BGEZL:
29248 case OPC_BLTZALL:
29249 case OPC_BGEZALL:
29250 check_insn(ctx, ISA_MIPS2);
29251 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29252 /* Fallthrough */
29253 case OPC_BLTZ:
29254 case OPC_BGEZ:
29255 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
29256 break;
29257 case OPC_BLTZAL:
29258 case OPC_BGEZAL:
29259 if (ctx->insn_flags & ISA_MIPS32R6) {
29260 if (rs == 0) {
29261 /* OPC_NAL, OPC_BAL */
29262 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
29263 } else {
29264 generate_exception_end(ctx, EXCP_RI);
29266 } else {
29267 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
29269 break;
29270 case OPC_TGEI: /* REGIMM traps */
29271 case OPC_TGEIU:
29272 case OPC_TLTI:
29273 case OPC_TLTIU:
29274 case OPC_TEQI:
29276 case OPC_TNEI:
29277 check_insn(ctx, ISA_MIPS2);
29278 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29279 gen_trap(ctx, op1, rs, -1, imm);
29280 break;
29281 case OPC_SIGRIE:
29282 check_insn(ctx, ISA_MIPS32R6);
29283 generate_exception_end(ctx, EXCP_RI);
29284 break;
29285 case OPC_SYNCI:
29286 check_insn(ctx, ISA_MIPS32R2);
29288 * Break the TB to be able to sync copied instructions
29289 * immediately.
29291 ctx->base.is_jmp = DISAS_STOP;
29292 break;
29293 case OPC_BPOSGE32: /* MIPS DSP branch */
29294 #if defined(TARGET_MIPS64)
29295 case OPC_BPOSGE64:
29296 #endif
29297 check_dsp(ctx);
29298 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
29299 break;
29300 #if defined(TARGET_MIPS64)
29301 case OPC_DAHI:
29302 check_insn(ctx, ISA_MIPS32R6);
29303 check_mips_64(ctx);
29304 if (rs != 0) {
29305 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
29307 break;
29308 case OPC_DATI:
29309 check_insn(ctx, ISA_MIPS32R6);
29310 check_mips_64(ctx);
29311 if (rs != 0) {
29312 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
29314 break;
29315 #endif
29316 default: /* Invalid */
29317 MIPS_INVAL("regimm");
29318 generate_exception_end(ctx, EXCP_RI);
29319 break;
29321 break;
29322 case OPC_CP0:
29323 check_cp0_enabled(ctx);
29324 op1 = MASK_CP0(ctx->opcode);
29325 switch (op1) {
29326 case OPC_MFC0:
29327 case OPC_MTC0:
29328 case OPC_MFTR:
29329 case OPC_MTTR:
29330 case OPC_MFHC0:
29331 case OPC_MTHC0:
29332 #if defined(TARGET_MIPS64)
29333 case OPC_DMFC0:
29334 case OPC_DMTC0:
29335 #endif
29336 #ifndef CONFIG_USER_ONLY
29337 gen_cp0(env, ctx, op1, rt, rd);
29338 #endif /* !CONFIG_USER_ONLY */
29339 break;
29340 case OPC_C0:
29341 case OPC_C0_1:
29342 case OPC_C0_2:
29343 case OPC_C0_3:
29344 case OPC_C0_4:
29345 case OPC_C0_5:
29346 case OPC_C0_6:
29347 case OPC_C0_7:
29348 case OPC_C0_8:
29349 case OPC_C0_9:
29350 case OPC_C0_A:
29351 case OPC_C0_B:
29352 case OPC_C0_C:
29353 case OPC_C0_D:
29354 case OPC_C0_E:
29355 case OPC_C0_F:
29356 #ifndef CONFIG_USER_ONLY
29357 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
29358 #endif /* !CONFIG_USER_ONLY */
29359 break;
29360 case OPC_MFMC0:
29361 #ifndef CONFIG_USER_ONLY
29363 uint32_t op2;
29364 TCGv t0 = tcg_temp_new();
29366 op2 = MASK_MFMC0(ctx->opcode);
29367 switch (op2) {
29368 case OPC_DMT:
29369 check_cp0_mt(ctx);
29370 gen_helper_dmt(t0);
29371 gen_store_gpr(t0, rt);
29372 break;
29373 case OPC_EMT:
29374 check_cp0_mt(ctx);
29375 gen_helper_emt(t0);
29376 gen_store_gpr(t0, rt);
29377 break;
29378 case OPC_DVPE:
29379 check_cp0_mt(ctx);
29380 gen_helper_dvpe(t0, cpu_env);
29381 gen_store_gpr(t0, rt);
29382 break;
29383 case OPC_EVPE:
29384 check_cp0_mt(ctx);
29385 gen_helper_evpe(t0, cpu_env);
29386 gen_store_gpr(t0, rt);
29387 break;
29388 case OPC_DVP:
29389 check_insn(ctx, ISA_MIPS32R6);
29390 if (ctx->vp) {
29391 gen_helper_dvp(t0, cpu_env);
29392 gen_store_gpr(t0, rt);
29394 break;
29395 case OPC_EVP:
29396 check_insn(ctx, ISA_MIPS32R6);
29397 if (ctx->vp) {
29398 gen_helper_evp(t0, cpu_env);
29399 gen_store_gpr(t0, rt);
29401 break;
29402 case OPC_DI:
29403 check_insn(ctx, ISA_MIPS32R2);
29404 save_cpu_state(ctx, 1);
29405 gen_helper_di(t0, cpu_env);
29406 gen_store_gpr(t0, rt);
29408 * Stop translation as we may have switched
29409 * the execution mode.
29411 ctx->base.is_jmp = DISAS_STOP;
29412 break;
29413 case OPC_EI:
29414 check_insn(ctx, ISA_MIPS32R2);
29415 save_cpu_state(ctx, 1);
29416 gen_helper_ei(t0, cpu_env);
29417 gen_store_gpr(t0, rt);
29419 * DISAS_STOP isn't sufficient, we need to ensure we break
29420 * out of translated code to check for pending interrupts.
29422 gen_save_pc(ctx->base.pc_next + 4);
29423 ctx->base.is_jmp = DISAS_EXIT;
29424 break;
29425 default: /* Invalid */
29426 MIPS_INVAL("mfmc0");
29427 generate_exception_end(ctx, EXCP_RI);
29428 break;
29430 tcg_temp_free(t0);
29432 #endif /* !CONFIG_USER_ONLY */
29433 break;
29434 case OPC_RDPGPR:
29435 check_insn(ctx, ISA_MIPS32R2);
29436 gen_load_srsgpr(rt, rd);
29437 break;
29438 case OPC_WRPGPR:
29439 check_insn(ctx, ISA_MIPS32R2);
29440 gen_store_srsgpr(rt, rd);
29441 break;
29442 default:
29443 MIPS_INVAL("cp0");
29444 generate_exception_end(ctx, EXCP_RI);
29445 break;
29447 break;
29448 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
29449 if (ctx->insn_flags & ISA_MIPS32R6) {
29450 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
29451 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29452 } else {
29453 /* OPC_ADDI */
29454 /* Arithmetic with immediate opcode */
29455 gen_arith_imm(ctx, op, rt, rs, imm);
29457 break;
29458 case OPC_ADDIU:
29459 gen_arith_imm(ctx, op, rt, rs, imm);
29460 break;
29461 case OPC_SLTI: /* Set on less than with immediate opcode */
29462 case OPC_SLTIU:
29463 gen_slt_imm(ctx, op, rt, rs, imm);
29464 break;
29465 case OPC_ANDI: /* Arithmetic with immediate opcode */
29466 case OPC_LUI: /* OPC_AUI */
29467 case OPC_ORI:
29468 case OPC_XORI:
29469 gen_logic_imm(ctx, op, rt, rs, imm);
29470 break;
29471 case OPC_J: /* Jump */
29472 case OPC_JAL:
29473 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
29474 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
29475 break;
29476 /* Branch */
29477 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
29478 if (ctx->insn_flags & ISA_MIPS32R6) {
29479 if (rt == 0) {
29480 generate_exception_end(ctx, EXCP_RI);
29481 break;
29483 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
29484 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29485 } else {
29486 /* OPC_BLEZL */
29487 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29489 break;
29490 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
29491 if (ctx->insn_flags & ISA_MIPS32R6) {
29492 if (rt == 0) {
29493 generate_exception_end(ctx, EXCP_RI);
29494 break;
29496 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
29497 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29498 } else {
29499 /* OPC_BGTZL */
29500 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29502 break;
29503 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
29504 if (rt == 0) {
29505 /* OPC_BLEZ */
29506 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29507 } else {
29508 check_insn(ctx, ISA_MIPS32R6);
29509 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
29510 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29512 break;
29513 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
29514 if (rt == 0) {
29515 /* OPC_BGTZ */
29516 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29517 } else {
29518 check_insn(ctx, ISA_MIPS32R6);
29519 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
29520 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29522 break;
29523 case OPC_BEQL:
29524 case OPC_BNEL:
29525 check_insn(ctx, ISA_MIPS2);
29526 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29527 /* Fallthrough */
29528 case OPC_BEQ:
29529 case OPC_BNE:
29530 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
29531 break;
29532 case OPC_LL: /* Load and stores */
29533 check_insn(ctx, ISA_MIPS2);
29534 if (ctx->insn_flags & INSN_R5900) {
29535 check_insn_opc_user_only(ctx, INSN_R5900);
29537 /* Fallthrough */
29538 case OPC_LWL:
29539 case OPC_LWR:
29540 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29541 /* Fallthrough */
29542 case OPC_LB:
29543 case OPC_LH:
29544 case OPC_LW:
29545 case OPC_LWPC:
29546 case OPC_LBU:
29547 case OPC_LHU:
29548 gen_ld(ctx, op, rt, rs, imm);
29549 break;
29550 case OPC_SWL:
29551 case OPC_SWR:
29552 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29553 /* fall through */
29554 case OPC_SB:
29555 case OPC_SH:
29556 case OPC_SW:
29557 gen_st(ctx, op, rt, rs, imm);
29558 break;
29559 case OPC_SC:
29560 check_insn(ctx, ISA_MIPS2);
29561 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29562 if (ctx->insn_flags & INSN_R5900) {
29563 check_insn_opc_user_only(ctx, INSN_R5900);
29565 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
29566 break;
29567 case OPC_CACHE:
29568 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29569 check_cp0_enabled(ctx);
29570 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
29571 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
29572 gen_cache_operation(ctx, rt, rs, imm);
29574 /* Treat as NOP. */
29575 break;
29576 case OPC_PREF:
29577 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29578 if (ctx->insn_flags & INSN_R5900) {
29579 /* Treat as NOP. */
29580 } else {
29581 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
29582 /* Treat as NOP. */
29584 break;
29586 /* Floating point (COP1). */
29587 case OPC_LWC1:
29588 case OPC_LDC1:
29589 case OPC_SWC1:
29590 case OPC_SDC1:
29591 gen_cop1_ldst(ctx, op, rt, rs, imm);
29592 break;
29594 case OPC_CP1:
29595 op1 = MASK_CP1(ctx->opcode);
29597 switch (op1) {
29598 case OPC_MFHC1:
29599 case OPC_MTHC1:
29600 check_cp1_enabled(ctx);
29601 check_insn(ctx, ISA_MIPS32R2);
29602 /* fall through */
29603 case OPC_MFC1:
29604 case OPC_CFC1:
29605 case OPC_MTC1:
29606 case OPC_CTC1:
29607 check_cp1_enabled(ctx);
29608 gen_cp1(ctx, op1, rt, rd);
29609 break;
29610 #if defined(TARGET_MIPS64)
29611 case OPC_DMFC1:
29612 case OPC_DMTC1:
29613 check_cp1_enabled(ctx);
29614 check_insn(ctx, ISA_MIPS3);
29615 check_mips_64(ctx);
29616 gen_cp1(ctx, op1, rt, rd);
29617 break;
29618 #endif
29619 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
29620 check_cp1_enabled(ctx);
29621 if (ctx->insn_flags & ISA_MIPS32R6) {
29622 /* OPC_BC1EQZ */
29623 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
29624 rt, imm << 2, 4);
29625 } else {
29626 /* OPC_BC1ANY2 */
29627 check_cop1x(ctx);
29628 check_insn(ctx, ASE_MIPS3D);
29629 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
29630 (rt >> 2) & 0x7, imm << 2);
29632 break;
29633 case OPC_BC1NEZ:
29634 check_cp1_enabled(ctx);
29635 check_insn(ctx, ISA_MIPS32R6);
29636 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
29637 rt, imm << 2, 4);
29638 break;
29639 case OPC_BC1ANY4:
29640 check_cp1_enabled(ctx);
29641 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29642 check_cop1x(ctx);
29643 check_insn(ctx, ASE_MIPS3D);
29644 /* fall through */
29645 case OPC_BC1:
29646 check_cp1_enabled(ctx);
29647 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29648 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
29649 (rt >> 2) & 0x7, imm << 2);
29650 break;
29651 case OPC_PS_FMT:
29652 check_ps(ctx);
29653 /* fall through */
29654 case OPC_S_FMT:
29655 case OPC_D_FMT:
29656 check_cp1_enabled(ctx);
29657 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
29658 (imm >> 8) & 0x7);
29659 break;
29660 case OPC_W_FMT:
29661 case OPC_L_FMT:
29663 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
29664 check_cp1_enabled(ctx);
29665 if (ctx->insn_flags & ISA_MIPS32R6) {
29666 switch (r6_op) {
29667 case R6_OPC_CMP_AF_S:
29668 case R6_OPC_CMP_UN_S:
29669 case R6_OPC_CMP_EQ_S:
29670 case R6_OPC_CMP_UEQ_S:
29671 case R6_OPC_CMP_LT_S:
29672 case R6_OPC_CMP_ULT_S:
29673 case R6_OPC_CMP_LE_S:
29674 case R6_OPC_CMP_ULE_S:
29675 case R6_OPC_CMP_SAF_S:
29676 case R6_OPC_CMP_SUN_S:
29677 case R6_OPC_CMP_SEQ_S:
29678 case R6_OPC_CMP_SEUQ_S:
29679 case R6_OPC_CMP_SLT_S:
29680 case R6_OPC_CMP_SULT_S:
29681 case R6_OPC_CMP_SLE_S:
29682 case R6_OPC_CMP_SULE_S:
29683 case R6_OPC_CMP_OR_S:
29684 case R6_OPC_CMP_UNE_S:
29685 case R6_OPC_CMP_NE_S:
29686 case R6_OPC_CMP_SOR_S:
29687 case R6_OPC_CMP_SUNE_S:
29688 case R6_OPC_CMP_SNE_S:
29689 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
29690 break;
29691 case R6_OPC_CMP_AF_D:
29692 case R6_OPC_CMP_UN_D:
29693 case R6_OPC_CMP_EQ_D:
29694 case R6_OPC_CMP_UEQ_D:
29695 case R6_OPC_CMP_LT_D:
29696 case R6_OPC_CMP_ULT_D:
29697 case R6_OPC_CMP_LE_D:
29698 case R6_OPC_CMP_ULE_D:
29699 case R6_OPC_CMP_SAF_D:
29700 case R6_OPC_CMP_SUN_D:
29701 case R6_OPC_CMP_SEQ_D:
29702 case R6_OPC_CMP_SEUQ_D:
29703 case R6_OPC_CMP_SLT_D:
29704 case R6_OPC_CMP_SULT_D:
29705 case R6_OPC_CMP_SLE_D:
29706 case R6_OPC_CMP_SULE_D:
29707 case R6_OPC_CMP_OR_D:
29708 case R6_OPC_CMP_UNE_D:
29709 case R6_OPC_CMP_NE_D:
29710 case R6_OPC_CMP_SOR_D:
29711 case R6_OPC_CMP_SUNE_D:
29712 case R6_OPC_CMP_SNE_D:
29713 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
29714 break;
29715 default:
29716 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
29717 rt, rd, sa, (imm >> 8) & 0x7);
29719 break;
29721 } else {
29722 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
29723 (imm >> 8) & 0x7);
29725 break;
29727 case OPC_BZ_V:
29728 case OPC_BNZ_V:
29729 case OPC_BZ_B:
29730 case OPC_BZ_H:
29731 case OPC_BZ_W:
29732 case OPC_BZ_D:
29733 case OPC_BNZ_B:
29734 case OPC_BNZ_H:
29735 case OPC_BNZ_W:
29736 case OPC_BNZ_D:
29737 check_insn(ctx, ASE_MSA);
29738 gen_msa_branch(env, ctx, op1);
29739 break;
29740 default:
29741 MIPS_INVAL("cp1");
29742 generate_exception_end(ctx, EXCP_RI);
29743 break;
29745 break;
29747 /* Compact branches [R6] and COP2 [non-R6] */
29748 case OPC_BC: /* OPC_LWC2 */
29749 case OPC_BALC: /* OPC_SWC2 */
29750 if (ctx->insn_flags & ISA_MIPS32R6) {
29751 /* OPC_BC, OPC_BALC */
29752 gen_compute_compact_branch(ctx, op, 0, 0,
29753 sextract32(ctx->opcode << 2, 0, 28));
29754 } else {
29755 /* OPC_LWC2, OPC_SWC2 */
29756 /* COP2: Not implemented. */
29757 generate_exception_err(ctx, EXCP_CpU, 2);
29759 break;
29760 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
29761 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
29762 if (ctx->insn_flags & ISA_MIPS32R6) {
29763 if (rs != 0) {
29764 /* OPC_BEQZC, OPC_BNEZC */
29765 gen_compute_compact_branch(ctx, op, rs, 0,
29766 sextract32(ctx->opcode << 2, 0, 23));
29767 } else {
29768 /* OPC_JIC, OPC_JIALC */
29769 gen_compute_compact_branch(ctx, op, 0, rt, imm);
29771 } else {
29772 /* OPC_LWC2, OPC_SWC2 */
29773 /* COP2: Not implemented. */
29774 generate_exception_err(ctx, EXCP_CpU, 2);
29776 break;
29777 case OPC_CP2:
29778 check_insn(ctx, INSN_LOONGSON2F);
29779 /* Note that these instructions use different fields. */
29780 gen_loongson_multimedia(ctx, sa, rd, rt);
29781 break;
29783 case OPC_CP3:
29784 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29785 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
29786 check_cp1_enabled(ctx);
29787 op1 = MASK_CP3(ctx->opcode);
29788 switch (op1) {
29789 case OPC_LUXC1:
29790 case OPC_SUXC1:
29791 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
29792 /* Fallthrough */
29793 case OPC_LWXC1:
29794 case OPC_LDXC1:
29795 case OPC_SWXC1:
29796 case OPC_SDXC1:
29797 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
29798 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
29799 break;
29800 case OPC_PREFX:
29801 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
29802 /* Treat as NOP. */
29803 break;
29804 case OPC_ALNV_PS:
29805 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
29806 /* Fallthrough */
29807 case OPC_MADD_S:
29808 case OPC_MADD_D:
29809 case OPC_MADD_PS:
29810 case OPC_MSUB_S:
29811 case OPC_MSUB_D:
29812 case OPC_MSUB_PS:
29813 case OPC_NMADD_S:
29814 case OPC_NMADD_D:
29815 case OPC_NMADD_PS:
29816 case OPC_NMSUB_S:
29817 case OPC_NMSUB_D:
29818 case OPC_NMSUB_PS:
29819 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
29820 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
29821 break;
29822 default:
29823 MIPS_INVAL("cp3");
29824 generate_exception_end(ctx, EXCP_RI);
29825 break;
29827 } else {
29828 generate_exception_err(ctx, EXCP_CpU, 1);
29830 break;
29832 #if defined(TARGET_MIPS64)
29833 /* MIPS64 opcodes */
29834 case OPC_LLD:
29835 if (ctx->insn_flags & INSN_R5900) {
29836 check_insn_opc_user_only(ctx, INSN_R5900);
29838 /* fall through */
29839 case OPC_LDL:
29840 case OPC_LDR:
29841 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29842 /* fall through */
29843 case OPC_LWU:
29844 case OPC_LD:
29845 check_insn(ctx, ISA_MIPS3);
29846 check_mips_64(ctx);
29847 gen_ld(ctx, op, rt, rs, imm);
29848 break;
29849 case OPC_SDL:
29850 case OPC_SDR:
29851 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29852 /* fall through */
29853 case OPC_SD:
29854 check_insn(ctx, ISA_MIPS3);
29855 check_mips_64(ctx);
29856 gen_st(ctx, op, rt, rs, imm);
29857 break;
29858 case OPC_SCD:
29859 check_insn_opc_removed(ctx, ISA_MIPS32R6);
29860 check_insn(ctx, ISA_MIPS3);
29861 if (ctx->insn_flags & INSN_R5900) {
29862 check_insn_opc_user_only(ctx, INSN_R5900);
29864 check_mips_64(ctx);
29865 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
29866 break;
29867 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
29868 if (ctx->insn_flags & ISA_MIPS32R6) {
29869 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
29870 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29871 } else {
29872 /* OPC_DADDI */
29873 check_insn(ctx, ISA_MIPS3);
29874 check_mips_64(ctx);
29875 gen_arith_imm(ctx, op, rt, rs, imm);
29877 break;
29878 case OPC_DADDIU:
29879 check_insn(ctx, ISA_MIPS3);
29880 check_mips_64(ctx);
29881 gen_arith_imm(ctx, op, rt, rs, imm);
29882 break;
29883 #else
29884 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
29885 if (ctx->insn_flags & ISA_MIPS32R6) {
29886 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
29887 } else {
29888 MIPS_INVAL("major opcode");
29889 generate_exception_end(ctx, EXCP_RI);
29891 break;
29892 #endif
29893 case OPC_DAUI: /* OPC_JALX */
29894 if (ctx->insn_flags & ISA_MIPS32R6) {
29895 #if defined(TARGET_MIPS64)
29896 /* OPC_DAUI */
29897 check_mips_64(ctx);
29898 if (rs == 0) {
29899 generate_exception(ctx, EXCP_RI);
29900 } else if (rt != 0) {
29901 TCGv t0 = tcg_temp_new();
29902 gen_load_gpr(t0, rs);
29903 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
29904 tcg_temp_free(t0);
29906 #else
29907 generate_exception_end(ctx, EXCP_RI);
29908 MIPS_INVAL("major opcode");
29909 #endif
29910 } else {
29911 /* OPC_JALX */
29912 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
29913 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
29914 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
29916 break;
29917 case OPC_MSA: /* OPC_MDMX */
29918 if (ctx->insn_flags & INSN_R5900) {
29919 #if defined(TARGET_MIPS64)
29920 gen_mmi_lq(env, ctx); /* MMI_OPC_LQ */
29921 #endif
29922 } else {
29923 /* MDMX: Not implemented. */
29924 gen_msa(env, ctx);
29926 break;
29927 case OPC_PCREL:
29928 check_insn(ctx, ISA_MIPS32R6);
29929 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
29930 break;
29931 default: /* Invalid */
29932 MIPS_INVAL("major opcode");
29933 generate_exception_end(ctx, EXCP_RI);
29934 break;
29938 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
29940 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29941 CPUMIPSState *env = cs->env_ptr;
29943 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
29944 ctx->saved_pc = -1;
29945 ctx->insn_flags = env->insn_flags;
29946 ctx->CP0_Config1 = env->CP0_Config1;
29947 ctx->CP0_Config2 = env->CP0_Config2;
29948 ctx->CP0_Config3 = env->CP0_Config3;
29949 ctx->CP0_Config5 = env->CP0_Config5;
29950 ctx->btarget = 0;
29951 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
29952 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
29953 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
29954 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
29955 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
29956 ctx->PAMask = env->PAMask;
29957 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
29958 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
29959 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
29960 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
29961 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
29962 /* Restore delay slot state from the tb context. */
29963 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
29964 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
29965 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
29966 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
29967 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
29968 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
29969 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
29970 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
29971 restore_cpu_state(env, ctx);
29972 #ifdef CONFIG_USER_ONLY
29973 ctx->mem_idx = MIPS_HFLAG_UM;
29974 #else
29975 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
29976 #endif
29977 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
29978 MO_UNALN : MO_ALIGN;
29980 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
29981 ctx->hflags);
29984 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
29988 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
29990 DisasContext *ctx = container_of(dcbase, DisasContext, base);
29992 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
29993 ctx->btarget);
29996 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
29997 const CPUBreakpoint *bp)
29999 DisasContext *ctx = container_of(dcbase, DisasContext, base);
30001 save_cpu_state(ctx, 1);
30002 ctx->base.is_jmp = DISAS_NORETURN;
30003 gen_helper_raise_exception_debug(cpu_env);
30005 * The address covered by the breakpoint must be included in
30006 * [tb->pc, tb->pc + tb->size) in order to for it to be
30007 * properly cleared -- thus we increment the PC here so that
30008 * the logic setting tb->size below does the right thing.
30010 ctx->base.pc_next += 4;
30011 return true;
30014 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
30016 CPUMIPSState *env = cs->env_ptr;
30017 DisasContext *ctx = container_of(dcbase, DisasContext, base);
30018 int insn_bytes;
30019 int is_slot;
30021 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
30022 if (ctx->insn_flags & ISA_NANOMIPS32) {
30023 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
30024 insn_bytes = decode_nanomips_opc(env, ctx);
30025 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
30026 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
30027 insn_bytes = 4;
30028 decode_opc(env, ctx);
30029 } else if (ctx->insn_flags & ASE_MICROMIPS) {
30030 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
30031 insn_bytes = decode_micromips_opc(env, ctx);
30032 } else if (ctx->insn_flags & ASE_MIPS16) {
30033 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
30034 insn_bytes = decode_mips16_opc(env, ctx);
30035 } else {
30036 generate_exception_end(ctx, EXCP_RI);
30037 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
30038 return;
30041 if (ctx->hflags & MIPS_HFLAG_BMASK) {
30042 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
30043 MIPS_HFLAG_FBNSLOT))) {
30045 * Force to generate branch as there is neither delay nor
30046 * forbidden slot.
30048 is_slot = 1;
30050 if ((ctx->hflags & MIPS_HFLAG_M16) &&
30051 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
30053 * Force to generate branch as microMIPS R6 doesn't restrict
30054 * branches in the forbidden slot.
30056 is_slot = 1;
30059 if (is_slot) {
30060 gen_branch(ctx, insn_bytes);
30062 ctx->base.pc_next += insn_bytes;
30064 if (ctx->base.is_jmp != DISAS_NEXT) {
30065 return;
30068 * Execute a branch and its delay slot as a single instruction.
30069 * This is what GDB expects and is consistent with what the
30070 * hardware does (e.g. if a delay slot instruction faults, the
30071 * reported PC is the PC of the branch).
30073 if (ctx->base.singlestep_enabled &&
30074 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
30075 ctx->base.is_jmp = DISAS_TOO_MANY;
30077 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
30078 ctx->base.is_jmp = DISAS_TOO_MANY;
30082 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
30084 DisasContext *ctx = container_of(dcbase, DisasContext, base);
30086 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
30087 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
30088 gen_helper_raise_exception_debug(cpu_env);
30089 } else {
30090 switch (ctx->base.is_jmp) {
30091 case DISAS_STOP:
30092 gen_save_pc(ctx->base.pc_next);
30093 tcg_gen_lookup_and_goto_ptr();
30094 break;
30095 case DISAS_NEXT:
30096 case DISAS_TOO_MANY:
30097 save_cpu_state(ctx, 0);
30098 gen_goto_tb(ctx, 0, ctx->base.pc_next);
30099 break;
30100 case DISAS_EXIT:
30101 tcg_gen_exit_tb(NULL, 0);
30102 break;
30103 case DISAS_NORETURN:
30104 break;
30105 default:
30106 g_assert_not_reached();
30111 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
30113 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
30114 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
30117 static const TranslatorOps mips_tr_ops = {
30118 .init_disas_context = mips_tr_init_disas_context,
30119 .tb_start = mips_tr_tb_start,
30120 .insn_start = mips_tr_insn_start,
30121 .breakpoint_check = mips_tr_breakpoint_check,
30122 .translate_insn = mips_tr_translate_insn,
30123 .tb_stop = mips_tr_tb_stop,
30124 .disas_log = mips_tr_disas_log,
30127 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
30129 DisasContext ctx;
30131 translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
30134 static void fpu_dump_state(CPUMIPSState *env, FILE * f, int flags)
30136 int i;
30137 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
30139 #define printfpr(fp) \
30140 do { \
30141 if (is_fpu64) \
30142 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
30143 " fd:%13g fs:%13g psu: %13g\n", \
30144 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
30145 (double)(fp)->fd, \
30146 (double)(fp)->fs[FP_ENDIAN_IDX], \
30147 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
30148 else { \
30149 fpr_t tmp; \
30150 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
30151 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
30152 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
30153 " fd:%13g fs:%13g psu:%13g\n", \
30154 tmp.w[FP_ENDIAN_IDX], tmp.d, \
30155 (double)tmp.fd, \
30156 (double)tmp.fs[FP_ENDIAN_IDX], \
30157 (double)tmp.fs[!FP_ENDIAN_IDX]); \
30159 } while (0)
30162 qemu_fprintf(f,
30163 "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
30164 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
30165 get_float_exception_flags(&env->active_fpu.fp_status));
30166 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
30167 qemu_fprintf(f, "%3s: ", fregnames[i]);
30168 printfpr(&env->active_fpu.fpr[i]);
30171 #undef printfpr
30174 void mips_cpu_dump_state(CPUState *cs, FILE *f, int flags)
30176 MIPSCPU *cpu = MIPS_CPU(cs);
30177 CPUMIPSState *env = &cpu->env;
30178 int i;
30180 qemu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
30181 " LO=0x" TARGET_FMT_lx " ds %04x "
30182 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
30183 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
30184 env->hflags, env->btarget, env->bcond);
30185 for (i = 0; i < 32; i++) {
30186 if ((i & 3) == 0) {
30187 qemu_fprintf(f, "GPR%02d:", i);
30189 qemu_fprintf(f, " %s " TARGET_FMT_lx,
30190 regnames[i], env->active_tc.gpr[i]);
30191 if ((i & 3) == 3) {
30192 qemu_fprintf(f, "\n");
30196 qemu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x"
30197 TARGET_FMT_lx "\n",
30198 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
30199 qemu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
30200 PRIx64 "\n",
30201 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
30202 qemu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
30203 env->CP0_Config2, env->CP0_Config3);
30204 qemu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
30205 env->CP0_Config4, env->CP0_Config5);
30206 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
30207 fpu_dump_state(env, f, flags);
30211 void mips_tcg_init(void)
30213 int i;
30215 cpu_gpr[0] = NULL;
30216 for (i = 1; i < 32; i++)
30217 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
30218 offsetof(CPUMIPSState,
30219 active_tc.gpr[i]),
30220 regnames[i]);
30222 for (i = 0; i < 32; i++) {
30223 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
30224 msa_wr_d[i * 2] =
30225 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
30227 * The scalar floating-point unit (FPU) registers are mapped on
30228 * the MSA vector registers.
30230 fpu_f64[i] = msa_wr_d[i * 2];
30231 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
30232 msa_wr_d[i * 2 + 1] =
30233 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
30236 cpu_PC = tcg_global_mem_new(cpu_env,
30237 offsetof(CPUMIPSState, active_tc.PC), "PC");
30238 for (i = 0; i < MIPS_DSP_ACC; i++) {
30239 cpu_HI[i] = tcg_global_mem_new(cpu_env,
30240 offsetof(CPUMIPSState, active_tc.HI[i]),
30241 regnames_HI[i]);
30242 cpu_LO[i] = tcg_global_mem_new(cpu_env,
30243 offsetof(CPUMIPSState, active_tc.LO[i]),
30244 regnames_LO[i]);
30246 cpu_dspctrl = tcg_global_mem_new(cpu_env,
30247 offsetof(CPUMIPSState,
30248 active_tc.DSPControl),
30249 "DSPControl");
30250 bcond = tcg_global_mem_new(cpu_env,
30251 offsetof(CPUMIPSState, bcond), "bcond");
30252 btarget = tcg_global_mem_new(cpu_env,
30253 offsetof(CPUMIPSState, btarget), "btarget");
30254 hflags = tcg_global_mem_new_i32(cpu_env,
30255 offsetof(CPUMIPSState, hflags), "hflags");
30257 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
30258 offsetof(CPUMIPSState, active_fpu.fcr0),
30259 "fcr0");
30260 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
30261 offsetof(CPUMIPSState, active_fpu.fcr31),
30262 "fcr31");
30263 cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
30264 "lladdr");
30265 cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
30266 "llval");
30268 #if defined(TARGET_MIPS64)
30269 cpu_mmr[0] = NULL;
30270 for (i = 1; i < 32; i++) {
30271 cpu_mmr[i] = tcg_global_mem_new_i64(cpu_env,
30272 offsetof(CPUMIPSState,
30273 active_tc.mmr[i]),
30274 regnames[i]);
30276 #endif
30278 #if !defined(TARGET_MIPS64)
30279 for (i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
30280 mxu_gpr[i] = tcg_global_mem_new(cpu_env,
30281 offsetof(CPUMIPSState,
30282 active_tc.mxu_gpr[i]),
30283 mxuregnames[i]);
30286 mxu_CR = tcg_global_mem_new(cpu_env,
30287 offsetof(CPUMIPSState, active_tc.mxu_cr),
30288 mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
30289 #endif
30292 #include "translate_init.inc.c"
30294 void cpu_mips_realize_env(CPUMIPSState *env)
30296 env->exception_base = (int32_t)0xBFC00000;
30298 #ifndef CONFIG_USER_ONLY
30299 mmu_init(env, env->cpu_model);
30300 #endif
30301 fpu_init(env, env->cpu_model);
30302 mvp_init(env, env->cpu_model);
30305 bool cpu_supports_cps_smp(const char *cpu_type)
30307 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
30308 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
30311 bool cpu_supports_isa(const char *cpu_type, uint64_t isa)
30313 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
30314 return (mcc->cpu_def->insn_flags & isa) != 0;
30317 void cpu_set_exception_base(int vp_index, target_ulong address)
30319 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
30320 vp->env.exception_base = address;
30323 void cpu_state_reset(CPUMIPSState *env)
30325 CPUState *cs = env_cpu(env);
30327 /* Reset registers to their default values */
30328 env->CP0_PRid = env->cpu_model->CP0_PRid;
30329 env->CP0_Config0 = env->cpu_model->CP0_Config0;
30330 #ifdef TARGET_WORDS_BIGENDIAN
30331 env->CP0_Config0 |= (1 << CP0C0_BE);
30332 #endif
30333 env->CP0_Config1 = env->cpu_model->CP0_Config1;
30334 env->CP0_Config2 = env->cpu_model->CP0_Config2;
30335 env->CP0_Config3 = env->cpu_model->CP0_Config3;
30336 env->CP0_Config4 = env->cpu_model->CP0_Config4;
30337 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
30338 env->CP0_Config5 = env->cpu_model->CP0_Config5;
30339 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
30340 env->CP0_Config6 = env->cpu_model->CP0_Config6;
30341 env->CP0_Config7 = env->cpu_model->CP0_Config7;
30342 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
30343 << env->cpu_model->CP0_LLAddr_shift;
30344 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
30345 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
30346 env->CCRes = env->cpu_model->CCRes;
30347 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
30348 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
30349 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
30350 env->current_tc = 0;
30351 env->SEGBITS = env->cpu_model->SEGBITS;
30352 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
30353 #if defined(TARGET_MIPS64)
30354 if (env->cpu_model->insn_flags & ISA_MIPS3) {
30355 env->SEGMask |= 3ULL << 62;
30357 #endif
30358 env->PABITS = env->cpu_model->PABITS;
30359 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
30360 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
30361 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
30362 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
30363 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
30364 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
30365 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
30366 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
30367 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
30368 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
30369 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
30370 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
30371 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
30372 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
30373 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
30374 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
30375 env->msair = env->cpu_model->MSAIR;
30376 env->insn_flags = env->cpu_model->insn_flags;
30378 #if defined(CONFIG_USER_ONLY)
30379 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
30380 # ifdef TARGET_MIPS64
30381 /* Enable 64-bit register mode. */
30382 env->CP0_Status |= (1 << CP0St_PX);
30383 # endif
30384 # ifdef TARGET_ABI_MIPSN64
30385 /* Enable 64-bit address mode. */
30386 env->CP0_Status |= (1 << CP0St_UX);
30387 # endif
30389 * Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
30390 * hardware registers.
30392 env->CP0_HWREna |= 0x0000000F;
30393 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
30394 env->CP0_Status |= (1 << CP0St_CU1);
30396 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
30397 env->CP0_Status |= (1 << CP0St_MX);
30399 # if defined(TARGET_MIPS64)
30400 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
30401 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
30402 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
30403 env->CP0_Status |= (1 << CP0St_FR);
30405 # endif
30406 #else
30407 if (env->hflags & MIPS_HFLAG_BMASK) {
30409 * If the exception was raised from a delay slot,
30410 * come back to the jump.
30412 env->CP0_ErrorEPC = (env->active_tc.PC
30413 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
30414 } else {
30415 env->CP0_ErrorEPC = env->active_tc.PC;
30417 env->active_tc.PC = env->exception_base;
30418 env->CP0_Random = env->tlb->nb_tlb - 1;
30419 env->tlb->tlb_in_use = env->tlb->nb_tlb;
30420 env->CP0_Wired = 0;
30421 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
30422 env->CP0_EBase = (cs->cpu_index & 0x3FF);
30423 if (mips_um_ksegs_enabled()) {
30424 env->CP0_EBase |= 0x40000000;
30425 } else {
30426 env->CP0_EBase |= (int32_t)0x80000000;
30428 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
30429 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
30431 env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
30432 0x3ff : 0xff;
30433 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
30435 * Vectored interrupts not implemented, timer on int 7,
30436 * no performance counters.
30438 env->CP0_IntCtl = 0xe0000000;
30440 int i;
30442 for (i = 0; i < 7; i++) {
30443 env->CP0_WatchLo[i] = 0;
30444 env->CP0_WatchHi[i] = 0x80000000;
30446 env->CP0_WatchLo[7] = 0;
30447 env->CP0_WatchHi[7] = 0;
30449 /* Count register increments in debug mode, EJTAG version 1 */
30450 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
30452 cpu_mips_store_count(env, 1);
30454 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
30455 int i;
30457 /* Only TC0 on VPE 0 starts as active. */
30458 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
30459 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
30460 env->tcs[i].CP0_TCHalt = 1;
30462 env->active_tc.CP0_TCHalt = 1;
30463 cs->halted = 1;
30465 if (cs->cpu_index == 0) {
30466 /* VPE0 starts up enabled. */
30467 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
30468 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
30470 /* TC0 starts up unhalted. */
30471 cs->halted = 0;
30472 env->active_tc.CP0_TCHalt = 0;
30473 env->tcs[0].CP0_TCHalt = 0;
30474 /* With thread 0 active. */
30475 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
30476 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
30481 * Configure default legacy segmentation control. We use this regardless of
30482 * whether segmentation control is presented to the guest.
30484 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
30485 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
30486 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
30487 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
30488 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
30489 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
30490 (2 << CP0SC_C);
30491 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
30492 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
30493 (3 << CP0SC_C)) << 16;
30494 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
30495 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
30496 (1 << CP0SC_EU) | (2 << CP0SC_C);
30497 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
30498 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
30499 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
30500 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
30501 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
30502 #endif
30503 if ((env->insn_flags & ISA_MIPS32R6) &&
30504 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
30505 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
30506 env->CP0_Status |= (1 << CP0St_FR);
30509 if (env->insn_flags & ISA_MIPS32R6) {
30510 /* PTW = 1 */
30511 env->CP0_PWSize = 0x40;
30512 /* GDI = 12 */
30513 /* UDI = 12 */
30514 /* MDI = 12 */
30515 /* PRI = 12 */
30516 /* PTEI = 2 */
30517 env->CP0_PWField = 0x0C30C302;
30518 } else {
30519 /* GDI = 0 */
30520 /* UDI = 0 */
30521 /* MDI = 0 */
30522 /* PRI = 0 */
30523 /* PTEI = 2 */
30524 env->CP0_PWField = 0x02;
30527 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
30528 /* microMIPS on reset when Config3.ISA is 3 */
30529 env->hflags |= MIPS_HFLAG_M16;
30532 /* MSA */
30533 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
30534 msa_reset(env);
30537 compute_hflags(env);
30538 restore_fp_status(env);
30539 restore_pamask(env);
30540 cs->exception_index = EXCP_NONE;
30542 if (semihosting_get_argc()) {
30543 /* UHI interface can be used to obtain argc and argv */
30544 env->active_tc.gpr[4] = -1;
30548 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
30549 target_ulong *data)
30551 env->active_tc.PC = data[0];
30552 env->hflags &= ~MIPS_HFLAG_BMASK;
30553 env->hflags |= data[1];
30554 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
30555 case MIPS_HFLAG_BR:
30556 break;
30557 case MIPS_HFLAG_BC:
30558 case MIPS_HFLAG_BL:
30559 case MIPS_HFLAG_B:
30560 env->btarget = data[2];
30561 break;