ppc/pnv: Add a PNOR model
[qemu/ar7.git] / target / mips / translate.c
blob4bff585bd63ce1985b1ebb174cb59915871c1ffe
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 MemOp 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 MemOp 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 MemOp 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 switch (opc) {
5550 case OPC_PADDSH:
5551 gen_helper_paddsh(t0, t0, t1);
5552 break;
5553 case OPC_PADDUSH:
5554 gen_helper_paddush(t0, t0, t1);
5555 break;
5556 case OPC_PADDH:
5557 gen_helper_paddh(t0, t0, t1);
5558 break;
5559 case OPC_PADDW:
5560 gen_helper_paddw(t0, t0, t1);
5561 break;
5562 case OPC_PADDSB:
5563 gen_helper_paddsb(t0, t0, t1);
5564 break;
5565 case OPC_PADDUSB:
5566 gen_helper_paddusb(t0, t0, t1);
5567 break;
5568 case OPC_PADDB:
5569 gen_helper_paddb(t0, t0, t1);
5570 break;
5572 case OPC_PSUBSH:
5573 gen_helper_psubsh(t0, t0, t1);
5574 break;
5575 case OPC_PSUBUSH:
5576 gen_helper_psubush(t0, t0, t1);
5577 break;
5578 case OPC_PSUBH:
5579 gen_helper_psubh(t0, t0, t1);
5580 break;
5581 case OPC_PSUBW:
5582 gen_helper_psubw(t0, t0, t1);
5583 break;
5584 case OPC_PSUBSB:
5585 gen_helper_psubsb(t0, t0, t1);
5586 break;
5587 case OPC_PSUBUSB:
5588 gen_helper_psubusb(t0, t0, t1);
5589 break;
5590 case OPC_PSUBB:
5591 gen_helper_psubb(t0, t0, t1);
5592 break;
5594 case OPC_PSHUFH:
5595 gen_helper_pshufh(t0, t0, t1);
5596 break;
5597 case OPC_PACKSSWH:
5598 gen_helper_packsswh(t0, t0, t1);
5599 break;
5600 case OPC_PACKSSHB:
5601 gen_helper_packsshb(t0, t0, t1);
5602 break;
5603 case OPC_PACKUSHB:
5604 gen_helper_packushb(t0, t0, t1);
5605 break;
5607 case OPC_PUNPCKLHW:
5608 gen_helper_punpcklhw(t0, t0, t1);
5609 break;
5610 case OPC_PUNPCKHHW:
5611 gen_helper_punpckhhw(t0, t0, t1);
5612 break;
5613 case OPC_PUNPCKLBH:
5614 gen_helper_punpcklbh(t0, t0, t1);
5615 break;
5616 case OPC_PUNPCKHBH:
5617 gen_helper_punpckhbh(t0, t0, t1);
5618 break;
5619 case OPC_PUNPCKLWD:
5620 gen_helper_punpcklwd(t0, t0, t1);
5621 break;
5622 case OPC_PUNPCKHWD:
5623 gen_helper_punpckhwd(t0, t0, t1);
5624 break;
5626 case OPC_PAVGH:
5627 gen_helper_pavgh(t0, t0, t1);
5628 break;
5629 case OPC_PAVGB:
5630 gen_helper_pavgb(t0, t0, t1);
5631 break;
5632 case OPC_PMAXSH:
5633 gen_helper_pmaxsh(t0, t0, t1);
5634 break;
5635 case OPC_PMINSH:
5636 gen_helper_pminsh(t0, t0, t1);
5637 break;
5638 case OPC_PMAXUB:
5639 gen_helper_pmaxub(t0, t0, t1);
5640 break;
5641 case OPC_PMINUB:
5642 gen_helper_pminub(t0, t0, t1);
5643 break;
5645 case OPC_PCMPEQW:
5646 gen_helper_pcmpeqw(t0, t0, t1);
5647 break;
5648 case OPC_PCMPGTW:
5649 gen_helper_pcmpgtw(t0, t0, t1);
5650 break;
5651 case OPC_PCMPEQH:
5652 gen_helper_pcmpeqh(t0, t0, t1);
5653 break;
5654 case OPC_PCMPGTH:
5655 gen_helper_pcmpgth(t0, t0, t1);
5656 break;
5657 case OPC_PCMPEQB:
5658 gen_helper_pcmpeqb(t0, t0, t1);
5659 break;
5660 case OPC_PCMPGTB:
5661 gen_helper_pcmpgtb(t0, t0, t1);
5662 break;
5664 case OPC_PSLLW:
5665 gen_helper_psllw(t0, t0, t1);
5666 break;
5667 case OPC_PSLLH:
5668 gen_helper_psllh(t0, t0, t1);
5669 break;
5670 case OPC_PSRLW:
5671 gen_helper_psrlw(t0, t0, t1);
5672 break;
5673 case OPC_PSRLH:
5674 gen_helper_psrlh(t0, t0, t1);
5675 break;
5676 case OPC_PSRAW:
5677 gen_helper_psraw(t0, t0, t1);
5678 break;
5679 case OPC_PSRAH:
5680 gen_helper_psrah(t0, t0, t1);
5681 break;
5683 case OPC_PMULLH:
5684 gen_helper_pmullh(t0, t0, t1);
5685 break;
5686 case OPC_PMULHH:
5687 gen_helper_pmulhh(t0, t0, t1);
5688 break;
5689 case OPC_PMULHUH:
5690 gen_helper_pmulhuh(t0, t0, t1);
5691 break;
5692 case OPC_PMADDHW:
5693 gen_helper_pmaddhw(t0, t0, t1);
5694 break;
5696 case OPC_PASUBUB:
5697 gen_helper_pasubub(t0, t0, t1);
5698 break;
5699 case OPC_BIADD:
5700 gen_helper_biadd(t0, t0);
5701 break;
5702 case OPC_PMOVMSKB:
5703 gen_helper_pmovmskb(t0, t0);
5704 break;
5706 case OPC_PADDD:
5707 tcg_gen_add_i64(t0, t0, t1);
5708 break;
5709 case OPC_PSUBD:
5710 tcg_gen_sub_i64(t0, t0, t1);
5711 break;
5712 case OPC_XOR_CP2:
5713 tcg_gen_xor_i64(t0, t0, t1);
5714 break;
5715 case OPC_NOR_CP2:
5716 tcg_gen_nor_i64(t0, t0, t1);
5717 break;
5718 case OPC_AND_CP2:
5719 tcg_gen_and_i64(t0, t0, t1);
5720 break;
5721 case OPC_OR_CP2:
5722 tcg_gen_or_i64(t0, t0, t1);
5723 break;
5725 case OPC_PANDN:
5726 tcg_gen_andc_i64(t0, t1, t0);
5727 break;
5729 case OPC_PINSRH_0:
5730 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
5731 break;
5732 case OPC_PINSRH_1:
5733 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
5734 break;
5735 case OPC_PINSRH_2:
5736 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
5737 break;
5738 case OPC_PINSRH_3:
5739 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
5740 break;
5742 case OPC_PEXTRH:
5743 tcg_gen_andi_i64(t1, t1, 3);
5744 tcg_gen_shli_i64(t1, t1, 4);
5745 tcg_gen_shr_i64(t0, t0, t1);
5746 tcg_gen_ext16u_i64(t0, t0);
5747 break;
5749 case OPC_ADDU_CP2:
5750 tcg_gen_add_i64(t0, t0, t1);
5751 tcg_gen_ext32s_i64(t0, t0);
5752 break;
5753 case OPC_SUBU_CP2:
5754 tcg_gen_sub_i64(t0, t0, t1);
5755 tcg_gen_ext32s_i64(t0, t0);
5756 break;
5758 case OPC_SLL_CP2:
5759 shift_max = 32;
5760 goto do_shift;
5761 case OPC_SRL_CP2:
5762 shift_max = 32;
5763 goto do_shift;
5764 case OPC_SRA_CP2:
5765 shift_max = 32;
5766 goto do_shift;
5767 case OPC_DSLL_CP2:
5768 shift_max = 64;
5769 goto do_shift;
5770 case OPC_DSRL_CP2:
5771 shift_max = 64;
5772 goto do_shift;
5773 case OPC_DSRA_CP2:
5774 shift_max = 64;
5775 goto do_shift;
5776 do_shift:
5777 /* Make sure shift count isn't TCG undefined behaviour. */
5778 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5780 switch (opc) {
5781 case OPC_SLL_CP2:
5782 case OPC_DSLL_CP2:
5783 tcg_gen_shl_i64(t0, t0, t1);
5784 break;
5785 case OPC_SRA_CP2:
5786 case OPC_DSRA_CP2:
5788 * Since SRA is UndefinedResult without sign-extended inputs,
5789 * we can treat SRA and DSRA the same.
5791 tcg_gen_sar_i64(t0, t0, t1);
5792 break;
5793 case OPC_SRL_CP2:
5794 /* We want to shift in zeros for SRL; zero-extend first. */
5795 tcg_gen_ext32u_i64(t0, t0);
5796 /* FALLTHRU */
5797 case OPC_DSRL_CP2:
5798 tcg_gen_shr_i64(t0, t0, t1);
5799 break;
5802 if (shift_max == 32) {
5803 tcg_gen_ext32s_i64(t0, t0);
5806 /* Shifts larger than MAX produce zero. */
5807 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5808 tcg_gen_neg_i64(t1, t1);
5809 tcg_gen_and_i64(t0, t0, t1);
5810 break;
5812 case OPC_ADD_CP2:
5813 case OPC_DADD_CP2:
5815 TCGv_i64 t2 = tcg_temp_new_i64();
5816 TCGLabel *lab = gen_new_label();
5818 tcg_gen_mov_i64(t2, t0);
5819 tcg_gen_add_i64(t0, t1, t2);
5820 if (opc == OPC_ADD_CP2) {
5821 tcg_gen_ext32s_i64(t0, t0);
5823 tcg_gen_xor_i64(t1, t1, t2);
5824 tcg_gen_xor_i64(t2, t2, t0);
5825 tcg_gen_andc_i64(t1, t2, t1);
5826 tcg_temp_free_i64(t2);
5827 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5828 generate_exception(ctx, EXCP_OVERFLOW);
5829 gen_set_label(lab);
5830 break;
5833 case OPC_SUB_CP2:
5834 case OPC_DSUB_CP2:
5836 TCGv_i64 t2 = tcg_temp_new_i64();
5837 TCGLabel *lab = gen_new_label();
5839 tcg_gen_mov_i64(t2, t0);
5840 tcg_gen_sub_i64(t0, t1, t2);
5841 if (opc == OPC_SUB_CP2) {
5842 tcg_gen_ext32s_i64(t0, t0);
5844 tcg_gen_xor_i64(t1, t1, t2);
5845 tcg_gen_xor_i64(t2, t2, t0);
5846 tcg_gen_and_i64(t1, t1, t2);
5847 tcg_temp_free_i64(t2);
5848 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5849 generate_exception(ctx, EXCP_OVERFLOW);
5850 gen_set_label(lab);
5851 break;
5854 case OPC_PMULUW:
5855 tcg_gen_ext32u_i64(t0, t0);
5856 tcg_gen_ext32u_i64(t1, t1);
5857 tcg_gen_mul_i64(t0, t0, t1);
5858 break;
5860 case OPC_SEQU_CP2:
5861 case OPC_SEQ_CP2:
5862 case OPC_SLTU_CP2:
5863 case OPC_SLT_CP2:
5864 case OPC_SLEU_CP2:
5865 case OPC_SLE_CP2:
5867 * ??? Document is unclear: Set FCC[CC]. Does that mean the
5868 * FD field is the CC field?
5870 default:
5871 MIPS_INVAL("loongson_cp2");
5872 generate_exception_end(ctx, EXCP_RI);
5873 return;
5876 gen_store_fpr64(ctx, t0, rd);
5878 tcg_temp_free_i64(t0);
5879 tcg_temp_free_i64(t1);
5882 /* Traps */
5883 static void gen_trap(DisasContext *ctx, uint32_t opc,
5884 int rs, int rt, int16_t imm)
5886 int cond;
5887 TCGv t0 = tcg_temp_new();
5888 TCGv t1 = tcg_temp_new();
5890 cond = 0;
5891 /* Load needed operands */
5892 switch (opc) {
5893 case OPC_TEQ:
5894 case OPC_TGE:
5895 case OPC_TGEU:
5896 case OPC_TLT:
5897 case OPC_TLTU:
5898 case OPC_TNE:
5899 /* Compare two registers */
5900 if (rs != rt) {
5901 gen_load_gpr(t0, rs);
5902 gen_load_gpr(t1, rt);
5903 cond = 1;
5905 break;
5906 case OPC_TEQI:
5907 case OPC_TGEI:
5908 case OPC_TGEIU:
5909 case OPC_TLTI:
5910 case OPC_TLTIU:
5911 case OPC_TNEI:
5912 /* Compare register to immediate */
5913 if (rs != 0 || imm != 0) {
5914 gen_load_gpr(t0, rs);
5915 tcg_gen_movi_tl(t1, (int32_t)imm);
5916 cond = 1;
5918 break;
5920 if (cond == 0) {
5921 switch (opc) {
5922 case OPC_TEQ: /* rs == rs */
5923 case OPC_TEQI: /* r0 == 0 */
5924 case OPC_TGE: /* rs >= rs */
5925 case OPC_TGEI: /* r0 >= 0 */
5926 case OPC_TGEU: /* rs >= rs unsigned */
5927 case OPC_TGEIU: /* r0 >= 0 unsigned */
5928 /* Always trap */
5929 generate_exception_end(ctx, EXCP_TRAP);
5930 break;
5931 case OPC_TLT: /* rs < rs */
5932 case OPC_TLTI: /* r0 < 0 */
5933 case OPC_TLTU: /* rs < rs unsigned */
5934 case OPC_TLTIU: /* r0 < 0 unsigned */
5935 case OPC_TNE: /* rs != rs */
5936 case OPC_TNEI: /* r0 != 0 */
5937 /* Never trap: treat as NOP. */
5938 break;
5940 } else {
5941 TCGLabel *l1 = gen_new_label();
5943 switch (opc) {
5944 case OPC_TEQ:
5945 case OPC_TEQI:
5946 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
5947 break;
5948 case OPC_TGE:
5949 case OPC_TGEI:
5950 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
5951 break;
5952 case OPC_TGEU:
5953 case OPC_TGEIU:
5954 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
5955 break;
5956 case OPC_TLT:
5957 case OPC_TLTI:
5958 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
5959 break;
5960 case OPC_TLTU:
5961 case OPC_TLTIU:
5962 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
5963 break;
5964 case OPC_TNE:
5965 case OPC_TNEI:
5966 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
5967 break;
5969 generate_exception(ctx, EXCP_TRAP);
5970 gen_set_label(l1);
5972 tcg_temp_free(t0);
5973 tcg_temp_free(t1);
5976 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
5978 if (unlikely(ctx->base.singlestep_enabled)) {
5979 return false;
5982 #ifndef CONFIG_USER_ONLY
5983 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
5984 #else
5985 return true;
5986 #endif
5989 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
5991 if (use_goto_tb(ctx, dest)) {
5992 tcg_gen_goto_tb(n);
5993 gen_save_pc(dest);
5994 tcg_gen_exit_tb(ctx->base.tb, n);
5995 } else {
5996 gen_save_pc(dest);
5997 if (ctx->base.singlestep_enabled) {
5998 save_cpu_state(ctx, 0);
5999 gen_helper_raise_exception_debug(cpu_env);
6001 tcg_gen_lookup_and_goto_ptr();
6005 /* Branches (before delay slot) */
6006 static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
6007 int insn_bytes,
6008 int rs, int rt, int32_t offset,
6009 int delayslot_size)
6011 target_ulong btgt = -1;
6012 int blink = 0;
6013 int bcond_compute = 0;
6014 TCGv t0 = tcg_temp_new();
6015 TCGv t1 = tcg_temp_new();
6017 if (ctx->hflags & MIPS_HFLAG_BMASK) {
6018 #ifdef MIPS_DEBUG_DISAS
6019 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
6020 TARGET_FMT_lx "\n", ctx->base.pc_next);
6021 #endif
6022 generate_exception_end(ctx, EXCP_RI);
6023 goto out;
6026 /* Load needed operands */
6027 switch (opc) {
6028 case OPC_BEQ:
6029 case OPC_BEQL:
6030 case OPC_BNE:
6031 case OPC_BNEL:
6032 /* Compare two registers */
6033 if (rs != rt) {
6034 gen_load_gpr(t0, rs);
6035 gen_load_gpr(t1, rt);
6036 bcond_compute = 1;
6038 btgt = ctx->base.pc_next + insn_bytes + offset;
6039 break;
6040 case OPC_BGEZ:
6041 case OPC_BGEZAL:
6042 case OPC_BGEZALL:
6043 case OPC_BGEZL:
6044 case OPC_BGTZ:
6045 case OPC_BGTZL:
6046 case OPC_BLEZ:
6047 case OPC_BLEZL:
6048 case OPC_BLTZ:
6049 case OPC_BLTZAL:
6050 case OPC_BLTZALL:
6051 case OPC_BLTZL:
6052 /* Compare to zero */
6053 if (rs != 0) {
6054 gen_load_gpr(t0, rs);
6055 bcond_compute = 1;
6057 btgt = ctx->base.pc_next + insn_bytes + offset;
6058 break;
6059 case OPC_BPOSGE32:
6060 #if defined(TARGET_MIPS64)
6061 case OPC_BPOSGE64:
6062 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
6063 #else
6064 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6065 #endif
6066 bcond_compute = 1;
6067 btgt = ctx->base.pc_next + insn_bytes + offset;
6068 break;
6069 case OPC_J:
6070 case OPC_JAL:
6071 case OPC_JALX:
6072 /* Jump to immediate */
6073 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
6074 (uint32_t)offset;
6075 break;
6076 case OPC_JR:
6077 case OPC_JALR:
6078 /* Jump to register */
6079 if (offset != 0 && offset != 16) {
6081 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6082 * others are reserved.
6084 MIPS_INVAL("jump hint");
6085 generate_exception_end(ctx, EXCP_RI);
6086 goto out;
6088 gen_load_gpr(btarget, rs);
6089 break;
6090 default:
6091 MIPS_INVAL("branch/jump");
6092 generate_exception_end(ctx, EXCP_RI);
6093 goto out;
6095 if (bcond_compute == 0) {
6096 /* No condition to be computed */
6097 switch (opc) {
6098 case OPC_BEQ: /* rx == rx */
6099 case OPC_BEQL: /* rx == rx likely */
6100 case OPC_BGEZ: /* 0 >= 0 */
6101 case OPC_BGEZL: /* 0 >= 0 likely */
6102 case OPC_BLEZ: /* 0 <= 0 */
6103 case OPC_BLEZL: /* 0 <= 0 likely */
6104 /* Always take */
6105 ctx->hflags |= MIPS_HFLAG_B;
6106 break;
6107 case OPC_BGEZAL: /* 0 >= 0 */
6108 case OPC_BGEZALL: /* 0 >= 0 likely */
6109 /* Always take and link */
6110 blink = 31;
6111 ctx->hflags |= MIPS_HFLAG_B;
6112 break;
6113 case OPC_BNE: /* rx != rx */
6114 case OPC_BGTZ: /* 0 > 0 */
6115 case OPC_BLTZ: /* 0 < 0 */
6116 /* Treat as NOP. */
6117 goto out;
6118 case OPC_BLTZAL: /* 0 < 0 */
6120 * Handle as an unconditional branch to get correct delay
6121 * slot checking.
6123 blink = 31;
6124 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
6125 ctx->hflags |= MIPS_HFLAG_B;
6126 break;
6127 case OPC_BLTZALL: /* 0 < 0 likely */
6128 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6129 /* Skip the instruction in the delay slot */
6130 ctx->base.pc_next += 4;
6131 goto out;
6132 case OPC_BNEL: /* rx != rx likely */
6133 case OPC_BGTZL: /* 0 > 0 likely */
6134 case OPC_BLTZL: /* 0 < 0 likely */
6135 /* Skip the instruction in the delay slot */
6136 ctx->base.pc_next += 4;
6137 goto out;
6138 case OPC_J:
6139 ctx->hflags |= MIPS_HFLAG_B;
6140 break;
6141 case OPC_JALX:
6142 ctx->hflags |= MIPS_HFLAG_BX;
6143 /* Fallthrough */
6144 case OPC_JAL:
6145 blink = 31;
6146 ctx->hflags |= MIPS_HFLAG_B;
6147 break;
6148 case OPC_JR:
6149 ctx->hflags |= MIPS_HFLAG_BR;
6150 break;
6151 case OPC_JALR:
6152 blink = rt;
6153 ctx->hflags |= MIPS_HFLAG_BR;
6154 break;
6155 default:
6156 MIPS_INVAL("branch/jump");
6157 generate_exception_end(ctx, EXCP_RI);
6158 goto out;
6160 } else {
6161 switch (opc) {
6162 case OPC_BEQ:
6163 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6164 goto not_likely;
6165 case OPC_BEQL:
6166 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6167 goto likely;
6168 case OPC_BNE:
6169 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6170 goto not_likely;
6171 case OPC_BNEL:
6172 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6173 goto likely;
6174 case OPC_BGEZ:
6175 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6176 goto not_likely;
6177 case OPC_BGEZL:
6178 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6179 goto likely;
6180 case OPC_BGEZAL:
6181 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6182 blink = 31;
6183 goto not_likely;
6184 case OPC_BGEZALL:
6185 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6186 blink = 31;
6187 goto likely;
6188 case OPC_BGTZ:
6189 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6190 goto not_likely;
6191 case OPC_BGTZL:
6192 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6193 goto likely;
6194 case OPC_BLEZ:
6195 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6196 goto not_likely;
6197 case OPC_BLEZL:
6198 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6199 goto likely;
6200 case OPC_BLTZ:
6201 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6202 goto not_likely;
6203 case OPC_BLTZL:
6204 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6205 goto likely;
6206 case OPC_BPOSGE32:
6207 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6208 goto not_likely;
6209 #if defined(TARGET_MIPS64)
6210 case OPC_BPOSGE64:
6211 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
6212 goto not_likely;
6213 #endif
6214 case OPC_BLTZAL:
6215 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6216 blink = 31;
6217 not_likely:
6218 ctx->hflags |= MIPS_HFLAG_BC;
6219 break;
6220 case OPC_BLTZALL:
6221 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6222 blink = 31;
6223 likely:
6224 ctx->hflags |= MIPS_HFLAG_BL;
6225 break;
6226 default:
6227 MIPS_INVAL("conditional branch/jump");
6228 generate_exception_end(ctx, EXCP_RI);
6229 goto out;
6233 ctx->btarget = btgt;
6235 switch (delayslot_size) {
6236 case 2:
6237 ctx->hflags |= MIPS_HFLAG_BDS16;
6238 break;
6239 case 4:
6240 ctx->hflags |= MIPS_HFLAG_BDS32;
6241 break;
6244 if (blink > 0) {
6245 int post_delay = insn_bytes + delayslot_size;
6246 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
6248 tcg_gen_movi_tl(cpu_gpr[blink],
6249 ctx->base.pc_next + post_delay + lowbit);
6252 out:
6253 if (insn_bytes == 2) {
6254 ctx->hflags |= MIPS_HFLAG_B16;
6256 tcg_temp_free(t0);
6257 tcg_temp_free(t1);
6261 /* nanoMIPS Branches */
6262 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
6263 int insn_bytes,
6264 int rs, int rt, int32_t offset)
6266 target_ulong btgt = -1;
6267 int bcond_compute = 0;
6268 TCGv t0 = tcg_temp_new();
6269 TCGv t1 = tcg_temp_new();
6271 /* Load needed operands */
6272 switch (opc) {
6273 case OPC_BEQ:
6274 case OPC_BNE:
6275 /* Compare two registers */
6276 if (rs != rt) {
6277 gen_load_gpr(t0, rs);
6278 gen_load_gpr(t1, rt);
6279 bcond_compute = 1;
6281 btgt = ctx->base.pc_next + insn_bytes + offset;
6282 break;
6283 case OPC_BGEZAL:
6284 /* Compare to zero */
6285 if (rs != 0) {
6286 gen_load_gpr(t0, rs);
6287 bcond_compute = 1;
6289 btgt = ctx->base.pc_next + insn_bytes + offset;
6290 break;
6291 case OPC_BPOSGE32:
6292 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6293 bcond_compute = 1;
6294 btgt = ctx->base.pc_next + insn_bytes + offset;
6295 break;
6296 case OPC_JR:
6297 case OPC_JALR:
6298 /* Jump to register */
6299 if (offset != 0 && offset != 16) {
6301 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6302 * others are reserved.
6304 MIPS_INVAL("jump hint");
6305 generate_exception_end(ctx, EXCP_RI);
6306 goto out;
6308 gen_load_gpr(btarget, rs);
6309 break;
6310 default:
6311 MIPS_INVAL("branch/jump");
6312 generate_exception_end(ctx, EXCP_RI);
6313 goto out;
6315 if (bcond_compute == 0) {
6316 /* No condition to be computed */
6317 switch (opc) {
6318 case OPC_BEQ: /* rx == rx */
6319 /* Always take */
6320 ctx->hflags |= MIPS_HFLAG_B;
6321 break;
6322 case OPC_BGEZAL: /* 0 >= 0 */
6323 /* Always take and link */
6324 tcg_gen_movi_tl(cpu_gpr[31],
6325 ctx->base.pc_next + insn_bytes);
6326 ctx->hflags |= MIPS_HFLAG_B;
6327 break;
6328 case OPC_BNE: /* rx != rx */
6329 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6330 /* Skip the instruction in the delay slot */
6331 ctx->base.pc_next += 4;
6332 goto out;
6333 case OPC_JR:
6334 ctx->hflags |= MIPS_HFLAG_BR;
6335 break;
6336 case OPC_JALR:
6337 if (rt > 0) {
6338 tcg_gen_movi_tl(cpu_gpr[rt],
6339 ctx->base.pc_next + insn_bytes);
6341 ctx->hflags |= MIPS_HFLAG_BR;
6342 break;
6343 default:
6344 MIPS_INVAL("branch/jump");
6345 generate_exception_end(ctx, EXCP_RI);
6346 goto out;
6348 } else {
6349 switch (opc) {
6350 case OPC_BEQ:
6351 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6352 goto not_likely;
6353 case OPC_BNE:
6354 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6355 goto not_likely;
6356 case OPC_BGEZAL:
6357 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6358 tcg_gen_movi_tl(cpu_gpr[31],
6359 ctx->base.pc_next + insn_bytes);
6360 goto not_likely;
6361 case OPC_BPOSGE32:
6362 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6363 not_likely:
6364 ctx->hflags |= MIPS_HFLAG_BC;
6365 break;
6366 default:
6367 MIPS_INVAL("conditional branch/jump");
6368 generate_exception_end(ctx, EXCP_RI);
6369 goto out;
6373 ctx->btarget = btgt;
6375 out:
6376 if (insn_bytes == 2) {
6377 ctx->hflags |= MIPS_HFLAG_B16;
6379 tcg_temp_free(t0);
6380 tcg_temp_free(t1);
6384 /* special3 bitfield operations */
6385 static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
6386 int rs, int lsb, int msb)
6388 TCGv t0 = tcg_temp_new();
6389 TCGv t1 = tcg_temp_new();
6391 gen_load_gpr(t1, rs);
6392 switch (opc) {
6393 case OPC_EXT:
6394 if (lsb + msb > 31) {
6395 goto fail;
6397 if (msb != 31) {
6398 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6399 } else {
6401 * The two checks together imply that lsb == 0,
6402 * so this is a simple sign-extension.
6404 tcg_gen_ext32s_tl(t0, t1);
6406 break;
6407 #if defined(TARGET_MIPS64)
6408 case OPC_DEXTU:
6409 lsb += 32;
6410 goto do_dext;
6411 case OPC_DEXTM:
6412 msb += 32;
6413 goto do_dext;
6414 case OPC_DEXT:
6415 do_dext:
6416 if (lsb + msb > 63) {
6417 goto fail;
6419 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6420 break;
6421 #endif
6422 case OPC_INS:
6423 if (lsb > msb) {
6424 goto fail;
6426 gen_load_gpr(t0, rt);
6427 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6428 tcg_gen_ext32s_tl(t0, t0);
6429 break;
6430 #if defined(TARGET_MIPS64)
6431 case OPC_DINSU:
6432 lsb += 32;
6433 /* FALLTHRU */
6434 case OPC_DINSM:
6435 msb += 32;
6436 /* FALLTHRU */
6437 case OPC_DINS:
6438 if (lsb > msb) {
6439 goto fail;
6441 gen_load_gpr(t0, rt);
6442 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6443 break;
6444 #endif
6445 default:
6446 fail:
6447 MIPS_INVAL("bitops");
6448 generate_exception_end(ctx, EXCP_RI);
6449 tcg_temp_free(t0);
6450 tcg_temp_free(t1);
6451 return;
6453 gen_store_gpr(t0, rt);
6454 tcg_temp_free(t0);
6455 tcg_temp_free(t1);
6458 static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
6460 TCGv t0;
6462 if (rd == 0) {
6463 /* If no destination, treat it as a NOP. */
6464 return;
6467 t0 = tcg_temp_new();
6468 gen_load_gpr(t0, rt);
6469 switch (op2) {
6470 case OPC_WSBH:
6472 TCGv t1 = tcg_temp_new();
6473 TCGv t2 = tcg_const_tl(0x00FF00FF);
6475 tcg_gen_shri_tl(t1, t0, 8);
6476 tcg_gen_and_tl(t1, t1, t2);
6477 tcg_gen_and_tl(t0, t0, t2);
6478 tcg_gen_shli_tl(t0, t0, 8);
6479 tcg_gen_or_tl(t0, t0, t1);
6480 tcg_temp_free(t2);
6481 tcg_temp_free(t1);
6482 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6484 break;
6485 case OPC_SEB:
6486 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
6487 break;
6488 case OPC_SEH:
6489 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
6490 break;
6491 #if defined(TARGET_MIPS64)
6492 case OPC_DSBH:
6494 TCGv t1 = tcg_temp_new();
6495 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
6497 tcg_gen_shri_tl(t1, t0, 8);
6498 tcg_gen_and_tl(t1, t1, t2);
6499 tcg_gen_and_tl(t0, t0, t2);
6500 tcg_gen_shli_tl(t0, t0, 8);
6501 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6502 tcg_temp_free(t2);
6503 tcg_temp_free(t1);
6505 break;
6506 case OPC_DSHD:
6508 TCGv t1 = tcg_temp_new();
6509 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
6511 tcg_gen_shri_tl(t1, t0, 16);
6512 tcg_gen_and_tl(t1, t1, t2);
6513 tcg_gen_and_tl(t0, t0, t2);
6514 tcg_gen_shli_tl(t0, t0, 16);
6515 tcg_gen_or_tl(t0, t0, t1);
6516 tcg_gen_shri_tl(t1, t0, 32);
6517 tcg_gen_shli_tl(t0, t0, 32);
6518 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6519 tcg_temp_free(t2);
6520 tcg_temp_free(t1);
6522 break;
6523 #endif
6524 default:
6525 MIPS_INVAL("bsfhl");
6526 generate_exception_end(ctx, EXCP_RI);
6527 tcg_temp_free(t0);
6528 return;
6530 tcg_temp_free(t0);
6533 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
6534 int imm2)
6536 TCGv t0;
6537 TCGv t1;
6538 if (rd == 0) {
6539 /* Treat as NOP. */
6540 return;
6542 t0 = tcg_temp_new();
6543 t1 = tcg_temp_new();
6544 gen_load_gpr(t0, rs);
6545 gen_load_gpr(t1, rt);
6546 tcg_gen_shli_tl(t0, t0, imm2 + 1);
6547 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
6548 if (opc == OPC_LSA) {
6549 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
6552 tcg_temp_free(t1);
6553 tcg_temp_free(t0);
6555 return;
6558 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
6559 int rt, int bits)
6561 TCGv t0;
6562 if (rd == 0) {
6563 /* Treat as NOP. */
6564 return;
6566 t0 = tcg_temp_new();
6567 if (bits == 0 || bits == wordsz) {
6568 if (bits == 0) {
6569 gen_load_gpr(t0, rt);
6570 } else {
6571 gen_load_gpr(t0, rs);
6573 switch (wordsz) {
6574 case 32:
6575 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6576 break;
6577 #if defined(TARGET_MIPS64)
6578 case 64:
6579 tcg_gen_mov_tl(cpu_gpr[rd], t0);
6580 break;
6581 #endif
6583 } else {
6584 TCGv t1 = tcg_temp_new();
6585 gen_load_gpr(t0, rt);
6586 gen_load_gpr(t1, rs);
6587 switch (wordsz) {
6588 case 32:
6590 TCGv_i64 t2 = tcg_temp_new_i64();
6591 tcg_gen_concat_tl_i64(t2, t1, t0);
6592 tcg_gen_shri_i64(t2, t2, 32 - bits);
6593 gen_move_low32(cpu_gpr[rd], t2);
6594 tcg_temp_free_i64(t2);
6596 break;
6597 #if defined(TARGET_MIPS64)
6598 case 64:
6599 tcg_gen_shli_tl(t0, t0, bits);
6600 tcg_gen_shri_tl(t1, t1, 64 - bits);
6601 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
6602 break;
6603 #endif
6605 tcg_temp_free(t1);
6608 tcg_temp_free(t0);
6611 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6612 int bp)
6614 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
6617 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6618 int shift)
6620 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
6623 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
6625 TCGv t0;
6626 if (rd == 0) {
6627 /* Treat as NOP. */
6628 return;
6630 t0 = tcg_temp_new();
6631 gen_load_gpr(t0, rt);
6632 switch (opc) {
6633 case OPC_BITSWAP:
6634 gen_helper_bitswap(cpu_gpr[rd], t0);
6635 break;
6636 #if defined(TARGET_MIPS64)
6637 case OPC_DBITSWAP:
6638 gen_helper_dbitswap(cpu_gpr[rd], t0);
6639 break;
6640 #endif
6642 tcg_temp_free(t0);
6645 #ifndef CONFIG_USER_ONLY
6646 /* CP0 (MMU and control) */
6647 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
6649 TCGv_i64 t0 = tcg_temp_new_i64();
6650 TCGv_i64 t1 = tcg_temp_new_i64();
6652 tcg_gen_ext_tl_i64(t0, arg);
6653 tcg_gen_ld_i64(t1, cpu_env, off);
6654 #if defined(TARGET_MIPS64)
6655 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
6656 #else
6657 tcg_gen_concat32_i64(t1, t1, t0);
6658 #endif
6659 tcg_gen_st_i64(t1, cpu_env, off);
6660 tcg_temp_free_i64(t1);
6661 tcg_temp_free_i64(t0);
6664 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
6666 TCGv_i64 t0 = tcg_temp_new_i64();
6667 TCGv_i64 t1 = tcg_temp_new_i64();
6669 tcg_gen_ext_tl_i64(t0, arg);
6670 tcg_gen_ld_i64(t1, cpu_env, off);
6671 tcg_gen_concat32_i64(t1, t1, t0);
6672 tcg_gen_st_i64(t1, cpu_env, off);
6673 tcg_temp_free_i64(t1);
6674 tcg_temp_free_i64(t0);
6677 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
6679 TCGv_i64 t0 = tcg_temp_new_i64();
6681 tcg_gen_ld_i64(t0, cpu_env, off);
6682 #if defined(TARGET_MIPS64)
6683 tcg_gen_shri_i64(t0, t0, 30);
6684 #else
6685 tcg_gen_shri_i64(t0, t0, 32);
6686 #endif
6687 gen_move_low32(arg, t0);
6688 tcg_temp_free_i64(t0);
6691 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
6693 TCGv_i64 t0 = tcg_temp_new_i64();
6695 tcg_gen_ld_i64(t0, cpu_env, off);
6696 tcg_gen_shri_i64(t0, t0, 32 + shift);
6697 gen_move_low32(arg, t0);
6698 tcg_temp_free_i64(t0);
6701 static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
6703 TCGv_i32 t0 = tcg_temp_new_i32();
6705 tcg_gen_ld_i32(t0, cpu_env, off);
6706 tcg_gen_ext_i32_tl(arg, t0);
6707 tcg_temp_free_i32(t0);
6710 static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
6712 tcg_gen_ld_tl(arg, cpu_env, off);
6713 tcg_gen_ext32s_tl(arg, arg);
6716 static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
6718 TCGv_i32 t0 = tcg_temp_new_i32();
6720 tcg_gen_trunc_tl_i32(t0, arg);
6721 tcg_gen_st_i32(t0, cpu_env, off);
6722 tcg_temp_free_i32(t0);
6725 #define CP0_CHECK(c) \
6726 do { \
6727 if (!(c)) { \
6728 goto cp0_unimplemented; \
6730 } while (0)
6732 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6734 const char *register_name = "invalid";
6736 switch (reg) {
6737 case CP0_REGISTER_02:
6738 switch (sel) {
6739 case 0:
6740 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6741 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6742 register_name = "EntryLo0";
6743 break;
6744 default:
6745 goto cp0_unimplemented;
6747 break;
6748 case CP0_REGISTER_03:
6749 switch (sel) {
6750 case CP0_REG03__ENTRYLO1:
6751 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6752 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6753 register_name = "EntryLo1";
6754 break;
6755 default:
6756 goto cp0_unimplemented;
6758 break;
6759 case CP0_REGISTER_09:
6760 switch (sel) {
6761 case CP0_REG09__SAAR:
6762 CP0_CHECK(ctx->saar);
6763 gen_helper_mfhc0_saar(arg, cpu_env);
6764 register_name = "SAAR";
6765 break;
6766 default:
6767 goto cp0_unimplemented;
6769 break;
6770 case CP0_REGISTER_17:
6771 switch (sel) {
6772 case CP0_REG17__LLADDR:
6773 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
6774 ctx->CP0_LLAddr_shift);
6775 register_name = "LLAddr";
6776 break;
6777 case CP0_REG17__MAAR:
6778 CP0_CHECK(ctx->mrp);
6779 gen_helper_mfhc0_maar(arg, cpu_env);
6780 register_name = "MAAR";
6781 break;
6782 default:
6783 goto cp0_unimplemented;
6785 break;
6786 case CP0_REGISTER_28:
6787 switch (sel) {
6788 case 0:
6789 case 2:
6790 case 4:
6791 case 6:
6792 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
6793 register_name = "TagLo";
6794 break;
6795 default:
6796 goto cp0_unimplemented;
6798 break;
6799 default:
6800 goto cp0_unimplemented;
6802 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
6803 return;
6805 cp0_unimplemented:
6806 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
6807 register_name, reg, sel);
6808 tcg_gen_movi_tl(arg, 0);
6811 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6813 const char *register_name = "invalid";
6814 uint64_t mask = ctx->PAMask >> 36;
6816 switch (reg) {
6817 case CP0_REGISTER_02:
6818 switch (sel) {
6819 case 0:
6820 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6821 tcg_gen_andi_tl(arg, arg, mask);
6822 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6823 register_name = "EntryLo0";
6824 break;
6825 default:
6826 goto cp0_unimplemented;
6828 break;
6829 case CP0_REGISTER_03:
6830 switch (sel) {
6831 case CP0_REG03__ENTRYLO1:
6832 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6833 tcg_gen_andi_tl(arg, arg, mask);
6834 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6835 register_name = "EntryLo1";
6836 break;
6837 default:
6838 goto cp0_unimplemented;
6840 break;
6841 case CP0_REGISTER_09:
6842 switch (sel) {
6843 case CP0_REG09__SAAR:
6844 CP0_CHECK(ctx->saar);
6845 gen_helper_mthc0_saar(cpu_env, arg);
6846 register_name = "SAAR";
6847 break;
6848 default:
6849 goto cp0_unimplemented;
6851 break;
6852 case CP0_REGISTER_17:
6853 switch (sel) {
6854 case CP0_REG17__LLADDR:
6856 * LLAddr is read-only (the only exception is bit 0 if LLB is
6857 * supported); the CP0_LLAddr_rw_bitmask does not seem to be
6858 * relevant for modern MIPS cores supporting MTHC0, therefore
6859 * treating MTHC0 to LLAddr as NOP.
6861 register_name = "LLAddr";
6862 break;
6863 case CP0_REG17__MAAR:
6864 CP0_CHECK(ctx->mrp);
6865 gen_helper_mthc0_maar(cpu_env, arg);
6866 register_name = "MAAR";
6867 break;
6868 default:
6869 goto cp0_unimplemented;
6871 break;
6872 case CP0_REGISTER_28:
6873 switch (sel) {
6874 case 0:
6875 case 2:
6876 case 4:
6877 case 6:
6878 tcg_gen_andi_tl(arg, arg, mask);
6879 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
6880 register_name = "TagLo";
6881 break;
6882 default:
6883 goto cp0_unimplemented;
6885 break;
6886 default:
6887 goto cp0_unimplemented;
6889 trace_mips_translate_c0("mthc0", register_name, reg, sel);
6891 cp0_unimplemented:
6892 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
6893 register_name, reg, sel);
6896 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
6898 if (ctx->insn_flags & ISA_MIPS32R6) {
6899 tcg_gen_movi_tl(arg, 0);
6900 } else {
6901 tcg_gen_movi_tl(arg, ~0);
6905 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6907 const char *register_name = "invalid";
6909 if (sel != 0) {
6910 check_insn(ctx, ISA_MIPS32);
6913 switch (reg) {
6914 case CP0_REGISTER_00:
6915 switch (sel) {
6916 case CP0_REG00__INDEX:
6917 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6918 register_name = "Index";
6919 break;
6920 case CP0_REG00__MVPCONTROL:
6921 CP0_CHECK(ctx->insn_flags & ASE_MT);
6922 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6923 register_name = "MVPControl";
6924 break;
6925 case CP0_REG00__MVPCONF0:
6926 CP0_CHECK(ctx->insn_flags & ASE_MT);
6927 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6928 register_name = "MVPConf0";
6929 break;
6930 case CP0_REG00__MVPCONF1:
6931 CP0_CHECK(ctx->insn_flags & ASE_MT);
6932 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6933 register_name = "MVPConf1";
6934 break;
6935 case CP0_REG00__VPCONTROL:
6936 CP0_CHECK(ctx->vp);
6937 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6938 register_name = "VPControl";
6939 break;
6940 default:
6941 goto cp0_unimplemented;
6943 break;
6944 case CP0_REGISTER_01:
6945 switch (sel) {
6946 case CP0_REG01__RANDOM:
6947 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6948 gen_helper_mfc0_random(arg, cpu_env);
6949 register_name = "Random";
6950 break;
6951 case CP0_REG01__VPECONTROL:
6952 CP0_CHECK(ctx->insn_flags & ASE_MT);
6953 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6954 register_name = "VPEControl";
6955 break;
6956 case CP0_REG01__VPECONF0:
6957 CP0_CHECK(ctx->insn_flags & ASE_MT);
6958 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6959 register_name = "VPEConf0";
6960 break;
6961 case CP0_REG01__VPECONF1:
6962 CP0_CHECK(ctx->insn_flags & ASE_MT);
6963 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6964 register_name = "VPEConf1";
6965 break;
6966 case CP0_REG01__YQMASK:
6967 CP0_CHECK(ctx->insn_flags & ASE_MT);
6968 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
6969 register_name = "YQMask";
6970 break;
6971 case CP0_REG01__VPESCHEDULE:
6972 CP0_CHECK(ctx->insn_flags & ASE_MT);
6973 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
6974 register_name = "VPESchedule";
6975 break;
6976 case CP0_REG01__VPESCHEFBACK:
6977 CP0_CHECK(ctx->insn_flags & ASE_MT);
6978 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6979 register_name = "VPEScheFBack";
6980 break;
6981 case CP0_REG01__VPEOPT:
6982 CP0_CHECK(ctx->insn_flags & ASE_MT);
6983 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6984 register_name = "VPEOpt";
6985 break;
6986 default:
6987 goto cp0_unimplemented;
6989 break;
6990 case CP0_REGISTER_02:
6991 switch (sel) {
6992 case CP0_REG02__ENTRYLO0:
6994 TCGv_i64 tmp = tcg_temp_new_i64();
6995 tcg_gen_ld_i64(tmp, cpu_env,
6996 offsetof(CPUMIPSState, CP0_EntryLo0));
6997 #if defined(TARGET_MIPS64)
6998 if (ctx->rxi) {
6999 /* Move RI/XI fields to bits 31:30 */
7000 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
7001 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
7003 #endif
7004 gen_move_low32(arg, tmp);
7005 tcg_temp_free_i64(tmp);
7007 register_name = "EntryLo0";
7008 break;
7009 case CP0_REG02__TCSTATUS:
7010 CP0_CHECK(ctx->insn_flags & ASE_MT);
7011 gen_helper_mfc0_tcstatus(arg, cpu_env);
7012 register_name = "TCStatus";
7013 break;
7014 case CP0_REG02__TCBIND:
7015 CP0_CHECK(ctx->insn_flags & ASE_MT);
7016 gen_helper_mfc0_tcbind(arg, cpu_env);
7017 register_name = "TCBind";
7018 break;
7019 case CP0_REG02__TCRESTART:
7020 CP0_CHECK(ctx->insn_flags & ASE_MT);
7021 gen_helper_mfc0_tcrestart(arg, cpu_env);
7022 register_name = "TCRestart";
7023 break;
7024 case CP0_REG02__TCHALT:
7025 CP0_CHECK(ctx->insn_flags & ASE_MT);
7026 gen_helper_mfc0_tchalt(arg, cpu_env);
7027 register_name = "TCHalt";
7028 break;
7029 case CP0_REG02__TCCONTEXT:
7030 CP0_CHECK(ctx->insn_flags & ASE_MT);
7031 gen_helper_mfc0_tccontext(arg, cpu_env);
7032 register_name = "TCContext";
7033 break;
7034 case CP0_REG02__TCSCHEDULE:
7035 CP0_CHECK(ctx->insn_flags & ASE_MT);
7036 gen_helper_mfc0_tcschedule(arg, cpu_env);
7037 register_name = "TCSchedule";
7038 break;
7039 case CP0_REG02__TCSCHEFBACK:
7040 CP0_CHECK(ctx->insn_flags & ASE_MT);
7041 gen_helper_mfc0_tcschefback(arg, cpu_env);
7042 register_name = "TCScheFBack";
7043 break;
7044 default:
7045 goto cp0_unimplemented;
7047 break;
7048 case CP0_REGISTER_03:
7049 switch (sel) {
7050 case CP0_REG03__ENTRYLO1:
7052 TCGv_i64 tmp = tcg_temp_new_i64();
7053 tcg_gen_ld_i64(tmp, cpu_env,
7054 offsetof(CPUMIPSState, CP0_EntryLo1));
7055 #if defined(TARGET_MIPS64)
7056 if (ctx->rxi) {
7057 /* Move RI/XI fields to bits 31:30 */
7058 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
7059 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
7061 #endif
7062 gen_move_low32(arg, tmp);
7063 tcg_temp_free_i64(tmp);
7065 register_name = "EntryLo1";
7066 break;
7067 case CP0_REG03__GLOBALNUM:
7068 CP0_CHECK(ctx->vp);
7069 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
7070 register_name = "GlobalNumber";
7071 break;
7072 default:
7073 goto cp0_unimplemented;
7075 break;
7076 case CP0_REGISTER_04:
7077 switch (sel) {
7078 case CP0_REG04__CONTEXT:
7079 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
7080 tcg_gen_ext32s_tl(arg, arg);
7081 register_name = "Context";
7082 break;
7083 case CP0_REG04__CONTEXTCONFIG:
7084 /* SmartMIPS ASE */
7085 /* gen_helper_mfc0_contextconfig(arg); */
7086 register_name = "ContextConfig";
7087 goto cp0_unimplemented;
7088 case CP0_REG04__USERLOCAL:
7089 CP0_CHECK(ctx->ulri);
7090 tcg_gen_ld_tl(arg, cpu_env,
7091 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7092 tcg_gen_ext32s_tl(arg, arg);
7093 register_name = "UserLocal";
7094 break;
7095 default:
7096 goto cp0_unimplemented;
7098 break;
7099 case CP0_REGISTER_05:
7100 switch (sel) {
7101 case CP0_REG05__PAGEMASK:
7102 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
7103 register_name = "PageMask";
7104 break;
7105 case CP0_REG05__PAGEGRAIN:
7106 check_insn(ctx, ISA_MIPS32R2);
7107 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
7108 register_name = "PageGrain";
7109 break;
7110 case CP0_REG05__SEGCTL0:
7111 CP0_CHECK(ctx->sc);
7112 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
7113 tcg_gen_ext32s_tl(arg, arg);
7114 register_name = "SegCtl0";
7115 break;
7116 case CP0_REG05__SEGCTL1:
7117 CP0_CHECK(ctx->sc);
7118 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
7119 tcg_gen_ext32s_tl(arg, arg);
7120 register_name = "SegCtl1";
7121 break;
7122 case CP0_REG05__SEGCTL2:
7123 CP0_CHECK(ctx->sc);
7124 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
7125 tcg_gen_ext32s_tl(arg, arg);
7126 register_name = "SegCtl2";
7127 break;
7128 case CP0_REG05__PWBASE:
7129 check_pw(ctx);
7130 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7131 register_name = "PWBase";
7132 break;
7133 case CP0_REG05__PWFIELD:
7134 check_pw(ctx);
7135 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
7136 register_name = "PWField";
7137 break;
7138 case CP0_REG05__PWSIZE:
7139 check_pw(ctx);
7140 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
7141 register_name = "PWSize";
7142 break;
7143 default:
7144 goto cp0_unimplemented;
7146 break;
7147 case CP0_REGISTER_06:
7148 switch (sel) {
7149 case CP0_REG06__WIRED:
7150 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
7151 register_name = "Wired";
7152 break;
7153 case CP0_REG06__SRSCONF0:
7154 check_insn(ctx, ISA_MIPS32R2);
7155 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
7156 register_name = "SRSConf0";
7157 break;
7158 case CP0_REG06__SRSCONF1:
7159 check_insn(ctx, ISA_MIPS32R2);
7160 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
7161 register_name = "SRSConf1";
7162 break;
7163 case CP0_REG06__SRSCONF2:
7164 check_insn(ctx, ISA_MIPS32R2);
7165 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
7166 register_name = "SRSConf2";
7167 break;
7168 case CP0_REG06__SRSCONF3:
7169 check_insn(ctx, ISA_MIPS32R2);
7170 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
7171 register_name = "SRSConf3";
7172 break;
7173 case CP0_REG06__SRSCONF4:
7174 check_insn(ctx, ISA_MIPS32R2);
7175 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
7176 register_name = "SRSConf4";
7177 break;
7178 case CP0_REG06__PWCTL:
7179 check_pw(ctx);
7180 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
7181 register_name = "PWCtl";
7182 break;
7183 default:
7184 goto cp0_unimplemented;
7186 break;
7187 case CP0_REGISTER_07:
7188 switch (sel) {
7189 case CP0_REG07__HWRENA:
7190 check_insn(ctx, ISA_MIPS32R2);
7191 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
7192 register_name = "HWREna";
7193 break;
7194 default:
7195 goto cp0_unimplemented;
7197 break;
7198 case CP0_REGISTER_08:
7199 switch (sel) {
7200 case CP0_REG08__BADVADDR:
7201 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
7202 tcg_gen_ext32s_tl(arg, arg);
7203 register_name = "BadVAddr";
7204 break;
7205 case CP0_REG08__BADINSTR:
7206 CP0_CHECK(ctx->bi);
7207 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
7208 register_name = "BadInstr";
7209 break;
7210 case CP0_REG08__BADINSTRP:
7211 CP0_CHECK(ctx->bp);
7212 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
7213 register_name = "BadInstrP";
7214 break;
7215 case CP0_REG08__BADINSTRX:
7216 CP0_CHECK(ctx->bi);
7217 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7218 tcg_gen_andi_tl(arg, arg, ~0xffff);
7219 register_name = "BadInstrX";
7220 break;
7221 default:
7222 goto cp0_unimplemented;
7224 break;
7225 case CP0_REGISTER_09:
7226 switch (sel) {
7227 case CP0_REG09__COUNT:
7228 /* Mark as an IO operation because we read the time. */
7229 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7230 gen_io_start();
7232 gen_helper_mfc0_count(arg, cpu_env);
7234 * Break the TB to be able to take timer interrupts immediately
7235 * after reading count. DISAS_STOP isn't sufficient, we need to
7236 * ensure we break completely out of translated code.
7238 gen_save_pc(ctx->base.pc_next + 4);
7239 ctx->base.is_jmp = DISAS_EXIT;
7240 register_name = "Count";
7241 break;
7242 case CP0_REG09__SAARI:
7243 CP0_CHECK(ctx->saar);
7244 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
7245 register_name = "SAARI";
7246 break;
7247 case CP0_REG09__SAAR:
7248 CP0_CHECK(ctx->saar);
7249 gen_helper_mfc0_saar(arg, cpu_env);
7250 register_name = "SAAR";
7251 break;
7252 default:
7253 goto cp0_unimplemented;
7255 break;
7256 case CP0_REGISTER_10:
7257 switch (sel) {
7258 case CP0_REG10__ENTRYHI:
7259 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
7260 tcg_gen_ext32s_tl(arg, arg);
7261 register_name = "EntryHi";
7262 break;
7263 default:
7264 goto cp0_unimplemented;
7266 break;
7267 case CP0_REGISTER_11:
7268 switch (sel) {
7269 case CP0_REG11__COMPARE:
7270 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
7271 register_name = "Compare";
7272 break;
7273 /* 6,7 are implementation dependent */
7274 default:
7275 goto cp0_unimplemented;
7277 break;
7278 case CP0_REGISTER_12:
7279 switch (sel) {
7280 case CP0_REG12__STATUS:
7281 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
7282 register_name = "Status";
7283 break;
7284 case CP0_REG12__INTCTL:
7285 check_insn(ctx, ISA_MIPS32R2);
7286 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
7287 register_name = "IntCtl";
7288 break;
7289 case CP0_REG12__SRSCTL:
7290 check_insn(ctx, ISA_MIPS32R2);
7291 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
7292 register_name = "SRSCtl";
7293 break;
7294 case CP0_REG12__SRSMAP:
7295 check_insn(ctx, ISA_MIPS32R2);
7296 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7297 register_name = "SRSMap";
7298 break;
7299 default:
7300 goto cp0_unimplemented;
7302 break;
7303 case CP0_REGISTER_13:
7304 switch (sel) {
7305 case CP0_REG13__CAUSE:
7306 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
7307 register_name = "Cause";
7308 break;
7309 default:
7310 goto cp0_unimplemented;
7312 break;
7313 case CP0_REGISTER_14:
7314 switch (sel) {
7315 case CP0_REG14__EPC:
7316 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7317 tcg_gen_ext32s_tl(arg, arg);
7318 register_name = "EPC";
7319 break;
7320 default:
7321 goto cp0_unimplemented;
7323 break;
7324 case CP0_REGISTER_15:
7325 switch (sel) {
7326 case CP0_REG15__PRID:
7327 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
7328 register_name = "PRid";
7329 break;
7330 case CP0_REG15__EBASE:
7331 check_insn(ctx, ISA_MIPS32R2);
7332 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7333 tcg_gen_ext32s_tl(arg, arg);
7334 register_name = "EBase";
7335 break;
7336 case CP0_REG15__CMGCRBASE:
7337 check_insn(ctx, ISA_MIPS32R2);
7338 CP0_CHECK(ctx->cmgcr);
7339 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7340 tcg_gen_ext32s_tl(arg, arg);
7341 register_name = "CMGCRBase";
7342 break;
7343 default:
7344 goto cp0_unimplemented;
7346 break;
7347 case CP0_REGISTER_16:
7348 switch (sel) {
7349 case CP0_REG16__CONFIG:
7350 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
7351 register_name = "Config";
7352 break;
7353 case CP0_REG16__CONFIG1:
7354 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
7355 register_name = "Config1";
7356 break;
7357 case CP0_REG16__CONFIG2:
7358 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7359 register_name = "Config2";
7360 break;
7361 case CP0_REG16__CONFIG3:
7362 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7363 register_name = "Config3";
7364 break;
7365 case CP0_REG16__CONFIG4:
7366 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7367 register_name = "Config4";
7368 break;
7369 case CP0_REG16__CONFIG5:
7370 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7371 register_name = "Config5";
7372 break;
7373 /* 6,7 are implementation dependent */
7374 case CP0_REG16__CONFIG6:
7375 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
7376 register_name = "Config6";
7377 break;
7378 case CP0_REG16__CONFIG7:
7379 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
7380 register_name = "Config7";
7381 break;
7382 default:
7383 goto cp0_unimplemented;
7385 break;
7386 case CP0_REGISTER_17:
7387 switch (sel) {
7388 case CP0_REG17__LLADDR:
7389 gen_helper_mfc0_lladdr(arg, cpu_env);
7390 register_name = "LLAddr";
7391 break;
7392 case CP0_REG17__MAAR:
7393 CP0_CHECK(ctx->mrp);
7394 gen_helper_mfc0_maar(arg, cpu_env);
7395 register_name = "MAAR";
7396 break;
7397 case CP0_REG17__MAARI:
7398 CP0_CHECK(ctx->mrp);
7399 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7400 register_name = "MAARI";
7401 break;
7402 default:
7403 goto cp0_unimplemented;
7405 break;
7406 case CP0_REGISTER_18:
7407 switch (sel) {
7408 case CP0_REG18__WATCHLO0:
7409 case CP0_REG18__WATCHLO1:
7410 case CP0_REG18__WATCHLO2:
7411 case CP0_REG18__WATCHLO3:
7412 case CP0_REG18__WATCHLO4:
7413 case CP0_REG18__WATCHLO5:
7414 case CP0_REG18__WATCHLO6:
7415 case CP0_REG18__WATCHLO7:
7416 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7417 gen_helper_1e0i(mfc0_watchlo, arg, sel);
7418 register_name = "WatchLo";
7419 break;
7420 default:
7421 goto cp0_unimplemented;
7423 break;
7424 case CP0_REGISTER_19:
7425 switch (sel) {
7426 case CP0_REG19__WATCHHI0:
7427 case CP0_REG19__WATCHHI1:
7428 case CP0_REG19__WATCHHI2:
7429 case CP0_REG19__WATCHHI3:
7430 case CP0_REG19__WATCHHI4:
7431 case CP0_REG19__WATCHHI5:
7432 case CP0_REG19__WATCHHI6:
7433 case CP0_REG19__WATCHHI7:
7434 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7435 gen_helper_1e0i(mfc0_watchhi, arg, sel);
7436 register_name = "WatchHi";
7437 break;
7438 default:
7439 goto cp0_unimplemented;
7441 break;
7442 case CP0_REGISTER_20:
7443 switch (sel) {
7444 case CP0_REG20__XCONTEXT:
7445 #if defined(TARGET_MIPS64)
7446 check_insn(ctx, ISA_MIPS3);
7447 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
7448 tcg_gen_ext32s_tl(arg, arg);
7449 register_name = "XContext";
7450 break;
7451 #endif
7452 default:
7453 goto cp0_unimplemented;
7455 break;
7456 case CP0_REGISTER_21:
7457 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7458 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7459 switch (sel) {
7460 case 0:
7461 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
7462 register_name = "Framemask";
7463 break;
7464 default:
7465 goto cp0_unimplemented;
7467 break;
7468 case CP0_REGISTER_22:
7469 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7470 register_name = "'Diagnostic"; /* implementation dependent */
7471 break;
7472 case CP0_REGISTER_23:
7473 switch (sel) {
7474 case CP0_REG23__DEBUG:
7475 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
7476 register_name = "Debug";
7477 break;
7478 case CP0_REG23__TRACECONTROL:
7479 /* PDtrace support */
7480 /* gen_helper_mfc0_tracecontrol(arg); */
7481 register_name = "TraceControl";
7482 goto cp0_unimplemented;
7483 case CP0_REG23__TRACECONTROL2:
7484 /* PDtrace support */
7485 /* gen_helper_mfc0_tracecontrol2(arg); */
7486 register_name = "TraceControl2";
7487 goto cp0_unimplemented;
7488 case CP0_REG23__USERTRACEDATA1:
7489 /* PDtrace support */
7490 /* gen_helper_mfc0_usertracedata1(arg);*/
7491 register_name = "UserTraceData1";
7492 goto cp0_unimplemented;
7493 case CP0_REG23__TRACEIBPC:
7494 /* PDtrace support */
7495 /* gen_helper_mfc0_traceibpc(arg); */
7496 register_name = "TraceIBPC";
7497 goto cp0_unimplemented;
7498 case CP0_REG23__TRACEDBPC:
7499 /* PDtrace support */
7500 /* gen_helper_mfc0_tracedbpc(arg); */
7501 register_name = "TraceDBPC";
7502 goto cp0_unimplemented;
7503 default:
7504 goto cp0_unimplemented;
7506 break;
7507 case CP0_REGISTER_24:
7508 switch (sel) {
7509 case CP0_REG24__DEPC:
7510 /* EJTAG support */
7511 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7512 tcg_gen_ext32s_tl(arg, arg);
7513 register_name = "DEPC";
7514 break;
7515 default:
7516 goto cp0_unimplemented;
7518 break;
7519 case CP0_REGISTER_25:
7520 switch (sel) {
7521 case CP0_REG25__PERFCTL0:
7522 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
7523 register_name = "Performance0";
7524 break;
7525 case CP0_REG25__PERFCNT0:
7526 /* gen_helper_mfc0_performance1(arg); */
7527 register_name = "Performance1";
7528 goto cp0_unimplemented;
7529 case CP0_REG25__PERFCTL1:
7530 /* gen_helper_mfc0_performance2(arg); */
7531 register_name = "Performance2";
7532 goto cp0_unimplemented;
7533 case CP0_REG25__PERFCNT1:
7534 /* gen_helper_mfc0_performance3(arg); */
7535 register_name = "Performance3";
7536 goto cp0_unimplemented;
7537 case CP0_REG25__PERFCTL2:
7538 /* gen_helper_mfc0_performance4(arg); */
7539 register_name = "Performance4";
7540 goto cp0_unimplemented;
7541 case CP0_REG25__PERFCNT2:
7542 /* gen_helper_mfc0_performance5(arg); */
7543 register_name = "Performance5";
7544 goto cp0_unimplemented;
7545 case CP0_REG25__PERFCTL3:
7546 /* gen_helper_mfc0_performance6(arg); */
7547 register_name = "Performance6";
7548 goto cp0_unimplemented;
7549 case CP0_REG25__PERFCNT3:
7550 /* gen_helper_mfc0_performance7(arg); */
7551 register_name = "Performance7";
7552 goto cp0_unimplemented;
7553 default:
7554 goto cp0_unimplemented;
7556 break;
7557 case CP0_REGISTER_26:
7558 switch (sel) {
7559 case CP0_REG26__ERRCTL:
7560 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7561 register_name = "ErrCtl";
7562 break;
7563 default:
7564 goto cp0_unimplemented;
7566 break;
7567 case CP0_REGISTER_27:
7568 switch (sel) {
7569 case CP0_REG27__CACHERR:
7570 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7571 register_name = "CacheErr";
7572 break;
7573 default:
7574 goto cp0_unimplemented;
7576 break;
7577 case CP0_REGISTER_28:
7578 switch (sel) {
7579 case CP0_REG28__TAGLO:
7580 case CP0_REG28__TAGLO1:
7581 case CP0_REG28__TAGLO2:
7582 case CP0_REG28__TAGLO3:
7584 TCGv_i64 tmp = tcg_temp_new_i64();
7585 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
7586 gen_move_low32(arg, tmp);
7587 tcg_temp_free_i64(tmp);
7589 register_name = "TagLo";
7590 break;
7591 case CP0_REG28__DATALO:
7592 case CP0_REG28__DATALO1:
7593 case CP0_REG28__DATALO2:
7594 case CP0_REG28__DATALO3:
7595 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7596 register_name = "DataLo";
7597 break;
7598 default:
7599 goto cp0_unimplemented;
7601 break;
7602 case CP0_REGISTER_29:
7603 switch (sel) {
7604 case CP0_REG29__TAGHI:
7605 case CP0_REG29__TAGHI1:
7606 case CP0_REG29__TAGHI2:
7607 case CP0_REG29__TAGHI3:
7608 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7609 register_name = "TagHi";
7610 break;
7611 case CP0_REG29__DATAHI:
7612 case CP0_REG29__DATAHI1:
7613 case CP0_REG29__DATAHI2:
7614 case CP0_REG29__DATAHI3:
7615 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7616 register_name = "DataHi";
7617 break;
7618 default:
7619 goto cp0_unimplemented;
7621 break;
7622 case CP0_REGISTER_30:
7623 switch (sel) {
7624 case CP0_REG30__ERROREPC:
7625 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7626 tcg_gen_ext32s_tl(arg, arg);
7627 register_name = "ErrorEPC";
7628 break;
7629 default:
7630 goto cp0_unimplemented;
7632 break;
7633 case CP0_REGISTER_31:
7634 switch (sel) {
7635 case CP0_REG31__DESAVE:
7636 /* EJTAG support */
7637 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7638 register_name = "DESAVE";
7639 break;
7640 case CP0_REG31__KSCRATCH1:
7641 case CP0_REG31__KSCRATCH2:
7642 case CP0_REG31__KSCRATCH3:
7643 case CP0_REG31__KSCRATCH4:
7644 case CP0_REG31__KSCRATCH5:
7645 case CP0_REG31__KSCRATCH6:
7646 CP0_CHECK(ctx->kscrexist & (1 << sel));
7647 tcg_gen_ld_tl(arg, cpu_env,
7648 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
7649 tcg_gen_ext32s_tl(arg, arg);
7650 register_name = "KScratch";
7651 break;
7652 default:
7653 goto cp0_unimplemented;
7655 break;
7656 default:
7657 goto cp0_unimplemented;
7659 trace_mips_translate_c0("mfc0", register_name, reg, sel);
7660 return;
7662 cp0_unimplemented:
7663 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
7664 register_name, reg, sel);
7665 gen_mfc0_unimplemented(ctx, arg);
7668 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7670 const char *register_name = "invalid";
7672 if (sel != 0) {
7673 check_insn(ctx, ISA_MIPS32);
7676 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7677 gen_io_start();
7680 switch (reg) {
7681 case CP0_REGISTER_00:
7682 switch (sel) {
7683 case CP0_REG00__INDEX:
7684 gen_helper_mtc0_index(cpu_env, arg);
7685 register_name = "Index";
7686 break;
7687 case CP0_REG00__MVPCONTROL:
7688 CP0_CHECK(ctx->insn_flags & ASE_MT);
7689 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7690 register_name = "MVPControl";
7691 break;
7692 case CP0_REG00__MVPCONF0:
7693 CP0_CHECK(ctx->insn_flags & ASE_MT);
7694 /* ignored */
7695 register_name = "MVPConf0";
7696 break;
7697 case CP0_REG00__MVPCONF1:
7698 CP0_CHECK(ctx->insn_flags & ASE_MT);
7699 /* ignored */
7700 register_name = "MVPConf1";
7701 break;
7702 case CP0_REG00__VPCONTROL:
7703 CP0_CHECK(ctx->vp);
7704 /* ignored */
7705 register_name = "VPControl";
7706 break;
7707 default:
7708 goto cp0_unimplemented;
7710 break;
7711 case CP0_REGISTER_01:
7712 switch (sel) {
7713 case CP0_REG01__RANDOM:
7714 /* ignored */
7715 register_name = "Random";
7716 break;
7717 case CP0_REG01__VPECONTROL:
7718 CP0_CHECK(ctx->insn_flags & ASE_MT);
7719 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7720 register_name = "VPEControl";
7721 break;
7722 case CP0_REG01__VPECONF0:
7723 CP0_CHECK(ctx->insn_flags & ASE_MT);
7724 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7725 register_name = "VPEConf0";
7726 break;
7727 case CP0_REG01__VPECONF1:
7728 CP0_CHECK(ctx->insn_flags & ASE_MT);
7729 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7730 register_name = "VPEConf1";
7731 break;
7732 case CP0_REG01__YQMASK:
7733 CP0_CHECK(ctx->insn_flags & ASE_MT);
7734 gen_helper_mtc0_yqmask(cpu_env, arg);
7735 register_name = "YQMask";
7736 break;
7737 case CP0_REG01__VPESCHEDULE:
7738 CP0_CHECK(ctx->insn_flags & ASE_MT);
7739 tcg_gen_st_tl(arg, cpu_env,
7740 offsetof(CPUMIPSState, CP0_VPESchedule));
7741 register_name = "VPESchedule";
7742 break;
7743 case CP0_REG01__VPESCHEFBACK:
7744 CP0_CHECK(ctx->insn_flags & ASE_MT);
7745 tcg_gen_st_tl(arg, cpu_env,
7746 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7747 register_name = "VPEScheFBack";
7748 break;
7749 case CP0_REG01__VPEOPT:
7750 CP0_CHECK(ctx->insn_flags & ASE_MT);
7751 gen_helper_mtc0_vpeopt(cpu_env, arg);
7752 register_name = "VPEOpt";
7753 break;
7754 default:
7755 goto cp0_unimplemented;
7757 break;
7758 case CP0_REGISTER_02:
7759 switch (sel) {
7760 case CP0_REG02__ENTRYLO0:
7761 gen_helper_mtc0_entrylo0(cpu_env, arg);
7762 register_name = "EntryLo0";
7763 break;
7764 case CP0_REG02__TCSTATUS:
7765 CP0_CHECK(ctx->insn_flags & ASE_MT);
7766 gen_helper_mtc0_tcstatus(cpu_env, arg);
7767 register_name = "TCStatus";
7768 break;
7769 case CP0_REG02__TCBIND:
7770 CP0_CHECK(ctx->insn_flags & ASE_MT);
7771 gen_helper_mtc0_tcbind(cpu_env, arg);
7772 register_name = "TCBind";
7773 break;
7774 case CP0_REG02__TCRESTART:
7775 CP0_CHECK(ctx->insn_flags & ASE_MT);
7776 gen_helper_mtc0_tcrestart(cpu_env, arg);
7777 register_name = "TCRestart";
7778 break;
7779 case CP0_REG02__TCHALT:
7780 CP0_CHECK(ctx->insn_flags & ASE_MT);
7781 gen_helper_mtc0_tchalt(cpu_env, arg);
7782 register_name = "TCHalt";
7783 break;
7784 case CP0_REG02__TCCONTEXT:
7785 CP0_CHECK(ctx->insn_flags & ASE_MT);
7786 gen_helper_mtc0_tccontext(cpu_env, arg);
7787 register_name = "TCContext";
7788 break;
7789 case CP0_REG02__TCSCHEDULE:
7790 CP0_CHECK(ctx->insn_flags & ASE_MT);
7791 gen_helper_mtc0_tcschedule(cpu_env, arg);
7792 register_name = "TCSchedule";
7793 break;
7794 case CP0_REG02__TCSCHEFBACK:
7795 CP0_CHECK(ctx->insn_flags & ASE_MT);
7796 gen_helper_mtc0_tcschefback(cpu_env, arg);
7797 register_name = "TCScheFBack";
7798 break;
7799 default:
7800 goto cp0_unimplemented;
7802 break;
7803 case CP0_REGISTER_03:
7804 switch (sel) {
7805 case CP0_REG03__ENTRYLO1:
7806 gen_helper_mtc0_entrylo1(cpu_env, arg);
7807 register_name = "EntryLo1";
7808 break;
7809 case CP0_REG03__GLOBALNUM:
7810 CP0_CHECK(ctx->vp);
7811 /* ignored */
7812 register_name = "GlobalNumber";
7813 break;
7814 default:
7815 goto cp0_unimplemented;
7817 break;
7818 case CP0_REGISTER_04:
7819 switch (sel) {
7820 case CP0_REG04__CONTEXT:
7821 gen_helper_mtc0_context(cpu_env, arg);
7822 register_name = "Context";
7823 break;
7824 case CP0_REG04__CONTEXTCONFIG:
7825 /* SmartMIPS ASE */
7826 /* gen_helper_mtc0_contextconfig(arg); */
7827 register_name = "ContextConfig";
7828 goto cp0_unimplemented;
7829 case CP0_REG04__USERLOCAL:
7830 CP0_CHECK(ctx->ulri);
7831 tcg_gen_st_tl(arg, cpu_env,
7832 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7833 register_name = "UserLocal";
7834 break;
7835 default:
7836 goto cp0_unimplemented;
7838 break;
7839 case CP0_REGISTER_05:
7840 switch (sel) {
7841 case CP0_REG05__PAGEMASK:
7842 gen_helper_mtc0_pagemask(cpu_env, arg);
7843 register_name = "PageMask";
7844 break;
7845 case CP0_REG05__PAGEGRAIN:
7846 check_insn(ctx, ISA_MIPS32R2);
7847 gen_helper_mtc0_pagegrain(cpu_env, arg);
7848 register_name = "PageGrain";
7849 ctx->base.is_jmp = DISAS_STOP;
7850 break;
7851 case CP0_REG05__SEGCTL0:
7852 CP0_CHECK(ctx->sc);
7853 gen_helper_mtc0_segctl0(cpu_env, arg);
7854 register_name = "SegCtl0";
7855 break;
7856 case CP0_REG05__SEGCTL1:
7857 CP0_CHECK(ctx->sc);
7858 gen_helper_mtc0_segctl1(cpu_env, arg);
7859 register_name = "SegCtl1";
7860 break;
7861 case CP0_REG05__SEGCTL2:
7862 CP0_CHECK(ctx->sc);
7863 gen_helper_mtc0_segctl2(cpu_env, arg);
7864 register_name = "SegCtl2";
7865 break;
7866 case CP0_REG05__PWBASE:
7867 check_pw(ctx);
7868 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7869 register_name = "PWBase";
7870 break;
7871 case CP0_REG05__PWFIELD:
7872 check_pw(ctx);
7873 gen_helper_mtc0_pwfield(cpu_env, arg);
7874 register_name = "PWField";
7875 break;
7876 case CP0_REG05__PWSIZE:
7877 check_pw(ctx);
7878 gen_helper_mtc0_pwsize(cpu_env, arg);
7879 register_name = "PWSize";
7880 break;
7881 default:
7882 goto cp0_unimplemented;
7884 break;
7885 case CP0_REGISTER_06:
7886 switch (sel) {
7887 case CP0_REG06__WIRED:
7888 gen_helper_mtc0_wired(cpu_env, arg);
7889 register_name = "Wired";
7890 break;
7891 case CP0_REG06__SRSCONF0:
7892 check_insn(ctx, ISA_MIPS32R2);
7893 gen_helper_mtc0_srsconf0(cpu_env, arg);
7894 register_name = "SRSConf0";
7895 break;
7896 case CP0_REG06__SRSCONF1:
7897 check_insn(ctx, ISA_MIPS32R2);
7898 gen_helper_mtc0_srsconf1(cpu_env, arg);
7899 register_name = "SRSConf1";
7900 break;
7901 case CP0_REG06__SRSCONF2:
7902 check_insn(ctx, ISA_MIPS32R2);
7903 gen_helper_mtc0_srsconf2(cpu_env, arg);
7904 register_name = "SRSConf2";
7905 break;
7906 case CP0_REG06__SRSCONF3:
7907 check_insn(ctx, ISA_MIPS32R2);
7908 gen_helper_mtc0_srsconf3(cpu_env, arg);
7909 register_name = "SRSConf3";
7910 break;
7911 case CP0_REG06__SRSCONF4:
7912 check_insn(ctx, ISA_MIPS32R2);
7913 gen_helper_mtc0_srsconf4(cpu_env, arg);
7914 register_name = "SRSConf4";
7915 break;
7916 case CP0_REG06__PWCTL:
7917 check_pw(ctx);
7918 gen_helper_mtc0_pwctl(cpu_env, arg);
7919 register_name = "PWCtl";
7920 break;
7921 default:
7922 goto cp0_unimplemented;
7924 break;
7925 case CP0_REGISTER_07:
7926 switch (sel) {
7927 case CP0_REG07__HWRENA:
7928 check_insn(ctx, ISA_MIPS32R2);
7929 gen_helper_mtc0_hwrena(cpu_env, arg);
7930 ctx->base.is_jmp = DISAS_STOP;
7931 register_name = "HWREna";
7932 break;
7933 default:
7934 goto cp0_unimplemented;
7936 break;
7937 case CP0_REGISTER_08:
7938 switch (sel) {
7939 case CP0_REG08__BADVADDR:
7940 /* ignored */
7941 register_name = "BadVAddr";
7942 break;
7943 case CP0_REG08__BADINSTR:
7944 /* ignored */
7945 register_name = "BadInstr";
7946 break;
7947 case CP0_REG08__BADINSTRP:
7948 /* ignored */
7949 register_name = "BadInstrP";
7950 break;
7951 case CP0_REG08__BADINSTRX:
7952 /* ignored */
7953 register_name = "BadInstrX";
7954 break;
7955 default:
7956 goto cp0_unimplemented;
7958 break;
7959 case CP0_REGISTER_09:
7960 switch (sel) {
7961 case CP0_REG09__COUNT:
7962 gen_helper_mtc0_count(cpu_env, arg);
7963 register_name = "Count";
7964 break;
7965 case CP0_REG09__SAARI:
7966 CP0_CHECK(ctx->saar);
7967 gen_helper_mtc0_saari(cpu_env, arg);
7968 register_name = "SAARI";
7969 break;
7970 case CP0_REG09__SAAR:
7971 CP0_CHECK(ctx->saar);
7972 gen_helper_mtc0_saar(cpu_env, arg);
7973 register_name = "SAAR";
7974 break;
7975 default:
7976 goto cp0_unimplemented;
7978 break;
7979 case CP0_REGISTER_10:
7980 switch (sel) {
7981 case CP0_REG10__ENTRYHI:
7982 gen_helper_mtc0_entryhi(cpu_env, arg);
7983 register_name = "EntryHi";
7984 break;
7985 default:
7986 goto cp0_unimplemented;
7988 break;
7989 case CP0_REGISTER_11:
7990 switch (sel) {
7991 case CP0_REG11__COMPARE:
7992 gen_helper_mtc0_compare(cpu_env, arg);
7993 register_name = "Compare";
7994 break;
7995 /* 6,7 are implementation dependent */
7996 default:
7997 goto cp0_unimplemented;
7999 break;
8000 case CP0_REGISTER_12:
8001 switch (sel) {
8002 case CP0_REG12__STATUS:
8003 save_cpu_state(ctx, 1);
8004 gen_helper_mtc0_status(cpu_env, arg);
8005 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8006 gen_save_pc(ctx->base.pc_next + 4);
8007 ctx->base.is_jmp = DISAS_EXIT;
8008 register_name = "Status";
8009 break;
8010 case CP0_REG12__INTCTL:
8011 check_insn(ctx, ISA_MIPS32R2);
8012 gen_helper_mtc0_intctl(cpu_env, arg);
8013 /* Stop translation as we may have switched the execution mode */
8014 ctx->base.is_jmp = DISAS_STOP;
8015 register_name = "IntCtl";
8016 break;
8017 case CP0_REG12__SRSCTL:
8018 check_insn(ctx, ISA_MIPS32R2);
8019 gen_helper_mtc0_srsctl(cpu_env, arg);
8020 /* Stop translation as we may have switched the execution mode */
8021 ctx->base.is_jmp = DISAS_STOP;
8022 register_name = "SRSCtl";
8023 break;
8024 case CP0_REG12__SRSMAP:
8025 check_insn(ctx, ISA_MIPS32R2);
8026 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8027 /* Stop translation as we may have switched the execution mode */
8028 ctx->base.is_jmp = DISAS_STOP;
8029 register_name = "SRSMap";
8030 break;
8031 default:
8032 goto cp0_unimplemented;
8034 break;
8035 case CP0_REGISTER_13:
8036 switch (sel) {
8037 case CP0_REG13__CAUSE:
8038 save_cpu_state(ctx, 1);
8039 gen_helper_mtc0_cause(cpu_env, arg);
8041 * Stop translation as we may have triggered an interrupt.
8042 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8043 * translated code to check for pending interrupts.
8045 gen_save_pc(ctx->base.pc_next + 4);
8046 ctx->base.is_jmp = DISAS_EXIT;
8047 register_name = "Cause";
8048 break;
8049 default:
8050 goto cp0_unimplemented;
8052 break;
8053 case CP0_REGISTER_14:
8054 switch (sel) {
8055 case CP0_REG14__EPC:
8056 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8057 register_name = "EPC";
8058 break;
8059 default:
8060 goto cp0_unimplemented;
8062 break;
8063 case CP0_REGISTER_15:
8064 switch (sel) {
8065 case CP0_REG15__PRID:
8066 /* ignored */
8067 register_name = "PRid";
8068 break;
8069 case CP0_REG15__EBASE:
8070 check_insn(ctx, ISA_MIPS32R2);
8071 gen_helper_mtc0_ebase(cpu_env, arg);
8072 register_name = "EBase";
8073 break;
8074 default:
8075 goto cp0_unimplemented;
8077 break;
8078 case CP0_REGISTER_16:
8079 switch (sel) {
8080 case CP0_REG16__CONFIG:
8081 gen_helper_mtc0_config0(cpu_env, arg);
8082 register_name = "Config";
8083 /* Stop translation as we may have switched the execution mode */
8084 ctx->base.is_jmp = DISAS_STOP;
8085 break;
8086 case CP0_REG16__CONFIG1:
8087 /* ignored, read only */
8088 register_name = "Config1";
8089 break;
8090 case CP0_REG16__CONFIG2:
8091 gen_helper_mtc0_config2(cpu_env, arg);
8092 register_name = "Config2";
8093 /* Stop translation as we may have switched the execution mode */
8094 ctx->base.is_jmp = DISAS_STOP;
8095 break;
8096 case CP0_REG16__CONFIG3:
8097 gen_helper_mtc0_config3(cpu_env, arg);
8098 register_name = "Config3";
8099 /* Stop translation as we may have switched the execution mode */
8100 ctx->base.is_jmp = DISAS_STOP;
8101 break;
8102 case CP0_REG16__CONFIG4:
8103 gen_helper_mtc0_config4(cpu_env, arg);
8104 register_name = "Config4";
8105 ctx->base.is_jmp = DISAS_STOP;
8106 break;
8107 case CP0_REG16__CONFIG5:
8108 gen_helper_mtc0_config5(cpu_env, arg);
8109 register_name = "Config5";
8110 /* Stop translation as we may have switched the execution mode */
8111 ctx->base.is_jmp = DISAS_STOP;
8112 break;
8113 /* 6,7 are implementation dependent */
8114 case CP0_REG16__CONFIG6:
8115 /* ignored */
8116 register_name = "Config6";
8117 break;
8118 case CP0_REG16__CONFIG7:
8119 /* ignored */
8120 register_name = "Config7";
8121 break;
8122 default:
8123 register_name = "Invalid config selector";
8124 goto cp0_unimplemented;
8126 break;
8127 case CP0_REGISTER_17:
8128 switch (sel) {
8129 case CP0_REG17__LLADDR:
8130 gen_helper_mtc0_lladdr(cpu_env, arg);
8131 register_name = "LLAddr";
8132 break;
8133 case CP0_REG17__MAAR:
8134 CP0_CHECK(ctx->mrp);
8135 gen_helper_mtc0_maar(cpu_env, arg);
8136 register_name = "MAAR";
8137 break;
8138 case CP0_REG17__MAARI:
8139 CP0_CHECK(ctx->mrp);
8140 gen_helper_mtc0_maari(cpu_env, arg);
8141 register_name = "MAARI";
8142 break;
8143 default:
8144 goto cp0_unimplemented;
8146 break;
8147 case CP0_REGISTER_18:
8148 switch (sel) {
8149 case CP0_REG18__WATCHLO0:
8150 case CP0_REG18__WATCHLO1:
8151 case CP0_REG18__WATCHLO2:
8152 case CP0_REG18__WATCHLO3:
8153 case CP0_REG18__WATCHLO4:
8154 case CP0_REG18__WATCHLO5:
8155 case CP0_REG18__WATCHLO6:
8156 case CP0_REG18__WATCHLO7:
8157 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8158 gen_helper_0e1i(mtc0_watchlo, arg, sel);
8159 register_name = "WatchLo";
8160 break;
8161 default:
8162 goto cp0_unimplemented;
8164 break;
8165 case CP0_REGISTER_19:
8166 switch (sel) {
8167 case CP0_REG19__WATCHHI0:
8168 case CP0_REG19__WATCHHI1:
8169 case CP0_REG19__WATCHHI2:
8170 case CP0_REG19__WATCHHI3:
8171 case CP0_REG19__WATCHHI4:
8172 case CP0_REG19__WATCHHI5:
8173 case CP0_REG19__WATCHHI6:
8174 case CP0_REG19__WATCHHI7:
8175 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8176 gen_helper_0e1i(mtc0_watchhi, arg, sel);
8177 register_name = "WatchHi";
8178 break;
8179 default:
8180 goto cp0_unimplemented;
8182 break;
8183 case CP0_REGISTER_20:
8184 switch (sel) {
8185 case CP0_REG20__XCONTEXT:
8186 #if defined(TARGET_MIPS64)
8187 check_insn(ctx, ISA_MIPS3);
8188 gen_helper_mtc0_xcontext(cpu_env, arg);
8189 register_name = "XContext";
8190 break;
8191 #endif
8192 default:
8193 goto cp0_unimplemented;
8195 break;
8196 case CP0_REGISTER_21:
8197 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8198 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8199 switch (sel) {
8200 case 0:
8201 gen_helper_mtc0_framemask(cpu_env, arg);
8202 register_name = "Framemask";
8203 break;
8204 default:
8205 goto cp0_unimplemented;
8207 break;
8208 case CP0_REGISTER_22:
8209 /* ignored */
8210 register_name = "Diagnostic"; /* implementation dependent */
8211 break;
8212 case CP0_REGISTER_23:
8213 switch (sel) {
8214 case CP0_REG23__DEBUG:
8215 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8216 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8217 gen_save_pc(ctx->base.pc_next + 4);
8218 ctx->base.is_jmp = DISAS_EXIT;
8219 register_name = "Debug";
8220 break;
8221 case CP0_REG23__TRACECONTROL:
8222 /* PDtrace support */
8223 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
8224 register_name = "TraceControl";
8225 /* Stop translation as we may have switched the execution mode */
8226 ctx->base.is_jmp = DISAS_STOP;
8227 goto cp0_unimplemented;
8228 case CP0_REG23__TRACECONTROL2:
8229 /* PDtrace support */
8230 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
8231 register_name = "TraceControl2";
8232 /* Stop translation as we may have switched the execution mode */
8233 ctx->base.is_jmp = DISAS_STOP;
8234 goto cp0_unimplemented;
8235 case CP0_REG23__USERTRACEDATA1:
8236 /* Stop translation as we may have switched the execution mode */
8237 ctx->base.is_jmp = DISAS_STOP;
8238 /* PDtrace support */
8239 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
8240 register_name = "UserTraceData";
8241 /* Stop translation as we may have switched the execution mode */
8242 ctx->base.is_jmp = DISAS_STOP;
8243 goto cp0_unimplemented;
8244 case CP0_REG23__TRACEIBPC:
8245 /* PDtrace support */
8246 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
8247 /* Stop translation as we may have switched the execution mode */
8248 ctx->base.is_jmp = DISAS_STOP;
8249 register_name = "TraceIBPC";
8250 goto cp0_unimplemented;
8251 case CP0_REG23__TRACEDBPC:
8252 /* PDtrace support */
8253 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
8254 /* Stop translation as we may have switched the execution mode */
8255 ctx->base.is_jmp = DISAS_STOP;
8256 register_name = "TraceDBPC";
8257 goto cp0_unimplemented;
8258 default:
8259 goto cp0_unimplemented;
8261 break;
8262 case CP0_REGISTER_24:
8263 switch (sel) {
8264 case CP0_REG24__DEPC:
8265 /* EJTAG support */
8266 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8267 register_name = "DEPC";
8268 break;
8269 default:
8270 goto cp0_unimplemented;
8272 break;
8273 case CP0_REGISTER_25:
8274 switch (sel) {
8275 case CP0_REG25__PERFCTL0:
8276 gen_helper_mtc0_performance0(cpu_env, arg);
8277 register_name = "Performance0";
8278 break;
8279 case CP0_REG25__PERFCNT0:
8280 /* gen_helper_mtc0_performance1(arg); */
8281 register_name = "Performance1";
8282 goto cp0_unimplemented;
8283 case CP0_REG25__PERFCTL1:
8284 /* gen_helper_mtc0_performance2(arg); */
8285 register_name = "Performance2";
8286 goto cp0_unimplemented;
8287 case CP0_REG25__PERFCNT1:
8288 /* gen_helper_mtc0_performance3(arg); */
8289 register_name = "Performance3";
8290 goto cp0_unimplemented;
8291 case CP0_REG25__PERFCTL2:
8292 /* gen_helper_mtc0_performance4(arg); */
8293 register_name = "Performance4";
8294 goto cp0_unimplemented;
8295 case CP0_REG25__PERFCNT2:
8296 /* gen_helper_mtc0_performance5(arg); */
8297 register_name = "Performance5";
8298 goto cp0_unimplemented;
8299 case CP0_REG25__PERFCTL3:
8300 /* gen_helper_mtc0_performance6(arg); */
8301 register_name = "Performance6";
8302 goto cp0_unimplemented;
8303 case CP0_REG25__PERFCNT3:
8304 /* gen_helper_mtc0_performance7(arg); */
8305 register_name = "Performance7";
8306 goto cp0_unimplemented;
8307 default:
8308 goto cp0_unimplemented;
8310 break;
8311 case CP0_REGISTER_26:
8312 switch (sel) {
8313 case CP0_REG26__ERRCTL:
8314 gen_helper_mtc0_errctl(cpu_env, arg);
8315 ctx->base.is_jmp = DISAS_STOP;
8316 register_name = "ErrCtl";
8317 break;
8318 default:
8319 goto cp0_unimplemented;
8321 break;
8322 case CP0_REGISTER_27:
8323 switch (sel) {
8324 case CP0_REG27__CACHERR:
8325 /* ignored */
8326 register_name = "CacheErr";
8327 break;
8328 default:
8329 goto cp0_unimplemented;
8331 break;
8332 case CP0_REGISTER_28:
8333 switch (sel) {
8334 case CP0_REG28__TAGLO:
8335 case CP0_REG28__TAGLO1:
8336 case CP0_REG28__TAGLO2:
8337 case CP0_REG28__TAGLO3:
8338 gen_helper_mtc0_taglo(cpu_env, arg);
8339 register_name = "TagLo";
8340 break;
8341 case CP0_REG28__DATALO:
8342 case CP0_REG28__DATALO1:
8343 case CP0_REG28__DATALO2:
8344 case CP0_REG28__DATALO3:
8345 gen_helper_mtc0_datalo(cpu_env, arg);
8346 register_name = "DataLo";
8347 break;
8348 default:
8349 goto cp0_unimplemented;
8351 break;
8352 case CP0_REGISTER_29:
8353 switch (sel) {
8354 case CP0_REG29__TAGHI:
8355 case CP0_REG29__TAGHI1:
8356 case CP0_REG29__TAGHI2:
8357 case CP0_REG29__TAGHI3:
8358 gen_helper_mtc0_taghi(cpu_env, arg);
8359 register_name = "TagHi";
8360 break;
8361 case CP0_REG29__DATAHI:
8362 case CP0_REG29__DATAHI1:
8363 case CP0_REG29__DATAHI2:
8364 case CP0_REG29__DATAHI3:
8365 gen_helper_mtc0_datahi(cpu_env, arg);
8366 register_name = "DataHi";
8367 break;
8368 default:
8369 register_name = "invalid sel";
8370 goto cp0_unimplemented;
8372 break;
8373 case CP0_REGISTER_30:
8374 switch (sel) {
8375 case CP0_REG30__ERROREPC:
8376 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8377 register_name = "ErrorEPC";
8378 break;
8379 default:
8380 goto cp0_unimplemented;
8382 break;
8383 case CP0_REGISTER_31:
8384 switch (sel) {
8385 case CP0_REG31__DESAVE:
8386 /* EJTAG support */
8387 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8388 register_name = "DESAVE";
8389 break;
8390 case CP0_REG31__KSCRATCH1:
8391 case CP0_REG31__KSCRATCH2:
8392 case CP0_REG31__KSCRATCH3:
8393 case CP0_REG31__KSCRATCH4:
8394 case CP0_REG31__KSCRATCH5:
8395 case CP0_REG31__KSCRATCH6:
8396 CP0_CHECK(ctx->kscrexist & (1 << sel));
8397 tcg_gen_st_tl(arg, cpu_env,
8398 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
8399 register_name = "KScratch";
8400 break;
8401 default:
8402 goto cp0_unimplemented;
8404 break;
8405 default:
8406 goto cp0_unimplemented;
8408 trace_mips_translate_c0("mtc0", register_name, reg, sel);
8410 /* For simplicity assume that all writes can cause interrupts. */
8411 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8413 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8414 * translated code to check for pending interrupts.
8416 gen_save_pc(ctx->base.pc_next + 4);
8417 ctx->base.is_jmp = DISAS_EXIT;
8419 return;
8421 cp0_unimplemented:
8422 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
8423 register_name, reg, sel);
8426 #if defined(TARGET_MIPS64)
8427 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8429 const char *register_name = "invalid";
8431 if (sel != 0) {
8432 check_insn(ctx, ISA_MIPS64);
8435 switch (reg) {
8436 case CP0_REGISTER_00:
8437 switch (sel) {
8438 case CP0_REG00__INDEX:
8439 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
8440 register_name = "Index";
8441 break;
8442 case CP0_REG00__MVPCONTROL:
8443 CP0_CHECK(ctx->insn_flags & ASE_MT);
8444 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
8445 register_name = "MVPControl";
8446 break;
8447 case CP0_REG00__MVPCONF0:
8448 CP0_CHECK(ctx->insn_flags & ASE_MT);
8449 gen_helper_mfc0_mvpconf0(arg, cpu_env);
8450 register_name = "MVPConf0";
8451 break;
8452 case CP0_REG00__MVPCONF1:
8453 CP0_CHECK(ctx->insn_flags & ASE_MT);
8454 gen_helper_mfc0_mvpconf1(arg, cpu_env);
8455 register_name = "MVPConf1";
8456 break;
8457 case CP0_REG00__VPCONTROL:
8458 CP0_CHECK(ctx->vp);
8459 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
8460 register_name = "VPControl";
8461 break;
8462 default:
8463 goto cp0_unimplemented;
8465 break;
8466 case CP0_REGISTER_01:
8467 switch (sel) {
8468 case CP0_REG01__RANDOM:
8469 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8470 gen_helper_mfc0_random(arg, cpu_env);
8471 register_name = "Random";
8472 break;
8473 case CP0_REG01__VPECONTROL:
8474 CP0_CHECK(ctx->insn_flags & ASE_MT);
8475 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
8476 register_name = "VPEControl";
8477 break;
8478 case CP0_REG01__VPECONF0:
8479 CP0_CHECK(ctx->insn_flags & ASE_MT);
8480 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
8481 register_name = "VPEConf0";
8482 break;
8483 case CP0_REG01__VPECONF1:
8484 CP0_CHECK(ctx->insn_flags & ASE_MT);
8485 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
8486 register_name = "VPEConf1";
8487 break;
8488 case CP0_REG01__YQMASK:
8489 CP0_CHECK(ctx->insn_flags & ASE_MT);
8490 tcg_gen_ld_tl(arg, cpu_env,
8491 offsetof(CPUMIPSState, CP0_YQMask));
8492 register_name = "YQMask";
8493 break;
8494 case CP0_REG01__VPESCHEDULE:
8495 CP0_CHECK(ctx->insn_flags & ASE_MT);
8496 tcg_gen_ld_tl(arg, cpu_env,
8497 offsetof(CPUMIPSState, CP0_VPESchedule));
8498 register_name = "VPESchedule";
8499 break;
8500 case CP0_REG01__VPESCHEFBACK:
8501 CP0_CHECK(ctx->insn_flags & ASE_MT);
8502 tcg_gen_ld_tl(arg, cpu_env,
8503 offsetof(CPUMIPSState, CP0_VPEScheFBack));
8504 register_name = "VPEScheFBack";
8505 break;
8506 case CP0_REG01__VPEOPT:
8507 CP0_CHECK(ctx->insn_flags & ASE_MT);
8508 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
8509 register_name = "VPEOpt";
8510 break;
8511 default:
8512 goto cp0_unimplemented;
8514 break;
8515 case CP0_REGISTER_02:
8516 switch (sel) {
8517 case CP0_REG02__ENTRYLO0:
8518 tcg_gen_ld_tl(arg, cpu_env,
8519 offsetof(CPUMIPSState, CP0_EntryLo0));
8520 register_name = "EntryLo0";
8521 break;
8522 case CP0_REG02__TCSTATUS:
8523 CP0_CHECK(ctx->insn_flags & ASE_MT);
8524 gen_helper_mfc0_tcstatus(arg, cpu_env);
8525 register_name = "TCStatus";
8526 break;
8527 case CP0_REG02__TCBIND:
8528 CP0_CHECK(ctx->insn_flags & ASE_MT);
8529 gen_helper_mfc0_tcbind(arg, cpu_env);
8530 register_name = "TCBind";
8531 break;
8532 case CP0_REG02__TCRESTART:
8533 CP0_CHECK(ctx->insn_flags & ASE_MT);
8534 gen_helper_dmfc0_tcrestart(arg, cpu_env);
8535 register_name = "TCRestart";
8536 break;
8537 case CP0_REG02__TCHALT:
8538 CP0_CHECK(ctx->insn_flags & ASE_MT);
8539 gen_helper_dmfc0_tchalt(arg, cpu_env);
8540 register_name = "TCHalt";
8541 break;
8542 case CP0_REG02__TCCONTEXT:
8543 CP0_CHECK(ctx->insn_flags & ASE_MT);
8544 gen_helper_dmfc0_tccontext(arg, cpu_env);
8545 register_name = "TCContext";
8546 break;
8547 case CP0_REG02__TCSCHEDULE:
8548 CP0_CHECK(ctx->insn_flags & ASE_MT);
8549 gen_helper_dmfc0_tcschedule(arg, cpu_env);
8550 register_name = "TCSchedule";
8551 break;
8552 case CP0_REG02__TCSCHEFBACK:
8553 CP0_CHECK(ctx->insn_flags & ASE_MT);
8554 gen_helper_dmfc0_tcschefback(arg, cpu_env);
8555 register_name = "TCScheFBack";
8556 break;
8557 default:
8558 goto cp0_unimplemented;
8560 break;
8561 case CP0_REGISTER_03:
8562 switch (sel) {
8563 case CP0_REG03__ENTRYLO1:
8564 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
8565 register_name = "EntryLo1";
8566 break;
8567 case CP0_REG03__GLOBALNUM:
8568 CP0_CHECK(ctx->vp);
8569 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
8570 register_name = "GlobalNumber";
8571 break;
8572 default:
8573 goto cp0_unimplemented;
8575 break;
8576 case CP0_REGISTER_04:
8577 switch (sel) {
8578 case CP0_REG04__CONTEXT:
8579 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
8580 register_name = "Context";
8581 break;
8582 case CP0_REG04__CONTEXTCONFIG:
8583 /* SmartMIPS ASE */
8584 /* gen_helper_dmfc0_contextconfig(arg); */
8585 register_name = "ContextConfig";
8586 goto cp0_unimplemented;
8587 case CP0_REG04__USERLOCAL:
8588 CP0_CHECK(ctx->ulri);
8589 tcg_gen_ld_tl(arg, cpu_env,
8590 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8591 register_name = "UserLocal";
8592 break;
8593 default:
8594 goto cp0_unimplemented;
8596 break;
8597 case CP0_REGISTER_05:
8598 switch (sel) {
8599 case CP0_REG05__PAGEMASK:
8600 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
8601 register_name = "PageMask";
8602 break;
8603 case CP0_REG05__PAGEGRAIN:
8604 check_insn(ctx, ISA_MIPS32R2);
8605 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
8606 register_name = "PageGrain";
8607 break;
8608 case CP0_REG05__SEGCTL0:
8609 CP0_CHECK(ctx->sc);
8610 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
8611 register_name = "SegCtl0";
8612 break;
8613 case CP0_REG05__SEGCTL1:
8614 CP0_CHECK(ctx->sc);
8615 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
8616 register_name = "SegCtl1";
8617 break;
8618 case CP0_REG05__SEGCTL2:
8619 CP0_CHECK(ctx->sc);
8620 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
8621 register_name = "SegCtl2";
8622 break;
8623 case CP0_REG05__PWBASE:
8624 check_pw(ctx);
8625 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8626 register_name = "PWBase";
8627 break;
8628 case CP0_REG05__PWFIELD:
8629 check_pw(ctx);
8630 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
8631 register_name = "PWField";
8632 break;
8633 case CP0_REG05__PWSIZE:
8634 check_pw(ctx);
8635 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
8636 register_name = "PWSize";
8637 break;
8638 default:
8639 goto cp0_unimplemented;
8641 break;
8642 case CP0_REGISTER_06:
8643 switch (sel) {
8644 case CP0_REG06__WIRED:
8645 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
8646 register_name = "Wired";
8647 break;
8648 case CP0_REG06__SRSCONF0:
8649 check_insn(ctx, ISA_MIPS32R2);
8650 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
8651 register_name = "SRSConf0";
8652 break;
8653 case CP0_REG06__SRSCONF1:
8654 check_insn(ctx, ISA_MIPS32R2);
8655 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
8656 register_name = "SRSConf1";
8657 break;
8658 case CP0_REG06__SRSCONF2:
8659 check_insn(ctx, ISA_MIPS32R2);
8660 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
8661 register_name = "SRSConf2";
8662 break;
8663 case CP0_REG06__SRSCONF3:
8664 check_insn(ctx, ISA_MIPS32R2);
8665 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
8666 register_name = "SRSConf3";
8667 break;
8668 case CP0_REG06__SRSCONF4:
8669 check_insn(ctx, ISA_MIPS32R2);
8670 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
8671 register_name = "SRSConf4";
8672 break;
8673 case CP0_REG06__PWCTL:
8674 check_pw(ctx);
8675 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
8676 register_name = "PWCtl";
8677 break;
8678 default:
8679 goto cp0_unimplemented;
8681 break;
8682 case CP0_REGISTER_07:
8683 switch (sel) {
8684 case CP0_REG07__HWRENA:
8685 check_insn(ctx, ISA_MIPS32R2);
8686 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
8687 register_name = "HWREna";
8688 break;
8689 default:
8690 goto cp0_unimplemented;
8692 break;
8693 case CP0_REGISTER_08:
8694 switch (sel) {
8695 case CP0_REG08__BADVADDR:
8696 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
8697 register_name = "BadVAddr";
8698 break;
8699 case CP0_REG08__BADINSTR:
8700 CP0_CHECK(ctx->bi);
8701 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
8702 register_name = "BadInstr";
8703 break;
8704 case CP0_REG08__BADINSTRP:
8705 CP0_CHECK(ctx->bp);
8706 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
8707 register_name = "BadInstrP";
8708 break;
8709 case CP0_REG08__BADINSTRX:
8710 CP0_CHECK(ctx->bi);
8711 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
8712 tcg_gen_andi_tl(arg, arg, ~0xffff);
8713 register_name = "BadInstrX";
8714 break;
8715 default:
8716 goto cp0_unimplemented;
8718 break;
8719 case CP0_REGISTER_09:
8720 switch (sel) {
8721 case CP0_REG09__COUNT:
8722 /* Mark as an IO operation because we read the time. */
8723 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8724 gen_io_start();
8726 gen_helper_mfc0_count(arg, cpu_env);
8728 * Break the TB to be able to take timer interrupts immediately
8729 * after reading count. DISAS_STOP isn't sufficient, we need to
8730 * ensure we break completely out of translated code.
8732 gen_save_pc(ctx->base.pc_next + 4);
8733 ctx->base.is_jmp = DISAS_EXIT;
8734 register_name = "Count";
8735 break;
8736 case CP0_REG09__SAARI:
8737 CP0_CHECK(ctx->saar);
8738 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
8739 register_name = "SAARI";
8740 break;
8741 case CP0_REG09__SAAR:
8742 CP0_CHECK(ctx->saar);
8743 gen_helper_dmfc0_saar(arg, cpu_env);
8744 register_name = "SAAR";
8745 break;
8746 default:
8747 goto cp0_unimplemented;
8749 break;
8750 case CP0_REGISTER_10:
8751 switch (sel) {
8752 case CP0_REG10__ENTRYHI:
8753 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
8754 register_name = "EntryHi";
8755 break;
8756 default:
8757 goto cp0_unimplemented;
8759 break;
8760 case CP0_REGISTER_11:
8761 switch (sel) {
8762 case CP0_REG11__COMPARE:
8763 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
8764 register_name = "Compare";
8765 break;
8766 /* 6,7 are implementation dependent */
8767 default:
8768 goto cp0_unimplemented;
8770 break;
8771 case CP0_REGISTER_12:
8772 switch (sel) {
8773 case CP0_REG12__STATUS:
8774 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
8775 register_name = "Status";
8776 break;
8777 case CP0_REG12__INTCTL:
8778 check_insn(ctx, ISA_MIPS32R2);
8779 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
8780 register_name = "IntCtl";
8781 break;
8782 case CP0_REG12__SRSCTL:
8783 check_insn(ctx, ISA_MIPS32R2);
8784 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
8785 register_name = "SRSCtl";
8786 break;
8787 case CP0_REG12__SRSMAP:
8788 check_insn(ctx, ISA_MIPS32R2);
8789 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8790 register_name = "SRSMap";
8791 break;
8792 default:
8793 goto cp0_unimplemented;
8795 break;
8796 case CP0_REGISTER_13:
8797 switch (sel) {
8798 case CP0_REG13__CAUSE:
8799 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
8800 register_name = "Cause";
8801 break;
8802 default:
8803 goto cp0_unimplemented;
8805 break;
8806 case CP0_REGISTER_14:
8807 switch (sel) {
8808 case CP0_REG14__EPC:
8809 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8810 register_name = "EPC";
8811 break;
8812 default:
8813 goto cp0_unimplemented;
8815 break;
8816 case CP0_REGISTER_15:
8817 switch (sel) {
8818 case CP0_REG15__PRID:
8819 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
8820 register_name = "PRid";
8821 break;
8822 case CP0_REG15__EBASE:
8823 check_insn(ctx, ISA_MIPS32R2);
8824 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
8825 register_name = "EBase";
8826 break;
8827 case CP0_REG15__CMGCRBASE:
8828 check_insn(ctx, ISA_MIPS32R2);
8829 CP0_CHECK(ctx->cmgcr);
8830 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
8831 register_name = "CMGCRBase";
8832 break;
8833 default:
8834 goto cp0_unimplemented;
8836 break;
8837 case CP0_REGISTER_16:
8838 switch (sel) {
8839 case CP0_REG16__CONFIG:
8840 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
8841 register_name = "Config";
8842 break;
8843 case CP0_REG16__CONFIG1:
8844 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
8845 register_name = "Config1";
8846 break;
8847 case CP0_REG16__CONFIG2:
8848 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
8849 register_name = "Config2";
8850 break;
8851 case CP0_REG16__CONFIG3:
8852 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
8853 register_name = "Config3";
8854 break;
8855 case CP0_REG16__CONFIG4:
8856 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
8857 register_name = "Config4";
8858 break;
8859 case CP0_REG16__CONFIG5:
8860 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
8861 register_name = "Config5";
8862 break;
8863 /* 6,7 are implementation dependent */
8864 case CP0_REG16__CONFIG6:
8865 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
8866 register_name = "Config6";
8867 break;
8868 case CP0_REG16__CONFIG7:
8869 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
8870 register_name = "Config7";
8871 break;
8872 default:
8873 goto cp0_unimplemented;
8875 break;
8876 case CP0_REGISTER_17:
8877 switch (sel) {
8878 case CP0_REG17__LLADDR:
8879 gen_helper_dmfc0_lladdr(arg, cpu_env);
8880 register_name = "LLAddr";
8881 break;
8882 case CP0_REG17__MAAR:
8883 CP0_CHECK(ctx->mrp);
8884 gen_helper_dmfc0_maar(arg, cpu_env);
8885 register_name = "MAAR";
8886 break;
8887 case CP0_REG17__MAARI:
8888 CP0_CHECK(ctx->mrp);
8889 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
8890 register_name = "MAARI";
8891 break;
8892 default:
8893 goto cp0_unimplemented;
8895 break;
8896 case CP0_REGISTER_18:
8897 switch (sel) {
8898 case CP0_REG18__WATCHLO0:
8899 case CP0_REG18__WATCHLO1:
8900 case CP0_REG18__WATCHLO2:
8901 case CP0_REG18__WATCHLO3:
8902 case CP0_REG18__WATCHLO4:
8903 case CP0_REG18__WATCHLO5:
8904 case CP0_REG18__WATCHLO6:
8905 case CP0_REG18__WATCHLO7:
8906 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8907 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
8908 register_name = "WatchLo";
8909 break;
8910 default:
8911 goto cp0_unimplemented;
8913 break;
8914 case CP0_REGISTER_19:
8915 switch (sel) {
8916 case CP0_REG19__WATCHHI0:
8917 case CP0_REG19__WATCHHI1:
8918 case CP0_REG19__WATCHHI2:
8919 case CP0_REG19__WATCHHI3:
8920 case CP0_REG19__WATCHHI4:
8921 case CP0_REG19__WATCHHI5:
8922 case CP0_REG19__WATCHHI6:
8923 case CP0_REG19__WATCHHI7:
8924 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8925 gen_helper_1e0i(mfc0_watchhi, arg, sel);
8926 register_name = "WatchHi";
8927 break;
8928 default:
8929 goto cp0_unimplemented;
8931 break;
8932 case CP0_REGISTER_20:
8933 switch (sel) {
8934 case CP0_REG20__XCONTEXT:
8935 check_insn(ctx, ISA_MIPS3);
8936 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
8937 register_name = "XContext";
8938 break;
8939 default:
8940 goto cp0_unimplemented;
8942 break;
8943 case CP0_REGISTER_21:
8944 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8945 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8946 switch (sel) {
8947 case 0:
8948 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
8949 register_name = "Framemask";
8950 break;
8951 default:
8952 goto cp0_unimplemented;
8954 break;
8955 case CP0_REGISTER_22:
8956 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8957 register_name = "'Diagnostic"; /* implementation dependent */
8958 break;
8959 case CP0_REGISTER_23:
8960 switch (sel) {
8961 case CP0_REG23__DEBUG:
8962 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
8963 register_name = "Debug";
8964 break;
8965 case CP0_REG23__TRACECONTROL:
8966 /* PDtrace support */
8967 /* gen_helper_dmfc0_tracecontrol(arg, cpu_env); */
8968 register_name = "TraceControl";
8969 goto cp0_unimplemented;
8970 case CP0_REG23__TRACECONTROL2:
8971 /* PDtrace support */
8972 /* gen_helper_dmfc0_tracecontrol2(arg, cpu_env); */
8973 register_name = "TraceControl2";
8974 goto cp0_unimplemented;
8975 case CP0_REG23__USERTRACEDATA1:
8976 /* PDtrace support */
8977 /* gen_helper_dmfc0_usertracedata1(arg, cpu_env);*/
8978 register_name = "UserTraceData1";
8979 goto cp0_unimplemented;
8980 case CP0_REG23__TRACEIBPC:
8981 /* PDtrace support */
8982 /* gen_helper_dmfc0_traceibpc(arg, cpu_env); */
8983 register_name = "TraceIBPC";
8984 goto cp0_unimplemented;
8985 case CP0_REG23__TRACEDBPC:
8986 /* PDtrace support */
8987 /* gen_helper_dmfc0_tracedbpc(arg, cpu_env); */
8988 register_name = "TraceDBPC";
8989 goto cp0_unimplemented;
8990 default:
8991 goto cp0_unimplemented;
8993 break;
8994 case CP0_REGISTER_24:
8995 switch (sel) {
8996 case CP0_REG24__DEPC:
8997 /* EJTAG support */
8998 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8999 register_name = "DEPC";
9000 break;
9001 default:
9002 goto cp0_unimplemented;
9004 break;
9005 case CP0_REGISTER_25:
9006 switch (sel) {
9007 case CP0_REG25__PERFCTL0:
9008 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
9009 register_name = "Performance0";
9010 break;
9011 case CP0_REG25__PERFCNT0:
9012 /* gen_helper_dmfc0_performance1(arg); */
9013 register_name = "Performance1";
9014 goto cp0_unimplemented;
9015 case CP0_REG25__PERFCTL1:
9016 /* gen_helper_dmfc0_performance2(arg); */
9017 register_name = "Performance2";
9018 goto cp0_unimplemented;
9019 case CP0_REG25__PERFCNT1:
9020 /* gen_helper_dmfc0_performance3(arg); */
9021 register_name = "Performance3";
9022 goto cp0_unimplemented;
9023 case CP0_REG25__PERFCTL2:
9024 /* gen_helper_dmfc0_performance4(arg); */
9025 register_name = "Performance4";
9026 goto cp0_unimplemented;
9027 case CP0_REG25__PERFCNT2:
9028 /* gen_helper_dmfc0_performance5(arg); */
9029 register_name = "Performance5";
9030 goto cp0_unimplemented;
9031 case CP0_REG25__PERFCTL3:
9032 /* gen_helper_dmfc0_performance6(arg); */
9033 register_name = "Performance6";
9034 goto cp0_unimplemented;
9035 case CP0_REG25__PERFCNT3:
9036 /* gen_helper_dmfc0_performance7(arg); */
9037 register_name = "Performance7";
9038 goto cp0_unimplemented;
9039 default:
9040 goto cp0_unimplemented;
9042 break;
9043 case CP0_REGISTER_26:
9044 switch (sel) {
9045 case CP0_REG26__ERRCTL:
9046 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
9047 register_name = "ErrCtl";
9048 break;
9049 default:
9050 goto cp0_unimplemented;
9052 break;
9053 case CP0_REGISTER_27:
9054 switch (sel) {
9055 /* ignored */
9056 case CP0_REG27__CACHERR:
9057 tcg_gen_movi_tl(arg, 0); /* unimplemented */
9058 register_name = "CacheErr";
9059 break;
9060 default:
9061 goto cp0_unimplemented;
9063 break;
9064 case CP0_REGISTER_28:
9065 switch (sel) {
9066 case CP0_REG28__TAGLO:
9067 case CP0_REG28__TAGLO1:
9068 case CP0_REG28__TAGLO2:
9069 case CP0_REG28__TAGLO3:
9070 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
9071 register_name = "TagLo";
9072 break;
9073 case CP0_REG28__DATALO:
9074 case CP0_REG28__DATALO1:
9075 case CP0_REG28__DATALO2:
9076 case CP0_REG28__DATALO3:
9077 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
9078 register_name = "DataLo";
9079 break;
9080 default:
9081 goto cp0_unimplemented;
9083 break;
9084 case CP0_REGISTER_29:
9085 switch (sel) {
9086 case CP0_REG29__TAGHI:
9087 case CP0_REG29__TAGHI1:
9088 case CP0_REG29__TAGHI2:
9089 case CP0_REG29__TAGHI3:
9090 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
9091 register_name = "TagHi";
9092 break;
9093 case CP0_REG29__DATAHI:
9094 case CP0_REG29__DATAHI1:
9095 case CP0_REG29__DATAHI2:
9096 case CP0_REG29__DATAHI3:
9097 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
9098 register_name = "DataHi";
9099 break;
9100 default:
9101 goto cp0_unimplemented;
9103 break;
9104 case CP0_REGISTER_30:
9105 switch (sel) {
9106 case CP0_REG30__ERROREPC:
9107 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9108 register_name = "ErrorEPC";
9109 break;
9110 default:
9111 goto cp0_unimplemented;
9113 break;
9114 case CP0_REGISTER_31:
9115 switch (sel) {
9116 case CP0_REG31__DESAVE:
9117 /* EJTAG support */
9118 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9119 register_name = "DESAVE";
9120 break;
9121 case CP0_REG31__KSCRATCH1:
9122 case CP0_REG31__KSCRATCH2:
9123 case CP0_REG31__KSCRATCH3:
9124 case CP0_REG31__KSCRATCH4:
9125 case CP0_REG31__KSCRATCH5:
9126 case CP0_REG31__KSCRATCH6:
9127 CP0_CHECK(ctx->kscrexist & (1 << sel));
9128 tcg_gen_ld_tl(arg, cpu_env,
9129 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
9130 register_name = "KScratch";
9131 break;
9132 default:
9133 goto cp0_unimplemented;
9135 break;
9136 default:
9137 goto cp0_unimplemented;
9139 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
9140 return;
9142 cp0_unimplemented:
9143 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
9144 register_name, reg, sel);
9145 gen_mfc0_unimplemented(ctx, arg);
9148 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9150 const char *register_name = "invalid";
9152 if (sel != 0) {
9153 check_insn(ctx, ISA_MIPS64);
9156 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9157 gen_io_start();
9160 switch (reg) {
9161 case CP0_REGISTER_00:
9162 switch (sel) {
9163 case CP0_REG00__INDEX:
9164 gen_helper_mtc0_index(cpu_env, arg);
9165 register_name = "Index";
9166 break;
9167 case CP0_REG00__MVPCONTROL:
9168 CP0_CHECK(ctx->insn_flags & ASE_MT);
9169 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
9170 register_name = "MVPControl";
9171 break;
9172 case CP0_REG00__MVPCONF0:
9173 CP0_CHECK(ctx->insn_flags & ASE_MT);
9174 /* ignored */
9175 register_name = "MVPConf0";
9176 break;
9177 case CP0_REG00__MVPCONF1:
9178 CP0_CHECK(ctx->insn_flags & ASE_MT);
9179 /* ignored */
9180 register_name = "MVPConf1";
9181 break;
9182 case CP0_REG00__VPCONTROL:
9183 CP0_CHECK(ctx->vp);
9184 /* ignored */
9185 register_name = "VPControl";
9186 break;
9187 default:
9188 goto cp0_unimplemented;
9190 break;
9191 case CP0_REGISTER_01:
9192 switch (sel) {
9193 case CP0_REG01__RANDOM:
9194 /* ignored */
9195 register_name = "Random";
9196 break;
9197 case CP0_REG01__VPECONTROL:
9198 CP0_CHECK(ctx->insn_flags & ASE_MT);
9199 gen_helper_mtc0_vpecontrol(cpu_env, arg);
9200 register_name = "VPEControl";
9201 break;
9202 case CP0_REG01__VPECONF0:
9203 CP0_CHECK(ctx->insn_flags & ASE_MT);
9204 gen_helper_mtc0_vpeconf0(cpu_env, arg);
9205 register_name = "VPEConf0";
9206 break;
9207 case CP0_REG01__VPECONF1:
9208 CP0_CHECK(ctx->insn_flags & ASE_MT);
9209 gen_helper_mtc0_vpeconf1(cpu_env, arg);
9210 register_name = "VPEConf1";
9211 break;
9212 case CP0_REG01__YQMASK:
9213 CP0_CHECK(ctx->insn_flags & ASE_MT);
9214 gen_helper_mtc0_yqmask(cpu_env, arg);
9215 register_name = "YQMask";
9216 break;
9217 case CP0_REG01__VPESCHEDULE:
9218 CP0_CHECK(ctx->insn_flags & ASE_MT);
9219 tcg_gen_st_tl(arg, cpu_env,
9220 offsetof(CPUMIPSState, CP0_VPESchedule));
9221 register_name = "VPESchedule";
9222 break;
9223 case CP0_REG01__VPESCHEFBACK:
9224 CP0_CHECK(ctx->insn_flags & ASE_MT);
9225 tcg_gen_st_tl(arg, cpu_env,
9226 offsetof(CPUMIPSState, CP0_VPEScheFBack));
9227 register_name = "VPEScheFBack";
9228 break;
9229 case CP0_REG01__VPEOPT:
9230 CP0_CHECK(ctx->insn_flags & ASE_MT);
9231 gen_helper_mtc0_vpeopt(cpu_env, arg);
9232 register_name = "VPEOpt";
9233 break;
9234 default:
9235 goto cp0_unimplemented;
9237 break;
9238 case CP0_REGISTER_02:
9239 switch (sel) {
9240 case CP0_REG02__ENTRYLO0:
9241 gen_helper_dmtc0_entrylo0(cpu_env, arg);
9242 register_name = "EntryLo0";
9243 break;
9244 case CP0_REG02__TCSTATUS:
9245 CP0_CHECK(ctx->insn_flags & ASE_MT);
9246 gen_helper_mtc0_tcstatus(cpu_env, arg);
9247 register_name = "TCStatus";
9248 break;
9249 case CP0_REG02__TCBIND:
9250 CP0_CHECK(ctx->insn_flags & ASE_MT);
9251 gen_helper_mtc0_tcbind(cpu_env, arg);
9252 register_name = "TCBind";
9253 break;
9254 case CP0_REG02__TCRESTART:
9255 CP0_CHECK(ctx->insn_flags & ASE_MT);
9256 gen_helper_mtc0_tcrestart(cpu_env, arg);
9257 register_name = "TCRestart";
9258 break;
9259 case CP0_REG02__TCHALT:
9260 CP0_CHECK(ctx->insn_flags & ASE_MT);
9261 gen_helper_mtc0_tchalt(cpu_env, arg);
9262 register_name = "TCHalt";
9263 break;
9264 case CP0_REG02__TCCONTEXT:
9265 CP0_CHECK(ctx->insn_flags & ASE_MT);
9266 gen_helper_mtc0_tccontext(cpu_env, arg);
9267 register_name = "TCContext";
9268 break;
9269 case CP0_REG02__TCSCHEDULE:
9270 CP0_CHECK(ctx->insn_flags & ASE_MT);
9271 gen_helper_mtc0_tcschedule(cpu_env, arg);
9272 register_name = "TCSchedule";
9273 break;
9274 case CP0_REG02__TCSCHEFBACK:
9275 CP0_CHECK(ctx->insn_flags & ASE_MT);
9276 gen_helper_mtc0_tcschefback(cpu_env, arg);
9277 register_name = "TCScheFBack";
9278 break;
9279 default:
9280 goto cp0_unimplemented;
9282 break;
9283 case CP0_REGISTER_03:
9284 switch (sel) {
9285 case CP0_REG03__ENTRYLO1:
9286 gen_helper_dmtc0_entrylo1(cpu_env, arg);
9287 register_name = "EntryLo1";
9288 break;
9289 case CP0_REG03__GLOBALNUM:
9290 CP0_CHECK(ctx->vp);
9291 /* ignored */
9292 register_name = "GlobalNumber";
9293 break;
9294 default:
9295 goto cp0_unimplemented;
9297 break;
9298 case CP0_REGISTER_04:
9299 switch (sel) {
9300 case CP0_REG04__CONTEXT:
9301 gen_helper_mtc0_context(cpu_env, arg);
9302 register_name = "Context";
9303 break;
9304 case CP0_REG04__CONTEXTCONFIG:
9305 /* SmartMIPS ASE */
9306 /* gen_helper_dmtc0_contextconfig(arg); */
9307 register_name = "ContextConfig";
9308 goto cp0_unimplemented;
9309 case CP0_REG04__USERLOCAL:
9310 CP0_CHECK(ctx->ulri);
9311 tcg_gen_st_tl(arg, cpu_env,
9312 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
9313 register_name = "UserLocal";
9314 break;
9315 default:
9316 goto cp0_unimplemented;
9318 break;
9319 case CP0_REGISTER_05:
9320 switch (sel) {
9321 case CP0_REG05__PAGEMASK:
9322 gen_helper_mtc0_pagemask(cpu_env, arg);
9323 register_name = "PageMask";
9324 break;
9325 case CP0_REG05__PAGEGRAIN:
9326 check_insn(ctx, ISA_MIPS32R2);
9327 gen_helper_mtc0_pagegrain(cpu_env, arg);
9328 register_name = "PageGrain";
9329 break;
9330 case CP0_REG05__SEGCTL0:
9331 CP0_CHECK(ctx->sc);
9332 gen_helper_mtc0_segctl0(cpu_env, arg);
9333 register_name = "SegCtl0";
9334 break;
9335 case CP0_REG05__SEGCTL1:
9336 CP0_CHECK(ctx->sc);
9337 gen_helper_mtc0_segctl1(cpu_env, arg);
9338 register_name = "SegCtl1";
9339 break;
9340 case CP0_REG05__SEGCTL2:
9341 CP0_CHECK(ctx->sc);
9342 gen_helper_mtc0_segctl2(cpu_env, arg);
9343 register_name = "SegCtl2";
9344 break;
9345 case CP0_REG05__PWBASE:
9346 check_pw(ctx);
9347 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
9348 register_name = "PWBase";
9349 break;
9350 case CP0_REG05__PWFIELD:
9351 check_pw(ctx);
9352 gen_helper_mtc0_pwfield(cpu_env, arg);
9353 register_name = "PWField";
9354 break;
9355 case CP0_REG05__PWSIZE:
9356 check_pw(ctx);
9357 gen_helper_mtc0_pwsize(cpu_env, arg);
9358 register_name = "PWSize";
9359 break;
9360 default:
9361 goto cp0_unimplemented;
9363 break;
9364 case CP0_REGISTER_06:
9365 switch (sel) {
9366 case CP0_REG06__WIRED:
9367 gen_helper_mtc0_wired(cpu_env, arg);
9368 register_name = "Wired";
9369 break;
9370 case CP0_REG06__SRSCONF0:
9371 check_insn(ctx, ISA_MIPS32R2);
9372 gen_helper_mtc0_srsconf0(cpu_env, arg);
9373 register_name = "SRSConf0";
9374 break;
9375 case CP0_REG06__SRSCONF1:
9376 check_insn(ctx, ISA_MIPS32R2);
9377 gen_helper_mtc0_srsconf1(cpu_env, arg);
9378 register_name = "SRSConf1";
9379 break;
9380 case CP0_REG06__SRSCONF2:
9381 check_insn(ctx, ISA_MIPS32R2);
9382 gen_helper_mtc0_srsconf2(cpu_env, arg);
9383 register_name = "SRSConf2";
9384 break;
9385 case CP0_REG06__SRSCONF3:
9386 check_insn(ctx, ISA_MIPS32R2);
9387 gen_helper_mtc0_srsconf3(cpu_env, arg);
9388 register_name = "SRSConf3";
9389 break;
9390 case CP0_REG06__SRSCONF4:
9391 check_insn(ctx, ISA_MIPS32R2);
9392 gen_helper_mtc0_srsconf4(cpu_env, arg);
9393 register_name = "SRSConf4";
9394 break;
9395 case CP0_REG06__PWCTL:
9396 check_pw(ctx);
9397 gen_helper_mtc0_pwctl(cpu_env, arg);
9398 register_name = "PWCtl";
9399 break;
9400 default:
9401 goto cp0_unimplemented;
9403 break;
9404 case CP0_REGISTER_07:
9405 switch (sel) {
9406 case CP0_REG07__HWRENA:
9407 check_insn(ctx, ISA_MIPS32R2);
9408 gen_helper_mtc0_hwrena(cpu_env, arg);
9409 ctx->base.is_jmp = DISAS_STOP;
9410 register_name = "HWREna";
9411 break;
9412 default:
9413 goto cp0_unimplemented;
9415 break;
9416 case CP0_REGISTER_08:
9417 switch (sel) {
9418 case CP0_REG08__BADVADDR:
9419 /* ignored */
9420 register_name = "BadVAddr";
9421 break;
9422 case CP0_REG08__BADINSTR:
9423 /* ignored */
9424 register_name = "BadInstr";
9425 break;
9426 case CP0_REG08__BADINSTRP:
9427 /* ignored */
9428 register_name = "BadInstrP";
9429 break;
9430 case CP0_REG08__BADINSTRX:
9431 /* ignored */
9432 register_name = "BadInstrX";
9433 break;
9434 default:
9435 goto cp0_unimplemented;
9437 break;
9438 case CP0_REGISTER_09:
9439 switch (sel) {
9440 case CP0_REG09__COUNT:
9441 gen_helper_mtc0_count(cpu_env, arg);
9442 register_name = "Count";
9443 break;
9444 case CP0_REG09__SAARI:
9445 CP0_CHECK(ctx->saar);
9446 gen_helper_mtc0_saari(cpu_env, arg);
9447 register_name = "SAARI";
9448 break;
9449 case CP0_REG09__SAAR:
9450 CP0_CHECK(ctx->saar);
9451 gen_helper_mtc0_saar(cpu_env, arg);
9452 register_name = "SAAR";
9453 break;
9454 default:
9455 goto cp0_unimplemented;
9457 /* Stop translation as we may have switched the execution mode */
9458 ctx->base.is_jmp = DISAS_STOP;
9459 break;
9460 case CP0_REGISTER_10:
9461 switch (sel) {
9462 case CP0_REG10__ENTRYHI:
9463 gen_helper_mtc0_entryhi(cpu_env, arg);
9464 register_name = "EntryHi";
9465 break;
9466 default:
9467 goto cp0_unimplemented;
9469 break;
9470 case CP0_REGISTER_11:
9471 switch (sel) {
9472 case CP0_REG11__COMPARE:
9473 gen_helper_mtc0_compare(cpu_env, arg);
9474 register_name = "Compare";
9475 break;
9476 /* 6,7 are implementation dependent */
9477 default:
9478 goto cp0_unimplemented;
9480 /* Stop translation as we may have switched the execution mode */
9481 ctx->base.is_jmp = DISAS_STOP;
9482 break;
9483 case CP0_REGISTER_12:
9484 switch (sel) {
9485 case CP0_REG12__STATUS:
9486 save_cpu_state(ctx, 1);
9487 gen_helper_mtc0_status(cpu_env, arg);
9488 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9489 gen_save_pc(ctx->base.pc_next + 4);
9490 ctx->base.is_jmp = DISAS_EXIT;
9491 register_name = "Status";
9492 break;
9493 case CP0_REG12__INTCTL:
9494 check_insn(ctx, ISA_MIPS32R2);
9495 gen_helper_mtc0_intctl(cpu_env, arg);
9496 /* Stop translation as we may have switched the execution mode */
9497 ctx->base.is_jmp = DISAS_STOP;
9498 register_name = "IntCtl";
9499 break;
9500 case CP0_REG12__SRSCTL:
9501 check_insn(ctx, ISA_MIPS32R2);
9502 gen_helper_mtc0_srsctl(cpu_env, arg);
9503 /* Stop translation as we may have switched the execution mode */
9504 ctx->base.is_jmp = DISAS_STOP;
9505 register_name = "SRSCtl";
9506 break;
9507 case CP0_REG12__SRSMAP:
9508 check_insn(ctx, ISA_MIPS32R2);
9509 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
9510 /* Stop translation as we may have switched the execution mode */
9511 ctx->base.is_jmp = DISAS_STOP;
9512 register_name = "SRSMap";
9513 break;
9514 default:
9515 goto cp0_unimplemented;
9517 break;
9518 case CP0_REGISTER_13:
9519 switch (sel) {
9520 case CP0_REG13__CAUSE:
9521 save_cpu_state(ctx, 1);
9522 gen_helper_mtc0_cause(cpu_env, arg);
9524 * Stop translation as we may have triggered an interrupt.
9525 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9526 * translated code to check for pending interrupts.
9528 gen_save_pc(ctx->base.pc_next + 4);
9529 ctx->base.is_jmp = DISAS_EXIT;
9530 register_name = "Cause";
9531 break;
9532 default:
9533 goto cp0_unimplemented;
9535 break;
9536 case CP0_REGISTER_14:
9537 switch (sel) {
9538 case CP0_REG14__EPC:
9539 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
9540 register_name = "EPC";
9541 break;
9542 default:
9543 goto cp0_unimplemented;
9545 break;
9546 case CP0_REGISTER_15:
9547 switch (sel) {
9548 case CP0_REG15__PRID:
9549 /* ignored */
9550 register_name = "PRid";
9551 break;
9552 case CP0_REG15__EBASE:
9553 check_insn(ctx, ISA_MIPS32R2);
9554 gen_helper_mtc0_ebase(cpu_env, arg);
9555 register_name = "EBase";
9556 break;
9557 default:
9558 goto cp0_unimplemented;
9560 break;
9561 case CP0_REGISTER_16:
9562 switch (sel) {
9563 case CP0_REG16__CONFIG:
9564 gen_helper_mtc0_config0(cpu_env, arg);
9565 register_name = "Config";
9566 /* Stop translation as we may have switched the execution mode */
9567 ctx->base.is_jmp = DISAS_STOP;
9568 break;
9569 case CP0_REG16__CONFIG1:
9570 /* ignored, read only */
9571 register_name = "Config1";
9572 break;
9573 case CP0_REG16__CONFIG2:
9574 gen_helper_mtc0_config2(cpu_env, arg);
9575 register_name = "Config2";
9576 /* Stop translation as we may have switched the execution mode */
9577 ctx->base.is_jmp = DISAS_STOP;
9578 break;
9579 case CP0_REG16__CONFIG3:
9580 gen_helper_mtc0_config3(cpu_env, arg);
9581 register_name = "Config3";
9582 /* Stop translation as we may have switched the execution mode */
9583 ctx->base.is_jmp = DISAS_STOP;
9584 break;
9585 case CP0_REG16__CONFIG4:
9586 /* currently ignored */
9587 register_name = "Config4";
9588 break;
9589 case CP0_REG16__CONFIG5:
9590 gen_helper_mtc0_config5(cpu_env, arg);
9591 register_name = "Config5";
9592 /* Stop translation as we may have switched the execution mode */
9593 ctx->base.is_jmp = DISAS_STOP;
9594 break;
9595 /* 6,7 are implementation dependent */
9596 default:
9597 register_name = "Invalid config selector";
9598 goto cp0_unimplemented;
9600 break;
9601 case CP0_REGISTER_17:
9602 switch (sel) {
9603 case CP0_REG17__LLADDR:
9604 gen_helper_mtc0_lladdr(cpu_env, arg);
9605 register_name = "LLAddr";
9606 break;
9607 case CP0_REG17__MAAR:
9608 CP0_CHECK(ctx->mrp);
9609 gen_helper_mtc0_maar(cpu_env, arg);
9610 register_name = "MAAR";
9611 break;
9612 case CP0_REG17__MAARI:
9613 CP0_CHECK(ctx->mrp);
9614 gen_helper_mtc0_maari(cpu_env, arg);
9615 register_name = "MAARI";
9616 break;
9617 default:
9618 goto cp0_unimplemented;
9620 break;
9621 case CP0_REGISTER_18:
9622 switch (sel) {
9623 case CP0_REG18__WATCHLO0:
9624 case CP0_REG18__WATCHLO1:
9625 case CP0_REG18__WATCHLO2:
9626 case CP0_REG18__WATCHLO3:
9627 case CP0_REG18__WATCHLO4:
9628 case CP0_REG18__WATCHLO5:
9629 case CP0_REG18__WATCHLO6:
9630 case CP0_REG18__WATCHLO7:
9631 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9632 gen_helper_0e1i(mtc0_watchlo, arg, sel);
9633 register_name = "WatchLo";
9634 break;
9635 default:
9636 goto cp0_unimplemented;
9638 break;
9639 case CP0_REGISTER_19:
9640 switch (sel) {
9641 case CP0_REG19__WATCHHI0:
9642 case CP0_REG19__WATCHHI1:
9643 case CP0_REG19__WATCHHI2:
9644 case CP0_REG19__WATCHHI3:
9645 case CP0_REG19__WATCHHI4:
9646 case CP0_REG19__WATCHHI5:
9647 case CP0_REG19__WATCHHI6:
9648 case CP0_REG19__WATCHHI7:
9649 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9650 gen_helper_0e1i(mtc0_watchhi, arg, sel);
9651 register_name = "WatchHi";
9652 break;
9653 default:
9654 goto cp0_unimplemented;
9656 break;
9657 case CP0_REGISTER_20:
9658 switch (sel) {
9659 case CP0_REG20__XCONTEXT:
9660 check_insn(ctx, ISA_MIPS3);
9661 gen_helper_mtc0_xcontext(cpu_env, arg);
9662 register_name = "XContext";
9663 break;
9664 default:
9665 goto cp0_unimplemented;
9667 break;
9668 case CP0_REGISTER_21:
9669 /* Officially reserved, but sel 0 is used for R1x000 framemask */
9670 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9671 switch (sel) {
9672 case 0:
9673 gen_helper_mtc0_framemask(cpu_env, arg);
9674 register_name = "Framemask";
9675 break;
9676 default:
9677 goto cp0_unimplemented;
9679 break;
9680 case CP0_REGISTER_22:
9681 /* ignored */
9682 register_name = "Diagnostic"; /* implementation dependent */
9683 break;
9684 case CP0_REGISTER_23:
9685 switch (sel) {
9686 case CP0_REG23__DEBUG:
9687 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
9688 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9689 gen_save_pc(ctx->base.pc_next + 4);
9690 ctx->base.is_jmp = DISAS_EXIT;
9691 register_name = "Debug";
9692 break;
9693 case CP0_REG23__TRACECONTROL:
9694 /* PDtrace support */
9695 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
9696 /* Stop translation as we may have switched the execution mode */
9697 ctx->base.is_jmp = DISAS_STOP;
9698 register_name = "TraceControl";
9699 goto cp0_unimplemented;
9700 case CP0_REG23__TRACECONTROL2:
9701 /* PDtrace support */
9702 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
9703 /* Stop translation as we may have switched the execution mode */
9704 ctx->base.is_jmp = DISAS_STOP;
9705 register_name = "TraceControl2";
9706 goto cp0_unimplemented;
9707 case CP0_REG23__USERTRACEDATA1:
9708 /* PDtrace support */
9709 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
9710 /* Stop translation as we may have switched the execution mode */
9711 ctx->base.is_jmp = DISAS_STOP;
9712 register_name = "UserTraceData1";
9713 goto cp0_unimplemented;
9714 case CP0_REG23__TRACEIBPC:
9715 /* PDtrace support */
9716 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
9717 /* Stop translation as we may have switched the execution mode */
9718 ctx->base.is_jmp = DISAS_STOP;
9719 register_name = "TraceIBPC";
9720 goto cp0_unimplemented;
9721 case CP0_REG23__TRACEDBPC:
9722 /* PDtrace support */
9723 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
9724 /* Stop translation as we may have switched the execution mode */
9725 ctx->base.is_jmp = DISAS_STOP;
9726 register_name = "TraceDBPC";
9727 goto cp0_unimplemented;
9728 default:
9729 goto cp0_unimplemented;
9731 break;
9732 case CP0_REGISTER_24:
9733 switch (sel) {
9734 case CP0_REG24__DEPC:
9735 /* EJTAG support */
9736 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
9737 register_name = "DEPC";
9738 break;
9739 default:
9740 goto cp0_unimplemented;
9742 break;
9743 case CP0_REGISTER_25:
9744 switch (sel) {
9745 case CP0_REG25__PERFCTL0:
9746 gen_helper_mtc0_performance0(cpu_env, arg);
9747 register_name = "Performance0";
9748 break;
9749 case CP0_REG25__PERFCNT0:
9750 /* gen_helper_mtc0_performance1(cpu_env, arg); */
9751 register_name = "Performance1";
9752 goto cp0_unimplemented;
9753 case CP0_REG25__PERFCTL1:
9754 /* gen_helper_mtc0_performance2(cpu_env, arg); */
9755 register_name = "Performance2";
9756 goto cp0_unimplemented;
9757 case CP0_REG25__PERFCNT1:
9758 /* gen_helper_mtc0_performance3(cpu_env, arg); */
9759 register_name = "Performance3";
9760 goto cp0_unimplemented;
9761 case CP0_REG25__PERFCTL2:
9762 /* gen_helper_mtc0_performance4(cpu_env, arg); */
9763 register_name = "Performance4";
9764 goto cp0_unimplemented;
9765 case CP0_REG25__PERFCNT2:
9766 /* gen_helper_mtc0_performance5(cpu_env, arg); */
9767 register_name = "Performance5";
9768 goto cp0_unimplemented;
9769 case CP0_REG25__PERFCTL3:
9770 /* gen_helper_mtc0_performance6(cpu_env, arg); */
9771 register_name = "Performance6";
9772 goto cp0_unimplemented;
9773 case CP0_REG25__PERFCNT3:
9774 /* gen_helper_mtc0_performance7(cpu_env, arg); */
9775 register_name = "Performance7";
9776 goto cp0_unimplemented;
9777 default:
9778 goto cp0_unimplemented;
9780 break;
9781 case CP0_REGISTER_26:
9782 switch (sel) {
9783 case CP0_REG26__ERRCTL:
9784 gen_helper_mtc0_errctl(cpu_env, arg);
9785 ctx->base.is_jmp = DISAS_STOP;
9786 register_name = "ErrCtl";
9787 break;
9788 default:
9789 goto cp0_unimplemented;
9791 break;
9792 case CP0_REGISTER_27:
9793 switch (sel) {
9794 case CP0_REG27__CACHERR:
9795 /* ignored */
9796 register_name = "CacheErr";
9797 break;
9798 default:
9799 goto cp0_unimplemented;
9801 break;
9802 case CP0_REGISTER_28:
9803 switch (sel) {
9804 case CP0_REG28__TAGLO:
9805 case CP0_REG28__TAGLO1:
9806 case CP0_REG28__TAGLO2:
9807 case CP0_REG28__TAGLO3:
9808 gen_helper_mtc0_taglo(cpu_env, arg);
9809 register_name = "TagLo";
9810 break;
9811 case CP0_REG28__DATALO:
9812 case CP0_REG28__DATALO1:
9813 case CP0_REG28__DATALO2:
9814 case CP0_REG28__DATALO3:
9815 gen_helper_mtc0_datalo(cpu_env, arg);
9816 register_name = "DataLo";
9817 break;
9818 default:
9819 goto cp0_unimplemented;
9821 break;
9822 case CP0_REGISTER_29:
9823 switch (sel) {
9824 case CP0_REG29__TAGHI:
9825 case CP0_REG29__TAGHI1:
9826 case CP0_REG29__TAGHI2:
9827 case CP0_REG29__TAGHI3:
9828 gen_helper_mtc0_taghi(cpu_env, arg);
9829 register_name = "TagHi";
9830 break;
9831 case CP0_REG29__DATAHI:
9832 case CP0_REG29__DATAHI1:
9833 case CP0_REG29__DATAHI2:
9834 case CP0_REG29__DATAHI3:
9835 gen_helper_mtc0_datahi(cpu_env, arg);
9836 register_name = "DataHi";
9837 break;
9838 default:
9839 register_name = "invalid sel";
9840 goto cp0_unimplemented;
9842 break;
9843 case CP0_REGISTER_30:
9844 switch (sel) {
9845 case CP0_REG30__ERROREPC:
9846 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9847 register_name = "ErrorEPC";
9848 break;
9849 default:
9850 goto cp0_unimplemented;
9852 break;
9853 case CP0_REGISTER_31:
9854 switch (sel) {
9855 case CP0_REG31__DESAVE:
9856 /* EJTAG support */
9857 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9858 register_name = "DESAVE";
9859 break;
9860 case CP0_REG31__KSCRATCH1:
9861 case CP0_REG31__KSCRATCH2:
9862 case CP0_REG31__KSCRATCH3:
9863 case CP0_REG31__KSCRATCH4:
9864 case CP0_REG31__KSCRATCH5:
9865 case CP0_REG31__KSCRATCH6:
9866 CP0_CHECK(ctx->kscrexist & (1 << sel));
9867 tcg_gen_st_tl(arg, cpu_env,
9868 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
9869 register_name = "KScratch";
9870 break;
9871 default:
9872 goto cp0_unimplemented;
9874 break;
9875 default:
9876 goto cp0_unimplemented;
9878 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
9880 /* For simplicity assume that all writes can cause interrupts. */
9881 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9883 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9884 * translated code to check for pending interrupts.
9886 gen_save_pc(ctx->base.pc_next + 4);
9887 ctx->base.is_jmp = DISAS_EXIT;
9889 return;
9891 cp0_unimplemented:
9892 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
9893 register_name, reg, sel);
9895 #endif /* TARGET_MIPS64 */
9897 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
9898 int u, int sel, int h)
9900 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9901 TCGv t0 = tcg_temp_local_new();
9903 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9904 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9905 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
9906 tcg_gen_movi_tl(t0, -1);
9907 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9908 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
9909 tcg_gen_movi_tl(t0, -1);
9910 } else if (u == 0) {
9911 switch (rt) {
9912 case 1:
9913 switch (sel) {
9914 case 1:
9915 gen_helper_mftc0_vpecontrol(t0, cpu_env);
9916 break;
9917 case 2:
9918 gen_helper_mftc0_vpeconf0(t0, cpu_env);
9919 break;
9920 default:
9921 goto die;
9922 break;
9924 break;
9925 case 2:
9926 switch (sel) {
9927 case 1:
9928 gen_helper_mftc0_tcstatus(t0, cpu_env);
9929 break;
9930 case 2:
9931 gen_helper_mftc0_tcbind(t0, cpu_env);
9932 break;
9933 case 3:
9934 gen_helper_mftc0_tcrestart(t0, cpu_env);
9935 break;
9936 case 4:
9937 gen_helper_mftc0_tchalt(t0, cpu_env);
9938 break;
9939 case 5:
9940 gen_helper_mftc0_tccontext(t0, cpu_env);
9941 break;
9942 case 6:
9943 gen_helper_mftc0_tcschedule(t0, cpu_env);
9944 break;
9945 case 7:
9946 gen_helper_mftc0_tcschefback(t0, cpu_env);
9947 break;
9948 default:
9949 gen_mfc0(ctx, t0, rt, sel);
9950 break;
9952 break;
9953 case 10:
9954 switch (sel) {
9955 case 0:
9956 gen_helper_mftc0_entryhi(t0, cpu_env);
9957 break;
9958 default:
9959 gen_mfc0(ctx, t0, rt, sel);
9960 break;
9962 break;
9963 case 12:
9964 switch (sel) {
9965 case 0:
9966 gen_helper_mftc0_status(t0, cpu_env);
9967 break;
9968 default:
9969 gen_mfc0(ctx, t0, rt, sel);
9970 break;
9972 break;
9973 case 13:
9974 switch (sel) {
9975 case 0:
9976 gen_helper_mftc0_cause(t0, cpu_env);
9977 break;
9978 default:
9979 goto die;
9980 break;
9982 break;
9983 case 14:
9984 switch (sel) {
9985 case 0:
9986 gen_helper_mftc0_epc(t0, cpu_env);
9987 break;
9988 default:
9989 goto die;
9990 break;
9992 break;
9993 case 15:
9994 switch (sel) {
9995 case 1:
9996 gen_helper_mftc0_ebase(t0, cpu_env);
9997 break;
9998 default:
9999 goto die;
10000 break;
10002 break;
10003 case 16:
10004 switch (sel) {
10005 case 0:
10006 case 1:
10007 case 2:
10008 case 3:
10009 case 4:
10010 case 5:
10011 case 6:
10012 case 7:
10013 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
10014 break;
10015 default:
10016 goto die;
10017 break;
10019 break;
10020 case 23:
10021 switch (sel) {
10022 case 0:
10023 gen_helper_mftc0_debug(t0, cpu_env);
10024 break;
10025 default:
10026 gen_mfc0(ctx, t0, rt, sel);
10027 break;
10029 break;
10030 default:
10031 gen_mfc0(ctx, t0, rt, sel);
10033 } else {
10034 switch (sel) {
10035 /* GPR registers. */
10036 case 0:
10037 gen_helper_1e0i(mftgpr, t0, rt);
10038 break;
10039 /* Auxiliary CPU registers */
10040 case 1:
10041 switch (rt) {
10042 case 0:
10043 gen_helper_1e0i(mftlo, t0, 0);
10044 break;
10045 case 1:
10046 gen_helper_1e0i(mfthi, t0, 0);
10047 break;
10048 case 2:
10049 gen_helper_1e0i(mftacx, t0, 0);
10050 break;
10051 case 4:
10052 gen_helper_1e0i(mftlo, t0, 1);
10053 break;
10054 case 5:
10055 gen_helper_1e0i(mfthi, t0, 1);
10056 break;
10057 case 6:
10058 gen_helper_1e0i(mftacx, t0, 1);
10059 break;
10060 case 8:
10061 gen_helper_1e0i(mftlo, t0, 2);
10062 break;
10063 case 9:
10064 gen_helper_1e0i(mfthi, t0, 2);
10065 break;
10066 case 10:
10067 gen_helper_1e0i(mftacx, t0, 2);
10068 break;
10069 case 12:
10070 gen_helper_1e0i(mftlo, t0, 3);
10071 break;
10072 case 13:
10073 gen_helper_1e0i(mfthi, t0, 3);
10074 break;
10075 case 14:
10076 gen_helper_1e0i(mftacx, t0, 3);
10077 break;
10078 case 16:
10079 gen_helper_mftdsp(t0, cpu_env);
10080 break;
10081 default:
10082 goto die;
10084 break;
10085 /* Floating point (COP1). */
10086 case 2:
10087 /* XXX: For now we support only a single FPU context. */
10088 if (h == 0) {
10089 TCGv_i32 fp0 = tcg_temp_new_i32();
10091 gen_load_fpr32(ctx, fp0, rt);
10092 tcg_gen_ext_i32_tl(t0, fp0);
10093 tcg_temp_free_i32(fp0);
10094 } else {
10095 TCGv_i32 fp0 = tcg_temp_new_i32();
10097 gen_load_fpr32h(ctx, fp0, rt);
10098 tcg_gen_ext_i32_tl(t0, fp0);
10099 tcg_temp_free_i32(fp0);
10101 break;
10102 case 3:
10103 /* XXX: For now we support only a single FPU context. */
10104 gen_helper_1e0i(cfc1, t0, rt);
10105 break;
10106 /* COP2: Not implemented. */
10107 case 4:
10108 case 5:
10109 /* fall through */
10110 default:
10111 goto die;
10114 trace_mips_translate_tr("mftr", rt, u, sel, h);
10115 gen_store_gpr(t0, rd);
10116 tcg_temp_free(t0);
10117 return;
10119 die:
10120 tcg_temp_free(t0);
10121 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
10122 generate_exception_end(ctx, EXCP_RI);
10125 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
10126 int u, int sel, int h)
10128 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
10129 TCGv t0 = tcg_temp_local_new();
10131 gen_load_gpr(t0, rt);
10132 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
10133 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
10134 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
10135 /* NOP */
10137 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
10138 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
10139 /* NOP */
10141 } else if (u == 0) {
10142 switch (rd) {
10143 case 1:
10144 switch (sel) {
10145 case 1:
10146 gen_helper_mttc0_vpecontrol(cpu_env, t0);
10147 break;
10148 case 2:
10149 gen_helper_mttc0_vpeconf0(cpu_env, t0);
10150 break;
10151 default:
10152 goto die;
10153 break;
10155 break;
10156 case 2:
10157 switch (sel) {
10158 case 1:
10159 gen_helper_mttc0_tcstatus(cpu_env, t0);
10160 break;
10161 case 2:
10162 gen_helper_mttc0_tcbind(cpu_env, t0);
10163 break;
10164 case 3:
10165 gen_helper_mttc0_tcrestart(cpu_env, t0);
10166 break;
10167 case 4:
10168 gen_helper_mttc0_tchalt(cpu_env, t0);
10169 break;
10170 case 5:
10171 gen_helper_mttc0_tccontext(cpu_env, t0);
10172 break;
10173 case 6:
10174 gen_helper_mttc0_tcschedule(cpu_env, t0);
10175 break;
10176 case 7:
10177 gen_helper_mttc0_tcschefback(cpu_env, t0);
10178 break;
10179 default:
10180 gen_mtc0(ctx, t0, rd, sel);
10181 break;
10183 break;
10184 case 10:
10185 switch (sel) {
10186 case 0:
10187 gen_helper_mttc0_entryhi(cpu_env, t0);
10188 break;
10189 default:
10190 gen_mtc0(ctx, t0, rd, sel);
10191 break;
10193 break;
10194 case 12:
10195 switch (sel) {
10196 case 0:
10197 gen_helper_mttc0_status(cpu_env, t0);
10198 break;
10199 default:
10200 gen_mtc0(ctx, t0, rd, sel);
10201 break;
10203 break;
10204 case 13:
10205 switch (sel) {
10206 case 0:
10207 gen_helper_mttc0_cause(cpu_env, t0);
10208 break;
10209 default:
10210 goto die;
10211 break;
10213 break;
10214 case 15:
10215 switch (sel) {
10216 case 1:
10217 gen_helper_mttc0_ebase(cpu_env, t0);
10218 break;
10219 default:
10220 goto die;
10221 break;
10223 break;
10224 case 23:
10225 switch (sel) {
10226 case 0:
10227 gen_helper_mttc0_debug(cpu_env, t0);
10228 break;
10229 default:
10230 gen_mtc0(ctx, t0, rd, sel);
10231 break;
10233 break;
10234 default:
10235 gen_mtc0(ctx, t0, rd, sel);
10237 } else {
10238 switch (sel) {
10239 /* GPR registers. */
10240 case 0:
10241 gen_helper_0e1i(mttgpr, t0, rd);
10242 break;
10243 /* Auxiliary CPU registers */
10244 case 1:
10245 switch (rd) {
10246 case 0:
10247 gen_helper_0e1i(mttlo, t0, 0);
10248 break;
10249 case 1:
10250 gen_helper_0e1i(mtthi, t0, 0);
10251 break;
10252 case 2:
10253 gen_helper_0e1i(mttacx, t0, 0);
10254 break;
10255 case 4:
10256 gen_helper_0e1i(mttlo, t0, 1);
10257 break;
10258 case 5:
10259 gen_helper_0e1i(mtthi, t0, 1);
10260 break;
10261 case 6:
10262 gen_helper_0e1i(mttacx, t0, 1);
10263 break;
10264 case 8:
10265 gen_helper_0e1i(mttlo, t0, 2);
10266 break;
10267 case 9:
10268 gen_helper_0e1i(mtthi, t0, 2);
10269 break;
10270 case 10:
10271 gen_helper_0e1i(mttacx, t0, 2);
10272 break;
10273 case 12:
10274 gen_helper_0e1i(mttlo, t0, 3);
10275 break;
10276 case 13:
10277 gen_helper_0e1i(mtthi, t0, 3);
10278 break;
10279 case 14:
10280 gen_helper_0e1i(mttacx, t0, 3);
10281 break;
10282 case 16:
10283 gen_helper_mttdsp(cpu_env, t0);
10284 break;
10285 default:
10286 goto die;
10288 break;
10289 /* Floating point (COP1). */
10290 case 2:
10291 /* XXX: For now we support only a single FPU context. */
10292 if (h == 0) {
10293 TCGv_i32 fp0 = tcg_temp_new_i32();
10295 tcg_gen_trunc_tl_i32(fp0, t0);
10296 gen_store_fpr32(ctx, fp0, rd);
10297 tcg_temp_free_i32(fp0);
10298 } else {
10299 TCGv_i32 fp0 = tcg_temp_new_i32();
10301 tcg_gen_trunc_tl_i32(fp0, t0);
10302 gen_store_fpr32h(ctx, fp0, rd);
10303 tcg_temp_free_i32(fp0);
10305 break;
10306 case 3:
10307 /* XXX: For now we support only a single FPU context. */
10309 TCGv_i32 fs_tmp = tcg_const_i32(rd);
10311 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10312 tcg_temp_free_i32(fs_tmp);
10314 /* Stop translation as we may have changed hflags */
10315 ctx->base.is_jmp = DISAS_STOP;
10316 break;
10317 /* COP2: Not implemented. */
10318 case 4:
10319 case 5:
10320 /* fall through */
10321 default:
10322 goto die;
10325 trace_mips_translate_tr("mttr", rd, u, sel, h);
10326 tcg_temp_free(t0);
10327 return;
10329 die:
10330 tcg_temp_free(t0);
10331 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
10332 generate_exception_end(ctx, EXCP_RI);
10335 static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
10336 int rt, int rd)
10338 const char *opn = "ldst";
10340 check_cp0_enabled(ctx);
10341 switch (opc) {
10342 case OPC_MFC0:
10343 if (rt == 0) {
10344 /* Treat as NOP. */
10345 return;
10347 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10348 opn = "mfc0";
10349 break;
10350 case OPC_MTC0:
10352 TCGv t0 = tcg_temp_new();
10354 gen_load_gpr(t0, rt);
10355 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
10356 tcg_temp_free(t0);
10358 opn = "mtc0";
10359 break;
10360 #if defined(TARGET_MIPS64)
10361 case OPC_DMFC0:
10362 check_insn(ctx, ISA_MIPS3);
10363 if (rt == 0) {
10364 /* Treat as NOP. */
10365 return;
10367 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10368 opn = "dmfc0";
10369 break;
10370 case OPC_DMTC0:
10371 check_insn(ctx, ISA_MIPS3);
10373 TCGv t0 = tcg_temp_new();
10375 gen_load_gpr(t0, rt);
10376 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
10377 tcg_temp_free(t0);
10379 opn = "dmtc0";
10380 break;
10381 #endif
10382 case OPC_MFHC0:
10383 check_mvh(ctx);
10384 if (rt == 0) {
10385 /* Treat as NOP. */
10386 return;
10388 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10389 opn = "mfhc0";
10390 break;
10391 case OPC_MTHC0:
10392 check_mvh(ctx);
10394 TCGv t0 = tcg_temp_new();
10395 gen_load_gpr(t0, rt);
10396 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
10397 tcg_temp_free(t0);
10399 opn = "mthc0";
10400 break;
10401 case OPC_MFTR:
10402 check_cp0_enabled(ctx);
10403 if (rd == 0) {
10404 /* Treat as NOP. */
10405 return;
10407 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
10408 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10409 opn = "mftr";
10410 break;
10411 case OPC_MTTR:
10412 check_cp0_enabled(ctx);
10413 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
10414 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10415 opn = "mttr";
10416 break;
10417 case OPC_TLBWI:
10418 opn = "tlbwi";
10419 if (!env->tlb->helper_tlbwi) {
10420 goto die;
10422 gen_helper_tlbwi(cpu_env);
10423 break;
10424 case OPC_TLBINV:
10425 opn = "tlbinv";
10426 if (ctx->ie >= 2) {
10427 if (!env->tlb->helper_tlbinv) {
10428 goto die;
10430 gen_helper_tlbinv(cpu_env);
10431 } /* treat as nop if TLBINV not supported */
10432 break;
10433 case OPC_TLBINVF:
10434 opn = "tlbinvf";
10435 if (ctx->ie >= 2) {
10436 if (!env->tlb->helper_tlbinvf) {
10437 goto die;
10439 gen_helper_tlbinvf(cpu_env);
10440 } /* treat as nop if TLBINV not supported */
10441 break;
10442 case OPC_TLBWR:
10443 opn = "tlbwr";
10444 if (!env->tlb->helper_tlbwr) {
10445 goto die;
10447 gen_helper_tlbwr(cpu_env);
10448 break;
10449 case OPC_TLBP:
10450 opn = "tlbp";
10451 if (!env->tlb->helper_tlbp) {
10452 goto die;
10454 gen_helper_tlbp(cpu_env);
10455 break;
10456 case OPC_TLBR:
10457 opn = "tlbr";
10458 if (!env->tlb->helper_tlbr) {
10459 goto die;
10461 gen_helper_tlbr(cpu_env);
10462 break;
10463 case OPC_ERET: /* OPC_ERETNC */
10464 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10465 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10466 goto die;
10467 } else {
10468 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
10469 if (ctx->opcode & (1 << bit_shift)) {
10470 /* OPC_ERETNC */
10471 opn = "eretnc";
10472 check_insn(ctx, ISA_MIPS32R5);
10473 gen_helper_eretnc(cpu_env);
10474 } else {
10475 /* OPC_ERET */
10476 opn = "eret";
10477 check_insn(ctx, ISA_MIPS2);
10478 gen_helper_eret(cpu_env);
10480 ctx->base.is_jmp = DISAS_EXIT;
10482 break;
10483 case OPC_DERET:
10484 opn = "deret";
10485 check_insn(ctx, ISA_MIPS32);
10486 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10487 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10488 goto die;
10490 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10491 MIPS_INVAL(opn);
10492 generate_exception_end(ctx, EXCP_RI);
10493 } else {
10494 gen_helper_deret(cpu_env);
10495 ctx->base.is_jmp = DISAS_EXIT;
10497 break;
10498 case OPC_WAIT:
10499 opn = "wait";
10500 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
10501 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10502 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10503 goto die;
10505 /* If we get an exception, we want to restart at next instruction */
10506 ctx->base.pc_next += 4;
10507 save_cpu_state(ctx, 1);
10508 ctx->base.pc_next -= 4;
10509 gen_helper_wait(cpu_env);
10510 ctx->base.is_jmp = DISAS_NORETURN;
10511 break;
10512 default:
10513 die:
10514 MIPS_INVAL(opn);
10515 generate_exception_end(ctx, EXCP_RI);
10516 return;
10518 (void)opn; /* avoid a compiler warning */
10520 #endif /* !CONFIG_USER_ONLY */
10522 /* CP1 Branches (before delay slot) */
10523 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
10524 int32_t cc, int32_t offset)
10526 target_ulong btarget;
10527 TCGv_i32 t0 = tcg_temp_new_i32();
10529 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
10530 generate_exception_end(ctx, EXCP_RI);
10531 goto out;
10534 if (cc != 0) {
10535 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
10538 btarget = ctx->base.pc_next + 4 + offset;
10540 switch (op) {
10541 case OPC_BC1F:
10542 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10543 tcg_gen_not_i32(t0, t0);
10544 tcg_gen_andi_i32(t0, t0, 1);
10545 tcg_gen_extu_i32_tl(bcond, t0);
10546 goto not_likely;
10547 case OPC_BC1FL:
10548 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10549 tcg_gen_not_i32(t0, t0);
10550 tcg_gen_andi_i32(t0, t0, 1);
10551 tcg_gen_extu_i32_tl(bcond, t0);
10552 goto likely;
10553 case OPC_BC1T:
10554 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10555 tcg_gen_andi_i32(t0, t0, 1);
10556 tcg_gen_extu_i32_tl(bcond, t0);
10557 goto not_likely;
10558 case OPC_BC1TL:
10559 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10560 tcg_gen_andi_i32(t0, t0, 1);
10561 tcg_gen_extu_i32_tl(bcond, t0);
10562 likely:
10563 ctx->hflags |= MIPS_HFLAG_BL;
10564 break;
10565 case OPC_BC1FANY2:
10567 TCGv_i32 t1 = tcg_temp_new_i32();
10568 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10569 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10570 tcg_gen_nand_i32(t0, t0, t1);
10571 tcg_temp_free_i32(t1);
10572 tcg_gen_andi_i32(t0, t0, 1);
10573 tcg_gen_extu_i32_tl(bcond, t0);
10575 goto not_likely;
10576 case OPC_BC1TANY2:
10578 TCGv_i32 t1 = tcg_temp_new_i32();
10579 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10580 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10581 tcg_gen_or_i32(t0, t0, t1);
10582 tcg_temp_free_i32(t1);
10583 tcg_gen_andi_i32(t0, t0, 1);
10584 tcg_gen_extu_i32_tl(bcond, t0);
10586 goto not_likely;
10587 case OPC_BC1FANY4:
10589 TCGv_i32 t1 = tcg_temp_new_i32();
10590 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10591 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10592 tcg_gen_and_i32(t0, t0, t1);
10593 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
10594 tcg_gen_and_i32(t0, t0, t1);
10595 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
10596 tcg_gen_nand_i32(t0, t0, t1);
10597 tcg_temp_free_i32(t1);
10598 tcg_gen_andi_i32(t0, t0, 1);
10599 tcg_gen_extu_i32_tl(bcond, t0);
10601 goto not_likely;
10602 case OPC_BC1TANY4:
10604 TCGv_i32 t1 = tcg_temp_new_i32();
10605 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10606 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10607 tcg_gen_or_i32(t0, t0, t1);
10608 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
10609 tcg_gen_or_i32(t0, t0, t1);
10610 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
10611 tcg_gen_or_i32(t0, t0, t1);
10612 tcg_temp_free_i32(t1);
10613 tcg_gen_andi_i32(t0, t0, 1);
10614 tcg_gen_extu_i32_tl(bcond, t0);
10616 not_likely:
10617 ctx->hflags |= MIPS_HFLAG_BC;
10618 break;
10619 default:
10620 MIPS_INVAL("cp1 cond branch");
10621 generate_exception_end(ctx, EXCP_RI);
10622 goto out;
10624 ctx->btarget = btarget;
10625 ctx->hflags |= MIPS_HFLAG_BDS32;
10626 out:
10627 tcg_temp_free_i32(t0);
10630 /* R6 CP1 Branches */
10631 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
10632 int32_t ft, int32_t offset,
10633 int delayslot_size)
10635 target_ulong btarget;
10636 TCGv_i64 t0 = tcg_temp_new_i64();
10638 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10639 #ifdef MIPS_DEBUG_DISAS
10640 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
10641 "\n", ctx->base.pc_next);
10642 #endif
10643 generate_exception_end(ctx, EXCP_RI);
10644 goto out;
10647 gen_load_fpr64(ctx, t0, ft);
10648 tcg_gen_andi_i64(t0, t0, 1);
10650 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
10652 switch (op) {
10653 case OPC_BC1EQZ:
10654 tcg_gen_xori_i64(t0, t0, 1);
10655 ctx->hflags |= MIPS_HFLAG_BC;
10656 break;
10657 case OPC_BC1NEZ:
10658 /* t0 already set */
10659 ctx->hflags |= MIPS_HFLAG_BC;
10660 break;
10661 default:
10662 MIPS_INVAL("cp1 cond branch");
10663 generate_exception_end(ctx, EXCP_RI);
10664 goto out;
10667 tcg_gen_trunc_i64_tl(bcond, t0);
10669 ctx->btarget = btarget;
10671 switch (delayslot_size) {
10672 case 2:
10673 ctx->hflags |= MIPS_HFLAG_BDS16;
10674 break;
10675 case 4:
10676 ctx->hflags |= MIPS_HFLAG_BDS32;
10677 break;
10680 out:
10681 tcg_temp_free_i64(t0);
10684 /* Coprocessor 1 (FPU) */
10686 #define FOP(func, fmt) (((fmt) << 21) | (func))
10688 enum fopcode {
10689 OPC_ADD_S = FOP(0, FMT_S),
10690 OPC_SUB_S = FOP(1, FMT_S),
10691 OPC_MUL_S = FOP(2, FMT_S),
10692 OPC_DIV_S = FOP(3, FMT_S),
10693 OPC_SQRT_S = FOP(4, FMT_S),
10694 OPC_ABS_S = FOP(5, FMT_S),
10695 OPC_MOV_S = FOP(6, FMT_S),
10696 OPC_NEG_S = FOP(7, FMT_S),
10697 OPC_ROUND_L_S = FOP(8, FMT_S),
10698 OPC_TRUNC_L_S = FOP(9, FMT_S),
10699 OPC_CEIL_L_S = FOP(10, FMT_S),
10700 OPC_FLOOR_L_S = FOP(11, FMT_S),
10701 OPC_ROUND_W_S = FOP(12, FMT_S),
10702 OPC_TRUNC_W_S = FOP(13, FMT_S),
10703 OPC_CEIL_W_S = FOP(14, FMT_S),
10704 OPC_FLOOR_W_S = FOP(15, FMT_S),
10705 OPC_SEL_S = FOP(16, FMT_S),
10706 OPC_MOVCF_S = FOP(17, FMT_S),
10707 OPC_MOVZ_S = FOP(18, FMT_S),
10708 OPC_MOVN_S = FOP(19, FMT_S),
10709 OPC_SELEQZ_S = FOP(20, FMT_S),
10710 OPC_RECIP_S = FOP(21, FMT_S),
10711 OPC_RSQRT_S = FOP(22, FMT_S),
10712 OPC_SELNEZ_S = FOP(23, FMT_S),
10713 OPC_MADDF_S = FOP(24, FMT_S),
10714 OPC_MSUBF_S = FOP(25, FMT_S),
10715 OPC_RINT_S = FOP(26, FMT_S),
10716 OPC_CLASS_S = FOP(27, FMT_S),
10717 OPC_MIN_S = FOP(28, FMT_S),
10718 OPC_RECIP2_S = FOP(28, FMT_S),
10719 OPC_MINA_S = FOP(29, FMT_S),
10720 OPC_RECIP1_S = FOP(29, FMT_S),
10721 OPC_MAX_S = FOP(30, FMT_S),
10722 OPC_RSQRT1_S = FOP(30, FMT_S),
10723 OPC_MAXA_S = FOP(31, FMT_S),
10724 OPC_RSQRT2_S = FOP(31, FMT_S),
10725 OPC_CVT_D_S = FOP(33, FMT_S),
10726 OPC_CVT_W_S = FOP(36, FMT_S),
10727 OPC_CVT_L_S = FOP(37, FMT_S),
10728 OPC_CVT_PS_S = FOP(38, FMT_S),
10729 OPC_CMP_F_S = FOP(48, FMT_S),
10730 OPC_CMP_UN_S = FOP(49, FMT_S),
10731 OPC_CMP_EQ_S = FOP(50, FMT_S),
10732 OPC_CMP_UEQ_S = FOP(51, FMT_S),
10733 OPC_CMP_OLT_S = FOP(52, FMT_S),
10734 OPC_CMP_ULT_S = FOP(53, FMT_S),
10735 OPC_CMP_OLE_S = FOP(54, FMT_S),
10736 OPC_CMP_ULE_S = FOP(55, FMT_S),
10737 OPC_CMP_SF_S = FOP(56, FMT_S),
10738 OPC_CMP_NGLE_S = FOP(57, FMT_S),
10739 OPC_CMP_SEQ_S = FOP(58, FMT_S),
10740 OPC_CMP_NGL_S = FOP(59, FMT_S),
10741 OPC_CMP_LT_S = FOP(60, FMT_S),
10742 OPC_CMP_NGE_S = FOP(61, FMT_S),
10743 OPC_CMP_LE_S = FOP(62, FMT_S),
10744 OPC_CMP_NGT_S = FOP(63, FMT_S),
10746 OPC_ADD_D = FOP(0, FMT_D),
10747 OPC_SUB_D = FOP(1, FMT_D),
10748 OPC_MUL_D = FOP(2, FMT_D),
10749 OPC_DIV_D = FOP(3, FMT_D),
10750 OPC_SQRT_D = FOP(4, FMT_D),
10751 OPC_ABS_D = FOP(5, FMT_D),
10752 OPC_MOV_D = FOP(6, FMT_D),
10753 OPC_NEG_D = FOP(7, FMT_D),
10754 OPC_ROUND_L_D = FOP(8, FMT_D),
10755 OPC_TRUNC_L_D = FOP(9, FMT_D),
10756 OPC_CEIL_L_D = FOP(10, FMT_D),
10757 OPC_FLOOR_L_D = FOP(11, FMT_D),
10758 OPC_ROUND_W_D = FOP(12, FMT_D),
10759 OPC_TRUNC_W_D = FOP(13, FMT_D),
10760 OPC_CEIL_W_D = FOP(14, FMT_D),
10761 OPC_FLOOR_W_D = FOP(15, FMT_D),
10762 OPC_SEL_D = FOP(16, FMT_D),
10763 OPC_MOVCF_D = FOP(17, FMT_D),
10764 OPC_MOVZ_D = FOP(18, FMT_D),
10765 OPC_MOVN_D = FOP(19, FMT_D),
10766 OPC_SELEQZ_D = FOP(20, FMT_D),
10767 OPC_RECIP_D = FOP(21, FMT_D),
10768 OPC_RSQRT_D = FOP(22, FMT_D),
10769 OPC_SELNEZ_D = FOP(23, FMT_D),
10770 OPC_MADDF_D = FOP(24, FMT_D),
10771 OPC_MSUBF_D = FOP(25, FMT_D),
10772 OPC_RINT_D = FOP(26, FMT_D),
10773 OPC_CLASS_D = FOP(27, FMT_D),
10774 OPC_MIN_D = FOP(28, FMT_D),
10775 OPC_RECIP2_D = FOP(28, FMT_D),
10776 OPC_MINA_D = FOP(29, FMT_D),
10777 OPC_RECIP1_D = FOP(29, FMT_D),
10778 OPC_MAX_D = FOP(30, FMT_D),
10779 OPC_RSQRT1_D = FOP(30, FMT_D),
10780 OPC_MAXA_D = FOP(31, FMT_D),
10781 OPC_RSQRT2_D = FOP(31, FMT_D),
10782 OPC_CVT_S_D = FOP(32, FMT_D),
10783 OPC_CVT_W_D = FOP(36, FMT_D),
10784 OPC_CVT_L_D = FOP(37, FMT_D),
10785 OPC_CMP_F_D = FOP(48, FMT_D),
10786 OPC_CMP_UN_D = FOP(49, FMT_D),
10787 OPC_CMP_EQ_D = FOP(50, FMT_D),
10788 OPC_CMP_UEQ_D = FOP(51, FMT_D),
10789 OPC_CMP_OLT_D = FOP(52, FMT_D),
10790 OPC_CMP_ULT_D = FOP(53, FMT_D),
10791 OPC_CMP_OLE_D = FOP(54, FMT_D),
10792 OPC_CMP_ULE_D = FOP(55, FMT_D),
10793 OPC_CMP_SF_D = FOP(56, FMT_D),
10794 OPC_CMP_NGLE_D = FOP(57, FMT_D),
10795 OPC_CMP_SEQ_D = FOP(58, FMT_D),
10796 OPC_CMP_NGL_D = FOP(59, FMT_D),
10797 OPC_CMP_LT_D = FOP(60, FMT_D),
10798 OPC_CMP_NGE_D = FOP(61, FMT_D),
10799 OPC_CMP_LE_D = FOP(62, FMT_D),
10800 OPC_CMP_NGT_D = FOP(63, FMT_D),
10802 OPC_CVT_S_W = FOP(32, FMT_W),
10803 OPC_CVT_D_W = FOP(33, FMT_W),
10804 OPC_CVT_S_L = FOP(32, FMT_L),
10805 OPC_CVT_D_L = FOP(33, FMT_L),
10806 OPC_CVT_PS_PW = FOP(38, FMT_W),
10808 OPC_ADD_PS = FOP(0, FMT_PS),
10809 OPC_SUB_PS = FOP(1, FMT_PS),
10810 OPC_MUL_PS = FOP(2, FMT_PS),
10811 OPC_DIV_PS = FOP(3, FMT_PS),
10812 OPC_ABS_PS = FOP(5, FMT_PS),
10813 OPC_MOV_PS = FOP(6, FMT_PS),
10814 OPC_NEG_PS = FOP(7, FMT_PS),
10815 OPC_MOVCF_PS = FOP(17, FMT_PS),
10816 OPC_MOVZ_PS = FOP(18, FMT_PS),
10817 OPC_MOVN_PS = FOP(19, FMT_PS),
10818 OPC_ADDR_PS = FOP(24, FMT_PS),
10819 OPC_MULR_PS = FOP(26, FMT_PS),
10820 OPC_RECIP2_PS = FOP(28, FMT_PS),
10821 OPC_RECIP1_PS = FOP(29, FMT_PS),
10822 OPC_RSQRT1_PS = FOP(30, FMT_PS),
10823 OPC_RSQRT2_PS = FOP(31, FMT_PS),
10825 OPC_CVT_S_PU = FOP(32, FMT_PS),
10826 OPC_CVT_PW_PS = FOP(36, FMT_PS),
10827 OPC_CVT_S_PL = FOP(40, FMT_PS),
10828 OPC_PLL_PS = FOP(44, FMT_PS),
10829 OPC_PLU_PS = FOP(45, FMT_PS),
10830 OPC_PUL_PS = FOP(46, FMT_PS),
10831 OPC_PUU_PS = FOP(47, FMT_PS),
10832 OPC_CMP_F_PS = FOP(48, FMT_PS),
10833 OPC_CMP_UN_PS = FOP(49, FMT_PS),
10834 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
10835 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
10836 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
10837 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
10838 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
10839 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
10840 OPC_CMP_SF_PS = FOP(56, FMT_PS),
10841 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
10842 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
10843 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
10844 OPC_CMP_LT_PS = FOP(60, FMT_PS),
10845 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
10846 OPC_CMP_LE_PS = FOP(62, FMT_PS),
10847 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
10850 enum r6_f_cmp_op {
10851 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
10852 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
10853 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
10854 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
10855 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
10856 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
10857 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
10858 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
10859 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
10860 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
10861 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
10862 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
10863 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
10864 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
10865 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
10866 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
10867 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
10868 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
10869 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
10870 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
10871 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
10872 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
10874 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
10875 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
10876 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
10877 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
10878 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
10879 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
10880 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
10881 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
10882 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
10883 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
10884 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
10885 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
10886 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
10887 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
10888 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
10889 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
10890 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
10891 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
10892 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
10893 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
10894 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
10895 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
10898 static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
10900 TCGv t0 = tcg_temp_new();
10902 switch (opc) {
10903 case OPC_MFC1:
10905 TCGv_i32 fp0 = tcg_temp_new_i32();
10907 gen_load_fpr32(ctx, fp0, fs);
10908 tcg_gen_ext_i32_tl(t0, fp0);
10909 tcg_temp_free_i32(fp0);
10911 gen_store_gpr(t0, rt);
10912 break;
10913 case OPC_MTC1:
10914 gen_load_gpr(t0, rt);
10916 TCGv_i32 fp0 = tcg_temp_new_i32();
10918 tcg_gen_trunc_tl_i32(fp0, t0);
10919 gen_store_fpr32(ctx, fp0, fs);
10920 tcg_temp_free_i32(fp0);
10922 break;
10923 case OPC_CFC1:
10924 gen_helper_1e0i(cfc1, t0, fs);
10925 gen_store_gpr(t0, rt);
10926 break;
10927 case OPC_CTC1:
10928 gen_load_gpr(t0, rt);
10929 save_cpu_state(ctx, 0);
10931 TCGv_i32 fs_tmp = tcg_const_i32(fs);
10933 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10934 tcg_temp_free_i32(fs_tmp);
10936 /* Stop translation as we may have changed hflags */
10937 ctx->base.is_jmp = DISAS_STOP;
10938 break;
10939 #if defined(TARGET_MIPS64)
10940 case OPC_DMFC1:
10941 gen_load_fpr64(ctx, t0, fs);
10942 gen_store_gpr(t0, rt);
10943 break;
10944 case OPC_DMTC1:
10945 gen_load_gpr(t0, rt);
10946 gen_store_fpr64(ctx, t0, fs);
10947 break;
10948 #endif
10949 case OPC_MFHC1:
10951 TCGv_i32 fp0 = tcg_temp_new_i32();
10953 gen_load_fpr32h(ctx, fp0, fs);
10954 tcg_gen_ext_i32_tl(t0, fp0);
10955 tcg_temp_free_i32(fp0);
10957 gen_store_gpr(t0, rt);
10958 break;
10959 case OPC_MTHC1:
10960 gen_load_gpr(t0, rt);
10962 TCGv_i32 fp0 = tcg_temp_new_i32();
10964 tcg_gen_trunc_tl_i32(fp0, t0);
10965 gen_store_fpr32h(ctx, fp0, fs);
10966 tcg_temp_free_i32(fp0);
10968 break;
10969 default:
10970 MIPS_INVAL("cp1 move");
10971 generate_exception_end(ctx, EXCP_RI);
10972 goto out;
10975 out:
10976 tcg_temp_free(t0);
10979 static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
10981 TCGLabel *l1;
10982 TCGCond cond;
10983 TCGv_i32 t0;
10985 if (rd == 0) {
10986 /* Treat as NOP. */
10987 return;
10990 if (tf) {
10991 cond = TCG_COND_EQ;
10992 } else {
10993 cond = TCG_COND_NE;
10996 l1 = gen_new_label();
10997 t0 = tcg_temp_new_i32();
10998 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10999 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11000 tcg_temp_free_i32(t0);
11001 if (rs == 0) {
11002 tcg_gen_movi_tl(cpu_gpr[rd], 0);
11003 } else {
11004 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
11006 gen_set_label(l1);
11009 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
11010 int tf)
11012 int cond;
11013 TCGv_i32 t0 = tcg_temp_new_i32();
11014 TCGLabel *l1 = gen_new_label();
11016 if (tf) {
11017 cond = TCG_COND_EQ;
11018 } else {
11019 cond = TCG_COND_NE;
11022 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11023 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11024 gen_load_fpr32(ctx, t0, fs);
11025 gen_store_fpr32(ctx, t0, fd);
11026 gen_set_label(l1);
11027 tcg_temp_free_i32(t0);
11030 static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
11031 int tf)
11033 int cond;
11034 TCGv_i32 t0 = tcg_temp_new_i32();
11035 TCGv_i64 fp0;
11036 TCGLabel *l1 = gen_new_label();
11038 if (tf) {
11039 cond = TCG_COND_EQ;
11040 } else {
11041 cond = TCG_COND_NE;
11044 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11045 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11046 tcg_temp_free_i32(t0);
11047 fp0 = tcg_temp_new_i64();
11048 gen_load_fpr64(ctx, fp0, fs);
11049 gen_store_fpr64(ctx, fp0, fd);
11050 tcg_temp_free_i64(fp0);
11051 gen_set_label(l1);
11054 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
11055 int cc, int tf)
11057 int cond;
11058 TCGv_i32 t0 = tcg_temp_new_i32();
11059 TCGLabel *l1 = gen_new_label();
11060 TCGLabel *l2 = gen_new_label();
11062 if (tf) {
11063 cond = TCG_COND_EQ;
11064 } else {
11065 cond = TCG_COND_NE;
11068 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11069 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11070 gen_load_fpr32(ctx, t0, fs);
11071 gen_store_fpr32(ctx, t0, fd);
11072 gen_set_label(l1);
11074 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc + 1));
11075 tcg_gen_brcondi_i32(cond, t0, 0, l2);
11076 gen_load_fpr32h(ctx, t0, fs);
11077 gen_store_fpr32h(ctx, t0, fd);
11078 tcg_temp_free_i32(t0);
11079 gen_set_label(l2);
11082 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
11083 int fs)
11085 TCGv_i32 t1 = tcg_const_i32(0);
11086 TCGv_i32 fp0 = tcg_temp_new_i32();
11087 TCGv_i32 fp1 = tcg_temp_new_i32();
11088 TCGv_i32 fp2 = tcg_temp_new_i32();
11089 gen_load_fpr32(ctx, fp0, fd);
11090 gen_load_fpr32(ctx, fp1, ft);
11091 gen_load_fpr32(ctx, fp2, fs);
11093 switch (op1) {
11094 case OPC_SEL_S:
11095 tcg_gen_andi_i32(fp0, fp0, 1);
11096 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11097 break;
11098 case OPC_SELEQZ_S:
11099 tcg_gen_andi_i32(fp1, fp1, 1);
11100 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11101 break;
11102 case OPC_SELNEZ_S:
11103 tcg_gen_andi_i32(fp1, fp1, 1);
11104 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11105 break;
11106 default:
11107 MIPS_INVAL("gen_sel_s");
11108 generate_exception_end(ctx, EXCP_RI);
11109 break;
11112 gen_store_fpr32(ctx, fp0, fd);
11113 tcg_temp_free_i32(fp2);
11114 tcg_temp_free_i32(fp1);
11115 tcg_temp_free_i32(fp0);
11116 tcg_temp_free_i32(t1);
11119 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
11120 int fs)
11122 TCGv_i64 t1 = tcg_const_i64(0);
11123 TCGv_i64 fp0 = tcg_temp_new_i64();
11124 TCGv_i64 fp1 = tcg_temp_new_i64();
11125 TCGv_i64 fp2 = tcg_temp_new_i64();
11126 gen_load_fpr64(ctx, fp0, fd);
11127 gen_load_fpr64(ctx, fp1, ft);
11128 gen_load_fpr64(ctx, fp2, fs);
11130 switch (op1) {
11131 case OPC_SEL_D:
11132 tcg_gen_andi_i64(fp0, fp0, 1);
11133 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11134 break;
11135 case OPC_SELEQZ_D:
11136 tcg_gen_andi_i64(fp1, fp1, 1);
11137 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11138 break;
11139 case OPC_SELNEZ_D:
11140 tcg_gen_andi_i64(fp1, fp1, 1);
11141 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11142 break;
11143 default:
11144 MIPS_INVAL("gen_sel_d");
11145 generate_exception_end(ctx, EXCP_RI);
11146 break;
11149 gen_store_fpr64(ctx, fp0, fd);
11150 tcg_temp_free_i64(fp2);
11151 tcg_temp_free_i64(fp1);
11152 tcg_temp_free_i64(fp0);
11153 tcg_temp_free_i64(t1);
11156 static void gen_farith(DisasContext *ctx, enum fopcode op1,
11157 int ft, int fs, int fd, int cc)
11159 uint32_t func = ctx->opcode & 0x3f;
11160 switch (op1) {
11161 case OPC_ADD_S:
11163 TCGv_i32 fp0 = tcg_temp_new_i32();
11164 TCGv_i32 fp1 = tcg_temp_new_i32();
11166 gen_load_fpr32(ctx, fp0, fs);
11167 gen_load_fpr32(ctx, fp1, ft);
11168 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
11169 tcg_temp_free_i32(fp1);
11170 gen_store_fpr32(ctx, fp0, fd);
11171 tcg_temp_free_i32(fp0);
11173 break;
11174 case OPC_SUB_S:
11176 TCGv_i32 fp0 = tcg_temp_new_i32();
11177 TCGv_i32 fp1 = tcg_temp_new_i32();
11179 gen_load_fpr32(ctx, fp0, fs);
11180 gen_load_fpr32(ctx, fp1, ft);
11181 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
11182 tcg_temp_free_i32(fp1);
11183 gen_store_fpr32(ctx, fp0, fd);
11184 tcg_temp_free_i32(fp0);
11186 break;
11187 case OPC_MUL_S:
11189 TCGv_i32 fp0 = tcg_temp_new_i32();
11190 TCGv_i32 fp1 = tcg_temp_new_i32();
11192 gen_load_fpr32(ctx, fp0, fs);
11193 gen_load_fpr32(ctx, fp1, ft);
11194 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
11195 tcg_temp_free_i32(fp1);
11196 gen_store_fpr32(ctx, fp0, fd);
11197 tcg_temp_free_i32(fp0);
11199 break;
11200 case OPC_DIV_S:
11202 TCGv_i32 fp0 = tcg_temp_new_i32();
11203 TCGv_i32 fp1 = tcg_temp_new_i32();
11205 gen_load_fpr32(ctx, fp0, fs);
11206 gen_load_fpr32(ctx, fp1, ft);
11207 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
11208 tcg_temp_free_i32(fp1);
11209 gen_store_fpr32(ctx, fp0, fd);
11210 tcg_temp_free_i32(fp0);
11212 break;
11213 case OPC_SQRT_S:
11215 TCGv_i32 fp0 = tcg_temp_new_i32();
11217 gen_load_fpr32(ctx, fp0, fs);
11218 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
11219 gen_store_fpr32(ctx, fp0, fd);
11220 tcg_temp_free_i32(fp0);
11222 break;
11223 case OPC_ABS_S:
11225 TCGv_i32 fp0 = tcg_temp_new_i32();
11227 gen_load_fpr32(ctx, fp0, fs);
11228 if (ctx->abs2008) {
11229 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
11230 } else {
11231 gen_helper_float_abs_s(fp0, fp0);
11233 gen_store_fpr32(ctx, fp0, fd);
11234 tcg_temp_free_i32(fp0);
11236 break;
11237 case OPC_MOV_S:
11239 TCGv_i32 fp0 = tcg_temp_new_i32();
11241 gen_load_fpr32(ctx, fp0, fs);
11242 gen_store_fpr32(ctx, fp0, fd);
11243 tcg_temp_free_i32(fp0);
11245 break;
11246 case OPC_NEG_S:
11248 TCGv_i32 fp0 = tcg_temp_new_i32();
11250 gen_load_fpr32(ctx, fp0, fs);
11251 if (ctx->abs2008) {
11252 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
11253 } else {
11254 gen_helper_float_chs_s(fp0, fp0);
11256 gen_store_fpr32(ctx, fp0, fd);
11257 tcg_temp_free_i32(fp0);
11259 break;
11260 case OPC_ROUND_L_S:
11261 check_cp1_64bitmode(ctx);
11263 TCGv_i32 fp32 = tcg_temp_new_i32();
11264 TCGv_i64 fp64 = tcg_temp_new_i64();
11266 gen_load_fpr32(ctx, fp32, fs);
11267 if (ctx->nan2008) {
11268 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
11269 } else {
11270 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
11272 tcg_temp_free_i32(fp32);
11273 gen_store_fpr64(ctx, fp64, fd);
11274 tcg_temp_free_i64(fp64);
11276 break;
11277 case OPC_TRUNC_L_S:
11278 check_cp1_64bitmode(ctx);
11280 TCGv_i32 fp32 = tcg_temp_new_i32();
11281 TCGv_i64 fp64 = tcg_temp_new_i64();
11283 gen_load_fpr32(ctx, fp32, fs);
11284 if (ctx->nan2008) {
11285 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
11286 } else {
11287 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
11289 tcg_temp_free_i32(fp32);
11290 gen_store_fpr64(ctx, fp64, fd);
11291 tcg_temp_free_i64(fp64);
11293 break;
11294 case OPC_CEIL_L_S:
11295 check_cp1_64bitmode(ctx);
11297 TCGv_i32 fp32 = tcg_temp_new_i32();
11298 TCGv_i64 fp64 = tcg_temp_new_i64();
11300 gen_load_fpr32(ctx, fp32, fs);
11301 if (ctx->nan2008) {
11302 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
11303 } else {
11304 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
11306 tcg_temp_free_i32(fp32);
11307 gen_store_fpr64(ctx, fp64, fd);
11308 tcg_temp_free_i64(fp64);
11310 break;
11311 case OPC_FLOOR_L_S:
11312 check_cp1_64bitmode(ctx);
11314 TCGv_i32 fp32 = tcg_temp_new_i32();
11315 TCGv_i64 fp64 = tcg_temp_new_i64();
11317 gen_load_fpr32(ctx, fp32, fs);
11318 if (ctx->nan2008) {
11319 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
11320 } else {
11321 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
11323 tcg_temp_free_i32(fp32);
11324 gen_store_fpr64(ctx, fp64, fd);
11325 tcg_temp_free_i64(fp64);
11327 break;
11328 case OPC_ROUND_W_S:
11330 TCGv_i32 fp0 = tcg_temp_new_i32();
11332 gen_load_fpr32(ctx, fp0, fs);
11333 if (ctx->nan2008) {
11334 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
11335 } else {
11336 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
11338 gen_store_fpr32(ctx, fp0, fd);
11339 tcg_temp_free_i32(fp0);
11341 break;
11342 case OPC_TRUNC_W_S:
11344 TCGv_i32 fp0 = tcg_temp_new_i32();
11346 gen_load_fpr32(ctx, fp0, fs);
11347 if (ctx->nan2008) {
11348 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
11349 } else {
11350 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
11352 gen_store_fpr32(ctx, fp0, fd);
11353 tcg_temp_free_i32(fp0);
11355 break;
11356 case OPC_CEIL_W_S:
11358 TCGv_i32 fp0 = tcg_temp_new_i32();
11360 gen_load_fpr32(ctx, fp0, fs);
11361 if (ctx->nan2008) {
11362 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
11363 } else {
11364 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
11366 gen_store_fpr32(ctx, fp0, fd);
11367 tcg_temp_free_i32(fp0);
11369 break;
11370 case OPC_FLOOR_W_S:
11372 TCGv_i32 fp0 = tcg_temp_new_i32();
11374 gen_load_fpr32(ctx, fp0, fs);
11375 if (ctx->nan2008) {
11376 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
11377 } else {
11378 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
11380 gen_store_fpr32(ctx, fp0, fd);
11381 tcg_temp_free_i32(fp0);
11383 break;
11384 case OPC_SEL_S:
11385 check_insn(ctx, ISA_MIPS32R6);
11386 gen_sel_s(ctx, op1, fd, ft, fs);
11387 break;
11388 case OPC_SELEQZ_S:
11389 check_insn(ctx, ISA_MIPS32R6);
11390 gen_sel_s(ctx, op1, fd, ft, fs);
11391 break;
11392 case OPC_SELNEZ_S:
11393 check_insn(ctx, ISA_MIPS32R6);
11394 gen_sel_s(ctx, op1, fd, ft, fs);
11395 break;
11396 case OPC_MOVCF_S:
11397 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11398 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11399 break;
11400 case OPC_MOVZ_S:
11401 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11403 TCGLabel *l1 = gen_new_label();
11404 TCGv_i32 fp0;
11406 if (ft != 0) {
11407 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11409 fp0 = tcg_temp_new_i32();
11410 gen_load_fpr32(ctx, fp0, fs);
11411 gen_store_fpr32(ctx, fp0, fd);
11412 tcg_temp_free_i32(fp0);
11413 gen_set_label(l1);
11415 break;
11416 case OPC_MOVN_S:
11417 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11419 TCGLabel *l1 = gen_new_label();
11420 TCGv_i32 fp0;
11422 if (ft != 0) {
11423 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11424 fp0 = tcg_temp_new_i32();
11425 gen_load_fpr32(ctx, fp0, fs);
11426 gen_store_fpr32(ctx, fp0, fd);
11427 tcg_temp_free_i32(fp0);
11428 gen_set_label(l1);
11431 break;
11432 case OPC_RECIP_S:
11434 TCGv_i32 fp0 = tcg_temp_new_i32();
11436 gen_load_fpr32(ctx, fp0, fs);
11437 gen_helper_float_recip_s(fp0, cpu_env, fp0);
11438 gen_store_fpr32(ctx, fp0, fd);
11439 tcg_temp_free_i32(fp0);
11441 break;
11442 case OPC_RSQRT_S:
11444 TCGv_i32 fp0 = tcg_temp_new_i32();
11446 gen_load_fpr32(ctx, fp0, fs);
11447 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
11448 gen_store_fpr32(ctx, fp0, fd);
11449 tcg_temp_free_i32(fp0);
11451 break;
11452 case OPC_MADDF_S:
11453 check_insn(ctx, ISA_MIPS32R6);
11455 TCGv_i32 fp0 = tcg_temp_new_i32();
11456 TCGv_i32 fp1 = tcg_temp_new_i32();
11457 TCGv_i32 fp2 = tcg_temp_new_i32();
11458 gen_load_fpr32(ctx, fp0, fs);
11459 gen_load_fpr32(ctx, fp1, ft);
11460 gen_load_fpr32(ctx, fp2, fd);
11461 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
11462 gen_store_fpr32(ctx, fp2, fd);
11463 tcg_temp_free_i32(fp2);
11464 tcg_temp_free_i32(fp1);
11465 tcg_temp_free_i32(fp0);
11467 break;
11468 case OPC_MSUBF_S:
11469 check_insn(ctx, ISA_MIPS32R6);
11471 TCGv_i32 fp0 = tcg_temp_new_i32();
11472 TCGv_i32 fp1 = tcg_temp_new_i32();
11473 TCGv_i32 fp2 = tcg_temp_new_i32();
11474 gen_load_fpr32(ctx, fp0, fs);
11475 gen_load_fpr32(ctx, fp1, ft);
11476 gen_load_fpr32(ctx, fp2, fd);
11477 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
11478 gen_store_fpr32(ctx, fp2, fd);
11479 tcg_temp_free_i32(fp2);
11480 tcg_temp_free_i32(fp1);
11481 tcg_temp_free_i32(fp0);
11483 break;
11484 case OPC_RINT_S:
11485 check_insn(ctx, ISA_MIPS32R6);
11487 TCGv_i32 fp0 = tcg_temp_new_i32();
11488 gen_load_fpr32(ctx, fp0, fs);
11489 gen_helper_float_rint_s(fp0, cpu_env, fp0);
11490 gen_store_fpr32(ctx, fp0, fd);
11491 tcg_temp_free_i32(fp0);
11493 break;
11494 case OPC_CLASS_S:
11495 check_insn(ctx, ISA_MIPS32R6);
11497 TCGv_i32 fp0 = tcg_temp_new_i32();
11498 gen_load_fpr32(ctx, fp0, fs);
11499 gen_helper_float_class_s(fp0, cpu_env, fp0);
11500 gen_store_fpr32(ctx, fp0, fd);
11501 tcg_temp_free_i32(fp0);
11503 break;
11504 case OPC_MIN_S: /* OPC_RECIP2_S */
11505 if (ctx->insn_flags & ISA_MIPS32R6) {
11506 /* OPC_MIN_S */
11507 TCGv_i32 fp0 = tcg_temp_new_i32();
11508 TCGv_i32 fp1 = tcg_temp_new_i32();
11509 TCGv_i32 fp2 = tcg_temp_new_i32();
11510 gen_load_fpr32(ctx, fp0, fs);
11511 gen_load_fpr32(ctx, fp1, ft);
11512 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
11513 gen_store_fpr32(ctx, fp2, fd);
11514 tcg_temp_free_i32(fp2);
11515 tcg_temp_free_i32(fp1);
11516 tcg_temp_free_i32(fp0);
11517 } else {
11518 /* OPC_RECIP2_S */
11519 check_cp1_64bitmode(ctx);
11521 TCGv_i32 fp0 = tcg_temp_new_i32();
11522 TCGv_i32 fp1 = tcg_temp_new_i32();
11524 gen_load_fpr32(ctx, fp0, fs);
11525 gen_load_fpr32(ctx, fp1, ft);
11526 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
11527 tcg_temp_free_i32(fp1);
11528 gen_store_fpr32(ctx, fp0, fd);
11529 tcg_temp_free_i32(fp0);
11532 break;
11533 case OPC_MINA_S: /* OPC_RECIP1_S */
11534 if (ctx->insn_flags & ISA_MIPS32R6) {
11535 /* OPC_MINA_S */
11536 TCGv_i32 fp0 = tcg_temp_new_i32();
11537 TCGv_i32 fp1 = tcg_temp_new_i32();
11538 TCGv_i32 fp2 = tcg_temp_new_i32();
11539 gen_load_fpr32(ctx, fp0, fs);
11540 gen_load_fpr32(ctx, fp1, ft);
11541 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
11542 gen_store_fpr32(ctx, fp2, fd);
11543 tcg_temp_free_i32(fp2);
11544 tcg_temp_free_i32(fp1);
11545 tcg_temp_free_i32(fp0);
11546 } else {
11547 /* OPC_RECIP1_S */
11548 check_cp1_64bitmode(ctx);
11550 TCGv_i32 fp0 = tcg_temp_new_i32();
11552 gen_load_fpr32(ctx, fp0, fs);
11553 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
11554 gen_store_fpr32(ctx, fp0, fd);
11555 tcg_temp_free_i32(fp0);
11558 break;
11559 case OPC_MAX_S: /* OPC_RSQRT1_S */
11560 if (ctx->insn_flags & ISA_MIPS32R6) {
11561 /* OPC_MAX_S */
11562 TCGv_i32 fp0 = tcg_temp_new_i32();
11563 TCGv_i32 fp1 = tcg_temp_new_i32();
11564 gen_load_fpr32(ctx, fp0, fs);
11565 gen_load_fpr32(ctx, fp1, ft);
11566 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
11567 gen_store_fpr32(ctx, fp1, fd);
11568 tcg_temp_free_i32(fp1);
11569 tcg_temp_free_i32(fp0);
11570 } else {
11571 /* OPC_RSQRT1_S */
11572 check_cp1_64bitmode(ctx);
11574 TCGv_i32 fp0 = tcg_temp_new_i32();
11576 gen_load_fpr32(ctx, fp0, fs);
11577 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
11578 gen_store_fpr32(ctx, fp0, fd);
11579 tcg_temp_free_i32(fp0);
11582 break;
11583 case OPC_MAXA_S: /* OPC_RSQRT2_S */
11584 if (ctx->insn_flags & ISA_MIPS32R6) {
11585 /* OPC_MAXA_S */
11586 TCGv_i32 fp0 = tcg_temp_new_i32();
11587 TCGv_i32 fp1 = tcg_temp_new_i32();
11588 gen_load_fpr32(ctx, fp0, fs);
11589 gen_load_fpr32(ctx, fp1, ft);
11590 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
11591 gen_store_fpr32(ctx, fp1, fd);
11592 tcg_temp_free_i32(fp1);
11593 tcg_temp_free_i32(fp0);
11594 } else {
11595 /* OPC_RSQRT2_S */
11596 check_cp1_64bitmode(ctx);
11598 TCGv_i32 fp0 = tcg_temp_new_i32();
11599 TCGv_i32 fp1 = tcg_temp_new_i32();
11601 gen_load_fpr32(ctx, fp0, fs);
11602 gen_load_fpr32(ctx, fp1, ft);
11603 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
11604 tcg_temp_free_i32(fp1);
11605 gen_store_fpr32(ctx, fp0, fd);
11606 tcg_temp_free_i32(fp0);
11609 break;
11610 case OPC_CVT_D_S:
11611 check_cp1_registers(ctx, fd);
11613 TCGv_i32 fp32 = tcg_temp_new_i32();
11614 TCGv_i64 fp64 = tcg_temp_new_i64();
11616 gen_load_fpr32(ctx, fp32, fs);
11617 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
11618 tcg_temp_free_i32(fp32);
11619 gen_store_fpr64(ctx, fp64, fd);
11620 tcg_temp_free_i64(fp64);
11622 break;
11623 case OPC_CVT_W_S:
11625 TCGv_i32 fp0 = tcg_temp_new_i32();
11627 gen_load_fpr32(ctx, fp0, fs);
11628 if (ctx->nan2008) {
11629 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
11630 } else {
11631 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
11633 gen_store_fpr32(ctx, fp0, fd);
11634 tcg_temp_free_i32(fp0);
11636 break;
11637 case OPC_CVT_L_S:
11638 check_cp1_64bitmode(ctx);
11640 TCGv_i32 fp32 = tcg_temp_new_i32();
11641 TCGv_i64 fp64 = tcg_temp_new_i64();
11643 gen_load_fpr32(ctx, fp32, fs);
11644 if (ctx->nan2008) {
11645 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
11646 } else {
11647 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
11649 tcg_temp_free_i32(fp32);
11650 gen_store_fpr64(ctx, fp64, fd);
11651 tcg_temp_free_i64(fp64);
11653 break;
11654 case OPC_CVT_PS_S:
11655 check_ps(ctx);
11657 TCGv_i64 fp64 = tcg_temp_new_i64();
11658 TCGv_i32 fp32_0 = tcg_temp_new_i32();
11659 TCGv_i32 fp32_1 = tcg_temp_new_i32();
11661 gen_load_fpr32(ctx, fp32_0, fs);
11662 gen_load_fpr32(ctx, fp32_1, ft);
11663 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
11664 tcg_temp_free_i32(fp32_1);
11665 tcg_temp_free_i32(fp32_0);
11666 gen_store_fpr64(ctx, fp64, fd);
11667 tcg_temp_free_i64(fp64);
11669 break;
11670 case OPC_CMP_F_S:
11671 case OPC_CMP_UN_S:
11672 case OPC_CMP_EQ_S:
11673 case OPC_CMP_UEQ_S:
11674 case OPC_CMP_OLT_S:
11675 case OPC_CMP_ULT_S:
11676 case OPC_CMP_OLE_S:
11677 case OPC_CMP_ULE_S:
11678 case OPC_CMP_SF_S:
11679 case OPC_CMP_NGLE_S:
11680 case OPC_CMP_SEQ_S:
11681 case OPC_CMP_NGL_S:
11682 case OPC_CMP_LT_S:
11683 case OPC_CMP_NGE_S:
11684 case OPC_CMP_LE_S:
11685 case OPC_CMP_NGT_S:
11686 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11687 if (ctx->opcode & (1 << 6)) {
11688 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
11689 } else {
11690 gen_cmp_s(ctx, func - 48, ft, fs, cc);
11692 break;
11693 case OPC_ADD_D:
11694 check_cp1_registers(ctx, fs | ft | fd);
11696 TCGv_i64 fp0 = tcg_temp_new_i64();
11697 TCGv_i64 fp1 = tcg_temp_new_i64();
11699 gen_load_fpr64(ctx, fp0, fs);
11700 gen_load_fpr64(ctx, fp1, ft);
11701 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
11702 tcg_temp_free_i64(fp1);
11703 gen_store_fpr64(ctx, fp0, fd);
11704 tcg_temp_free_i64(fp0);
11706 break;
11707 case OPC_SUB_D:
11708 check_cp1_registers(ctx, fs | ft | fd);
11710 TCGv_i64 fp0 = tcg_temp_new_i64();
11711 TCGv_i64 fp1 = tcg_temp_new_i64();
11713 gen_load_fpr64(ctx, fp0, fs);
11714 gen_load_fpr64(ctx, fp1, ft);
11715 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
11716 tcg_temp_free_i64(fp1);
11717 gen_store_fpr64(ctx, fp0, fd);
11718 tcg_temp_free_i64(fp0);
11720 break;
11721 case OPC_MUL_D:
11722 check_cp1_registers(ctx, fs | ft | fd);
11724 TCGv_i64 fp0 = tcg_temp_new_i64();
11725 TCGv_i64 fp1 = tcg_temp_new_i64();
11727 gen_load_fpr64(ctx, fp0, fs);
11728 gen_load_fpr64(ctx, fp1, ft);
11729 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
11730 tcg_temp_free_i64(fp1);
11731 gen_store_fpr64(ctx, fp0, fd);
11732 tcg_temp_free_i64(fp0);
11734 break;
11735 case OPC_DIV_D:
11736 check_cp1_registers(ctx, fs | ft | fd);
11738 TCGv_i64 fp0 = tcg_temp_new_i64();
11739 TCGv_i64 fp1 = tcg_temp_new_i64();
11741 gen_load_fpr64(ctx, fp0, fs);
11742 gen_load_fpr64(ctx, fp1, ft);
11743 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
11744 tcg_temp_free_i64(fp1);
11745 gen_store_fpr64(ctx, fp0, fd);
11746 tcg_temp_free_i64(fp0);
11748 break;
11749 case OPC_SQRT_D:
11750 check_cp1_registers(ctx, fs | fd);
11752 TCGv_i64 fp0 = tcg_temp_new_i64();
11754 gen_load_fpr64(ctx, fp0, fs);
11755 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
11756 gen_store_fpr64(ctx, fp0, fd);
11757 tcg_temp_free_i64(fp0);
11759 break;
11760 case OPC_ABS_D:
11761 check_cp1_registers(ctx, fs | fd);
11763 TCGv_i64 fp0 = tcg_temp_new_i64();
11765 gen_load_fpr64(ctx, fp0, fs);
11766 if (ctx->abs2008) {
11767 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
11768 } else {
11769 gen_helper_float_abs_d(fp0, fp0);
11771 gen_store_fpr64(ctx, fp0, fd);
11772 tcg_temp_free_i64(fp0);
11774 break;
11775 case OPC_MOV_D:
11776 check_cp1_registers(ctx, fs | fd);
11778 TCGv_i64 fp0 = tcg_temp_new_i64();
11780 gen_load_fpr64(ctx, fp0, fs);
11781 gen_store_fpr64(ctx, fp0, fd);
11782 tcg_temp_free_i64(fp0);
11784 break;
11785 case OPC_NEG_D:
11786 check_cp1_registers(ctx, fs | fd);
11788 TCGv_i64 fp0 = tcg_temp_new_i64();
11790 gen_load_fpr64(ctx, fp0, fs);
11791 if (ctx->abs2008) {
11792 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
11793 } else {
11794 gen_helper_float_chs_d(fp0, fp0);
11796 gen_store_fpr64(ctx, fp0, fd);
11797 tcg_temp_free_i64(fp0);
11799 break;
11800 case OPC_ROUND_L_D:
11801 check_cp1_64bitmode(ctx);
11803 TCGv_i64 fp0 = tcg_temp_new_i64();
11805 gen_load_fpr64(ctx, fp0, fs);
11806 if (ctx->nan2008) {
11807 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
11808 } else {
11809 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
11811 gen_store_fpr64(ctx, fp0, fd);
11812 tcg_temp_free_i64(fp0);
11814 break;
11815 case OPC_TRUNC_L_D:
11816 check_cp1_64bitmode(ctx);
11818 TCGv_i64 fp0 = tcg_temp_new_i64();
11820 gen_load_fpr64(ctx, fp0, fs);
11821 if (ctx->nan2008) {
11822 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
11823 } else {
11824 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
11826 gen_store_fpr64(ctx, fp0, fd);
11827 tcg_temp_free_i64(fp0);
11829 break;
11830 case OPC_CEIL_L_D:
11831 check_cp1_64bitmode(ctx);
11833 TCGv_i64 fp0 = tcg_temp_new_i64();
11835 gen_load_fpr64(ctx, fp0, fs);
11836 if (ctx->nan2008) {
11837 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
11838 } else {
11839 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
11841 gen_store_fpr64(ctx, fp0, fd);
11842 tcg_temp_free_i64(fp0);
11844 break;
11845 case OPC_FLOOR_L_D:
11846 check_cp1_64bitmode(ctx);
11848 TCGv_i64 fp0 = tcg_temp_new_i64();
11850 gen_load_fpr64(ctx, fp0, fs);
11851 if (ctx->nan2008) {
11852 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
11853 } else {
11854 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
11856 gen_store_fpr64(ctx, fp0, fd);
11857 tcg_temp_free_i64(fp0);
11859 break;
11860 case OPC_ROUND_W_D:
11861 check_cp1_registers(ctx, fs);
11863 TCGv_i32 fp32 = tcg_temp_new_i32();
11864 TCGv_i64 fp64 = tcg_temp_new_i64();
11866 gen_load_fpr64(ctx, fp64, fs);
11867 if (ctx->nan2008) {
11868 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
11869 } else {
11870 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
11872 tcg_temp_free_i64(fp64);
11873 gen_store_fpr32(ctx, fp32, fd);
11874 tcg_temp_free_i32(fp32);
11876 break;
11877 case OPC_TRUNC_W_D:
11878 check_cp1_registers(ctx, fs);
11880 TCGv_i32 fp32 = tcg_temp_new_i32();
11881 TCGv_i64 fp64 = tcg_temp_new_i64();
11883 gen_load_fpr64(ctx, fp64, fs);
11884 if (ctx->nan2008) {
11885 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
11886 } else {
11887 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
11889 tcg_temp_free_i64(fp64);
11890 gen_store_fpr32(ctx, fp32, fd);
11891 tcg_temp_free_i32(fp32);
11893 break;
11894 case OPC_CEIL_W_D:
11895 check_cp1_registers(ctx, fs);
11897 TCGv_i32 fp32 = tcg_temp_new_i32();
11898 TCGv_i64 fp64 = tcg_temp_new_i64();
11900 gen_load_fpr64(ctx, fp64, fs);
11901 if (ctx->nan2008) {
11902 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
11903 } else {
11904 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
11906 tcg_temp_free_i64(fp64);
11907 gen_store_fpr32(ctx, fp32, fd);
11908 tcg_temp_free_i32(fp32);
11910 break;
11911 case OPC_FLOOR_W_D:
11912 check_cp1_registers(ctx, fs);
11914 TCGv_i32 fp32 = tcg_temp_new_i32();
11915 TCGv_i64 fp64 = tcg_temp_new_i64();
11917 gen_load_fpr64(ctx, fp64, fs);
11918 if (ctx->nan2008) {
11919 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
11920 } else {
11921 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
11923 tcg_temp_free_i64(fp64);
11924 gen_store_fpr32(ctx, fp32, fd);
11925 tcg_temp_free_i32(fp32);
11927 break;
11928 case OPC_SEL_D:
11929 check_insn(ctx, ISA_MIPS32R6);
11930 gen_sel_d(ctx, op1, fd, ft, fs);
11931 break;
11932 case OPC_SELEQZ_D:
11933 check_insn(ctx, ISA_MIPS32R6);
11934 gen_sel_d(ctx, op1, fd, ft, fs);
11935 break;
11936 case OPC_SELNEZ_D:
11937 check_insn(ctx, ISA_MIPS32R6);
11938 gen_sel_d(ctx, op1, fd, ft, fs);
11939 break;
11940 case OPC_MOVCF_D:
11941 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11942 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11943 break;
11944 case OPC_MOVZ_D:
11945 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11947 TCGLabel *l1 = gen_new_label();
11948 TCGv_i64 fp0;
11950 if (ft != 0) {
11951 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11953 fp0 = tcg_temp_new_i64();
11954 gen_load_fpr64(ctx, fp0, fs);
11955 gen_store_fpr64(ctx, fp0, fd);
11956 tcg_temp_free_i64(fp0);
11957 gen_set_label(l1);
11959 break;
11960 case OPC_MOVN_D:
11961 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11963 TCGLabel *l1 = gen_new_label();
11964 TCGv_i64 fp0;
11966 if (ft != 0) {
11967 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11968 fp0 = tcg_temp_new_i64();
11969 gen_load_fpr64(ctx, fp0, fs);
11970 gen_store_fpr64(ctx, fp0, fd);
11971 tcg_temp_free_i64(fp0);
11972 gen_set_label(l1);
11975 break;
11976 case OPC_RECIP_D:
11977 check_cp1_registers(ctx, fs | fd);
11979 TCGv_i64 fp0 = tcg_temp_new_i64();
11981 gen_load_fpr64(ctx, fp0, fs);
11982 gen_helper_float_recip_d(fp0, cpu_env, fp0);
11983 gen_store_fpr64(ctx, fp0, fd);
11984 tcg_temp_free_i64(fp0);
11986 break;
11987 case OPC_RSQRT_D:
11988 check_cp1_registers(ctx, fs | fd);
11990 TCGv_i64 fp0 = tcg_temp_new_i64();
11992 gen_load_fpr64(ctx, fp0, fs);
11993 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
11994 gen_store_fpr64(ctx, fp0, fd);
11995 tcg_temp_free_i64(fp0);
11997 break;
11998 case OPC_MADDF_D:
11999 check_insn(ctx, ISA_MIPS32R6);
12001 TCGv_i64 fp0 = tcg_temp_new_i64();
12002 TCGv_i64 fp1 = tcg_temp_new_i64();
12003 TCGv_i64 fp2 = tcg_temp_new_i64();
12004 gen_load_fpr64(ctx, fp0, fs);
12005 gen_load_fpr64(ctx, fp1, ft);
12006 gen_load_fpr64(ctx, fp2, fd);
12007 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
12008 gen_store_fpr64(ctx, fp2, fd);
12009 tcg_temp_free_i64(fp2);
12010 tcg_temp_free_i64(fp1);
12011 tcg_temp_free_i64(fp0);
12013 break;
12014 case OPC_MSUBF_D:
12015 check_insn(ctx, ISA_MIPS32R6);
12017 TCGv_i64 fp0 = tcg_temp_new_i64();
12018 TCGv_i64 fp1 = tcg_temp_new_i64();
12019 TCGv_i64 fp2 = tcg_temp_new_i64();
12020 gen_load_fpr64(ctx, fp0, fs);
12021 gen_load_fpr64(ctx, fp1, ft);
12022 gen_load_fpr64(ctx, fp2, fd);
12023 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
12024 gen_store_fpr64(ctx, fp2, fd);
12025 tcg_temp_free_i64(fp2);
12026 tcg_temp_free_i64(fp1);
12027 tcg_temp_free_i64(fp0);
12029 break;
12030 case OPC_RINT_D:
12031 check_insn(ctx, ISA_MIPS32R6);
12033 TCGv_i64 fp0 = tcg_temp_new_i64();
12034 gen_load_fpr64(ctx, fp0, fs);
12035 gen_helper_float_rint_d(fp0, cpu_env, fp0);
12036 gen_store_fpr64(ctx, fp0, fd);
12037 tcg_temp_free_i64(fp0);
12039 break;
12040 case OPC_CLASS_D:
12041 check_insn(ctx, ISA_MIPS32R6);
12043 TCGv_i64 fp0 = tcg_temp_new_i64();
12044 gen_load_fpr64(ctx, fp0, fs);
12045 gen_helper_float_class_d(fp0, cpu_env, fp0);
12046 gen_store_fpr64(ctx, fp0, fd);
12047 tcg_temp_free_i64(fp0);
12049 break;
12050 case OPC_MIN_D: /* OPC_RECIP2_D */
12051 if (ctx->insn_flags & ISA_MIPS32R6) {
12052 /* OPC_MIN_D */
12053 TCGv_i64 fp0 = tcg_temp_new_i64();
12054 TCGv_i64 fp1 = tcg_temp_new_i64();
12055 gen_load_fpr64(ctx, fp0, fs);
12056 gen_load_fpr64(ctx, fp1, ft);
12057 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
12058 gen_store_fpr64(ctx, fp1, fd);
12059 tcg_temp_free_i64(fp1);
12060 tcg_temp_free_i64(fp0);
12061 } else {
12062 /* OPC_RECIP2_D */
12063 check_cp1_64bitmode(ctx);
12065 TCGv_i64 fp0 = tcg_temp_new_i64();
12066 TCGv_i64 fp1 = tcg_temp_new_i64();
12068 gen_load_fpr64(ctx, fp0, fs);
12069 gen_load_fpr64(ctx, fp1, ft);
12070 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
12071 tcg_temp_free_i64(fp1);
12072 gen_store_fpr64(ctx, fp0, fd);
12073 tcg_temp_free_i64(fp0);
12076 break;
12077 case OPC_MINA_D: /* OPC_RECIP1_D */
12078 if (ctx->insn_flags & ISA_MIPS32R6) {
12079 /* OPC_MINA_D */
12080 TCGv_i64 fp0 = tcg_temp_new_i64();
12081 TCGv_i64 fp1 = tcg_temp_new_i64();
12082 gen_load_fpr64(ctx, fp0, fs);
12083 gen_load_fpr64(ctx, fp1, ft);
12084 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
12085 gen_store_fpr64(ctx, fp1, fd);
12086 tcg_temp_free_i64(fp1);
12087 tcg_temp_free_i64(fp0);
12088 } else {
12089 /* OPC_RECIP1_D */
12090 check_cp1_64bitmode(ctx);
12092 TCGv_i64 fp0 = tcg_temp_new_i64();
12094 gen_load_fpr64(ctx, fp0, fs);
12095 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
12096 gen_store_fpr64(ctx, fp0, fd);
12097 tcg_temp_free_i64(fp0);
12100 break;
12101 case OPC_MAX_D: /* OPC_RSQRT1_D */
12102 if (ctx->insn_flags & ISA_MIPS32R6) {
12103 /* OPC_MAX_D */
12104 TCGv_i64 fp0 = tcg_temp_new_i64();
12105 TCGv_i64 fp1 = tcg_temp_new_i64();
12106 gen_load_fpr64(ctx, fp0, fs);
12107 gen_load_fpr64(ctx, fp1, ft);
12108 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
12109 gen_store_fpr64(ctx, fp1, fd);
12110 tcg_temp_free_i64(fp1);
12111 tcg_temp_free_i64(fp0);
12112 } else {
12113 /* OPC_RSQRT1_D */
12114 check_cp1_64bitmode(ctx);
12116 TCGv_i64 fp0 = tcg_temp_new_i64();
12118 gen_load_fpr64(ctx, fp0, fs);
12119 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
12120 gen_store_fpr64(ctx, fp0, fd);
12121 tcg_temp_free_i64(fp0);
12124 break;
12125 case OPC_MAXA_D: /* OPC_RSQRT2_D */
12126 if (ctx->insn_flags & ISA_MIPS32R6) {
12127 /* OPC_MAXA_D */
12128 TCGv_i64 fp0 = tcg_temp_new_i64();
12129 TCGv_i64 fp1 = tcg_temp_new_i64();
12130 gen_load_fpr64(ctx, fp0, fs);
12131 gen_load_fpr64(ctx, fp1, ft);
12132 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
12133 gen_store_fpr64(ctx, fp1, fd);
12134 tcg_temp_free_i64(fp1);
12135 tcg_temp_free_i64(fp0);
12136 } else {
12137 /* OPC_RSQRT2_D */
12138 check_cp1_64bitmode(ctx);
12140 TCGv_i64 fp0 = tcg_temp_new_i64();
12141 TCGv_i64 fp1 = tcg_temp_new_i64();
12143 gen_load_fpr64(ctx, fp0, fs);
12144 gen_load_fpr64(ctx, fp1, ft);
12145 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
12146 tcg_temp_free_i64(fp1);
12147 gen_store_fpr64(ctx, fp0, fd);
12148 tcg_temp_free_i64(fp0);
12151 break;
12152 case OPC_CMP_F_D:
12153 case OPC_CMP_UN_D:
12154 case OPC_CMP_EQ_D:
12155 case OPC_CMP_UEQ_D:
12156 case OPC_CMP_OLT_D:
12157 case OPC_CMP_ULT_D:
12158 case OPC_CMP_OLE_D:
12159 case OPC_CMP_ULE_D:
12160 case OPC_CMP_SF_D:
12161 case OPC_CMP_NGLE_D:
12162 case OPC_CMP_SEQ_D:
12163 case OPC_CMP_NGL_D:
12164 case OPC_CMP_LT_D:
12165 case OPC_CMP_NGE_D:
12166 case OPC_CMP_LE_D:
12167 case OPC_CMP_NGT_D:
12168 check_insn_opc_removed(ctx, ISA_MIPS32R6);
12169 if (ctx->opcode & (1 << 6)) {
12170 gen_cmpabs_d(ctx, func - 48, ft, fs, cc);
12171 } else {
12172 gen_cmp_d(ctx, func - 48, ft, fs, cc);
12174 break;
12175 case OPC_CVT_S_D:
12176 check_cp1_registers(ctx, fs);
12178 TCGv_i32 fp32 = tcg_temp_new_i32();
12179 TCGv_i64 fp64 = tcg_temp_new_i64();
12181 gen_load_fpr64(ctx, fp64, fs);
12182 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
12183 tcg_temp_free_i64(fp64);
12184 gen_store_fpr32(ctx, fp32, fd);
12185 tcg_temp_free_i32(fp32);
12187 break;
12188 case OPC_CVT_W_D:
12189 check_cp1_registers(ctx, fs);
12191 TCGv_i32 fp32 = tcg_temp_new_i32();
12192 TCGv_i64 fp64 = tcg_temp_new_i64();
12194 gen_load_fpr64(ctx, fp64, fs);
12195 if (ctx->nan2008) {
12196 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
12197 } else {
12198 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
12200 tcg_temp_free_i64(fp64);
12201 gen_store_fpr32(ctx, fp32, fd);
12202 tcg_temp_free_i32(fp32);
12204 break;
12205 case OPC_CVT_L_D:
12206 check_cp1_64bitmode(ctx);
12208 TCGv_i64 fp0 = tcg_temp_new_i64();
12210 gen_load_fpr64(ctx, fp0, fs);
12211 if (ctx->nan2008) {
12212 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
12213 } else {
12214 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
12216 gen_store_fpr64(ctx, fp0, fd);
12217 tcg_temp_free_i64(fp0);
12219 break;
12220 case OPC_CVT_S_W:
12222 TCGv_i32 fp0 = tcg_temp_new_i32();
12224 gen_load_fpr32(ctx, fp0, fs);
12225 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
12226 gen_store_fpr32(ctx, fp0, fd);
12227 tcg_temp_free_i32(fp0);
12229 break;
12230 case OPC_CVT_D_W:
12231 check_cp1_registers(ctx, fd);
12233 TCGv_i32 fp32 = tcg_temp_new_i32();
12234 TCGv_i64 fp64 = tcg_temp_new_i64();
12236 gen_load_fpr32(ctx, fp32, fs);
12237 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
12238 tcg_temp_free_i32(fp32);
12239 gen_store_fpr64(ctx, fp64, fd);
12240 tcg_temp_free_i64(fp64);
12242 break;
12243 case OPC_CVT_S_L:
12244 check_cp1_64bitmode(ctx);
12246 TCGv_i32 fp32 = tcg_temp_new_i32();
12247 TCGv_i64 fp64 = tcg_temp_new_i64();
12249 gen_load_fpr64(ctx, fp64, fs);
12250 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
12251 tcg_temp_free_i64(fp64);
12252 gen_store_fpr32(ctx, fp32, fd);
12253 tcg_temp_free_i32(fp32);
12255 break;
12256 case OPC_CVT_D_L:
12257 check_cp1_64bitmode(ctx);
12259 TCGv_i64 fp0 = tcg_temp_new_i64();
12261 gen_load_fpr64(ctx, fp0, fs);
12262 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
12263 gen_store_fpr64(ctx, fp0, fd);
12264 tcg_temp_free_i64(fp0);
12266 break;
12267 case OPC_CVT_PS_PW:
12268 check_ps(ctx);
12270 TCGv_i64 fp0 = tcg_temp_new_i64();
12272 gen_load_fpr64(ctx, fp0, fs);
12273 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
12274 gen_store_fpr64(ctx, fp0, fd);
12275 tcg_temp_free_i64(fp0);
12277 break;
12278 case OPC_ADD_PS:
12279 check_ps(ctx);
12281 TCGv_i64 fp0 = tcg_temp_new_i64();
12282 TCGv_i64 fp1 = tcg_temp_new_i64();
12284 gen_load_fpr64(ctx, fp0, fs);
12285 gen_load_fpr64(ctx, fp1, ft);
12286 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
12287 tcg_temp_free_i64(fp1);
12288 gen_store_fpr64(ctx, fp0, fd);
12289 tcg_temp_free_i64(fp0);
12291 break;
12292 case OPC_SUB_PS:
12293 check_ps(ctx);
12295 TCGv_i64 fp0 = tcg_temp_new_i64();
12296 TCGv_i64 fp1 = tcg_temp_new_i64();
12298 gen_load_fpr64(ctx, fp0, fs);
12299 gen_load_fpr64(ctx, fp1, ft);
12300 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
12301 tcg_temp_free_i64(fp1);
12302 gen_store_fpr64(ctx, fp0, fd);
12303 tcg_temp_free_i64(fp0);
12305 break;
12306 case OPC_MUL_PS:
12307 check_ps(ctx);
12309 TCGv_i64 fp0 = tcg_temp_new_i64();
12310 TCGv_i64 fp1 = tcg_temp_new_i64();
12312 gen_load_fpr64(ctx, fp0, fs);
12313 gen_load_fpr64(ctx, fp1, ft);
12314 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
12315 tcg_temp_free_i64(fp1);
12316 gen_store_fpr64(ctx, fp0, fd);
12317 tcg_temp_free_i64(fp0);
12319 break;
12320 case OPC_ABS_PS:
12321 check_ps(ctx);
12323 TCGv_i64 fp0 = tcg_temp_new_i64();
12325 gen_load_fpr64(ctx, fp0, fs);
12326 gen_helper_float_abs_ps(fp0, fp0);
12327 gen_store_fpr64(ctx, fp0, fd);
12328 tcg_temp_free_i64(fp0);
12330 break;
12331 case OPC_MOV_PS:
12332 check_ps(ctx);
12334 TCGv_i64 fp0 = tcg_temp_new_i64();
12336 gen_load_fpr64(ctx, fp0, fs);
12337 gen_store_fpr64(ctx, fp0, fd);
12338 tcg_temp_free_i64(fp0);
12340 break;
12341 case OPC_NEG_PS:
12342 check_ps(ctx);
12344 TCGv_i64 fp0 = tcg_temp_new_i64();
12346 gen_load_fpr64(ctx, fp0, fs);
12347 gen_helper_float_chs_ps(fp0, fp0);
12348 gen_store_fpr64(ctx, fp0, fd);
12349 tcg_temp_free_i64(fp0);
12351 break;
12352 case OPC_MOVCF_PS:
12353 check_ps(ctx);
12354 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
12355 break;
12356 case OPC_MOVZ_PS:
12357 check_ps(ctx);
12359 TCGLabel *l1 = gen_new_label();
12360 TCGv_i64 fp0;
12362 if (ft != 0) {
12363 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
12365 fp0 = tcg_temp_new_i64();
12366 gen_load_fpr64(ctx, fp0, fs);
12367 gen_store_fpr64(ctx, fp0, fd);
12368 tcg_temp_free_i64(fp0);
12369 gen_set_label(l1);
12371 break;
12372 case OPC_MOVN_PS:
12373 check_ps(ctx);
12375 TCGLabel *l1 = gen_new_label();
12376 TCGv_i64 fp0;
12378 if (ft != 0) {
12379 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12380 fp0 = tcg_temp_new_i64();
12381 gen_load_fpr64(ctx, fp0, fs);
12382 gen_store_fpr64(ctx, fp0, fd);
12383 tcg_temp_free_i64(fp0);
12384 gen_set_label(l1);
12387 break;
12388 case OPC_ADDR_PS:
12389 check_ps(ctx);
12391 TCGv_i64 fp0 = tcg_temp_new_i64();
12392 TCGv_i64 fp1 = tcg_temp_new_i64();
12394 gen_load_fpr64(ctx, fp0, ft);
12395 gen_load_fpr64(ctx, fp1, fs);
12396 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
12397 tcg_temp_free_i64(fp1);
12398 gen_store_fpr64(ctx, fp0, fd);
12399 tcg_temp_free_i64(fp0);
12401 break;
12402 case OPC_MULR_PS:
12403 check_ps(ctx);
12405 TCGv_i64 fp0 = tcg_temp_new_i64();
12406 TCGv_i64 fp1 = tcg_temp_new_i64();
12408 gen_load_fpr64(ctx, fp0, ft);
12409 gen_load_fpr64(ctx, fp1, fs);
12410 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
12411 tcg_temp_free_i64(fp1);
12412 gen_store_fpr64(ctx, fp0, fd);
12413 tcg_temp_free_i64(fp0);
12415 break;
12416 case OPC_RECIP2_PS:
12417 check_ps(ctx);
12419 TCGv_i64 fp0 = tcg_temp_new_i64();
12420 TCGv_i64 fp1 = tcg_temp_new_i64();
12422 gen_load_fpr64(ctx, fp0, fs);
12423 gen_load_fpr64(ctx, fp1, ft);
12424 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
12425 tcg_temp_free_i64(fp1);
12426 gen_store_fpr64(ctx, fp0, fd);
12427 tcg_temp_free_i64(fp0);
12429 break;
12430 case OPC_RECIP1_PS:
12431 check_ps(ctx);
12433 TCGv_i64 fp0 = tcg_temp_new_i64();
12435 gen_load_fpr64(ctx, fp0, fs);
12436 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
12437 gen_store_fpr64(ctx, fp0, fd);
12438 tcg_temp_free_i64(fp0);
12440 break;
12441 case OPC_RSQRT1_PS:
12442 check_ps(ctx);
12444 TCGv_i64 fp0 = tcg_temp_new_i64();
12446 gen_load_fpr64(ctx, fp0, fs);
12447 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
12448 gen_store_fpr64(ctx, fp0, fd);
12449 tcg_temp_free_i64(fp0);
12451 break;
12452 case OPC_RSQRT2_PS:
12453 check_ps(ctx);
12455 TCGv_i64 fp0 = tcg_temp_new_i64();
12456 TCGv_i64 fp1 = tcg_temp_new_i64();
12458 gen_load_fpr64(ctx, fp0, fs);
12459 gen_load_fpr64(ctx, fp1, ft);
12460 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
12461 tcg_temp_free_i64(fp1);
12462 gen_store_fpr64(ctx, fp0, fd);
12463 tcg_temp_free_i64(fp0);
12465 break;
12466 case OPC_CVT_S_PU:
12467 check_cp1_64bitmode(ctx);
12469 TCGv_i32 fp0 = tcg_temp_new_i32();
12471 gen_load_fpr32h(ctx, fp0, fs);
12472 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
12473 gen_store_fpr32(ctx, fp0, fd);
12474 tcg_temp_free_i32(fp0);
12476 break;
12477 case OPC_CVT_PW_PS:
12478 check_ps(ctx);
12480 TCGv_i64 fp0 = tcg_temp_new_i64();
12482 gen_load_fpr64(ctx, fp0, fs);
12483 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
12484 gen_store_fpr64(ctx, fp0, fd);
12485 tcg_temp_free_i64(fp0);
12487 break;
12488 case OPC_CVT_S_PL:
12489 check_cp1_64bitmode(ctx);
12491 TCGv_i32 fp0 = tcg_temp_new_i32();
12493 gen_load_fpr32(ctx, fp0, fs);
12494 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
12495 gen_store_fpr32(ctx, fp0, fd);
12496 tcg_temp_free_i32(fp0);
12498 break;
12499 case OPC_PLL_PS:
12500 check_ps(ctx);
12502 TCGv_i32 fp0 = tcg_temp_new_i32();
12503 TCGv_i32 fp1 = tcg_temp_new_i32();
12505 gen_load_fpr32(ctx, fp0, fs);
12506 gen_load_fpr32(ctx, fp1, ft);
12507 gen_store_fpr32h(ctx, fp0, fd);
12508 gen_store_fpr32(ctx, fp1, fd);
12509 tcg_temp_free_i32(fp0);
12510 tcg_temp_free_i32(fp1);
12512 break;
12513 case OPC_PLU_PS:
12514 check_ps(ctx);
12516 TCGv_i32 fp0 = tcg_temp_new_i32();
12517 TCGv_i32 fp1 = tcg_temp_new_i32();
12519 gen_load_fpr32(ctx, fp0, fs);
12520 gen_load_fpr32h(ctx, fp1, ft);
12521 gen_store_fpr32(ctx, fp1, fd);
12522 gen_store_fpr32h(ctx, fp0, fd);
12523 tcg_temp_free_i32(fp0);
12524 tcg_temp_free_i32(fp1);
12526 break;
12527 case OPC_PUL_PS:
12528 check_ps(ctx);
12530 TCGv_i32 fp0 = tcg_temp_new_i32();
12531 TCGv_i32 fp1 = tcg_temp_new_i32();
12533 gen_load_fpr32h(ctx, fp0, fs);
12534 gen_load_fpr32(ctx, fp1, ft);
12535 gen_store_fpr32(ctx, fp1, fd);
12536 gen_store_fpr32h(ctx, fp0, fd);
12537 tcg_temp_free_i32(fp0);
12538 tcg_temp_free_i32(fp1);
12540 break;
12541 case OPC_PUU_PS:
12542 check_ps(ctx);
12544 TCGv_i32 fp0 = tcg_temp_new_i32();
12545 TCGv_i32 fp1 = tcg_temp_new_i32();
12547 gen_load_fpr32h(ctx, fp0, fs);
12548 gen_load_fpr32h(ctx, fp1, ft);
12549 gen_store_fpr32(ctx, fp1, fd);
12550 gen_store_fpr32h(ctx, fp0, fd);
12551 tcg_temp_free_i32(fp0);
12552 tcg_temp_free_i32(fp1);
12554 break;
12555 case OPC_CMP_F_PS:
12556 case OPC_CMP_UN_PS:
12557 case OPC_CMP_EQ_PS:
12558 case OPC_CMP_UEQ_PS:
12559 case OPC_CMP_OLT_PS:
12560 case OPC_CMP_ULT_PS:
12561 case OPC_CMP_OLE_PS:
12562 case OPC_CMP_ULE_PS:
12563 case OPC_CMP_SF_PS:
12564 case OPC_CMP_NGLE_PS:
12565 case OPC_CMP_SEQ_PS:
12566 case OPC_CMP_NGL_PS:
12567 case OPC_CMP_LT_PS:
12568 case OPC_CMP_NGE_PS:
12569 case OPC_CMP_LE_PS:
12570 case OPC_CMP_NGT_PS:
12571 if (ctx->opcode & (1 << 6)) {
12572 gen_cmpabs_ps(ctx, func - 48, ft, fs, cc);
12573 } else {
12574 gen_cmp_ps(ctx, func - 48, ft, fs, cc);
12576 break;
12577 default:
12578 MIPS_INVAL("farith");
12579 generate_exception_end(ctx, EXCP_RI);
12580 return;
12584 /* Coprocessor 3 (FPU) */
12585 static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
12586 int fd, int fs, int base, int index)
12588 TCGv t0 = tcg_temp_new();
12590 if (base == 0) {
12591 gen_load_gpr(t0, index);
12592 } else if (index == 0) {
12593 gen_load_gpr(t0, base);
12594 } else {
12595 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
12598 * Don't do NOP if destination is zero: we must perform the actual
12599 * memory access.
12601 switch (opc) {
12602 case OPC_LWXC1:
12603 check_cop1x(ctx);
12605 TCGv_i32 fp0 = tcg_temp_new_i32();
12607 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
12608 tcg_gen_trunc_tl_i32(fp0, t0);
12609 gen_store_fpr32(ctx, fp0, fd);
12610 tcg_temp_free_i32(fp0);
12612 break;
12613 case OPC_LDXC1:
12614 check_cop1x(ctx);
12615 check_cp1_registers(ctx, fd);
12617 TCGv_i64 fp0 = tcg_temp_new_i64();
12618 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12619 gen_store_fpr64(ctx, fp0, fd);
12620 tcg_temp_free_i64(fp0);
12622 break;
12623 case OPC_LUXC1:
12624 check_cp1_64bitmode(ctx);
12625 tcg_gen_andi_tl(t0, t0, ~0x7);
12627 TCGv_i64 fp0 = tcg_temp_new_i64();
12629 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12630 gen_store_fpr64(ctx, fp0, fd);
12631 tcg_temp_free_i64(fp0);
12633 break;
12634 case OPC_SWXC1:
12635 check_cop1x(ctx);
12637 TCGv_i32 fp0 = tcg_temp_new_i32();
12638 gen_load_fpr32(ctx, fp0, fs);
12639 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
12640 tcg_temp_free_i32(fp0);
12642 break;
12643 case OPC_SDXC1:
12644 check_cop1x(ctx);
12645 check_cp1_registers(ctx, fs);
12647 TCGv_i64 fp0 = tcg_temp_new_i64();
12648 gen_load_fpr64(ctx, fp0, fs);
12649 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12650 tcg_temp_free_i64(fp0);
12652 break;
12653 case OPC_SUXC1:
12654 check_cp1_64bitmode(ctx);
12655 tcg_gen_andi_tl(t0, t0, ~0x7);
12657 TCGv_i64 fp0 = tcg_temp_new_i64();
12658 gen_load_fpr64(ctx, fp0, fs);
12659 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12660 tcg_temp_free_i64(fp0);
12662 break;
12664 tcg_temp_free(t0);
12667 static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
12668 int fd, int fr, int fs, int ft)
12670 switch (opc) {
12671 case OPC_ALNV_PS:
12672 check_ps(ctx);
12674 TCGv t0 = tcg_temp_local_new();
12675 TCGv_i32 fp = tcg_temp_new_i32();
12676 TCGv_i32 fph = tcg_temp_new_i32();
12677 TCGLabel *l1 = gen_new_label();
12678 TCGLabel *l2 = gen_new_label();
12680 gen_load_gpr(t0, fr);
12681 tcg_gen_andi_tl(t0, t0, 0x7);
12683 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
12684 gen_load_fpr32(ctx, fp, fs);
12685 gen_load_fpr32h(ctx, fph, fs);
12686 gen_store_fpr32(ctx, fp, fd);
12687 gen_store_fpr32h(ctx, fph, fd);
12688 tcg_gen_br(l2);
12689 gen_set_label(l1);
12690 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
12691 tcg_temp_free(t0);
12692 #ifdef TARGET_WORDS_BIGENDIAN
12693 gen_load_fpr32(ctx, fp, fs);
12694 gen_load_fpr32h(ctx, fph, ft);
12695 gen_store_fpr32h(ctx, fp, fd);
12696 gen_store_fpr32(ctx, fph, fd);
12697 #else
12698 gen_load_fpr32h(ctx, fph, fs);
12699 gen_load_fpr32(ctx, fp, ft);
12700 gen_store_fpr32(ctx, fph, fd);
12701 gen_store_fpr32h(ctx, fp, fd);
12702 #endif
12703 gen_set_label(l2);
12704 tcg_temp_free_i32(fp);
12705 tcg_temp_free_i32(fph);
12707 break;
12708 case OPC_MADD_S:
12709 check_cop1x(ctx);
12711 TCGv_i32 fp0 = tcg_temp_new_i32();
12712 TCGv_i32 fp1 = tcg_temp_new_i32();
12713 TCGv_i32 fp2 = tcg_temp_new_i32();
12715 gen_load_fpr32(ctx, fp0, fs);
12716 gen_load_fpr32(ctx, fp1, ft);
12717 gen_load_fpr32(ctx, fp2, fr);
12718 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
12719 tcg_temp_free_i32(fp0);
12720 tcg_temp_free_i32(fp1);
12721 gen_store_fpr32(ctx, fp2, fd);
12722 tcg_temp_free_i32(fp2);
12724 break;
12725 case OPC_MADD_D:
12726 check_cop1x(ctx);
12727 check_cp1_registers(ctx, fd | fs | ft | fr);
12729 TCGv_i64 fp0 = tcg_temp_new_i64();
12730 TCGv_i64 fp1 = tcg_temp_new_i64();
12731 TCGv_i64 fp2 = tcg_temp_new_i64();
12733 gen_load_fpr64(ctx, fp0, fs);
12734 gen_load_fpr64(ctx, fp1, ft);
12735 gen_load_fpr64(ctx, fp2, fr);
12736 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
12737 tcg_temp_free_i64(fp0);
12738 tcg_temp_free_i64(fp1);
12739 gen_store_fpr64(ctx, fp2, fd);
12740 tcg_temp_free_i64(fp2);
12742 break;
12743 case OPC_MADD_PS:
12744 check_ps(ctx);
12746 TCGv_i64 fp0 = tcg_temp_new_i64();
12747 TCGv_i64 fp1 = tcg_temp_new_i64();
12748 TCGv_i64 fp2 = tcg_temp_new_i64();
12750 gen_load_fpr64(ctx, fp0, fs);
12751 gen_load_fpr64(ctx, fp1, ft);
12752 gen_load_fpr64(ctx, fp2, fr);
12753 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
12754 tcg_temp_free_i64(fp0);
12755 tcg_temp_free_i64(fp1);
12756 gen_store_fpr64(ctx, fp2, fd);
12757 tcg_temp_free_i64(fp2);
12759 break;
12760 case OPC_MSUB_S:
12761 check_cop1x(ctx);
12763 TCGv_i32 fp0 = tcg_temp_new_i32();
12764 TCGv_i32 fp1 = tcg_temp_new_i32();
12765 TCGv_i32 fp2 = tcg_temp_new_i32();
12767 gen_load_fpr32(ctx, fp0, fs);
12768 gen_load_fpr32(ctx, fp1, ft);
12769 gen_load_fpr32(ctx, fp2, fr);
12770 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
12771 tcg_temp_free_i32(fp0);
12772 tcg_temp_free_i32(fp1);
12773 gen_store_fpr32(ctx, fp2, fd);
12774 tcg_temp_free_i32(fp2);
12776 break;
12777 case OPC_MSUB_D:
12778 check_cop1x(ctx);
12779 check_cp1_registers(ctx, fd | fs | ft | fr);
12781 TCGv_i64 fp0 = tcg_temp_new_i64();
12782 TCGv_i64 fp1 = tcg_temp_new_i64();
12783 TCGv_i64 fp2 = tcg_temp_new_i64();
12785 gen_load_fpr64(ctx, fp0, fs);
12786 gen_load_fpr64(ctx, fp1, ft);
12787 gen_load_fpr64(ctx, fp2, fr);
12788 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
12789 tcg_temp_free_i64(fp0);
12790 tcg_temp_free_i64(fp1);
12791 gen_store_fpr64(ctx, fp2, fd);
12792 tcg_temp_free_i64(fp2);
12794 break;
12795 case OPC_MSUB_PS:
12796 check_ps(ctx);
12798 TCGv_i64 fp0 = tcg_temp_new_i64();
12799 TCGv_i64 fp1 = tcg_temp_new_i64();
12800 TCGv_i64 fp2 = tcg_temp_new_i64();
12802 gen_load_fpr64(ctx, fp0, fs);
12803 gen_load_fpr64(ctx, fp1, ft);
12804 gen_load_fpr64(ctx, fp2, fr);
12805 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
12806 tcg_temp_free_i64(fp0);
12807 tcg_temp_free_i64(fp1);
12808 gen_store_fpr64(ctx, fp2, fd);
12809 tcg_temp_free_i64(fp2);
12811 break;
12812 case OPC_NMADD_S:
12813 check_cop1x(ctx);
12815 TCGv_i32 fp0 = tcg_temp_new_i32();
12816 TCGv_i32 fp1 = tcg_temp_new_i32();
12817 TCGv_i32 fp2 = tcg_temp_new_i32();
12819 gen_load_fpr32(ctx, fp0, fs);
12820 gen_load_fpr32(ctx, fp1, ft);
12821 gen_load_fpr32(ctx, fp2, fr);
12822 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
12823 tcg_temp_free_i32(fp0);
12824 tcg_temp_free_i32(fp1);
12825 gen_store_fpr32(ctx, fp2, fd);
12826 tcg_temp_free_i32(fp2);
12828 break;
12829 case OPC_NMADD_D:
12830 check_cop1x(ctx);
12831 check_cp1_registers(ctx, fd | fs | ft | fr);
12833 TCGv_i64 fp0 = tcg_temp_new_i64();
12834 TCGv_i64 fp1 = tcg_temp_new_i64();
12835 TCGv_i64 fp2 = tcg_temp_new_i64();
12837 gen_load_fpr64(ctx, fp0, fs);
12838 gen_load_fpr64(ctx, fp1, ft);
12839 gen_load_fpr64(ctx, fp2, fr);
12840 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
12841 tcg_temp_free_i64(fp0);
12842 tcg_temp_free_i64(fp1);
12843 gen_store_fpr64(ctx, fp2, fd);
12844 tcg_temp_free_i64(fp2);
12846 break;
12847 case OPC_NMADD_PS:
12848 check_ps(ctx);
12850 TCGv_i64 fp0 = tcg_temp_new_i64();
12851 TCGv_i64 fp1 = tcg_temp_new_i64();
12852 TCGv_i64 fp2 = tcg_temp_new_i64();
12854 gen_load_fpr64(ctx, fp0, fs);
12855 gen_load_fpr64(ctx, fp1, ft);
12856 gen_load_fpr64(ctx, fp2, fr);
12857 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
12858 tcg_temp_free_i64(fp0);
12859 tcg_temp_free_i64(fp1);
12860 gen_store_fpr64(ctx, fp2, fd);
12861 tcg_temp_free_i64(fp2);
12863 break;
12864 case OPC_NMSUB_S:
12865 check_cop1x(ctx);
12867 TCGv_i32 fp0 = tcg_temp_new_i32();
12868 TCGv_i32 fp1 = tcg_temp_new_i32();
12869 TCGv_i32 fp2 = tcg_temp_new_i32();
12871 gen_load_fpr32(ctx, fp0, fs);
12872 gen_load_fpr32(ctx, fp1, ft);
12873 gen_load_fpr32(ctx, fp2, fr);
12874 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
12875 tcg_temp_free_i32(fp0);
12876 tcg_temp_free_i32(fp1);
12877 gen_store_fpr32(ctx, fp2, fd);
12878 tcg_temp_free_i32(fp2);
12880 break;
12881 case OPC_NMSUB_D:
12882 check_cop1x(ctx);
12883 check_cp1_registers(ctx, fd | fs | ft | fr);
12885 TCGv_i64 fp0 = tcg_temp_new_i64();
12886 TCGv_i64 fp1 = tcg_temp_new_i64();
12887 TCGv_i64 fp2 = tcg_temp_new_i64();
12889 gen_load_fpr64(ctx, fp0, fs);
12890 gen_load_fpr64(ctx, fp1, ft);
12891 gen_load_fpr64(ctx, fp2, fr);
12892 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
12893 tcg_temp_free_i64(fp0);
12894 tcg_temp_free_i64(fp1);
12895 gen_store_fpr64(ctx, fp2, fd);
12896 tcg_temp_free_i64(fp2);
12898 break;
12899 case OPC_NMSUB_PS:
12900 check_ps(ctx);
12902 TCGv_i64 fp0 = tcg_temp_new_i64();
12903 TCGv_i64 fp1 = tcg_temp_new_i64();
12904 TCGv_i64 fp2 = tcg_temp_new_i64();
12906 gen_load_fpr64(ctx, fp0, fs);
12907 gen_load_fpr64(ctx, fp1, ft);
12908 gen_load_fpr64(ctx, fp2, fr);
12909 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
12910 tcg_temp_free_i64(fp0);
12911 tcg_temp_free_i64(fp1);
12912 gen_store_fpr64(ctx, fp2, fd);
12913 tcg_temp_free_i64(fp2);
12915 break;
12916 default:
12917 MIPS_INVAL("flt3_arith");
12918 generate_exception_end(ctx, EXCP_RI);
12919 return;
12923 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
12925 TCGv t0;
12927 #if !defined(CONFIG_USER_ONLY)
12929 * The Linux kernel will emulate rdhwr if it's not supported natively.
12930 * Therefore only check the ISA in system mode.
12932 check_insn(ctx, ISA_MIPS32R2);
12933 #endif
12934 t0 = tcg_temp_new();
12936 switch (rd) {
12937 case 0:
12938 gen_helper_rdhwr_cpunum(t0, cpu_env);
12939 gen_store_gpr(t0, rt);
12940 break;
12941 case 1:
12942 gen_helper_rdhwr_synci_step(t0, cpu_env);
12943 gen_store_gpr(t0, rt);
12944 break;
12945 case 2:
12946 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12947 gen_io_start();
12949 gen_helper_rdhwr_cc(t0, cpu_env);
12950 gen_store_gpr(t0, rt);
12952 * Break the TB to be able to take timer interrupts immediately
12953 * after reading count. DISAS_STOP isn't sufficient, we need to ensure
12954 * we break completely out of translated code.
12956 gen_save_pc(ctx->base.pc_next + 4);
12957 ctx->base.is_jmp = DISAS_EXIT;
12958 break;
12959 case 3:
12960 gen_helper_rdhwr_ccres(t0, cpu_env);
12961 gen_store_gpr(t0, rt);
12962 break;
12963 case 4:
12964 check_insn(ctx, ISA_MIPS32R6);
12965 if (sel != 0) {
12967 * Performance counter registers are not implemented other than
12968 * control register 0.
12970 generate_exception(ctx, EXCP_RI);
12972 gen_helper_rdhwr_performance(t0, cpu_env);
12973 gen_store_gpr(t0, rt);
12974 break;
12975 case 5:
12976 check_insn(ctx, ISA_MIPS32R6);
12977 gen_helper_rdhwr_xnp(t0, cpu_env);
12978 gen_store_gpr(t0, rt);
12979 break;
12980 case 29:
12981 #if defined(CONFIG_USER_ONLY)
12982 tcg_gen_ld_tl(t0, cpu_env,
12983 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12984 gen_store_gpr(t0, rt);
12985 break;
12986 #else
12987 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
12988 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
12989 tcg_gen_ld_tl(t0, cpu_env,
12990 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12991 gen_store_gpr(t0, rt);
12992 } else {
12993 generate_exception_end(ctx, EXCP_RI);
12995 break;
12996 #endif
12997 default: /* Invalid */
12998 MIPS_INVAL("rdhwr");
12999 generate_exception_end(ctx, EXCP_RI);
13000 break;
13002 tcg_temp_free(t0);
13005 static inline void clear_branch_hflags(DisasContext *ctx)
13007 ctx->hflags &= ~MIPS_HFLAG_BMASK;
13008 if (ctx->base.is_jmp == DISAS_NEXT) {
13009 save_cpu_state(ctx, 0);
13010 } else {
13012 * It is not safe to save ctx->hflags as hflags may be changed
13013 * in execution time by the instruction in delay / forbidden slot.
13015 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
13019 static void gen_branch(DisasContext *ctx, int insn_bytes)
13021 if (ctx->hflags & MIPS_HFLAG_BMASK) {
13022 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
13023 /* Branches completion */
13024 clear_branch_hflags(ctx);
13025 ctx->base.is_jmp = DISAS_NORETURN;
13026 /* FIXME: Need to clear can_do_io. */
13027 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
13028 case MIPS_HFLAG_FBNSLOT:
13029 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
13030 break;
13031 case MIPS_HFLAG_B:
13032 /* unconditional branch */
13033 if (proc_hflags & MIPS_HFLAG_BX) {
13034 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
13036 gen_goto_tb(ctx, 0, ctx->btarget);
13037 break;
13038 case MIPS_HFLAG_BL:
13039 /* blikely taken case */
13040 gen_goto_tb(ctx, 0, ctx->btarget);
13041 break;
13042 case MIPS_HFLAG_BC:
13043 /* Conditional branch */
13045 TCGLabel *l1 = gen_new_label();
13047 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
13048 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
13049 gen_set_label(l1);
13050 gen_goto_tb(ctx, 0, ctx->btarget);
13052 break;
13053 case MIPS_HFLAG_BR:
13054 /* unconditional branch to register */
13055 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
13056 TCGv t0 = tcg_temp_new();
13057 TCGv_i32 t1 = tcg_temp_new_i32();
13059 tcg_gen_andi_tl(t0, btarget, 0x1);
13060 tcg_gen_trunc_tl_i32(t1, t0);
13061 tcg_temp_free(t0);
13062 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
13063 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
13064 tcg_gen_or_i32(hflags, hflags, t1);
13065 tcg_temp_free_i32(t1);
13067 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
13068 } else {
13069 tcg_gen_mov_tl(cpu_PC, btarget);
13071 if (ctx->base.singlestep_enabled) {
13072 save_cpu_state(ctx, 0);
13073 gen_helper_raise_exception_debug(cpu_env);
13075 tcg_gen_lookup_and_goto_ptr();
13076 break;
13077 default:
13078 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
13079 abort();
13084 /* Compact Branches */
13085 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
13086 int rs, int rt, int32_t offset)
13088 int bcond_compute = 0;
13089 TCGv t0 = tcg_temp_new();
13090 TCGv t1 = tcg_temp_new();
13091 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
13093 if (ctx->hflags & MIPS_HFLAG_BMASK) {
13094 #ifdef MIPS_DEBUG_DISAS
13095 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
13096 "\n", ctx->base.pc_next);
13097 #endif
13098 generate_exception_end(ctx, EXCP_RI);
13099 goto out;
13102 /* Load needed operands and calculate btarget */
13103 switch (opc) {
13104 /* compact branch */
13105 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13106 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13107 gen_load_gpr(t0, rs);
13108 gen_load_gpr(t1, rt);
13109 bcond_compute = 1;
13110 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13111 if (rs <= rt && rs == 0) {
13112 /* OPC_BEQZALC, OPC_BNEZALC */
13113 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13115 break;
13116 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13117 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13118 gen_load_gpr(t0, rs);
13119 gen_load_gpr(t1, rt);
13120 bcond_compute = 1;
13121 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13122 break;
13123 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13124 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13125 if (rs == 0 || rs == rt) {
13126 /* OPC_BLEZALC, OPC_BGEZALC */
13127 /* OPC_BGTZALC, OPC_BLTZALC */
13128 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13130 gen_load_gpr(t0, rs);
13131 gen_load_gpr(t1, rt);
13132 bcond_compute = 1;
13133 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13134 break;
13135 case OPC_BC:
13136 case OPC_BALC:
13137 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13138 break;
13139 case OPC_BEQZC:
13140 case OPC_BNEZC:
13141 if (rs != 0) {
13142 /* OPC_BEQZC, OPC_BNEZC */
13143 gen_load_gpr(t0, rs);
13144 bcond_compute = 1;
13145 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13146 } else {
13147 /* OPC_JIC, OPC_JIALC */
13148 TCGv tbase = tcg_temp_new();
13149 TCGv toffset = tcg_temp_new();
13151 gen_load_gpr(tbase, rt);
13152 tcg_gen_movi_tl(toffset, offset);
13153 gen_op_addr_add(ctx, btarget, tbase, toffset);
13154 tcg_temp_free(tbase);
13155 tcg_temp_free(toffset);
13157 break;
13158 default:
13159 MIPS_INVAL("Compact branch/jump");
13160 generate_exception_end(ctx, EXCP_RI);
13161 goto out;
13164 if (bcond_compute == 0) {
13165 /* Uncoditional compact branch */
13166 switch (opc) {
13167 case OPC_JIALC:
13168 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13169 /* Fallthrough */
13170 case OPC_JIC:
13171 ctx->hflags |= MIPS_HFLAG_BR;
13172 break;
13173 case OPC_BALC:
13174 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13175 /* Fallthrough */
13176 case OPC_BC:
13177 ctx->hflags |= MIPS_HFLAG_B;
13178 break;
13179 default:
13180 MIPS_INVAL("Compact branch/jump");
13181 generate_exception_end(ctx, EXCP_RI);
13182 goto out;
13185 /* Generating branch here as compact branches don't have delay slot */
13186 gen_branch(ctx, 4);
13187 } else {
13188 /* Conditional compact branch */
13189 TCGLabel *fs = gen_new_label();
13190 save_cpu_state(ctx, 0);
13192 switch (opc) {
13193 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13194 if (rs == 0 && rt != 0) {
13195 /* OPC_BLEZALC */
13196 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13197 } else if (rs != 0 && rt != 0 && rs == rt) {
13198 /* OPC_BGEZALC */
13199 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13200 } else {
13201 /* OPC_BGEUC */
13202 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
13204 break;
13205 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13206 if (rs == 0 && rt != 0) {
13207 /* OPC_BGTZALC */
13208 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13209 } else if (rs != 0 && rt != 0 && rs == rt) {
13210 /* OPC_BLTZALC */
13211 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13212 } else {
13213 /* OPC_BLTUC */
13214 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
13216 break;
13217 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13218 if (rs == 0 && rt != 0) {
13219 /* OPC_BLEZC */
13220 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13221 } else if (rs != 0 && rt != 0 && rs == rt) {
13222 /* OPC_BGEZC */
13223 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13224 } else {
13225 /* OPC_BGEC */
13226 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
13228 break;
13229 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13230 if (rs == 0 && rt != 0) {
13231 /* OPC_BGTZC */
13232 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13233 } else if (rs != 0 && rt != 0 && rs == rt) {
13234 /* OPC_BLTZC */
13235 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13236 } else {
13237 /* OPC_BLTC */
13238 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
13240 break;
13241 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13242 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13243 if (rs >= rt) {
13244 /* OPC_BOVC, OPC_BNVC */
13245 TCGv t2 = tcg_temp_new();
13246 TCGv t3 = tcg_temp_new();
13247 TCGv t4 = tcg_temp_new();
13248 TCGv input_overflow = tcg_temp_new();
13250 gen_load_gpr(t0, rs);
13251 gen_load_gpr(t1, rt);
13252 tcg_gen_ext32s_tl(t2, t0);
13253 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
13254 tcg_gen_ext32s_tl(t3, t1);
13255 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
13256 tcg_gen_or_tl(input_overflow, input_overflow, t4);
13258 tcg_gen_add_tl(t4, t2, t3);
13259 tcg_gen_ext32s_tl(t4, t4);
13260 tcg_gen_xor_tl(t2, t2, t3);
13261 tcg_gen_xor_tl(t3, t4, t3);
13262 tcg_gen_andc_tl(t2, t3, t2);
13263 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
13264 tcg_gen_or_tl(t4, t4, input_overflow);
13265 if (opc == OPC_BOVC) {
13266 /* OPC_BOVC */
13267 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
13268 } else {
13269 /* OPC_BNVC */
13270 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
13272 tcg_temp_free(input_overflow);
13273 tcg_temp_free(t4);
13274 tcg_temp_free(t3);
13275 tcg_temp_free(t2);
13276 } else if (rs < rt && rs == 0) {
13277 /* OPC_BEQZALC, OPC_BNEZALC */
13278 if (opc == OPC_BEQZALC) {
13279 /* OPC_BEQZALC */
13280 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
13281 } else {
13282 /* OPC_BNEZALC */
13283 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
13285 } else {
13286 /* OPC_BEQC, OPC_BNEC */
13287 if (opc == OPC_BEQC) {
13288 /* OPC_BEQC */
13289 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
13290 } else {
13291 /* OPC_BNEC */
13292 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
13295 break;
13296 case OPC_BEQZC:
13297 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
13298 break;
13299 case OPC_BNEZC:
13300 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
13301 break;
13302 default:
13303 MIPS_INVAL("Compact conditional branch/jump");
13304 generate_exception_end(ctx, EXCP_RI);
13305 goto out;
13308 /* Generating branch here as compact branches don't have delay slot */
13309 gen_goto_tb(ctx, 1, ctx->btarget);
13310 gen_set_label(fs);
13312 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
13315 out:
13316 tcg_temp_free(t0);
13317 tcg_temp_free(t1);
13320 /* ISA extensions (ASEs) */
13321 /* MIPS16 extension to MIPS32 */
13323 /* MIPS16 major opcodes */
13324 enum {
13325 M16_OPC_ADDIUSP = 0x00,
13326 M16_OPC_ADDIUPC = 0x01,
13327 M16_OPC_B = 0x02,
13328 M16_OPC_JAL = 0x03,
13329 M16_OPC_BEQZ = 0x04,
13330 M16_OPC_BNEQZ = 0x05,
13331 M16_OPC_SHIFT = 0x06,
13332 M16_OPC_LD = 0x07,
13333 M16_OPC_RRIA = 0x08,
13334 M16_OPC_ADDIU8 = 0x09,
13335 M16_OPC_SLTI = 0x0a,
13336 M16_OPC_SLTIU = 0x0b,
13337 M16_OPC_I8 = 0x0c,
13338 M16_OPC_LI = 0x0d,
13339 M16_OPC_CMPI = 0x0e,
13340 M16_OPC_SD = 0x0f,
13341 M16_OPC_LB = 0x10,
13342 M16_OPC_LH = 0x11,
13343 M16_OPC_LWSP = 0x12,
13344 M16_OPC_LW = 0x13,
13345 M16_OPC_LBU = 0x14,
13346 M16_OPC_LHU = 0x15,
13347 M16_OPC_LWPC = 0x16,
13348 M16_OPC_LWU = 0x17,
13349 M16_OPC_SB = 0x18,
13350 M16_OPC_SH = 0x19,
13351 M16_OPC_SWSP = 0x1a,
13352 M16_OPC_SW = 0x1b,
13353 M16_OPC_RRR = 0x1c,
13354 M16_OPC_RR = 0x1d,
13355 M16_OPC_EXTEND = 0x1e,
13356 M16_OPC_I64 = 0x1f
13359 /* I8 funct field */
13360 enum {
13361 I8_BTEQZ = 0x0,
13362 I8_BTNEZ = 0x1,
13363 I8_SWRASP = 0x2,
13364 I8_ADJSP = 0x3,
13365 I8_SVRS = 0x4,
13366 I8_MOV32R = 0x5,
13367 I8_MOVR32 = 0x7
13370 /* RRR f field */
13371 enum {
13372 RRR_DADDU = 0x0,
13373 RRR_ADDU = 0x1,
13374 RRR_DSUBU = 0x2,
13375 RRR_SUBU = 0x3
13378 /* RR funct field */
13379 enum {
13380 RR_JR = 0x00,
13381 RR_SDBBP = 0x01,
13382 RR_SLT = 0x02,
13383 RR_SLTU = 0x03,
13384 RR_SLLV = 0x04,
13385 RR_BREAK = 0x05,
13386 RR_SRLV = 0x06,
13387 RR_SRAV = 0x07,
13388 RR_DSRL = 0x08,
13389 RR_CMP = 0x0a,
13390 RR_NEG = 0x0b,
13391 RR_AND = 0x0c,
13392 RR_OR = 0x0d,
13393 RR_XOR = 0x0e,
13394 RR_NOT = 0x0f,
13395 RR_MFHI = 0x10,
13396 RR_CNVT = 0x11,
13397 RR_MFLO = 0x12,
13398 RR_DSRA = 0x13,
13399 RR_DSLLV = 0x14,
13400 RR_DSRLV = 0x16,
13401 RR_DSRAV = 0x17,
13402 RR_MULT = 0x18,
13403 RR_MULTU = 0x19,
13404 RR_DIV = 0x1a,
13405 RR_DIVU = 0x1b,
13406 RR_DMULT = 0x1c,
13407 RR_DMULTU = 0x1d,
13408 RR_DDIV = 0x1e,
13409 RR_DDIVU = 0x1f
13412 /* I64 funct field */
13413 enum {
13414 I64_LDSP = 0x0,
13415 I64_SDSP = 0x1,
13416 I64_SDRASP = 0x2,
13417 I64_DADJSP = 0x3,
13418 I64_LDPC = 0x4,
13419 I64_DADDIU5 = 0x5,
13420 I64_DADDIUPC = 0x6,
13421 I64_DADDIUSP = 0x7
13424 /* RR ry field for CNVT */
13425 enum {
13426 RR_RY_CNVT_ZEB = 0x0,
13427 RR_RY_CNVT_ZEH = 0x1,
13428 RR_RY_CNVT_ZEW = 0x2,
13429 RR_RY_CNVT_SEB = 0x4,
13430 RR_RY_CNVT_SEH = 0x5,
13431 RR_RY_CNVT_SEW = 0x6,
13434 static int xlat(int r)
13436 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
13438 return map[r];
13441 static void gen_mips16_save(DisasContext *ctx,
13442 int xsregs, int aregs,
13443 int do_ra, int do_s0, int do_s1,
13444 int framesize)
13446 TCGv t0 = tcg_temp_new();
13447 TCGv t1 = tcg_temp_new();
13448 TCGv t2 = tcg_temp_new();
13449 int args, astatic;
13451 switch (aregs) {
13452 case 0:
13453 case 1:
13454 case 2:
13455 case 3:
13456 case 11:
13457 args = 0;
13458 break;
13459 case 4:
13460 case 5:
13461 case 6:
13462 case 7:
13463 args = 1;
13464 break;
13465 case 8:
13466 case 9:
13467 case 10:
13468 args = 2;
13469 break;
13470 case 12:
13471 case 13:
13472 args = 3;
13473 break;
13474 case 14:
13475 args = 4;
13476 break;
13477 default:
13478 generate_exception_end(ctx, EXCP_RI);
13479 return;
13482 switch (args) {
13483 case 4:
13484 gen_base_offset_addr(ctx, t0, 29, 12);
13485 gen_load_gpr(t1, 7);
13486 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13487 /* Fall through */
13488 case 3:
13489 gen_base_offset_addr(ctx, t0, 29, 8);
13490 gen_load_gpr(t1, 6);
13491 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13492 /* Fall through */
13493 case 2:
13494 gen_base_offset_addr(ctx, t0, 29, 4);
13495 gen_load_gpr(t1, 5);
13496 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13497 /* Fall through */
13498 case 1:
13499 gen_base_offset_addr(ctx, t0, 29, 0);
13500 gen_load_gpr(t1, 4);
13501 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13504 gen_load_gpr(t0, 29);
13506 #define DECR_AND_STORE(reg) do { \
13507 tcg_gen_movi_tl(t2, -4); \
13508 gen_op_addr_add(ctx, t0, t0, t2); \
13509 gen_load_gpr(t1, reg); \
13510 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
13511 } while (0)
13513 if (do_ra) {
13514 DECR_AND_STORE(31);
13517 switch (xsregs) {
13518 case 7:
13519 DECR_AND_STORE(30);
13520 /* Fall through */
13521 case 6:
13522 DECR_AND_STORE(23);
13523 /* Fall through */
13524 case 5:
13525 DECR_AND_STORE(22);
13526 /* Fall through */
13527 case 4:
13528 DECR_AND_STORE(21);
13529 /* Fall through */
13530 case 3:
13531 DECR_AND_STORE(20);
13532 /* Fall through */
13533 case 2:
13534 DECR_AND_STORE(19);
13535 /* Fall through */
13536 case 1:
13537 DECR_AND_STORE(18);
13540 if (do_s1) {
13541 DECR_AND_STORE(17);
13543 if (do_s0) {
13544 DECR_AND_STORE(16);
13547 switch (aregs) {
13548 case 0:
13549 case 4:
13550 case 8:
13551 case 12:
13552 case 14:
13553 astatic = 0;
13554 break;
13555 case 1:
13556 case 5:
13557 case 9:
13558 case 13:
13559 astatic = 1;
13560 break;
13561 case 2:
13562 case 6:
13563 case 10:
13564 astatic = 2;
13565 break;
13566 case 3:
13567 case 7:
13568 astatic = 3;
13569 break;
13570 case 11:
13571 astatic = 4;
13572 break;
13573 default:
13574 generate_exception_end(ctx, EXCP_RI);
13575 return;
13578 if (astatic > 0) {
13579 DECR_AND_STORE(7);
13580 if (astatic > 1) {
13581 DECR_AND_STORE(6);
13582 if (astatic > 2) {
13583 DECR_AND_STORE(5);
13584 if (astatic > 3) {
13585 DECR_AND_STORE(4);
13590 #undef DECR_AND_STORE
13592 tcg_gen_movi_tl(t2, -framesize);
13593 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13594 tcg_temp_free(t0);
13595 tcg_temp_free(t1);
13596 tcg_temp_free(t2);
13599 static void gen_mips16_restore(DisasContext *ctx,
13600 int xsregs, int aregs,
13601 int do_ra, int do_s0, int do_s1,
13602 int framesize)
13604 int astatic;
13605 TCGv t0 = tcg_temp_new();
13606 TCGv t1 = tcg_temp_new();
13607 TCGv t2 = tcg_temp_new();
13609 tcg_gen_movi_tl(t2, framesize);
13610 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
13612 #define DECR_AND_LOAD(reg) do { \
13613 tcg_gen_movi_tl(t2, -4); \
13614 gen_op_addr_add(ctx, t0, t0, t2); \
13615 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
13616 gen_store_gpr(t1, reg); \
13617 } while (0)
13619 if (do_ra) {
13620 DECR_AND_LOAD(31);
13623 switch (xsregs) {
13624 case 7:
13625 DECR_AND_LOAD(30);
13626 /* Fall through */
13627 case 6:
13628 DECR_AND_LOAD(23);
13629 /* Fall through */
13630 case 5:
13631 DECR_AND_LOAD(22);
13632 /* Fall through */
13633 case 4:
13634 DECR_AND_LOAD(21);
13635 /* Fall through */
13636 case 3:
13637 DECR_AND_LOAD(20);
13638 /* Fall through */
13639 case 2:
13640 DECR_AND_LOAD(19);
13641 /* Fall through */
13642 case 1:
13643 DECR_AND_LOAD(18);
13646 if (do_s1) {
13647 DECR_AND_LOAD(17);
13649 if (do_s0) {
13650 DECR_AND_LOAD(16);
13653 switch (aregs) {
13654 case 0:
13655 case 4:
13656 case 8:
13657 case 12:
13658 case 14:
13659 astatic = 0;
13660 break;
13661 case 1:
13662 case 5:
13663 case 9:
13664 case 13:
13665 astatic = 1;
13666 break;
13667 case 2:
13668 case 6:
13669 case 10:
13670 astatic = 2;
13671 break;
13672 case 3:
13673 case 7:
13674 astatic = 3;
13675 break;
13676 case 11:
13677 astatic = 4;
13678 break;
13679 default:
13680 generate_exception_end(ctx, EXCP_RI);
13681 return;
13684 if (astatic > 0) {
13685 DECR_AND_LOAD(7);
13686 if (astatic > 1) {
13687 DECR_AND_LOAD(6);
13688 if (astatic > 2) {
13689 DECR_AND_LOAD(5);
13690 if (astatic > 3) {
13691 DECR_AND_LOAD(4);
13696 #undef DECR_AND_LOAD
13698 tcg_gen_movi_tl(t2, framesize);
13699 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13700 tcg_temp_free(t0);
13701 tcg_temp_free(t1);
13702 tcg_temp_free(t2);
13705 static void gen_addiupc(DisasContext *ctx, int rx, int imm,
13706 int is_64_bit, int extended)
13708 TCGv t0;
13710 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13711 generate_exception_end(ctx, EXCP_RI);
13712 return;
13715 t0 = tcg_temp_new();
13717 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
13718 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
13719 if (!is_64_bit) {
13720 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13723 tcg_temp_free(t0);
13726 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
13727 int16_t offset)
13729 TCGv_i32 t0 = tcg_const_i32(op);
13730 TCGv t1 = tcg_temp_new();
13731 gen_base_offset_addr(ctx, t1, base, offset);
13732 gen_helper_cache(cpu_env, t1, t0);
13735 #if defined(TARGET_MIPS64)
13736 static void decode_i64_mips16(DisasContext *ctx,
13737 int ry, int funct, int16_t offset,
13738 int extended)
13740 switch (funct) {
13741 case I64_LDSP:
13742 check_insn(ctx, ISA_MIPS3);
13743 check_mips_64(ctx);
13744 offset = extended ? offset : offset << 3;
13745 gen_ld(ctx, OPC_LD, ry, 29, offset);
13746 break;
13747 case I64_SDSP:
13748 check_insn(ctx, ISA_MIPS3);
13749 check_mips_64(ctx);
13750 offset = extended ? offset : offset << 3;
13751 gen_st(ctx, OPC_SD, ry, 29, offset);
13752 break;
13753 case I64_SDRASP:
13754 check_insn(ctx, ISA_MIPS3);
13755 check_mips_64(ctx);
13756 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
13757 gen_st(ctx, OPC_SD, 31, 29, offset);
13758 break;
13759 case I64_DADJSP:
13760 check_insn(ctx, ISA_MIPS3);
13761 check_mips_64(ctx);
13762 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
13763 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
13764 break;
13765 case I64_LDPC:
13766 check_insn(ctx, ISA_MIPS3);
13767 check_mips_64(ctx);
13768 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13769 generate_exception_end(ctx, EXCP_RI);
13770 } else {
13771 offset = extended ? offset : offset << 3;
13772 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
13774 break;
13775 case I64_DADDIU5:
13776 check_insn(ctx, ISA_MIPS3);
13777 check_mips_64(ctx);
13778 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
13779 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
13780 break;
13781 case I64_DADDIUPC:
13782 check_insn(ctx, ISA_MIPS3);
13783 check_mips_64(ctx);
13784 offset = extended ? offset : offset << 2;
13785 gen_addiupc(ctx, ry, offset, 1, extended);
13786 break;
13787 case I64_DADDIUSP:
13788 check_insn(ctx, ISA_MIPS3);
13789 check_mips_64(ctx);
13790 offset = extended ? offset : offset << 2;
13791 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
13792 break;
13795 #endif
13797 static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
13799 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
13800 int op, rx, ry, funct, sa;
13801 int16_t imm, offset;
13803 ctx->opcode = (ctx->opcode << 16) | extend;
13804 op = (ctx->opcode >> 11) & 0x1f;
13805 sa = (ctx->opcode >> 22) & 0x1f;
13806 funct = (ctx->opcode >> 8) & 0x7;
13807 rx = xlat((ctx->opcode >> 8) & 0x7);
13808 ry = xlat((ctx->opcode >> 5) & 0x7);
13809 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
13810 | ((ctx->opcode >> 21) & 0x3f) << 5
13811 | (ctx->opcode & 0x1f));
13814 * The extended opcodes cleverly reuse the opcodes from their 16-bit
13815 * counterparts.
13817 switch (op) {
13818 case M16_OPC_ADDIUSP:
13819 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13820 break;
13821 case M16_OPC_ADDIUPC:
13822 gen_addiupc(ctx, rx, imm, 0, 1);
13823 break;
13824 case M16_OPC_B:
13825 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
13826 /* No delay slot, so just process as a normal instruction */
13827 break;
13828 case M16_OPC_BEQZ:
13829 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
13830 /* No delay slot, so just process as a normal instruction */
13831 break;
13832 case M16_OPC_BNEQZ:
13833 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
13834 /* No delay slot, so just process as a normal instruction */
13835 break;
13836 case M16_OPC_SHIFT:
13837 switch (ctx->opcode & 0x3) {
13838 case 0x0:
13839 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13840 break;
13841 case 0x1:
13842 #if defined(TARGET_MIPS64)
13843 check_mips_64(ctx);
13844 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13845 #else
13846 generate_exception_end(ctx, EXCP_RI);
13847 #endif
13848 break;
13849 case 0x2:
13850 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13851 break;
13852 case 0x3:
13853 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13854 break;
13856 break;
13857 #if defined(TARGET_MIPS64)
13858 case M16_OPC_LD:
13859 check_insn(ctx, ISA_MIPS3);
13860 check_mips_64(ctx);
13861 gen_ld(ctx, OPC_LD, ry, rx, offset);
13862 break;
13863 #endif
13864 case M16_OPC_RRIA:
13865 imm = ctx->opcode & 0xf;
13866 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
13867 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
13868 imm = (int16_t) (imm << 1) >> 1;
13869 if ((ctx->opcode >> 4) & 0x1) {
13870 #if defined(TARGET_MIPS64)
13871 check_mips_64(ctx);
13872 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13873 #else
13874 generate_exception_end(ctx, EXCP_RI);
13875 #endif
13876 } else {
13877 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13879 break;
13880 case M16_OPC_ADDIU8:
13881 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13882 break;
13883 case M16_OPC_SLTI:
13884 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13885 break;
13886 case M16_OPC_SLTIU:
13887 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13888 break;
13889 case M16_OPC_I8:
13890 switch (funct) {
13891 case I8_BTEQZ:
13892 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
13893 break;
13894 case I8_BTNEZ:
13895 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
13896 break;
13897 case I8_SWRASP:
13898 gen_st(ctx, OPC_SW, 31, 29, imm);
13899 break;
13900 case I8_ADJSP:
13901 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
13902 break;
13903 case I8_SVRS:
13904 check_insn(ctx, ISA_MIPS32);
13906 int xsregs = (ctx->opcode >> 24) & 0x7;
13907 int aregs = (ctx->opcode >> 16) & 0xf;
13908 int do_ra = (ctx->opcode >> 6) & 0x1;
13909 int do_s0 = (ctx->opcode >> 5) & 0x1;
13910 int do_s1 = (ctx->opcode >> 4) & 0x1;
13911 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
13912 | (ctx->opcode & 0xf)) << 3;
13914 if (ctx->opcode & (1 << 7)) {
13915 gen_mips16_save(ctx, xsregs, aregs,
13916 do_ra, do_s0, do_s1,
13917 framesize);
13918 } else {
13919 gen_mips16_restore(ctx, xsregs, aregs,
13920 do_ra, do_s0, do_s1,
13921 framesize);
13924 break;
13925 default:
13926 generate_exception_end(ctx, EXCP_RI);
13927 break;
13929 break;
13930 case M16_OPC_LI:
13931 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
13932 break;
13933 case M16_OPC_CMPI:
13934 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
13935 break;
13936 #if defined(TARGET_MIPS64)
13937 case M16_OPC_SD:
13938 check_insn(ctx, ISA_MIPS3);
13939 check_mips_64(ctx);
13940 gen_st(ctx, OPC_SD, ry, rx, offset);
13941 break;
13942 #endif
13943 case M16_OPC_LB:
13944 gen_ld(ctx, OPC_LB, ry, rx, offset);
13945 break;
13946 case M16_OPC_LH:
13947 gen_ld(ctx, OPC_LH, ry, rx, offset);
13948 break;
13949 case M16_OPC_LWSP:
13950 gen_ld(ctx, OPC_LW, rx, 29, offset);
13951 break;
13952 case M16_OPC_LW:
13953 gen_ld(ctx, OPC_LW, ry, rx, offset);
13954 break;
13955 case M16_OPC_LBU:
13956 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13957 break;
13958 case M16_OPC_LHU:
13959 gen_ld(ctx, OPC_LHU, ry, rx, offset);
13960 break;
13961 case M16_OPC_LWPC:
13962 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
13963 break;
13964 #if defined(TARGET_MIPS64)
13965 case M16_OPC_LWU:
13966 check_insn(ctx, ISA_MIPS3);
13967 check_mips_64(ctx);
13968 gen_ld(ctx, OPC_LWU, ry, rx, offset);
13969 break;
13970 #endif
13971 case M16_OPC_SB:
13972 gen_st(ctx, OPC_SB, ry, rx, offset);
13973 break;
13974 case M16_OPC_SH:
13975 gen_st(ctx, OPC_SH, ry, rx, offset);
13976 break;
13977 case M16_OPC_SWSP:
13978 gen_st(ctx, OPC_SW, rx, 29, offset);
13979 break;
13980 case M16_OPC_SW:
13981 gen_st(ctx, OPC_SW, ry, rx, offset);
13982 break;
13983 #if defined(TARGET_MIPS64)
13984 case M16_OPC_I64:
13985 decode_i64_mips16(ctx, ry, funct, offset, 1);
13986 break;
13987 #endif
13988 default:
13989 generate_exception_end(ctx, EXCP_RI);
13990 break;
13993 return 4;
13996 static inline bool is_uhi(int sdbbp_code)
13998 #ifdef CONFIG_USER_ONLY
13999 return false;
14000 #else
14001 return semihosting_enabled() && sdbbp_code == 1;
14002 #endif
14005 #ifdef CONFIG_USER_ONLY
14006 /* The above should dead-code away any calls to this..*/
14007 static inline void gen_helper_do_semihosting(void *env)
14009 g_assert_not_reached();
14011 #endif
14013 static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
14015 int rx, ry;
14016 int sa;
14017 int op, cnvt_op, op1, offset;
14018 int funct;
14019 int n_bytes;
14021 op = (ctx->opcode >> 11) & 0x1f;
14022 sa = (ctx->opcode >> 2) & 0x7;
14023 sa = sa == 0 ? 8 : sa;
14024 rx = xlat((ctx->opcode >> 8) & 0x7);
14025 cnvt_op = (ctx->opcode >> 5) & 0x7;
14026 ry = xlat((ctx->opcode >> 5) & 0x7);
14027 op1 = offset = ctx->opcode & 0x1f;
14029 n_bytes = 2;
14031 switch (op) {
14032 case M16_OPC_ADDIUSP:
14034 int16_t imm = ((uint8_t) ctx->opcode) << 2;
14036 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
14038 break;
14039 case M16_OPC_ADDIUPC:
14040 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
14041 break;
14042 case M16_OPC_B:
14043 offset = (ctx->opcode & 0x7ff) << 1;
14044 offset = (int16_t)(offset << 4) >> 4;
14045 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
14046 /* No delay slot, so just process as a normal instruction */
14047 break;
14048 case M16_OPC_JAL:
14049 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
14050 offset = (((ctx->opcode & 0x1f) << 21)
14051 | ((ctx->opcode >> 5) & 0x1f) << 16
14052 | offset) << 2;
14053 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
14054 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
14055 n_bytes = 4;
14056 break;
14057 case M16_OPC_BEQZ:
14058 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
14059 ((int8_t)ctx->opcode) << 1, 0);
14060 /* No delay slot, so just process as a normal instruction */
14061 break;
14062 case M16_OPC_BNEQZ:
14063 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
14064 ((int8_t)ctx->opcode) << 1, 0);
14065 /* No delay slot, so just process as a normal instruction */
14066 break;
14067 case M16_OPC_SHIFT:
14068 switch (ctx->opcode & 0x3) {
14069 case 0x0:
14070 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
14071 break;
14072 case 0x1:
14073 #if defined(TARGET_MIPS64)
14074 check_insn(ctx, ISA_MIPS3);
14075 check_mips_64(ctx);
14076 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
14077 #else
14078 generate_exception_end(ctx, EXCP_RI);
14079 #endif
14080 break;
14081 case 0x2:
14082 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
14083 break;
14084 case 0x3:
14085 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
14086 break;
14088 break;
14089 #if defined(TARGET_MIPS64)
14090 case M16_OPC_LD:
14091 check_insn(ctx, ISA_MIPS3);
14092 check_mips_64(ctx);
14093 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
14094 break;
14095 #endif
14096 case M16_OPC_RRIA:
14098 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
14100 if ((ctx->opcode >> 4) & 1) {
14101 #if defined(TARGET_MIPS64)
14102 check_insn(ctx, ISA_MIPS3);
14103 check_mips_64(ctx);
14104 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
14105 #else
14106 generate_exception_end(ctx, EXCP_RI);
14107 #endif
14108 } else {
14109 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
14112 break;
14113 case M16_OPC_ADDIU8:
14115 int16_t imm = (int8_t) ctx->opcode;
14117 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
14119 break;
14120 case M16_OPC_SLTI:
14122 int16_t imm = (uint8_t) ctx->opcode;
14123 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
14125 break;
14126 case M16_OPC_SLTIU:
14128 int16_t imm = (uint8_t) ctx->opcode;
14129 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
14131 break;
14132 case M16_OPC_I8:
14134 int reg32;
14136 funct = (ctx->opcode >> 8) & 0x7;
14137 switch (funct) {
14138 case I8_BTEQZ:
14139 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
14140 ((int8_t)ctx->opcode) << 1, 0);
14141 break;
14142 case I8_BTNEZ:
14143 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
14144 ((int8_t)ctx->opcode) << 1, 0);
14145 break;
14146 case I8_SWRASP:
14147 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
14148 break;
14149 case I8_ADJSP:
14150 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
14151 ((int8_t)ctx->opcode) << 3);
14152 break;
14153 case I8_SVRS:
14154 check_insn(ctx, ISA_MIPS32);
14156 int do_ra = ctx->opcode & (1 << 6);
14157 int do_s0 = ctx->opcode & (1 << 5);
14158 int do_s1 = ctx->opcode & (1 << 4);
14159 int framesize = ctx->opcode & 0xf;
14161 if (framesize == 0) {
14162 framesize = 128;
14163 } else {
14164 framesize = framesize << 3;
14167 if (ctx->opcode & (1 << 7)) {
14168 gen_mips16_save(ctx, 0, 0,
14169 do_ra, do_s0, do_s1, framesize);
14170 } else {
14171 gen_mips16_restore(ctx, 0, 0,
14172 do_ra, do_s0, do_s1, framesize);
14175 break;
14176 case I8_MOV32R:
14178 int rz = xlat(ctx->opcode & 0x7);
14180 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
14181 ((ctx->opcode >> 5) & 0x7);
14182 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
14184 break;
14185 case I8_MOVR32:
14186 reg32 = ctx->opcode & 0x1f;
14187 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
14188 break;
14189 default:
14190 generate_exception_end(ctx, EXCP_RI);
14191 break;
14194 break;
14195 case M16_OPC_LI:
14197 int16_t imm = (uint8_t) ctx->opcode;
14199 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
14201 break;
14202 case M16_OPC_CMPI:
14204 int16_t imm = (uint8_t) ctx->opcode;
14205 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
14207 break;
14208 #if defined(TARGET_MIPS64)
14209 case M16_OPC_SD:
14210 check_insn(ctx, ISA_MIPS3);
14211 check_mips_64(ctx);
14212 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
14213 break;
14214 #endif
14215 case M16_OPC_LB:
14216 gen_ld(ctx, OPC_LB, ry, rx, offset);
14217 break;
14218 case M16_OPC_LH:
14219 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
14220 break;
14221 case M16_OPC_LWSP:
14222 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14223 break;
14224 case M16_OPC_LW:
14225 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
14226 break;
14227 case M16_OPC_LBU:
14228 gen_ld(ctx, OPC_LBU, ry, rx, offset);
14229 break;
14230 case M16_OPC_LHU:
14231 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
14232 break;
14233 case M16_OPC_LWPC:
14234 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
14235 break;
14236 #if defined(TARGET_MIPS64)
14237 case M16_OPC_LWU:
14238 check_insn(ctx, ISA_MIPS3);
14239 check_mips_64(ctx);
14240 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
14241 break;
14242 #endif
14243 case M16_OPC_SB:
14244 gen_st(ctx, OPC_SB, ry, rx, offset);
14245 break;
14246 case M16_OPC_SH:
14247 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
14248 break;
14249 case M16_OPC_SWSP:
14250 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14251 break;
14252 case M16_OPC_SW:
14253 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
14254 break;
14255 case M16_OPC_RRR:
14257 int rz = xlat((ctx->opcode >> 2) & 0x7);
14258 int mips32_op;
14260 switch (ctx->opcode & 0x3) {
14261 case RRR_ADDU:
14262 mips32_op = OPC_ADDU;
14263 break;
14264 case RRR_SUBU:
14265 mips32_op = OPC_SUBU;
14266 break;
14267 #if defined(TARGET_MIPS64)
14268 case RRR_DADDU:
14269 mips32_op = OPC_DADDU;
14270 check_insn(ctx, ISA_MIPS3);
14271 check_mips_64(ctx);
14272 break;
14273 case RRR_DSUBU:
14274 mips32_op = OPC_DSUBU;
14275 check_insn(ctx, ISA_MIPS3);
14276 check_mips_64(ctx);
14277 break;
14278 #endif
14279 default:
14280 generate_exception_end(ctx, EXCP_RI);
14281 goto done;
14284 gen_arith(ctx, mips32_op, rz, rx, ry);
14285 done:
14288 break;
14289 case M16_OPC_RR:
14290 switch (op1) {
14291 case RR_JR:
14293 int nd = (ctx->opcode >> 7) & 0x1;
14294 int link = (ctx->opcode >> 6) & 0x1;
14295 int ra = (ctx->opcode >> 5) & 0x1;
14297 if (nd) {
14298 check_insn(ctx, ISA_MIPS32);
14301 if (link) {
14302 op = OPC_JALR;
14303 } else {
14304 op = OPC_JR;
14307 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
14308 (nd ? 0 : 2));
14310 break;
14311 case RR_SDBBP:
14312 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
14313 gen_helper_do_semihosting(cpu_env);
14314 } else {
14316 * XXX: not clear which exception should be raised
14317 * when in debug mode...
14319 check_insn(ctx, ISA_MIPS32);
14320 generate_exception_end(ctx, EXCP_DBp);
14322 break;
14323 case RR_SLT:
14324 gen_slt(ctx, OPC_SLT, 24, rx, ry);
14325 break;
14326 case RR_SLTU:
14327 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
14328 break;
14329 case RR_BREAK:
14330 generate_exception_end(ctx, EXCP_BREAK);
14331 break;
14332 case RR_SLLV:
14333 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
14334 break;
14335 case RR_SRLV:
14336 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
14337 break;
14338 case RR_SRAV:
14339 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
14340 break;
14341 #if defined(TARGET_MIPS64)
14342 case RR_DSRL:
14343 check_insn(ctx, ISA_MIPS3);
14344 check_mips_64(ctx);
14345 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
14346 break;
14347 #endif
14348 case RR_CMP:
14349 gen_logic(ctx, OPC_XOR, 24, rx, ry);
14350 break;
14351 case RR_NEG:
14352 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
14353 break;
14354 case RR_AND:
14355 gen_logic(ctx, OPC_AND, rx, rx, ry);
14356 break;
14357 case RR_OR:
14358 gen_logic(ctx, OPC_OR, rx, rx, ry);
14359 break;
14360 case RR_XOR:
14361 gen_logic(ctx, OPC_XOR, rx, rx, ry);
14362 break;
14363 case RR_NOT:
14364 gen_logic(ctx, OPC_NOR, rx, ry, 0);
14365 break;
14366 case RR_MFHI:
14367 gen_HILO(ctx, OPC_MFHI, 0, rx);
14368 break;
14369 case RR_CNVT:
14370 check_insn(ctx, ISA_MIPS32);
14371 switch (cnvt_op) {
14372 case RR_RY_CNVT_ZEB:
14373 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14374 break;
14375 case RR_RY_CNVT_ZEH:
14376 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14377 break;
14378 case RR_RY_CNVT_SEB:
14379 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14380 break;
14381 case RR_RY_CNVT_SEH:
14382 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14383 break;
14384 #if defined(TARGET_MIPS64)
14385 case RR_RY_CNVT_ZEW:
14386 check_insn(ctx, ISA_MIPS64);
14387 check_mips_64(ctx);
14388 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14389 break;
14390 case RR_RY_CNVT_SEW:
14391 check_insn(ctx, ISA_MIPS64);
14392 check_mips_64(ctx);
14393 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14394 break;
14395 #endif
14396 default:
14397 generate_exception_end(ctx, EXCP_RI);
14398 break;
14400 break;
14401 case RR_MFLO:
14402 gen_HILO(ctx, OPC_MFLO, 0, rx);
14403 break;
14404 #if defined(TARGET_MIPS64)
14405 case RR_DSRA:
14406 check_insn(ctx, ISA_MIPS3);
14407 check_mips_64(ctx);
14408 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
14409 break;
14410 case RR_DSLLV:
14411 check_insn(ctx, ISA_MIPS3);
14412 check_mips_64(ctx);
14413 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
14414 break;
14415 case RR_DSRLV:
14416 check_insn(ctx, ISA_MIPS3);
14417 check_mips_64(ctx);
14418 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
14419 break;
14420 case RR_DSRAV:
14421 check_insn(ctx, ISA_MIPS3);
14422 check_mips_64(ctx);
14423 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
14424 break;
14425 #endif
14426 case RR_MULT:
14427 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
14428 break;
14429 case RR_MULTU:
14430 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
14431 break;
14432 case RR_DIV:
14433 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
14434 break;
14435 case RR_DIVU:
14436 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
14437 break;
14438 #if defined(TARGET_MIPS64)
14439 case RR_DMULT:
14440 check_insn(ctx, ISA_MIPS3);
14441 check_mips_64(ctx);
14442 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
14443 break;
14444 case RR_DMULTU:
14445 check_insn(ctx, ISA_MIPS3);
14446 check_mips_64(ctx);
14447 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
14448 break;
14449 case RR_DDIV:
14450 check_insn(ctx, ISA_MIPS3);
14451 check_mips_64(ctx);
14452 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
14453 break;
14454 case RR_DDIVU:
14455 check_insn(ctx, ISA_MIPS3);
14456 check_mips_64(ctx);
14457 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
14458 break;
14459 #endif
14460 default:
14461 generate_exception_end(ctx, EXCP_RI);
14462 break;
14464 break;
14465 case M16_OPC_EXTEND:
14466 decode_extended_mips16_opc(env, ctx);
14467 n_bytes = 4;
14468 break;
14469 #if defined(TARGET_MIPS64)
14470 case M16_OPC_I64:
14471 funct = (ctx->opcode >> 8) & 0x7;
14472 decode_i64_mips16(ctx, ry, funct, offset, 0);
14473 break;
14474 #endif
14475 default:
14476 generate_exception_end(ctx, EXCP_RI);
14477 break;
14480 return n_bytes;
14483 /* microMIPS extension to MIPS32/MIPS64 */
14486 * microMIPS32/microMIPS64 major opcodes
14488 * 1. MIPS Architecture for Programmers Volume II-B:
14489 * The microMIPS32 Instruction Set (Revision 3.05)
14491 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
14493 * 2. MIPS Architecture For Programmers Volume II-A:
14494 * The MIPS64 Instruction Set (Revision 3.51)
14497 enum {
14498 POOL32A = 0x00,
14499 POOL16A = 0x01,
14500 LBU16 = 0x02,
14501 MOVE16 = 0x03,
14502 ADDI32 = 0x04,
14503 R6_LUI = 0x04,
14504 AUI = 0x04,
14505 LBU32 = 0x05,
14506 SB32 = 0x06,
14507 LB32 = 0x07,
14509 POOL32B = 0x08,
14510 POOL16B = 0x09,
14511 LHU16 = 0x0a,
14512 ANDI16 = 0x0b,
14513 ADDIU32 = 0x0c,
14514 LHU32 = 0x0d,
14515 SH32 = 0x0e,
14516 LH32 = 0x0f,
14518 POOL32I = 0x10,
14519 POOL16C = 0x11,
14520 LWSP16 = 0x12,
14521 POOL16D = 0x13,
14522 ORI32 = 0x14,
14523 POOL32F = 0x15,
14524 POOL32S = 0x16, /* MIPS64 */
14525 DADDIU32 = 0x17, /* MIPS64 */
14527 POOL32C = 0x18,
14528 LWGP16 = 0x19,
14529 LW16 = 0x1a,
14530 POOL16E = 0x1b,
14531 XORI32 = 0x1c,
14532 JALS32 = 0x1d,
14533 BOVC = 0x1d,
14534 BEQC = 0x1d,
14535 BEQZALC = 0x1d,
14536 ADDIUPC = 0x1e,
14537 PCREL = 0x1e,
14538 BNVC = 0x1f,
14539 BNEC = 0x1f,
14540 BNEZALC = 0x1f,
14542 R6_BEQZC = 0x20,
14543 JIC = 0x20,
14544 POOL16F = 0x21,
14545 SB16 = 0x22,
14546 BEQZ16 = 0x23,
14547 BEQZC16 = 0x23,
14548 SLTI32 = 0x24,
14549 BEQ32 = 0x25,
14550 BC = 0x25,
14551 SWC132 = 0x26,
14552 LWC132 = 0x27,
14554 /* 0x29 is reserved */
14555 RES_29 = 0x29,
14556 R6_BNEZC = 0x28,
14557 JIALC = 0x28,
14558 SH16 = 0x2a,
14559 BNEZ16 = 0x2b,
14560 BNEZC16 = 0x2b,
14561 SLTIU32 = 0x2c,
14562 BNE32 = 0x2d,
14563 BALC = 0x2d,
14564 SDC132 = 0x2e,
14565 LDC132 = 0x2f,
14567 /* 0x31 is reserved */
14568 RES_31 = 0x31,
14569 BLEZALC = 0x30,
14570 BGEZALC = 0x30,
14571 BGEUC = 0x30,
14572 SWSP16 = 0x32,
14573 B16 = 0x33,
14574 BC16 = 0x33,
14575 ANDI32 = 0x34,
14576 J32 = 0x35,
14577 BGTZC = 0x35,
14578 BLTZC = 0x35,
14579 BLTC = 0x35,
14580 SD32 = 0x36, /* MIPS64 */
14581 LD32 = 0x37, /* MIPS64 */
14583 /* 0x39 is reserved */
14584 RES_39 = 0x39,
14585 BGTZALC = 0x38,
14586 BLTZALC = 0x38,
14587 BLTUC = 0x38,
14588 SW16 = 0x3a,
14589 LI16 = 0x3b,
14590 JALX32 = 0x3c,
14591 JAL32 = 0x3d,
14592 BLEZC = 0x3d,
14593 BGEZC = 0x3d,
14594 BGEC = 0x3d,
14595 SW32 = 0x3e,
14596 LW32 = 0x3f
14599 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
14600 enum {
14601 ADDIUPC_00 = 0x00,
14602 ADDIUPC_01 = 0x01,
14603 ADDIUPC_02 = 0x02,
14604 ADDIUPC_03 = 0x03,
14605 ADDIUPC_04 = 0x04,
14606 ADDIUPC_05 = 0x05,
14607 ADDIUPC_06 = 0x06,
14608 ADDIUPC_07 = 0x07,
14609 AUIPC = 0x1e,
14610 ALUIPC = 0x1f,
14611 LWPC_08 = 0x08,
14612 LWPC_09 = 0x09,
14613 LWPC_0A = 0x0A,
14614 LWPC_0B = 0x0B,
14615 LWPC_0C = 0x0C,
14616 LWPC_0D = 0x0D,
14617 LWPC_0E = 0x0E,
14618 LWPC_0F = 0x0F,
14621 /* POOL32A encoding of minor opcode field */
14623 enum {
14625 * These opcodes are distinguished only by bits 9..6; those bits are
14626 * what are recorded below.
14628 SLL32 = 0x0,
14629 SRL32 = 0x1,
14630 SRA = 0x2,
14631 ROTR = 0x3,
14632 SELEQZ = 0x5,
14633 SELNEZ = 0x6,
14634 R6_RDHWR = 0x7,
14636 SLLV = 0x0,
14637 SRLV = 0x1,
14638 SRAV = 0x2,
14639 ROTRV = 0x3,
14640 ADD = 0x4,
14641 ADDU32 = 0x5,
14642 SUB = 0x6,
14643 SUBU32 = 0x7,
14644 MUL = 0x8,
14645 AND = 0x9,
14646 OR32 = 0xa,
14647 NOR = 0xb,
14648 XOR32 = 0xc,
14649 SLT = 0xd,
14650 SLTU = 0xe,
14652 MOVN = 0x0,
14653 R6_MUL = 0x0,
14654 MOVZ = 0x1,
14655 MUH = 0x1,
14656 MULU = 0x2,
14657 MUHU = 0x3,
14658 LWXS = 0x4,
14659 R6_DIV = 0x4,
14660 MOD = 0x5,
14661 R6_DIVU = 0x6,
14662 MODU = 0x7,
14664 /* The following can be distinguished by their lower 6 bits. */
14665 BREAK32 = 0x07,
14666 INS = 0x0c,
14667 LSA = 0x0f,
14668 ALIGN = 0x1f,
14669 EXT = 0x2c,
14670 POOL32AXF = 0x3c,
14671 SIGRIE = 0x3f
14674 /* POOL32AXF encoding of minor opcode field extension */
14677 * 1. MIPS Architecture for Programmers Volume II-B:
14678 * The microMIPS32 Instruction Set (Revision 3.05)
14680 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
14682 * 2. MIPS Architecture for Programmers VolumeIV-e:
14683 * The MIPS DSP Application-Specific Extension
14684 * to the microMIPS32 Architecture (Revision 2.34)
14686 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
14689 enum {
14690 /* bits 11..6 */
14691 TEQ = 0x00,
14692 TGE = 0x08,
14693 TGEU = 0x10,
14694 TLT = 0x20,
14695 TLTU = 0x28,
14696 TNE = 0x30,
14698 MFC0 = 0x03,
14699 MTC0 = 0x0b,
14701 /* begin of microMIPS32 DSP */
14703 /* bits 13..12 for 0x01 */
14704 MFHI_ACC = 0x0,
14705 MFLO_ACC = 0x1,
14706 MTHI_ACC = 0x2,
14707 MTLO_ACC = 0x3,
14709 /* bits 13..12 for 0x2a */
14710 MADD_ACC = 0x0,
14711 MADDU_ACC = 0x1,
14712 MSUB_ACC = 0x2,
14713 MSUBU_ACC = 0x3,
14715 /* bits 13..12 for 0x32 */
14716 MULT_ACC = 0x0,
14717 MULTU_ACC = 0x1,
14719 /* end of microMIPS32 DSP */
14721 /* bits 15..12 for 0x2c */
14722 BITSWAP = 0x0,
14723 SEB = 0x2,
14724 SEH = 0x3,
14725 CLO = 0x4,
14726 CLZ = 0x5,
14727 RDHWR = 0x6,
14728 WSBH = 0x7,
14729 MULT = 0x8,
14730 MULTU = 0x9,
14731 DIV = 0xa,
14732 DIVU = 0xb,
14733 MADD = 0xc,
14734 MADDU = 0xd,
14735 MSUB = 0xe,
14736 MSUBU = 0xf,
14738 /* bits 15..12 for 0x34 */
14739 MFC2 = 0x4,
14740 MTC2 = 0x5,
14741 MFHC2 = 0x8,
14742 MTHC2 = 0x9,
14743 CFC2 = 0xc,
14744 CTC2 = 0xd,
14746 /* bits 15..12 for 0x3c */
14747 JALR = 0x0,
14748 JR = 0x0, /* alias */
14749 JALRC = 0x0,
14750 JRC = 0x0,
14751 JALR_HB = 0x1,
14752 JALRC_HB = 0x1,
14753 JALRS = 0x4,
14754 JALRS_HB = 0x5,
14756 /* bits 15..12 for 0x05 */
14757 RDPGPR = 0xe,
14758 WRPGPR = 0xf,
14760 /* bits 15..12 for 0x0d */
14761 TLBP = 0x0,
14762 TLBR = 0x1,
14763 TLBWI = 0x2,
14764 TLBWR = 0x3,
14765 TLBINV = 0x4,
14766 TLBINVF = 0x5,
14767 WAIT = 0x9,
14768 IRET = 0xd,
14769 DERET = 0xe,
14770 ERET = 0xf,
14772 /* bits 15..12 for 0x15 */
14773 DMT = 0x0,
14774 DVPE = 0x1,
14775 EMT = 0x2,
14776 EVPE = 0x3,
14778 /* bits 15..12 for 0x1d */
14779 DI = 0x4,
14780 EI = 0x5,
14782 /* bits 15..12 for 0x2d */
14783 SYNC = 0x6,
14784 SYSCALL = 0x8,
14785 SDBBP = 0xd,
14787 /* bits 15..12 for 0x35 */
14788 MFHI32 = 0x0,
14789 MFLO32 = 0x1,
14790 MTHI32 = 0x2,
14791 MTLO32 = 0x3,
14794 /* POOL32B encoding of minor opcode field (bits 15..12) */
14796 enum {
14797 LWC2 = 0x0,
14798 LWP = 0x1,
14799 LDP = 0x4,
14800 LWM32 = 0x5,
14801 CACHE = 0x6,
14802 LDM = 0x7,
14803 SWC2 = 0x8,
14804 SWP = 0x9,
14805 SDP = 0xc,
14806 SWM32 = 0xd,
14807 SDM = 0xf
14810 /* POOL32C encoding of minor opcode field (bits 15..12) */
14812 enum {
14813 LWL = 0x0,
14814 SWL = 0x8,
14815 LWR = 0x1,
14816 SWR = 0x9,
14817 PREF = 0x2,
14818 ST_EVA = 0xa,
14819 LL = 0x3,
14820 SC = 0xb,
14821 LDL = 0x4,
14822 SDL = 0xc,
14823 LDR = 0x5,
14824 SDR = 0xd,
14825 LD_EVA = 0x6,
14826 LWU = 0xe,
14827 LLD = 0x7,
14828 SCD = 0xf
14831 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
14833 enum {
14834 LBUE = 0x0,
14835 LHUE = 0x1,
14836 LWLE = 0x2,
14837 LWRE = 0x3,
14838 LBE = 0x4,
14839 LHE = 0x5,
14840 LLE = 0x6,
14841 LWE = 0x7,
14844 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
14846 enum {
14847 SWLE = 0x0,
14848 SWRE = 0x1,
14849 PREFE = 0x2,
14850 CACHEE = 0x3,
14851 SBE = 0x4,
14852 SHE = 0x5,
14853 SCE = 0x6,
14854 SWE = 0x7,
14857 /* POOL32F encoding of minor opcode field (bits 5..0) */
14859 enum {
14860 /* These are the bit 7..6 values */
14861 ADD_FMT = 0x0,
14863 SUB_FMT = 0x1,
14865 MUL_FMT = 0x2,
14867 DIV_FMT = 0x3,
14869 /* These are the bit 8..6 values */
14870 MOVN_FMT = 0x0,
14871 RSQRT2_FMT = 0x0,
14872 MOVF_FMT = 0x0,
14873 RINT_FMT = 0x0,
14874 SELNEZ_FMT = 0x0,
14876 MOVZ_FMT = 0x1,
14877 LWXC1 = 0x1,
14878 MOVT_FMT = 0x1,
14879 CLASS_FMT = 0x1,
14880 SELEQZ_FMT = 0x1,
14882 PLL_PS = 0x2,
14883 SWXC1 = 0x2,
14884 SEL_FMT = 0x2,
14886 PLU_PS = 0x3,
14887 LDXC1 = 0x3,
14889 MOVN_FMT_04 = 0x4,
14890 PUL_PS = 0x4,
14891 SDXC1 = 0x4,
14892 RECIP2_FMT = 0x4,
14894 MOVZ_FMT_05 = 0x05,
14895 PUU_PS = 0x5,
14896 LUXC1 = 0x5,
14898 CVT_PS_S = 0x6,
14899 SUXC1 = 0x6,
14900 ADDR_PS = 0x6,
14901 PREFX = 0x6,
14902 MADDF_FMT = 0x6,
14904 MULR_PS = 0x7,
14905 MSUBF_FMT = 0x7,
14907 MADD_S = 0x01,
14908 MADD_D = 0x09,
14909 MADD_PS = 0x11,
14910 ALNV_PS = 0x19,
14911 MSUB_S = 0x21,
14912 MSUB_D = 0x29,
14913 MSUB_PS = 0x31,
14915 NMADD_S = 0x02,
14916 NMADD_D = 0x0a,
14917 NMADD_PS = 0x12,
14918 NMSUB_S = 0x22,
14919 NMSUB_D = 0x2a,
14920 NMSUB_PS = 0x32,
14922 MIN_FMT = 0x3,
14923 MAX_FMT = 0xb,
14924 MINA_FMT = 0x23,
14925 MAXA_FMT = 0x2b,
14926 POOL32FXF = 0x3b,
14928 CABS_COND_FMT = 0x1c, /* MIPS3D */
14929 C_COND_FMT = 0x3c,
14931 CMP_CONDN_S = 0x5,
14932 CMP_CONDN_D = 0x15
14935 /* POOL32Fxf encoding of minor opcode extension field */
14937 enum {
14938 CVT_L = 0x04,
14939 RSQRT_FMT = 0x08,
14940 FLOOR_L = 0x0c,
14941 CVT_PW_PS = 0x1c,
14942 CVT_W = 0x24,
14943 SQRT_FMT = 0x28,
14944 FLOOR_W = 0x2c,
14945 CVT_PS_PW = 0x3c,
14946 CFC1 = 0x40,
14947 RECIP_FMT = 0x48,
14948 CEIL_L = 0x4c,
14949 CTC1 = 0x60,
14950 CEIL_W = 0x6c,
14951 MFC1 = 0x80,
14952 CVT_S_PL = 0x84,
14953 TRUNC_L = 0x8c,
14954 MTC1 = 0xa0,
14955 CVT_S_PU = 0xa4,
14956 TRUNC_W = 0xac,
14957 MFHC1 = 0xc0,
14958 ROUND_L = 0xcc,
14959 MTHC1 = 0xe0,
14960 ROUND_W = 0xec,
14962 MOV_FMT = 0x01,
14963 MOVF = 0x05,
14964 ABS_FMT = 0x0d,
14965 RSQRT1_FMT = 0x1d,
14966 MOVT = 0x25,
14967 NEG_FMT = 0x2d,
14968 CVT_D = 0x4d,
14969 RECIP1_FMT = 0x5d,
14970 CVT_S = 0x6d
14973 /* POOL32I encoding of minor opcode field (bits 25..21) */
14975 enum {
14976 BLTZ = 0x00,
14977 BLTZAL = 0x01,
14978 BGEZ = 0x02,
14979 BGEZAL = 0x03,
14980 BLEZ = 0x04,
14981 BNEZC = 0x05,
14982 BGTZ = 0x06,
14983 BEQZC = 0x07,
14984 TLTI = 0x08,
14985 BC1EQZC = 0x08,
14986 TGEI = 0x09,
14987 BC1NEZC = 0x09,
14988 TLTIU = 0x0a,
14989 BC2EQZC = 0x0a,
14990 TGEIU = 0x0b,
14991 BC2NEZC = 0x0a,
14992 TNEI = 0x0c,
14993 R6_SYNCI = 0x0c,
14994 LUI = 0x0d,
14995 TEQI = 0x0e,
14996 SYNCI = 0x10,
14997 BLTZALS = 0x11,
14998 BGEZALS = 0x13,
14999 BC2F = 0x14,
15000 BC2T = 0x15,
15001 BPOSGE64 = 0x1a,
15002 BPOSGE32 = 0x1b,
15003 /* These overlap and are distinguished by bit16 of the instruction */
15004 BC1F = 0x1c,
15005 BC1T = 0x1d,
15006 BC1ANY2F = 0x1c,
15007 BC1ANY2T = 0x1d,
15008 BC1ANY4F = 0x1e,
15009 BC1ANY4T = 0x1f
15012 /* POOL16A encoding of minor opcode field */
15014 enum {
15015 ADDU16 = 0x0,
15016 SUBU16 = 0x1
15019 /* POOL16B encoding of minor opcode field */
15021 enum {
15022 SLL16 = 0x0,
15023 SRL16 = 0x1
15026 /* POOL16C encoding of minor opcode field */
15028 enum {
15029 NOT16 = 0x00,
15030 XOR16 = 0x04,
15031 AND16 = 0x08,
15032 OR16 = 0x0c,
15033 LWM16 = 0x10,
15034 SWM16 = 0x14,
15035 JR16 = 0x18,
15036 JRC16 = 0x1a,
15037 JALR16 = 0x1c,
15038 JALR16S = 0x1e,
15039 MFHI16 = 0x20,
15040 MFLO16 = 0x24,
15041 BREAK16 = 0x28,
15042 SDBBP16 = 0x2c,
15043 JRADDIUSP = 0x30
15046 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
15048 enum {
15049 R6_NOT16 = 0x00,
15050 R6_AND16 = 0x01,
15051 R6_LWM16 = 0x02,
15052 R6_JRC16 = 0x03,
15053 MOVEP = 0x04,
15054 MOVEP_05 = 0x05,
15055 MOVEP_06 = 0x06,
15056 MOVEP_07 = 0x07,
15057 R6_XOR16 = 0x08,
15058 R6_OR16 = 0x09,
15059 R6_SWM16 = 0x0a,
15060 JALRC16 = 0x0b,
15061 MOVEP_0C = 0x0c,
15062 MOVEP_0D = 0x0d,
15063 MOVEP_0E = 0x0e,
15064 MOVEP_0F = 0x0f,
15065 JRCADDIUSP = 0x13,
15066 R6_BREAK16 = 0x1b,
15067 R6_SDBBP16 = 0x3b
15070 /* POOL16D encoding of minor opcode field */
15072 enum {
15073 ADDIUS5 = 0x0,
15074 ADDIUSP = 0x1
15077 /* POOL16E encoding of minor opcode field */
15079 enum {
15080 ADDIUR2 = 0x0,
15081 ADDIUR1SP = 0x1
15084 static int mmreg(int r)
15086 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
15088 return map[r];
15091 /* Used for 16-bit store instructions. */
15092 static int mmreg2(int r)
15094 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
15096 return map[r];
15099 #define uMIPS_RD(op) ((op >> 7) & 0x7)
15100 #define uMIPS_RS(op) ((op >> 4) & 0x7)
15101 #define uMIPS_RS2(op) uMIPS_RS(op)
15102 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
15103 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
15104 #define uMIPS_RS5(op) (op & 0x1f)
15106 /* Signed immediate */
15107 #define SIMM(op, start, width) \
15108 ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \
15109 << (32 - width)) \
15110 >> (32 - width))
15111 /* Zero-extended immediate */
15112 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width)))
15114 static void gen_addiur1sp(DisasContext *ctx)
15116 int rd = mmreg(uMIPS_RD(ctx->opcode));
15118 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
15121 static void gen_addiur2(DisasContext *ctx)
15123 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
15124 int rd = mmreg(uMIPS_RD(ctx->opcode));
15125 int rs = mmreg(uMIPS_RS(ctx->opcode));
15127 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
15130 static void gen_addiusp(DisasContext *ctx)
15132 int encoded = ZIMM(ctx->opcode, 1, 9);
15133 int decoded;
15135 if (encoded <= 1) {
15136 decoded = 256 + encoded;
15137 } else if (encoded <= 255) {
15138 decoded = encoded;
15139 } else if (encoded <= 509) {
15140 decoded = encoded - 512;
15141 } else {
15142 decoded = encoded - 768;
15145 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
15148 static void gen_addius5(DisasContext *ctx)
15150 int imm = SIMM(ctx->opcode, 1, 4);
15151 int rd = (ctx->opcode >> 5) & 0x1f;
15153 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
15156 static void gen_andi16(DisasContext *ctx)
15158 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
15159 31, 32, 63, 64, 255, 32768, 65535 };
15160 int rd = mmreg(uMIPS_RD(ctx->opcode));
15161 int rs = mmreg(uMIPS_RS(ctx->opcode));
15162 int encoded = ZIMM(ctx->opcode, 0, 4);
15164 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
15167 static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist,
15168 int base, int16_t offset)
15170 TCGv t0, t1;
15171 TCGv_i32 t2;
15173 if (ctx->hflags & MIPS_HFLAG_BMASK) {
15174 generate_exception_end(ctx, EXCP_RI);
15175 return;
15178 t0 = tcg_temp_new();
15180 gen_base_offset_addr(ctx, t0, base, offset);
15182 t1 = tcg_const_tl(reglist);
15183 t2 = tcg_const_i32(ctx->mem_idx);
15185 save_cpu_state(ctx, 1);
15186 switch (opc) {
15187 case LWM32:
15188 gen_helper_lwm(cpu_env, t0, t1, t2);
15189 break;
15190 case SWM32:
15191 gen_helper_swm(cpu_env, t0, t1, t2);
15192 break;
15193 #ifdef TARGET_MIPS64
15194 case LDM:
15195 gen_helper_ldm(cpu_env, t0, t1, t2);
15196 break;
15197 case SDM:
15198 gen_helper_sdm(cpu_env, t0, t1, t2);
15199 break;
15200 #endif
15202 tcg_temp_free(t0);
15203 tcg_temp_free(t1);
15204 tcg_temp_free_i32(t2);
15208 static void gen_pool16c_insn(DisasContext *ctx)
15210 int rd = mmreg((ctx->opcode >> 3) & 0x7);
15211 int rs = mmreg(ctx->opcode & 0x7);
15213 switch (((ctx->opcode) >> 4) & 0x3f) {
15214 case NOT16 + 0:
15215 case NOT16 + 1:
15216 case NOT16 + 2:
15217 case NOT16 + 3:
15218 gen_logic(ctx, OPC_NOR, rd, rs, 0);
15219 break;
15220 case XOR16 + 0:
15221 case XOR16 + 1:
15222 case XOR16 + 2:
15223 case XOR16 + 3:
15224 gen_logic(ctx, OPC_XOR, rd, rd, rs);
15225 break;
15226 case AND16 + 0:
15227 case AND16 + 1:
15228 case AND16 + 2:
15229 case AND16 + 3:
15230 gen_logic(ctx, OPC_AND, rd, rd, rs);
15231 break;
15232 case OR16 + 0:
15233 case OR16 + 1:
15234 case OR16 + 2:
15235 case OR16 + 3:
15236 gen_logic(ctx, OPC_OR, rd, rd, rs);
15237 break;
15238 case LWM16 + 0:
15239 case LWM16 + 1:
15240 case LWM16 + 2:
15241 case LWM16 + 3:
15243 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15244 int offset = ZIMM(ctx->opcode, 0, 4);
15246 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
15247 29, offset << 2);
15249 break;
15250 case SWM16 + 0:
15251 case SWM16 + 1:
15252 case SWM16 + 2:
15253 case SWM16 + 3:
15255 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15256 int offset = ZIMM(ctx->opcode, 0, 4);
15258 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
15259 29, offset << 2);
15261 break;
15262 case JR16 + 0:
15263 case JR16 + 1:
15265 int reg = ctx->opcode & 0x1f;
15267 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
15269 break;
15270 case JRC16 + 0:
15271 case JRC16 + 1:
15273 int reg = ctx->opcode & 0x1f;
15274 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
15276 * Let normal delay slot handling in our caller take us
15277 * to the branch target.
15280 break;
15281 case JALR16 + 0:
15282 case JALR16 + 1:
15283 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
15284 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15285 break;
15286 case JALR16S + 0:
15287 case JALR16S + 1:
15288 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
15289 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15290 break;
15291 case MFHI16 + 0:
15292 case MFHI16 + 1:
15293 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
15294 break;
15295 case MFLO16 + 0:
15296 case MFLO16 + 1:
15297 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
15298 break;
15299 case BREAK16:
15300 generate_exception_end(ctx, EXCP_BREAK);
15301 break;
15302 case SDBBP16:
15303 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
15304 gen_helper_do_semihosting(cpu_env);
15305 } else {
15307 * XXX: not clear which exception should be raised
15308 * when in debug mode...
15310 check_insn(ctx, ISA_MIPS32);
15311 generate_exception_end(ctx, EXCP_DBp);
15313 break;
15314 case JRADDIUSP + 0:
15315 case JRADDIUSP + 1:
15317 int imm = ZIMM(ctx->opcode, 0, 5);
15318 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15319 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15321 * Let normal delay slot handling in our caller take us
15322 * to the branch target.
15325 break;
15326 default:
15327 generate_exception_end(ctx, EXCP_RI);
15328 break;
15332 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
15333 int enc_rs)
15335 int rd, rs, re, rt;
15336 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
15337 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
15338 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
15339 rd = rd_enc[enc_dest];
15340 re = re_enc[enc_dest];
15341 rs = rs_rt_enc[enc_rs];
15342 rt = rs_rt_enc[enc_rt];
15343 if (rs) {
15344 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
15345 } else {
15346 tcg_gen_movi_tl(cpu_gpr[rd], 0);
15348 if (rt) {
15349 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
15350 } else {
15351 tcg_gen_movi_tl(cpu_gpr[re], 0);
15355 static void gen_pool16c_r6_insn(DisasContext *ctx)
15357 int rt = mmreg((ctx->opcode >> 7) & 0x7);
15358 int rs = mmreg((ctx->opcode >> 4) & 0x7);
15360 switch (ctx->opcode & 0xf) {
15361 case R6_NOT16:
15362 gen_logic(ctx, OPC_NOR, rt, rs, 0);
15363 break;
15364 case R6_AND16:
15365 gen_logic(ctx, OPC_AND, rt, rt, rs);
15366 break;
15367 case R6_LWM16:
15369 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15370 int offset = extract32(ctx->opcode, 4, 4);
15371 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
15373 break;
15374 case R6_JRC16: /* JRCADDIUSP */
15375 if ((ctx->opcode >> 4) & 1) {
15376 /* JRCADDIUSP */
15377 int imm = extract32(ctx->opcode, 5, 5);
15378 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15379 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15380 } else {
15381 /* JRC16 */
15382 rs = extract32(ctx->opcode, 5, 5);
15383 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
15385 break;
15386 case MOVEP:
15387 case MOVEP_05:
15388 case MOVEP_06:
15389 case MOVEP_07:
15390 case MOVEP_0C:
15391 case MOVEP_0D:
15392 case MOVEP_0E:
15393 case MOVEP_0F:
15395 int enc_dest = uMIPS_RD(ctx->opcode);
15396 int enc_rt = uMIPS_RS2(ctx->opcode);
15397 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
15398 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15400 break;
15401 case R6_XOR16:
15402 gen_logic(ctx, OPC_XOR, rt, rt, rs);
15403 break;
15404 case R6_OR16:
15405 gen_logic(ctx, OPC_OR, rt, rt, rs);
15406 break;
15407 case R6_SWM16:
15409 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15410 int offset = extract32(ctx->opcode, 4, 4);
15411 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
15413 break;
15414 case JALRC16: /* BREAK16, SDBBP16 */
15415 switch (ctx->opcode & 0x3f) {
15416 case JALRC16:
15417 case JALRC16 + 0x20:
15418 /* JALRC16 */
15419 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
15420 31, 0, 0);
15421 break;
15422 case R6_BREAK16:
15423 /* BREAK16 */
15424 generate_exception(ctx, EXCP_BREAK);
15425 break;
15426 case R6_SDBBP16:
15427 /* SDBBP16 */
15428 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
15429 gen_helper_do_semihosting(cpu_env);
15430 } else {
15431 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15432 generate_exception(ctx, EXCP_RI);
15433 } else {
15434 generate_exception(ctx, EXCP_DBp);
15437 break;
15439 break;
15440 default:
15441 generate_exception(ctx, EXCP_RI);
15442 break;
15446 static void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
15448 TCGv t0 = tcg_temp_new();
15449 TCGv t1 = tcg_temp_new();
15451 gen_load_gpr(t0, base);
15453 if (index != 0) {
15454 gen_load_gpr(t1, index);
15455 tcg_gen_shli_tl(t1, t1, 2);
15456 gen_op_addr_add(ctx, t0, t1, t0);
15459 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15460 gen_store_gpr(t1, rd);
15462 tcg_temp_free(t0);
15463 tcg_temp_free(t1);
15466 static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd,
15467 int base, int16_t offset)
15469 TCGv t0, t1;
15471 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
15472 generate_exception_end(ctx, EXCP_RI);
15473 return;
15476 t0 = tcg_temp_new();
15477 t1 = tcg_temp_new();
15479 gen_base_offset_addr(ctx, t0, base, offset);
15481 switch (opc) {
15482 case LWP:
15483 if (rd == base) {
15484 generate_exception_end(ctx, EXCP_RI);
15485 return;
15487 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15488 gen_store_gpr(t1, rd);
15489 tcg_gen_movi_tl(t1, 4);
15490 gen_op_addr_add(ctx, t0, t0, t1);
15491 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15492 gen_store_gpr(t1, rd + 1);
15493 break;
15494 case SWP:
15495 gen_load_gpr(t1, rd);
15496 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15497 tcg_gen_movi_tl(t1, 4);
15498 gen_op_addr_add(ctx, t0, t0, t1);
15499 gen_load_gpr(t1, rd + 1);
15500 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15501 break;
15502 #ifdef TARGET_MIPS64
15503 case LDP:
15504 if (rd == base) {
15505 generate_exception_end(ctx, EXCP_RI);
15506 return;
15508 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15509 gen_store_gpr(t1, rd);
15510 tcg_gen_movi_tl(t1, 8);
15511 gen_op_addr_add(ctx, t0, t0, t1);
15512 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15513 gen_store_gpr(t1, rd + 1);
15514 break;
15515 case SDP:
15516 gen_load_gpr(t1, rd);
15517 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15518 tcg_gen_movi_tl(t1, 8);
15519 gen_op_addr_add(ctx, t0, t0, t1);
15520 gen_load_gpr(t1, rd + 1);
15521 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15522 break;
15523 #endif
15525 tcg_temp_free(t0);
15526 tcg_temp_free(t1);
15529 static void gen_sync(int stype)
15531 TCGBar tcg_mo = TCG_BAR_SC;
15533 switch (stype) {
15534 case 0x4: /* SYNC_WMB */
15535 tcg_mo |= TCG_MO_ST_ST;
15536 break;
15537 case 0x10: /* SYNC_MB */
15538 tcg_mo |= TCG_MO_ALL;
15539 break;
15540 case 0x11: /* SYNC_ACQUIRE */
15541 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
15542 break;
15543 case 0x12: /* SYNC_RELEASE */
15544 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
15545 break;
15546 case 0x13: /* SYNC_RMB */
15547 tcg_mo |= TCG_MO_LD_LD;
15548 break;
15549 default:
15550 tcg_mo |= TCG_MO_ALL;
15551 break;
15554 tcg_gen_mb(tcg_mo);
15557 static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
15559 int extension = (ctx->opcode >> 6) & 0x3f;
15560 int minor = (ctx->opcode >> 12) & 0xf;
15561 uint32_t mips32_op;
15563 switch (extension) {
15564 case TEQ:
15565 mips32_op = OPC_TEQ;
15566 goto do_trap;
15567 case TGE:
15568 mips32_op = OPC_TGE;
15569 goto do_trap;
15570 case TGEU:
15571 mips32_op = OPC_TGEU;
15572 goto do_trap;
15573 case TLT:
15574 mips32_op = OPC_TLT;
15575 goto do_trap;
15576 case TLTU:
15577 mips32_op = OPC_TLTU;
15578 goto do_trap;
15579 case TNE:
15580 mips32_op = OPC_TNE;
15581 do_trap:
15582 gen_trap(ctx, mips32_op, rs, rt, -1);
15583 break;
15584 #ifndef CONFIG_USER_ONLY
15585 case MFC0:
15586 case MFC0 + 32:
15587 check_cp0_enabled(ctx);
15588 if (rt == 0) {
15589 /* Treat as NOP. */
15590 break;
15592 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
15593 break;
15594 case MTC0:
15595 case MTC0 + 32:
15596 check_cp0_enabled(ctx);
15598 TCGv t0 = tcg_temp_new();
15600 gen_load_gpr(t0, rt);
15601 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
15602 tcg_temp_free(t0);
15604 break;
15605 #endif
15606 case 0x2a:
15607 switch (minor & 3) {
15608 case MADD_ACC:
15609 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
15610 break;
15611 case MADDU_ACC:
15612 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
15613 break;
15614 case MSUB_ACC:
15615 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
15616 break;
15617 case MSUBU_ACC:
15618 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
15619 break;
15620 default:
15621 goto pool32axf_invalid;
15623 break;
15624 case 0x32:
15625 switch (minor & 3) {
15626 case MULT_ACC:
15627 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
15628 break;
15629 case MULTU_ACC:
15630 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
15631 break;
15632 default:
15633 goto pool32axf_invalid;
15635 break;
15636 case 0x2c:
15637 switch (minor) {
15638 case BITSWAP:
15639 check_insn(ctx, ISA_MIPS32R6);
15640 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
15641 break;
15642 case SEB:
15643 gen_bshfl(ctx, OPC_SEB, rs, rt);
15644 break;
15645 case SEH:
15646 gen_bshfl(ctx, OPC_SEH, rs, rt);
15647 break;
15648 case CLO:
15649 mips32_op = OPC_CLO;
15650 goto do_cl;
15651 case CLZ:
15652 mips32_op = OPC_CLZ;
15653 do_cl:
15654 check_insn(ctx, ISA_MIPS32);
15655 gen_cl(ctx, mips32_op, rt, rs);
15656 break;
15657 case RDHWR:
15658 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15659 gen_rdhwr(ctx, rt, rs, 0);
15660 break;
15661 case WSBH:
15662 gen_bshfl(ctx, OPC_WSBH, rs, rt);
15663 break;
15664 case MULT:
15665 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15666 mips32_op = OPC_MULT;
15667 goto do_mul;
15668 case MULTU:
15669 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15670 mips32_op = OPC_MULTU;
15671 goto do_mul;
15672 case DIV:
15673 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15674 mips32_op = OPC_DIV;
15675 goto do_div;
15676 case DIVU:
15677 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15678 mips32_op = OPC_DIVU;
15679 goto do_div;
15680 do_div:
15681 check_insn(ctx, ISA_MIPS32);
15682 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15683 break;
15684 case MADD:
15685 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15686 mips32_op = OPC_MADD;
15687 goto do_mul;
15688 case MADDU:
15689 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15690 mips32_op = OPC_MADDU;
15691 goto do_mul;
15692 case MSUB:
15693 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15694 mips32_op = OPC_MSUB;
15695 goto do_mul;
15696 case MSUBU:
15697 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15698 mips32_op = OPC_MSUBU;
15699 do_mul:
15700 check_insn(ctx, ISA_MIPS32);
15701 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15702 break;
15703 default:
15704 goto pool32axf_invalid;
15706 break;
15707 case 0x34:
15708 switch (minor) {
15709 case MFC2:
15710 case MTC2:
15711 case MFHC2:
15712 case MTHC2:
15713 case CFC2:
15714 case CTC2:
15715 generate_exception_err(ctx, EXCP_CpU, 2);
15716 break;
15717 default:
15718 goto pool32axf_invalid;
15720 break;
15721 case 0x3c:
15722 switch (minor) {
15723 case JALR: /* JALRC */
15724 case JALR_HB: /* JALRC_HB */
15725 if (ctx->insn_flags & ISA_MIPS32R6) {
15726 /* JALRC, JALRC_HB */
15727 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
15728 } else {
15729 /* JALR, JALR_HB */
15730 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
15731 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15733 break;
15734 case JALRS:
15735 case JALRS_HB:
15736 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15737 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
15738 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15739 break;
15740 default:
15741 goto pool32axf_invalid;
15743 break;
15744 case 0x05:
15745 switch (minor) {
15746 case RDPGPR:
15747 check_cp0_enabled(ctx);
15748 check_insn(ctx, ISA_MIPS32R2);
15749 gen_load_srsgpr(rs, rt);
15750 break;
15751 case WRPGPR:
15752 check_cp0_enabled(ctx);
15753 check_insn(ctx, ISA_MIPS32R2);
15754 gen_store_srsgpr(rs, rt);
15755 break;
15756 default:
15757 goto pool32axf_invalid;
15759 break;
15760 #ifndef CONFIG_USER_ONLY
15761 case 0x0d:
15762 switch (minor) {
15763 case TLBP:
15764 mips32_op = OPC_TLBP;
15765 goto do_cp0;
15766 case TLBR:
15767 mips32_op = OPC_TLBR;
15768 goto do_cp0;
15769 case TLBWI:
15770 mips32_op = OPC_TLBWI;
15771 goto do_cp0;
15772 case TLBWR:
15773 mips32_op = OPC_TLBWR;
15774 goto do_cp0;
15775 case TLBINV:
15776 mips32_op = OPC_TLBINV;
15777 goto do_cp0;
15778 case TLBINVF:
15779 mips32_op = OPC_TLBINVF;
15780 goto do_cp0;
15781 case WAIT:
15782 mips32_op = OPC_WAIT;
15783 goto do_cp0;
15784 case DERET:
15785 mips32_op = OPC_DERET;
15786 goto do_cp0;
15787 case ERET:
15788 mips32_op = OPC_ERET;
15789 do_cp0:
15790 gen_cp0(env, ctx, mips32_op, rt, rs);
15791 break;
15792 default:
15793 goto pool32axf_invalid;
15795 break;
15796 case 0x1d:
15797 switch (minor) {
15798 case DI:
15799 check_cp0_enabled(ctx);
15801 TCGv t0 = tcg_temp_new();
15803 save_cpu_state(ctx, 1);
15804 gen_helper_di(t0, cpu_env);
15805 gen_store_gpr(t0, rs);
15807 * Stop translation as we may have switched the execution
15808 * mode.
15810 ctx->base.is_jmp = DISAS_STOP;
15811 tcg_temp_free(t0);
15813 break;
15814 case EI:
15815 check_cp0_enabled(ctx);
15817 TCGv t0 = tcg_temp_new();
15819 save_cpu_state(ctx, 1);
15820 gen_helper_ei(t0, cpu_env);
15821 gen_store_gpr(t0, rs);
15823 * DISAS_STOP isn't sufficient, we need to ensure we break out
15824 * of translated code to check for pending interrupts.
15826 gen_save_pc(ctx->base.pc_next + 4);
15827 ctx->base.is_jmp = DISAS_EXIT;
15828 tcg_temp_free(t0);
15830 break;
15831 default:
15832 goto pool32axf_invalid;
15834 break;
15835 #endif
15836 case 0x2d:
15837 switch (minor) {
15838 case SYNC:
15839 gen_sync(extract32(ctx->opcode, 16, 5));
15840 break;
15841 case SYSCALL:
15842 generate_exception_end(ctx, EXCP_SYSCALL);
15843 break;
15844 case SDBBP:
15845 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
15846 gen_helper_do_semihosting(cpu_env);
15847 } else {
15848 check_insn(ctx, ISA_MIPS32);
15849 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15850 generate_exception_end(ctx, EXCP_RI);
15851 } else {
15852 generate_exception_end(ctx, EXCP_DBp);
15855 break;
15856 default:
15857 goto pool32axf_invalid;
15859 break;
15860 case 0x01:
15861 switch (minor & 3) {
15862 case MFHI_ACC:
15863 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
15864 break;
15865 case MFLO_ACC:
15866 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
15867 break;
15868 case MTHI_ACC:
15869 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
15870 break;
15871 case MTLO_ACC:
15872 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
15873 break;
15874 default:
15875 goto pool32axf_invalid;
15877 break;
15878 case 0x35:
15879 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15880 switch (minor) {
15881 case MFHI32:
15882 gen_HILO(ctx, OPC_MFHI, 0, rs);
15883 break;
15884 case MFLO32:
15885 gen_HILO(ctx, OPC_MFLO, 0, rs);
15886 break;
15887 case MTHI32:
15888 gen_HILO(ctx, OPC_MTHI, 0, rs);
15889 break;
15890 case MTLO32:
15891 gen_HILO(ctx, OPC_MTLO, 0, rs);
15892 break;
15893 default:
15894 goto pool32axf_invalid;
15896 break;
15897 default:
15898 pool32axf_invalid:
15899 MIPS_INVAL("pool32axf");
15900 generate_exception_end(ctx, EXCP_RI);
15901 break;
15906 * Values for microMIPS fmt field. Variable-width, depending on which
15907 * formats the instruction supports.
15909 enum {
15910 FMT_SD_S = 0,
15911 FMT_SD_D = 1,
15913 FMT_SDPS_S = 0,
15914 FMT_SDPS_D = 1,
15915 FMT_SDPS_PS = 2,
15917 FMT_SWL_S = 0,
15918 FMT_SWL_W = 1,
15919 FMT_SWL_L = 2,
15921 FMT_DWL_D = 0,
15922 FMT_DWL_W = 1,
15923 FMT_DWL_L = 2
15926 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
15928 int extension = (ctx->opcode >> 6) & 0x3ff;
15929 uint32_t mips32_op;
15931 #define FLOAT_1BIT_FMT(opc, fmt) ((fmt << 8) | opc)
15932 #define FLOAT_2BIT_FMT(opc, fmt) ((fmt << 7) | opc)
15933 #define COND_FLOAT_MOV(opc, cond) ((cond << 7) | opc)
15935 switch (extension) {
15936 case FLOAT_1BIT_FMT(CFC1, 0):
15937 mips32_op = OPC_CFC1;
15938 goto do_cp1;
15939 case FLOAT_1BIT_FMT(CTC1, 0):
15940 mips32_op = OPC_CTC1;
15941 goto do_cp1;
15942 case FLOAT_1BIT_FMT(MFC1, 0):
15943 mips32_op = OPC_MFC1;
15944 goto do_cp1;
15945 case FLOAT_1BIT_FMT(MTC1, 0):
15946 mips32_op = OPC_MTC1;
15947 goto do_cp1;
15948 case FLOAT_1BIT_FMT(MFHC1, 0):
15949 mips32_op = OPC_MFHC1;
15950 goto do_cp1;
15951 case FLOAT_1BIT_FMT(MTHC1, 0):
15952 mips32_op = OPC_MTHC1;
15953 do_cp1:
15954 gen_cp1(ctx, mips32_op, rt, rs);
15955 break;
15957 /* Reciprocal square root */
15958 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
15959 mips32_op = OPC_RSQRT_S;
15960 goto do_unaryfp;
15961 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
15962 mips32_op = OPC_RSQRT_D;
15963 goto do_unaryfp;
15965 /* Square root */
15966 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
15967 mips32_op = OPC_SQRT_S;
15968 goto do_unaryfp;
15969 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
15970 mips32_op = OPC_SQRT_D;
15971 goto do_unaryfp;
15973 /* Reciprocal */
15974 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
15975 mips32_op = OPC_RECIP_S;
15976 goto do_unaryfp;
15977 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
15978 mips32_op = OPC_RECIP_D;
15979 goto do_unaryfp;
15981 /* Floor */
15982 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
15983 mips32_op = OPC_FLOOR_L_S;
15984 goto do_unaryfp;
15985 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
15986 mips32_op = OPC_FLOOR_L_D;
15987 goto do_unaryfp;
15988 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
15989 mips32_op = OPC_FLOOR_W_S;
15990 goto do_unaryfp;
15991 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
15992 mips32_op = OPC_FLOOR_W_D;
15993 goto do_unaryfp;
15995 /* Ceiling */
15996 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
15997 mips32_op = OPC_CEIL_L_S;
15998 goto do_unaryfp;
15999 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
16000 mips32_op = OPC_CEIL_L_D;
16001 goto do_unaryfp;
16002 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
16003 mips32_op = OPC_CEIL_W_S;
16004 goto do_unaryfp;
16005 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
16006 mips32_op = OPC_CEIL_W_D;
16007 goto do_unaryfp;
16009 /* Truncation */
16010 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
16011 mips32_op = OPC_TRUNC_L_S;
16012 goto do_unaryfp;
16013 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
16014 mips32_op = OPC_TRUNC_L_D;
16015 goto do_unaryfp;
16016 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
16017 mips32_op = OPC_TRUNC_W_S;
16018 goto do_unaryfp;
16019 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
16020 mips32_op = OPC_TRUNC_W_D;
16021 goto do_unaryfp;
16023 /* Round */
16024 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
16025 mips32_op = OPC_ROUND_L_S;
16026 goto do_unaryfp;
16027 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
16028 mips32_op = OPC_ROUND_L_D;
16029 goto do_unaryfp;
16030 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
16031 mips32_op = OPC_ROUND_W_S;
16032 goto do_unaryfp;
16033 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
16034 mips32_op = OPC_ROUND_W_D;
16035 goto do_unaryfp;
16037 /* Integer to floating-point conversion */
16038 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
16039 mips32_op = OPC_CVT_L_S;
16040 goto do_unaryfp;
16041 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
16042 mips32_op = OPC_CVT_L_D;
16043 goto do_unaryfp;
16044 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
16045 mips32_op = OPC_CVT_W_S;
16046 goto do_unaryfp;
16047 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
16048 mips32_op = OPC_CVT_W_D;
16049 goto do_unaryfp;
16051 /* Paired-foo conversions */
16052 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
16053 mips32_op = OPC_CVT_S_PL;
16054 goto do_unaryfp;
16055 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
16056 mips32_op = OPC_CVT_S_PU;
16057 goto do_unaryfp;
16058 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
16059 mips32_op = OPC_CVT_PW_PS;
16060 goto do_unaryfp;
16061 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
16062 mips32_op = OPC_CVT_PS_PW;
16063 goto do_unaryfp;
16065 /* Floating-point moves */
16066 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
16067 mips32_op = OPC_MOV_S;
16068 goto do_unaryfp;
16069 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
16070 mips32_op = OPC_MOV_D;
16071 goto do_unaryfp;
16072 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
16073 mips32_op = OPC_MOV_PS;
16074 goto do_unaryfp;
16076 /* Absolute value */
16077 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
16078 mips32_op = OPC_ABS_S;
16079 goto do_unaryfp;
16080 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
16081 mips32_op = OPC_ABS_D;
16082 goto do_unaryfp;
16083 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
16084 mips32_op = OPC_ABS_PS;
16085 goto do_unaryfp;
16087 /* Negation */
16088 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
16089 mips32_op = OPC_NEG_S;
16090 goto do_unaryfp;
16091 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
16092 mips32_op = OPC_NEG_D;
16093 goto do_unaryfp;
16094 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
16095 mips32_op = OPC_NEG_PS;
16096 goto do_unaryfp;
16098 /* Reciprocal square root step */
16099 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
16100 mips32_op = OPC_RSQRT1_S;
16101 goto do_unaryfp;
16102 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
16103 mips32_op = OPC_RSQRT1_D;
16104 goto do_unaryfp;
16105 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
16106 mips32_op = OPC_RSQRT1_PS;
16107 goto do_unaryfp;
16109 /* Reciprocal step */
16110 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
16111 mips32_op = OPC_RECIP1_S;
16112 goto do_unaryfp;
16113 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
16114 mips32_op = OPC_RECIP1_S;
16115 goto do_unaryfp;
16116 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
16117 mips32_op = OPC_RECIP1_PS;
16118 goto do_unaryfp;
16120 /* Conversions from double */
16121 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
16122 mips32_op = OPC_CVT_D_S;
16123 goto do_unaryfp;
16124 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
16125 mips32_op = OPC_CVT_D_W;
16126 goto do_unaryfp;
16127 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
16128 mips32_op = OPC_CVT_D_L;
16129 goto do_unaryfp;
16131 /* Conversions from single */
16132 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
16133 mips32_op = OPC_CVT_S_D;
16134 goto do_unaryfp;
16135 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
16136 mips32_op = OPC_CVT_S_W;
16137 goto do_unaryfp;
16138 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
16139 mips32_op = OPC_CVT_S_L;
16140 do_unaryfp:
16141 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
16142 break;
16144 /* Conditional moves on floating-point codes */
16145 case COND_FLOAT_MOV(MOVT, 0):
16146 case COND_FLOAT_MOV(MOVT, 1):
16147 case COND_FLOAT_MOV(MOVT, 2):
16148 case COND_FLOAT_MOV(MOVT, 3):
16149 case COND_FLOAT_MOV(MOVT, 4):
16150 case COND_FLOAT_MOV(MOVT, 5):
16151 case COND_FLOAT_MOV(MOVT, 6):
16152 case COND_FLOAT_MOV(MOVT, 7):
16153 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16154 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
16155 break;
16156 case COND_FLOAT_MOV(MOVF, 0):
16157 case COND_FLOAT_MOV(MOVF, 1):
16158 case COND_FLOAT_MOV(MOVF, 2):
16159 case COND_FLOAT_MOV(MOVF, 3):
16160 case COND_FLOAT_MOV(MOVF, 4):
16161 case COND_FLOAT_MOV(MOVF, 5):
16162 case COND_FLOAT_MOV(MOVF, 6):
16163 case COND_FLOAT_MOV(MOVF, 7):
16164 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16165 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
16166 break;
16167 default:
16168 MIPS_INVAL("pool32fxf");
16169 generate_exception_end(ctx, EXCP_RI);
16170 break;
16174 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
16176 int32_t offset;
16177 uint16_t insn;
16178 int rt, rs, rd, rr;
16179 int16_t imm;
16180 uint32_t op, minor, minor2, mips32_op;
16181 uint32_t cond, fmt, cc;
16183 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
16184 ctx->opcode = (ctx->opcode << 16) | insn;
16186 rt = (ctx->opcode >> 21) & 0x1f;
16187 rs = (ctx->opcode >> 16) & 0x1f;
16188 rd = (ctx->opcode >> 11) & 0x1f;
16189 rr = (ctx->opcode >> 6) & 0x1f;
16190 imm = (int16_t) ctx->opcode;
16192 op = (ctx->opcode >> 26) & 0x3f;
16193 switch (op) {
16194 case POOL32A:
16195 minor = ctx->opcode & 0x3f;
16196 switch (minor) {
16197 case 0x00:
16198 minor = (ctx->opcode >> 6) & 0xf;
16199 switch (minor) {
16200 case SLL32:
16201 mips32_op = OPC_SLL;
16202 goto do_shifti;
16203 case SRA:
16204 mips32_op = OPC_SRA;
16205 goto do_shifti;
16206 case SRL32:
16207 mips32_op = OPC_SRL;
16208 goto do_shifti;
16209 case ROTR:
16210 mips32_op = OPC_ROTR;
16211 do_shifti:
16212 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
16213 break;
16214 case SELEQZ:
16215 check_insn(ctx, ISA_MIPS32R6);
16216 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
16217 break;
16218 case SELNEZ:
16219 check_insn(ctx, ISA_MIPS32R6);
16220 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
16221 break;
16222 case R6_RDHWR:
16223 check_insn(ctx, ISA_MIPS32R6);
16224 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
16225 break;
16226 default:
16227 goto pool32a_invalid;
16229 break;
16230 case 0x10:
16231 minor = (ctx->opcode >> 6) & 0xf;
16232 switch (minor) {
16233 /* Arithmetic */
16234 case ADD:
16235 mips32_op = OPC_ADD;
16236 goto do_arith;
16237 case ADDU32:
16238 mips32_op = OPC_ADDU;
16239 goto do_arith;
16240 case SUB:
16241 mips32_op = OPC_SUB;
16242 goto do_arith;
16243 case SUBU32:
16244 mips32_op = OPC_SUBU;
16245 goto do_arith;
16246 case MUL:
16247 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16248 mips32_op = OPC_MUL;
16249 do_arith:
16250 gen_arith(ctx, mips32_op, rd, rs, rt);
16251 break;
16252 /* Shifts */
16253 case SLLV:
16254 mips32_op = OPC_SLLV;
16255 goto do_shift;
16256 case SRLV:
16257 mips32_op = OPC_SRLV;
16258 goto do_shift;
16259 case SRAV:
16260 mips32_op = OPC_SRAV;
16261 goto do_shift;
16262 case ROTRV:
16263 mips32_op = OPC_ROTRV;
16264 do_shift:
16265 gen_shift(ctx, mips32_op, rd, rs, rt);
16266 break;
16267 /* Logical operations */
16268 case AND:
16269 mips32_op = OPC_AND;
16270 goto do_logic;
16271 case OR32:
16272 mips32_op = OPC_OR;
16273 goto do_logic;
16274 case NOR:
16275 mips32_op = OPC_NOR;
16276 goto do_logic;
16277 case XOR32:
16278 mips32_op = OPC_XOR;
16279 do_logic:
16280 gen_logic(ctx, mips32_op, rd, rs, rt);
16281 break;
16282 /* Set less than */
16283 case SLT:
16284 mips32_op = OPC_SLT;
16285 goto do_slt;
16286 case SLTU:
16287 mips32_op = OPC_SLTU;
16288 do_slt:
16289 gen_slt(ctx, mips32_op, rd, rs, rt);
16290 break;
16291 default:
16292 goto pool32a_invalid;
16294 break;
16295 case 0x18:
16296 minor = (ctx->opcode >> 6) & 0xf;
16297 switch (minor) {
16298 /* Conditional moves */
16299 case MOVN: /* MUL */
16300 if (ctx->insn_flags & ISA_MIPS32R6) {
16301 /* MUL */
16302 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
16303 } else {
16304 /* MOVN */
16305 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
16307 break;
16308 case MOVZ: /* MUH */
16309 if (ctx->insn_flags & ISA_MIPS32R6) {
16310 /* MUH */
16311 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
16312 } else {
16313 /* MOVZ */
16314 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
16316 break;
16317 case MULU:
16318 check_insn(ctx, ISA_MIPS32R6);
16319 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
16320 break;
16321 case MUHU:
16322 check_insn(ctx, ISA_MIPS32R6);
16323 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
16324 break;
16325 case LWXS: /* DIV */
16326 if (ctx->insn_flags & ISA_MIPS32R6) {
16327 /* DIV */
16328 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
16329 } else {
16330 /* LWXS */
16331 gen_ldxs(ctx, rs, rt, rd);
16333 break;
16334 case MOD:
16335 check_insn(ctx, ISA_MIPS32R6);
16336 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
16337 break;
16338 case R6_DIVU:
16339 check_insn(ctx, ISA_MIPS32R6);
16340 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
16341 break;
16342 case MODU:
16343 check_insn(ctx, ISA_MIPS32R6);
16344 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
16345 break;
16346 default:
16347 goto pool32a_invalid;
16349 break;
16350 case INS:
16351 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
16352 return;
16353 case LSA:
16354 check_insn(ctx, ISA_MIPS32R6);
16355 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
16356 extract32(ctx->opcode, 9, 2));
16357 break;
16358 case ALIGN:
16359 check_insn(ctx, ISA_MIPS32R6);
16360 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
16361 break;
16362 case EXT:
16363 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
16364 return;
16365 case POOL32AXF:
16366 gen_pool32axf(env, ctx, rt, rs);
16367 break;
16368 case BREAK32:
16369 generate_exception_end(ctx, EXCP_BREAK);
16370 break;
16371 case SIGRIE:
16372 check_insn(ctx, ISA_MIPS32R6);
16373 generate_exception_end(ctx, EXCP_RI);
16374 break;
16375 default:
16376 pool32a_invalid:
16377 MIPS_INVAL("pool32a");
16378 generate_exception_end(ctx, EXCP_RI);
16379 break;
16381 break;
16382 case POOL32B:
16383 minor = (ctx->opcode >> 12) & 0xf;
16384 switch (minor) {
16385 case CACHE:
16386 check_cp0_enabled(ctx);
16387 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16388 gen_cache_operation(ctx, rt, rs, imm);
16390 break;
16391 case LWC2:
16392 case SWC2:
16393 /* COP2: Not implemented. */
16394 generate_exception_err(ctx, EXCP_CpU, 2);
16395 break;
16396 #ifdef TARGET_MIPS64
16397 case LDP:
16398 case SDP:
16399 check_insn(ctx, ISA_MIPS3);
16400 check_mips_64(ctx);
16401 #endif
16402 /* fall through */
16403 case LWP:
16404 case SWP:
16405 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16406 break;
16407 #ifdef TARGET_MIPS64
16408 case LDM:
16409 case SDM:
16410 check_insn(ctx, ISA_MIPS3);
16411 check_mips_64(ctx);
16412 #endif
16413 /* fall through */
16414 case LWM32:
16415 case SWM32:
16416 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16417 break;
16418 default:
16419 MIPS_INVAL("pool32b");
16420 generate_exception_end(ctx, EXCP_RI);
16421 break;
16423 break;
16424 case POOL32F:
16425 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
16426 minor = ctx->opcode & 0x3f;
16427 check_cp1_enabled(ctx);
16428 switch (minor) {
16429 case ALNV_PS:
16430 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16431 mips32_op = OPC_ALNV_PS;
16432 goto do_madd;
16433 case MADD_S:
16434 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16435 mips32_op = OPC_MADD_S;
16436 goto do_madd;
16437 case MADD_D:
16438 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16439 mips32_op = OPC_MADD_D;
16440 goto do_madd;
16441 case MADD_PS:
16442 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16443 mips32_op = OPC_MADD_PS;
16444 goto do_madd;
16445 case MSUB_S:
16446 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16447 mips32_op = OPC_MSUB_S;
16448 goto do_madd;
16449 case MSUB_D:
16450 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16451 mips32_op = OPC_MSUB_D;
16452 goto do_madd;
16453 case MSUB_PS:
16454 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16455 mips32_op = OPC_MSUB_PS;
16456 goto do_madd;
16457 case NMADD_S:
16458 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16459 mips32_op = OPC_NMADD_S;
16460 goto do_madd;
16461 case NMADD_D:
16462 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16463 mips32_op = OPC_NMADD_D;
16464 goto do_madd;
16465 case NMADD_PS:
16466 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16467 mips32_op = OPC_NMADD_PS;
16468 goto do_madd;
16469 case NMSUB_S:
16470 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16471 mips32_op = OPC_NMSUB_S;
16472 goto do_madd;
16473 case NMSUB_D:
16474 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16475 mips32_op = OPC_NMSUB_D;
16476 goto do_madd;
16477 case NMSUB_PS:
16478 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16479 mips32_op = OPC_NMSUB_PS;
16480 do_madd:
16481 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
16482 break;
16483 case CABS_COND_FMT:
16484 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16485 cond = (ctx->opcode >> 6) & 0xf;
16486 cc = (ctx->opcode >> 13) & 0x7;
16487 fmt = (ctx->opcode >> 10) & 0x3;
16488 switch (fmt) {
16489 case 0x0:
16490 gen_cmpabs_s(ctx, cond, rt, rs, cc);
16491 break;
16492 case 0x1:
16493 gen_cmpabs_d(ctx, cond, rt, rs, cc);
16494 break;
16495 case 0x2:
16496 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
16497 break;
16498 default:
16499 goto pool32f_invalid;
16501 break;
16502 case C_COND_FMT:
16503 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16504 cond = (ctx->opcode >> 6) & 0xf;
16505 cc = (ctx->opcode >> 13) & 0x7;
16506 fmt = (ctx->opcode >> 10) & 0x3;
16507 switch (fmt) {
16508 case 0x0:
16509 gen_cmp_s(ctx, cond, rt, rs, cc);
16510 break;
16511 case 0x1:
16512 gen_cmp_d(ctx, cond, rt, rs, cc);
16513 break;
16514 case 0x2:
16515 gen_cmp_ps(ctx, cond, rt, rs, cc);
16516 break;
16517 default:
16518 goto pool32f_invalid;
16520 break;
16521 case CMP_CONDN_S:
16522 check_insn(ctx, ISA_MIPS32R6);
16523 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16524 break;
16525 case CMP_CONDN_D:
16526 check_insn(ctx, ISA_MIPS32R6);
16527 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16528 break;
16529 case POOL32FXF:
16530 gen_pool32fxf(ctx, rt, rs);
16531 break;
16532 case 0x00:
16533 /* PLL foo */
16534 switch ((ctx->opcode >> 6) & 0x7) {
16535 case PLL_PS:
16536 mips32_op = OPC_PLL_PS;
16537 goto do_ps;
16538 case PLU_PS:
16539 mips32_op = OPC_PLU_PS;
16540 goto do_ps;
16541 case PUL_PS:
16542 mips32_op = OPC_PUL_PS;
16543 goto do_ps;
16544 case PUU_PS:
16545 mips32_op = OPC_PUU_PS;
16546 goto do_ps;
16547 case CVT_PS_S:
16548 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16549 mips32_op = OPC_CVT_PS_S;
16550 do_ps:
16551 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16552 break;
16553 default:
16554 goto pool32f_invalid;
16556 break;
16557 case MIN_FMT:
16558 check_insn(ctx, ISA_MIPS32R6);
16559 switch ((ctx->opcode >> 9) & 0x3) {
16560 case FMT_SDPS_S:
16561 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
16562 break;
16563 case FMT_SDPS_D:
16564 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
16565 break;
16566 default:
16567 goto pool32f_invalid;
16569 break;
16570 case 0x08:
16571 /* [LS][WDU]XC1 */
16572 switch ((ctx->opcode >> 6) & 0x7) {
16573 case LWXC1:
16574 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16575 mips32_op = OPC_LWXC1;
16576 goto do_ldst_cp1;
16577 case SWXC1:
16578 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16579 mips32_op = OPC_SWXC1;
16580 goto do_ldst_cp1;
16581 case LDXC1:
16582 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16583 mips32_op = OPC_LDXC1;
16584 goto do_ldst_cp1;
16585 case SDXC1:
16586 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16587 mips32_op = OPC_SDXC1;
16588 goto do_ldst_cp1;
16589 case LUXC1:
16590 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16591 mips32_op = OPC_LUXC1;
16592 goto do_ldst_cp1;
16593 case SUXC1:
16594 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16595 mips32_op = OPC_SUXC1;
16596 do_ldst_cp1:
16597 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
16598 break;
16599 default:
16600 goto pool32f_invalid;
16602 break;
16603 case MAX_FMT:
16604 check_insn(ctx, ISA_MIPS32R6);
16605 switch ((ctx->opcode >> 9) & 0x3) {
16606 case FMT_SDPS_S:
16607 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
16608 break;
16609 case FMT_SDPS_D:
16610 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
16611 break;
16612 default:
16613 goto pool32f_invalid;
16615 break;
16616 case 0x18:
16617 /* 3D insns */
16618 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16619 fmt = (ctx->opcode >> 9) & 0x3;
16620 switch ((ctx->opcode >> 6) & 0x7) {
16621 case RSQRT2_FMT:
16622 switch (fmt) {
16623 case FMT_SDPS_S:
16624 mips32_op = OPC_RSQRT2_S;
16625 goto do_3d;
16626 case FMT_SDPS_D:
16627 mips32_op = OPC_RSQRT2_D;
16628 goto do_3d;
16629 case FMT_SDPS_PS:
16630 mips32_op = OPC_RSQRT2_PS;
16631 goto do_3d;
16632 default:
16633 goto pool32f_invalid;
16635 break;
16636 case RECIP2_FMT:
16637 switch (fmt) {
16638 case FMT_SDPS_S:
16639 mips32_op = OPC_RECIP2_S;
16640 goto do_3d;
16641 case FMT_SDPS_D:
16642 mips32_op = OPC_RECIP2_D;
16643 goto do_3d;
16644 case FMT_SDPS_PS:
16645 mips32_op = OPC_RECIP2_PS;
16646 goto do_3d;
16647 default:
16648 goto pool32f_invalid;
16650 break;
16651 case ADDR_PS:
16652 mips32_op = OPC_ADDR_PS;
16653 goto do_3d;
16654 case MULR_PS:
16655 mips32_op = OPC_MULR_PS;
16656 do_3d:
16657 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16658 break;
16659 default:
16660 goto pool32f_invalid;
16662 break;
16663 case 0x20:
16664 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
16665 cc = (ctx->opcode >> 13) & 0x7;
16666 fmt = (ctx->opcode >> 9) & 0x3;
16667 switch ((ctx->opcode >> 6) & 0x7) {
16668 case MOVF_FMT: /* RINT_FMT */
16669 if (ctx->insn_flags & ISA_MIPS32R6) {
16670 /* RINT_FMT */
16671 switch (fmt) {
16672 case FMT_SDPS_S:
16673 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
16674 break;
16675 case FMT_SDPS_D:
16676 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
16677 break;
16678 default:
16679 goto pool32f_invalid;
16681 } else {
16682 /* MOVF_FMT */
16683 switch (fmt) {
16684 case FMT_SDPS_S:
16685 gen_movcf_s(ctx, rs, rt, cc, 0);
16686 break;
16687 case FMT_SDPS_D:
16688 gen_movcf_d(ctx, rs, rt, cc, 0);
16689 break;
16690 case FMT_SDPS_PS:
16691 check_ps(ctx);
16692 gen_movcf_ps(ctx, rs, rt, cc, 0);
16693 break;
16694 default:
16695 goto pool32f_invalid;
16698 break;
16699 case MOVT_FMT: /* CLASS_FMT */
16700 if (ctx->insn_flags & ISA_MIPS32R6) {
16701 /* CLASS_FMT */
16702 switch (fmt) {
16703 case FMT_SDPS_S:
16704 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
16705 break;
16706 case FMT_SDPS_D:
16707 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
16708 break;
16709 default:
16710 goto pool32f_invalid;
16712 } else {
16713 /* MOVT_FMT */
16714 switch (fmt) {
16715 case FMT_SDPS_S:
16716 gen_movcf_s(ctx, rs, rt, cc, 1);
16717 break;
16718 case FMT_SDPS_D:
16719 gen_movcf_d(ctx, rs, rt, cc, 1);
16720 break;
16721 case FMT_SDPS_PS:
16722 check_ps(ctx);
16723 gen_movcf_ps(ctx, rs, rt, cc, 1);
16724 break;
16725 default:
16726 goto pool32f_invalid;
16729 break;
16730 case PREFX:
16731 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16732 break;
16733 default:
16734 goto pool32f_invalid;
16736 break;
16737 #define FINSN_3ARG_SDPS(prfx) \
16738 switch ((ctx->opcode >> 8) & 0x3) { \
16739 case FMT_SDPS_S: \
16740 mips32_op = OPC_##prfx##_S; \
16741 goto do_fpop; \
16742 case FMT_SDPS_D: \
16743 mips32_op = OPC_##prfx##_D; \
16744 goto do_fpop; \
16745 case FMT_SDPS_PS: \
16746 check_ps(ctx); \
16747 mips32_op = OPC_##prfx##_PS; \
16748 goto do_fpop; \
16749 default: \
16750 goto pool32f_invalid; \
16752 case MINA_FMT:
16753 check_insn(ctx, ISA_MIPS32R6);
16754 switch ((ctx->opcode >> 9) & 0x3) {
16755 case FMT_SDPS_S:
16756 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
16757 break;
16758 case FMT_SDPS_D:
16759 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
16760 break;
16761 default:
16762 goto pool32f_invalid;
16764 break;
16765 case MAXA_FMT:
16766 check_insn(ctx, ISA_MIPS32R6);
16767 switch ((ctx->opcode >> 9) & 0x3) {
16768 case FMT_SDPS_S:
16769 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
16770 break;
16771 case FMT_SDPS_D:
16772 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
16773 break;
16774 default:
16775 goto pool32f_invalid;
16777 break;
16778 case 0x30:
16779 /* regular FP ops */
16780 switch ((ctx->opcode >> 6) & 0x3) {
16781 case ADD_FMT:
16782 FINSN_3ARG_SDPS(ADD);
16783 break;
16784 case SUB_FMT:
16785 FINSN_3ARG_SDPS(SUB);
16786 break;
16787 case MUL_FMT:
16788 FINSN_3ARG_SDPS(MUL);
16789 break;
16790 case DIV_FMT:
16791 fmt = (ctx->opcode >> 8) & 0x3;
16792 if (fmt == 1) {
16793 mips32_op = OPC_DIV_D;
16794 } else if (fmt == 0) {
16795 mips32_op = OPC_DIV_S;
16796 } else {
16797 goto pool32f_invalid;
16799 goto do_fpop;
16800 default:
16801 goto pool32f_invalid;
16803 break;
16804 case 0x38:
16805 /* cmovs */
16806 switch ((ctx->opcode >> 6) & 0x7) {
16807 case MOVN_FMT: /* SELEQZ_FMT */
16808 if (ctx->insn_flags & ISA_MIPS32R6) {
16809 /* SELEQZ_FMT */
16810 switch ((ctx->opcode >> 9) & 0x3) {
16811 case FMT_SDPS_S:
16812 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
16813 break;
16814 case FMT_SDPS_D:
16815 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
16816 break;
16817 default:
16818 goto pool32f_invalid;
16820 } else {
16821 /* MOVN_FMT */
16822 FINSN_3ARG_SDPS(MOVN);
16824 break;
16825 case MOVN_FMT_04:
16826 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16827 FINSN_3ARG_SDPS(MOVN);
16828 break;
16829 case MOVZ_FMT: /* SELNEZ_FMT */
16830 if (ctx->insn_flags & ISA_MIPS32R6) {
16831 /* SELNEZ_FMT */
16832 switch ((ctx->opcode >> 9) & 0x3) {
16833 case FMT_SDPS_S:
16834 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
16835 break;
16836 case FMT_SDPS_D:
16837 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
16838 break;
16839 default:
16840 goto pool32f_invalid;
16842 } else {
16843 /* MOVZ_FMT */
16844 FINSN_3ARG_SDPS(MOVZ);
16846 break;
16847 case MOVZ_FMT_05:
16848 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16849 FINSN_3ARG_SDPS(MOVZ);
16850 break;
16851 case SEL_FMT:
16852 check_insn(ctx, ISA_MIPS32R6);
16853 switch ((ctx->opcode >> 9) & 0x3) {
16854 case FMT_SDPS_S:
16855 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
16856 break;
16857 case FMT_SDPS_D:
16858 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
16859 break;
16860 default:
16861 goto pool32f_invalid;
16863 break;
16864 case MADDF_FMT:
16865 check_insn(ctx, ISA_MIPS32R6);
16866 switch ((ctx->opcode >> 9) & 0x3) {
16867 case FMT_SDPS_S:
16868 mips32_op = OPC_MADDF_S;
16869 goto do_fpop;
16870 case FMT_SDPS_D:
16871 mips32_op = OPC_MADDF_D;
16872 goto do_fpop;
16873 default:
16874 goto pool32f_invalid;
16876 break;
16877 case MSUBF_FMT:
16878 check_insn(ctx, ISA_MIPS32R6);
16879 switch ((ctx->opcode >> 9) & 0x3) {
16880 case FMT_SDPS_S:
16881 mips32_op = OPC_MSUBF_S;
16882 goto do_fpop;
16883 case FMT_SDPS_D:
16884 mips32_op = OPC_MSUBF_D;
16885 goto do_fpop;
16886 default:
16887 goto pool32f_invalid;
16889 break;
16890 default:
16891 goto pool32f_invalid;
16893 break;
16894 do_fpop:
16895 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16896 break;
16897 default:
16898 pool32f_invalid:
16899 MIPS_INVAL("pool32f");
16900 generate_exception_end(ctx, EXCP_RI);
16901 break;
16903 } else {
16904 generate_exception_err(ctx, EXCP_CpU, 1);
16906 break;
16907 case POOL32I:
16908 minor = (ctx->opcode >> 21) & 0x1f;
16909 switch (minor) {
16910 case BLTZ:
16911 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16912 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
16913 break;
16914 case BLTZAL:
16915 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16916 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
16917 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16918 break;
16919 case BLTZALS:
16920 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16921 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
16922 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16923 break;
16924 case BGEZ:
16925 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16926 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
16927 break;
16928 case BGEZAL:
16929 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16930 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
16931 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16932 break;
16933 case BGEZALS:
16934 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16935 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
16936 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16937 break;
16938 case BLEZ:
16939 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16940 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
16941 break;
16942 case BGTZ:
16943 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16944 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
16945 break;
16947 /* Traps */
16948 case TLTI: /* BC1EQZC */
16949 if (ctx->insn_flags & ISA_MIPS32R6) {
16950 /* BC1EQZC */
16951 check_cp1_enabled(ctx);
16952 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
16953 } else {
16954 /* TLTI */
16955 mips32_op = OPC_TLTI;
16956 goto do_trapi;
16958 break;
16959 case TGEI: /* BC1NEZC */
16960 if (ctx->insn_flags & ISA_MIPS32R6) {
16961 /* BC1NEZC */
16962 check_cp1_enabled(ctx);
16963 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
16964 } else {
16965 /* TGEI */
16966 mips32_op = OPC_TGEI;
16967 goto do_trapi;
16969 break;
16970 case TLTIU:
16971 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16972 mips32_op = OPC_TLTIU;
16973 goto do_trapi;
16974 case TGEIU:
16975 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16976 mips32_op = OPC_TGEIU;
16977 goto do_trapi;
16978 case TNEI: /* SYNCI */
16979 if (ctx->insn_flags & ISA_MIPS32R6) {
16980 /* SYNCI */
16982 * Break the TB to be able to sync copied instructions
16983 * immediately.
16985 ctx->base.is_jmp = DISAS_STOP;
16986 } else {
16987 /* TNEI */
16988 mips32_op = OPC_TNEI;
16989 goto do_trapi;
16991 break;
16992 case TEQI:
16993 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16994 mips32_op = OPC_TEQI;
16995 do_trapi:
16996 gen_trap(ctx, mips32_op, rs, -1, imm);
16997 break;
16999 case BNEZC:
17000 case BEQZC:
17001 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17002 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
17003 4, rs, 0, imm << 1, 0);
17005 * Compact branches don't have a delay slot, so just let
17006 * the normal delay slot handling take us to the branch
17007 * target.
17009 break;
17010 case LUI:
17011 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17012 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
17013 break;
17014 case SYNCI:
17015 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17017 * Break the TB to be able to sync copied instructions
17018 * immediately.
17020 ctx->base.is_jmp = DISAS_STOP;
17021 break;
17022 case BC2F:
17023 case BC2T:
17024 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17025 /* COP2: Not implemented. */
17026 generate_exception_err(ctx, EXCP_CpU, 2);
17027 break;
17028 case BC1F:
17029 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17030 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
17031 goto do_cp1branch;
17032 case BC1T:
17033 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17034 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
17035 goto do_cp1branch;
17036 case BC1ANY4F:
17037 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17038 mips32_op = OPC_BC1FANY4;
17039 goto do_cp1mips3d;
17040 case BC1ANY4T:
17041 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17042 mips32_op = OPC_BC1TANY4;
17043 do_cp1mips3d:
17044 check_cop1x(ctx);
17045 check_insn(ctx, ASE_MIPS3D);
17046 /* Fall through */
17047 do_cp1branch:
17048 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
17049 check_cp1_enabled(ctx);
17050 gen_compute_branch1(ctx, mips32_op,
17051 (ctx->opcode >> 18) & 0x7, imm << 1);
17052 } else {
17053 generate_exception_err(ctx, EXCP_CpU, 1);
17055 break;
17056 case BPOSGE64:
17057 case BPOSGE32:
17058 /* MIPS DSP: not implemented */
17059 /* Fall through */
17060 default:
17061 MIPS_INVAL("pool32i");
17062 generate_exception_end(ctx, EXCP_RI);
17063 break;
17065 break;
17066 case POOL32C:
17067 minor = (ctx->opcode >> 12) & 0xf;
17068 offset = sextract32(ctx->opcode, 0,
17069 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
17070 switch (minor) {
17071 case LWL:
17072 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17073 mips32_op = OPC_LWL;
17074 goto do_ld_lr;
17075 case SWL:
17076 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17077 mips32_op = OPC_SWL;
17078 goto do_st_lr;
17079 case LWR:
17080 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17081 mips32_op = OPC_LWR;
17082 goto do_ld_lr;
17083 case SWR:
17084 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17085 mips32_op = OPC_SWR;
17086 goto do_st_lr;
17087 #if defined(TARGET_MIPS64)
17088 case LDL:
17089 check_insn(ctx, ISA_MIPS3);
17090 check_mips_64(ctx);
17091 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17092 mips32_op = OPC_LDL;
17093 goto do_ld_lr;
17094 case SDL:
17095 check_insn(ctx, ISA_MIPS3);
17096 check_mips_64(ctx);
17097 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17098 mips32_op = OPC_SDL;
17099 goto do_st_lr;
17100 case LDR:
17101 check_insn(ctx, ISA_MIPS3);
17102 check_mips_64(ctx);
17103 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17104 mips32_op = OPC_LDR;
17105 goto do_ld_lr;
17106 case SDR:
17107 check_insn(ctx, ISA_MIPS3);
17108 check_mips_64(ctx);
17109 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17110 mips32_op = OPC_SDR;
17111 goto do_st_lr;
17112 case LWU:
17113 check_insn(ctx, ISA_MIPS3);
17114 check_mips_64(ctx);
17115 mips32_op = OPC_LWU;
17116 goto do_ld_lr;
17117 case LLD:
17118 check_insn(ctx, ISA_MIPS3);
17119 check_mips_64(ctx);
17120 mips32_op = OPC_LLD;
17121 goto do_ld_lr;
17122 #endif
17123 case LL:
17124 mips32_op = OPC_LL;
17125 goto do_ld_lr;
17126 do_ld_lr:
17127 gen_ld(ctx, mips32_op, rt, rs, offset);
17128 break;
17129 do_st_lr:
17130 gen_st(ctx, mips32_op, rt, rs, offset);
17131 break;
17132 case SC:
17133 gen_st_cond(ctx, rt, rs, offset, MO_TESL, false);
17134 break;
17135 #if defined(TARGET_MIPS64)
17136 case SCD:
17137 check_insn(ctx, ISA_MIPS3);
17138 check_mips_64(ctx);
17139 gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false);
17140 break;
17141 #endif
17142 case LD_EVA:
17143 if (!ctx->eva) {
17144 MIPS_INVAL("pool32c ld-eva");
17145 generate_exception_end(ctx, EXCP_RI);
17146 break;
17148 check_cp0_enabled(ctx);
17150 minor2 = (ctx->opcode >> 9) & 0x7;
17151 offset = sextract32(ctx->opcode, 0, 9);
17152 switch (minor2) {
17153 case LBUE:
17154 mips32_op = OPC_LBUE;
17155 goto do_ld_lr;
17156 case LHUE:
17157 mips32_op = OPC_LHUE;
17158 goto do_ld_lr;
17159 case LWLE:
17160 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17161 mips32_op = OPC_LWLE;
17162 goto do_ld_lr;
17163 case LWRE:
17164 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17165 mips32_op = OPC_LWRE;
17166 goto do_ld_lr;
17167 case LBE:
17168 mips32_op = OPC_LBE;
17169 goto do_ld_lr;
17170 case LHE:
17171 mips32_op = OPC_LHE;
17172 goto do_ld_lr;
17173 case LLE:
17174 mips32_op = OPC_LLE;
17175 goto do_ld_lr;
17176 case LWE:
17177 mips32_op = OPC_LWE;
17178 goto do_ld_lr;
17180 break;
17181 case ST_EVA:
17182 if (!ctx->eva) {
17183 MIPS_INVAL("pool32c st-eva");
17184 generate_exception_end(ctx, EXCP_RI);
17185 break;
17187 check_cp0_enabled(ctx);
17189 minor2 = (ctx->opcode >> 9) & 0x7;
17190 offset = sextract32(ctx->opcode, 0, 9);
17191 switch (minor2) {
17192 case SWLE:
17193 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17194 mips32_op = OPC_SWLE;
17195 goto do_st_lr;
17196 case SWRE:
17197 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17198 mips32_op = OPC_SWRE;
17199 goto do_st_lr;
17200 case PREFE:
17201 /* Treat as no-op */
17202 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
17203 /* hint codes 24-31 are reserved and signal RI */
17204 generate_exception(ctx, EXCP_RI);
17206 break;
17207 case CACHEE:
17208 /* Treat as no-op */
17209 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
17210 gen_cache_operation(ctx, rt, rs, offset);
17212 break;
17213 case SBE:
17214 mips32_op = OPC_SBE;
17215 goto do_st_lr;
17216 case SHE:
17217 mips32_op = OPC_SHE;
17218 goto do_st_lr;
17219 case SCE:
17220 gen_st_cond(ctx, rt, rs, offset, MO_TESL, true);
17221 break;
17222 case SWE:
17223 mips32_op = OPC_SWE;
17224 goto do_st_lr;
17226 break;
17227 case PREF:
17228 /* Treat as no-op */
17229 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
17230 /* hint codes 24-31 are reserved and signal RI */
17231 generate_exception(ctx, EXCP_RI);
17233 break;
17234 default:
17235 MIPS_INVAL("pool32c");
17236 generate_exception_end(ctx, EXCP_RI);
17237 break;
17239 break;
17240 case ADDI32: /* AUI, LUI */
17241 if (ctx->insn_flags & ISA_MIPS32R6) {
17242 /* AUI, LUI */
17243 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
17244 } else {
17245 /* ADDI32 */
17246 mips32_op = OPC_ADDI;
17247 goto do_addi;
17249 break;
17250 case ADDIU32:
17251 mips32_op = OPC_ADDIU;
17252 do_addi:
17253 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
17254 break;
17256 /* Logical operations */
17257 case ORI32:
17258 mips32_op = OPC_ORI;
17259 goto do_logici;
17260 case XORI32:
17261 mips32_op = OPC_XORI;
17262 goto do_logici;
17263 case ANDI32:
17264 mips32_op = OPC_ANDI;
17265 do_logici:
17266 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
17267 break;
17269 /* Set less than immediate */
17270 case SLTI32:
17271 mips32_op = OPC_SLTI;
17272 goto do_slti;
17273 case SLTIU32:
17274 mips32_op = OPC_SLTIU;
17275 do_slti:
17276 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
17277 break;
17278 case JALX32:
17279 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17280 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
17281 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
17282 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17283 break;
17284 case JALS32: /* BOVC, BEQC, BEQZALC */
17285 if (ctx->insn_flags & ISA_MIPS32R6) {
17286 if (rs >= rt) {
17287 /* BOVC */
17288 mips32_op = OPC_BOVC;
17289 } else if (rs < rt && rs == 0) {
17290 /* BEQZALC */
17291 mips32_op = OPC_BEQZALC;
17292 } else {
17293 /* BEQC */
17294 mips32_op = OPC_BEQC;
17296 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17297 } else {
17298 /* JALS32 */
17299 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
17300 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
17301 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17303 break;
17304 case BEQ32: /* BC */
17305 if (ctx->insn_flags & ISA_MIPS32R6) {
17306 /* BC */
17307 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
17308 sextract32(ctx->opcode << 1, 0, 27));
17309 } else {
17310 /* BEQ32 */
17311 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
17313 break;
17314 case BNE32: /* BALC */
17315 if (ctx->insn_flags & ISA_MIPS32R6) {
17316 /* BALC */
17317 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
17318 sextract32(ctx->opcode << 1, 0, 27));
17319 } else {
17320 /* BNE32 */
17321 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
17323 break;
17324 case J32: /* BGTZC, BLTZC, BLTC */
17325 if (ctx->insn_flags & ISA_MIPS32R6) {
17326 if (rs == 0 && rt != 0) {
17327 /* BGTZC */
17328 mips32_op = OPC_BGTZC;
17329 } else if (rs != 0 && rt != 0 && rs == rt) {
17330 /* BLTZC */
17331 mips32_op = OPC_BLTZC;
17332 } else {
17333 /* BLTC */
17334 mips32_op = OPC_BLTC;
17336 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17337 } else {
17338 /* J32 */
17339 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
17340 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17342 break;
17343 case JAL32: /* BLEZC, BGEZC, BGEC */
17344 if (ctx->insn_flags & ISA_MIPS32R6) {
17345 if (rs == 0 && rt != 0) {
17346 /* BLEZC */
17347 mips32_op = OPC_BLEZC;
17348 } else if (rs != 0 && rt != 0 && rs == rt) {
17349 /* BGEZC */
17350 mips32_op = OPC_BGEZC;
17351 } else {
17352 /* BGEC */
17353 mips32_op = OPC_BGEC;
17355 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17356 } else {
17357 /* JAL32 */
17358 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
17359 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17360 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17362 break;
17363 /* Floating point (COP1) */
17364 case LWC132:
17365 mips32_op = OPC_LWC1;
17366 goto do_cop1;
17367 case LDC132:
17368 mips32_op = OPC_LDC1;
17369 goto do_cop1;
17370 case SWC132:
17371 mips32_op = OPC_SWC1;
17372 goto do_cop1;
17373 case SDC132:
17374 mips32_op = OPC_SDC1;
17375 do_cop1:
17376 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
17377 break;
17378 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17379 if (ctx->insn_flags & ISA_MIPS32R6) {
17380 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17381 switch ((ctx->opcode >> 16) & 0x1f) {
17382 case ADDIUPC_00:
17383 case ADDIUPC_01:
17384 case ADDIUPC_02:
17385 case ADDIUPC_03:
17386 case ADDIUPC_04:
17387 case ADDIUPC_05:
17388 case ADDIUPC_06:
17389 case ADDIUPC_07:
17390 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
17391 break;
17392 case AUIPC:
17393 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
17394 break;
17395 case ALUIPC:
17396 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
17397 break;
17398 case LWPC_08:
17399 case LWPC_09:
17400 case LWPC_0A:
17401 case LWPC_0B:
17402 case LWPC_0C:
17403 case LWPC_0D:
17404 case LWPC_0E:
17405 case LWPC_0F:
17406 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
17407 break;
17408 default:
17409 generate_exception(ctx, EXCP_RI);
17410 break;
17412 } else {
17413 /* ADDIUPC */
17414 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
17415 offset = SIMM(ctx->opcode, 0, 23) << 2;
17417 gen_addiupc(ctx, reg, offset, 0, 0);
17419 break;
17420 case BNVC: /* BNEC, BNEZALC */
17421 check_insn(ctx, ISA_MIPS32R6);
17422 if (rs >= rt) {
17423 /* BNVC */
17424 mips32_op = OPC_BNVC;
17425 } else if (rs < rt && rs == 0) {
17426 /* BNEZALC */
17427 mips32_op = OPC_BNEZALC;
17428 } else {
17429 /* BNEC */
17430 mips32_op = OPC_BNEC;
17432 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17433 break;
17434 case R6_BNEZC: /* JIALC */
17435 check_insn(ctx, ISA_MIPS32R6);
17436 if (rt != 0) {
17437 /* BNEZC */
17438 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
17439 sextract32(ctx->opcode << 1, 0, 22));
17440 } else {
17441 /* JIALC */
17442 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
17444 break;
17445 case R6_BEQZC: /* JIC */
17446 check_insn(ctx, ISA_MIPS32R6);
17447 if (rt != 0) {
17448 /* BEQZC */
17449 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
17450 sextract32(ctx->opcode << 1, 0, 22));
17451 } else {
17452 /* JIC */
17453 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
17455 break;
17456 case BLEZALC: /* BGEZALC, BGEUC */
17457 check_insn(ctx, ISA_MIPS32R6);
17458 if (rs == 0 && rt != 0) {
17459 /* BLEZALC */
17460 mips32_op = OPC_BLEZALC;
17461 } else if (rs != 0 && rt != 0 && rs == rt) {
17462 /* BGEZALC */
17463 mips32_op = OPC_BGEZALC;
17464 } else {
17465 /* BGEUC */
17466 mips32_op = OPC_BGEUC;
17468 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17469 break;
17470 case BGTZALC: /* BLTZALC, BLTUC */
17471 check_insn(ctx, ISA_MIPS32R6);
17472 if (rs == 0 && rt != 0) {
17473 /* BGTZALC */
17474 mips32_op = OPC_BGTZALC;
17475 } else if (rs != 0 && rt != 0 && rs == rt) {
17476 /* BLTZALC */
17477 mips32_op = OPC_BLTZALC;
17478 } else {
17479 /* BLTUC */
17480 mips32_op = OPC_BLTUC;
17482 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17483 break;
17484 /* Loads and stores */
17485 case LB32:
17486 mips32_op = OPC_LB;
17487 goto do_ld;
17488 case LBU32:
17489 mips32_op = OPC_LBU;
17490 goto do_ld;
17491 case LH32:
17492 mips32_op = OPC_LH;
17493 goto do_ld;
17494 case LHU32:
17495 mips32_op = OPC_LHU;
17496 goto do_ld;
17497 case LW32:
17498 mips32_op = OPC_LW;
17499 goto do_ld;
17500 #ifdef TARGET_MIPS64
17501 case LD32:
17502 check_insn(ctx, ISA_MIPS3);
17503 check_mips_64(ctx);
17504 mips32_op = OPC_LD;
17505 goto do_ld;
17506 case SD32:
17507 check_insn(ctx, ISA_MIPS3);
17508 check_mips_64(ctx);
17509 mips32_op = OPC_SD;
17510 goto do_st;
17511 #endif
17512 case SB32:
17513 mips32_op = OPC_SB;
17514 goto do_st;
17515 case SH32:
17516 mips32_op = OPC_SH;
17517 goto do_st;
17518 case SW32:
17519 mips32_op = OPC_SW;
17520 goto do_st;
17521 do_ld:
17522 gen_ld(ctx, mips32_op, rt, rs, imm);
17523 break;
17524 do_st:
17525 gen_st(ctx, mips32_op, rt, rs, imm);
17526 break;
17527 default:
17528 generate_exception_end(ctx, EXCP_RI);
17529 break;
17533 static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx)
17535 uint32_t op;
17537 /* make sure instructions are on a halfword boundary */
17538 if (ctx->base.pc_next & 0x1) {
17539 env->CP0_BadVAddr = ctx->base.pc_next;
17540 generate_exception_end(ctx, EXCP_AdEL);
17541 return 2;
17544 op = (ctx->opcode >> 10) & 0x3f;
17545 /* Enforce properly-sized instructions in a delay slot */
17546 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
17547 switch (op & 0x7) { /* MSB-3..MSB-5 */
17548 case 0:
17549 /* POOL32A, POOL32B, POOL32I, POOL32C */
17550 case 4:
17551 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
17552 case 5:
17553 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
17554 case 6:
17555 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
17556 case 7:
17557 /* LB32, LH32, LWC132, LDC132, LW32 */
17558 if (ctx->hflags & MIPS_HFLAG_BDS16) {
17559 generate_exception_end(ctx, EXCP_RI);
17560 return 2;
17562 break;
17563 case 1:
17564 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
17565 case 2:
17566 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
17567 case 3:
17568 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
17569 if (ctx->hflags & MIPS_HFLAG_BDS32) {
17570 generate_exception_end(ctx, EXCP_RI);
17571 return 2;
17573 break;
17577 switch (op) {
17578 case POOL16A:
17580 int rd = mmreg(uMIPS_RD(ctx->opcode));
17581 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
17582 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
17583 uint32_t opc = 0;
17585 switch (ctx->opcode & 0x1) {
17586 case ADDU16:
17587 opc = OPC_ADDU;
17588 break;
17589 case SUBU16:
17590 opc = OPC_SUBU;
17591 break;
17593 if (ctx->insn_flags & ISA_MIPS32R6) {
17595 * In the Release 6, the register number location in
17596 * the instruction encoding has changed.
17598 gen_arith(ctx, opc, rs1, rd, rs2);
17599 } else {
17600 gen_arith(ctx, opc, rd, rs1, rs2);
17603 break;
17604 case POOL16B:
17606 int rd = mmreg(uMIPS_RD(ctx->opcode));
17607 int rs = mmreg(uMIPS_RS(ctx->opcode));
17608 int amount = (ctx->opcode >> 1) & 0x7;
17609 uint32_t opc = 0;
17610 amount = amount == 0 ? 8 : amount;
17612 switch (ctx->opcode & 0x1) {
17613 case SLL16:
17614 opc = OPC_SLL;
17615 break;
17616 case SRL16:
17617 opc = OPC_SRL;
17618 break;
17621 gen_shift_imm(ctx, opc, rd, rs, amount);
17623 break;
17624 case POOL16C:
17625 if (ctx->insn_flags & ISA_MIPS32R6) {
17626 gen_pool16c_r6_insn(ctx);
17627 } else {
17628 gen_pool16c_insn(ctx);
17630 break;
17631 case LWGP16:
17633 int rd = mmreg(uMIPS_RD(ctx->opcode));
17634 int rb = 28; /* GP */
17635 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
17637 gen_ld(ctx, OPC_LW, rd, rb, offset);
17639 break;
17640 case POOL16F:
17641 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17642 if (ctx->opcode & 1) {
17643 generate_exception_end(ctx, EXCP_RI);
17644 } else {
17645 /* MOVEP */
17646 int enc_dest = uMIPS_RD(ctx->opcode);
17647 int enc_rt = uMIPS_RS2(ctx->opcode);
17648 int enc_rs = uMIPS_RS1(ctx->opcode);
17649 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
17651 break;
17652 case LBU16:
17654 int rd = mmreg(uMIPS_RD(ctx->opcode));
17655 int rb = mmreg(uMIPS_RS(ctx->opcode));
17656 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17657 offset = (offset == 0xf ? -1 : offset);
17659 gen_ld(ctx, OPC_LBU, rd, rb, offset);
17661 break;
17662 case LHU16:
17664 int rd = mmreg(uMIPS_RD(ctx->opcode));
17665 int rb = mmreg(uMIPS_RS(ctx->opcode));
17666 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17668 gen_ld(ctx, OPC_LHU, rd, rb, offset);
17670 break;
17671 case LWSP16:
17673 int rd = (ctx->opcode >> 5) & 0x1f;
17674 int rb = 29; /* SP */
17675 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17677 gen_ld(ctx, OPC_LW, rd, rb, offset);
17679 break;
17680 case LW16:
17682 int rd = mmreg(uMIPS_RD(ctx->opcode));
17683 int rb = mmreg(uMIPS_RS(ctx->opcode));
17684 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17686 gen_ld(ctx, OPC_LW, rd, rb, offset);
17688 break;
17689 case SB16:
17691 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17692 int rb = mmreg(uMIPS_RS(ctx->opcode));
17693 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17695 gen_st(ctx, OPC_SB, rd, rb, offset);
17697 break;
17698 case SH16:
17700 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17701 int rb = mmreg(uMIPS_RS(ctx->opcode));
17702 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17704 gen_st(ctx, OPC_SH, rd, rb, offset);
17706 break;
17707 case SWSP16:
17709 int rd = (ctx->opcode >> 5) & 0x1f;
17710 int rb = 29; /* SP */
17711 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17713 gen_st(ctx, OPC_SW, rd, rb, offset);
17715 break;
17716 case SW16:
17718 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17719 int rb = mmreg(uMIPS_RS(ctx->opcode));
17720 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17722 gen_st(ctx, OPC_SW, rd, rb, offset);
17724 break;
17725 case MOVE16:
17727 int rd = uMIPS_RD5(ctx->opcode);
17728 int rs = uMIPS_RS5(ctx->opcode);
17730 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
17732 break;
17733 case ANDI16:
17734 gen_andi16(ctx);
17735 break;
17736 case POOL16D:
17737 switch (ctx->opcode & 0x1) {
17738 case ADDIUS5:
17739 gen_addius5(ctx);
17740 break;
17741 case ADDIUSP:
17742 gen_addiusp(ctx);
17743 break;
17745 break;
17746 case POOL16E:
17747 switch (ctx->opcode & 0x1) {
17748 case ADDIUR2:
17749 gen_addiur2(ctx);
17750 break;
17751 case ADDIUR1SP:
17752 gen_addiur1sp(ctx);
17753 break;
17755 break;
17756 case B16: /* BC16 */
17757 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
17758 sextract32(ctx->opcode, 0, 10) << 1,
17759 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17760 break;
17761 case BNEZ16: /* BNEZC16 */
17762 case BEQZ16: /* BEQZC16 */
17763 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
17764 mmreg(uMIPS_RD(ctx->opcode)),
17765 0, sextract32(ctx->opcode, 0, 7) << 1,
17766 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17768 break;
17769 case LI16:
17771 int reg = mmreg(uMIPS_RD(ctx->opcode));
17772 int imm = ZIMM(ctx->opcode, 0, 7);
17774 imm = (imm == 0x7f ? -1 : imm);
17775 tcg_gen_movi_tl(cpu_gpr[reg], imm);
17777 break;
17778 case RES_29:
17779 case RES_31:
17780 case RES_39:
17781 generate_exception_end(ctx, EXCP_RI);
17782 break;
17783 default:
17784 decode_micromips32_opc(env, ctx);
17785 return 4;
17788 return 2;
17793 * nanoMIPS opcodes
17797 /* MAJOR, P16, and P32 pools opcodes */
17798 enum {
17799 NM_P_ADDIU = 0x00,
17800 NM_ADDIUPC = 0x01,
17801 NM_MOVE_BALC = 0x02,
17802 NM_P16_MV = 0x04,
17803 NM_LW16 = 0x05,
17804 NM_BC16 = 0x06,
17805 NM_P16_SR = 0x07,
17807 NM_POOL32A = 0x08,
17808 NM_P_BAL = 0x0a,
17809 NM_P16_SHIFT = 0x0c,
17810 NM_LWSP16 = 0x0d,
17811 NM_BALC16 = 0x0e,
17812 NM_P16_4X4 = 0x0f,
17814 NM_P_GP_W = 0x10,
17815 NM_P_GP_BH = 0x11,
17816 NM_P_J = 0x12,
17817 NM_P16C = 0x14,
17818 NM_LWGP16 = 0x15,
17819 NM_P16_LB = 0x17,
17821 NM_P48I = 0x18,
17822 NM_P16_A1 = 0x1c,
17823 NM_LW4X4 = 0x1d,
17824 NM_P16_LH = 0x1f,
17826 NM_P_U12 = 0x20,
17827 NM_P_LS_U12 = 0x21,
17828 NM_P_BR1 = 0x22,
17829 NM_P16_A2 = 0x24,
17830 NM_SW16 = 0x25,
17831 NM_BEQZC16 = 0x26,
17833 NM_POOL32F = 0x28,
17834 NM_P_LS_S9 = 0x29,
17835 NM_P_BR2 = 0x2a,
17837 NM_P16_ADDU = 0x2c,
17838 NM_SWSP16 = 0x2d,
17839 NM_BNEZC16 = 0x2e,
17840 NM_MOVEP = 0x2f,
17842 NM_POOL32S = 0x30,
17843 NM_P_BRI = 0x32,
17844 NM_LI16 = 0x34,
17845 NM_SWGP16 = 0x35,
17846 NM_P16_BR = 0x36,
17848 NM_P_LUI = 0x38,
17849 NM_ANDI16 = 0x3c,
17850 NM_SW4X4 = 0x3d,
17851 NM_MOVEPREV = 0x3f,
17854 /* POOL32A instruction pool */
17855 enum {
17856 NM_POOL32A0 = 0x00,
17857 NM_SPECIAL2 = 0x01,
17858 NM_COP2_1 = 0x02,
17859 NM_UDI = 0x03,
17860 NM_POOL32A5 = 0x05,
17861 NM_POOL32A7 = 0x07,
17864 /* P.GP.W instruction pool */
17865 enum {
17866 NM_ADDIUGP_W = 0x00,
17867 NM_LWGP = 0x02,
17868 NM_SWGP = 0x03,
17871 /* P48I instruction pool */
17872 enum {
17873 NM_LI48 = 0x00,
17874 NM_ADDIU48 = 0x01,
17875 NM_ADDIUGP48 = 0x02,
17876 NM_ADDIUPC48 = 0x03,
17877 NM_LWPC48 = 0x0b,
17878 NM_SWPC48 = 0x0f,
17881 /* P.U12 instruction pool */
17882 enum {
17883 NM_ORI = 0x00,
17884 NM_XORI = 0x01,
17885 NM_ANDI = 0x02,
17886 NM_P_SR = 0x03,
17887 NM_SLTI = 0x04,
17888 NM_SLTIU = 0x05,
17889 NM_SEQI = 0x06,
17890 NM_ADDIUNEG = 0x08,
17891 NM_P_SHIFT = 0x0c,
17892 NM_P_ROTX = 0x0d,
17893 NM_P_INS = 0x0e,
17894 NM_P_EXT = 0x0f,
17897 /* POOL32F instruction pool */
17898 enum {
17899 NM_POOL32F_0 = 0x00,
17900 NM_POOL32F_3 = 0x03,
17901 NM_POOL32F_5 = 0x05,
17904 /* POOL32S instruction pool */
17905 enum {
17906 NM_POOL32S_0 = 0x00,
17907 NM_POOL32S_4 = 0x04,
17910 /* P.LUI instruction pool */
17911 enum {
17912 NM_LUI = 0x00,
17913 NM_ALUIPC = 0x01,
17916 /* P.GP.BH instruction pool */
17917 enum {
17918 NM_LBGP = 0x00,
17919 NM_SBGP = 0x01,
17920 NM_LBUGP = 0x02,
17921 NM_ADDIUGP_B = 0x03,
17922 NM_P_GP_LH = 0x04,
17923 NM_P_GP_SH = 0x05,
17924 NM_P_GP_CP1 = 0x06,
17927 /* P.LS.U12 instruction pool */
17928 enum {
17929 NM_LB = 0x00,
17930 NM_SB = 0x01,
17931 NM_LBU = 0x02,
17932 NM_P_PREFU12 = 0x03,
17933 NM_LH = 0x04,
17934 NM_SH = 0x05,
17935 NM_LHU = 0x06,
17936 NM_LWU = 0x07,
17937 NM_LW = 0x08,
17938 NM_SW = 0x09,
17939 NM_LWC1 = 0x0a,
17940 NM_SWC1 = 0x0b,
17941 NM_LDC1 = 0x0e,
17942 NM_SDC1 = 0x0f,
17945 /* P.LS.S9 instruction pool */
17946 enum {
17947 NM_P_LS_S0 = 0x00,
17948 NM_P_LS_S1 = 0x01,
17949 NM_P_LS_E0 = 0x02,
17950 NM_P_LS_WM = 0x04,
17951 NM_P_LS_UAWM = 0x05,
17954 /* P.BAL instruction pool */
17955 enum {
17956 NM_BC = 0x00,
17957 NM_BALC = 0x01,
17960 /* P.J instruction pool */
17961 enum {
17962 NM_JALRC = 0x00,
17963 NM_JALRC_HB = 0x01,
17964 NM_P_BALRSC = 0x08,
17967 /* P.BR1 instruction pool */
17968 enum {
17969 NM_BEQC = 0x00,
17970 NM_P_BR3A = 0x01,
17971 NM_BGEC = 0x02,
17972 NM_BGEUC = 0x03,
17975 /* P.BR2 instruction pool */
17976 enum {
17977 NM_BNEC = 0x00,
17978 NM_BLTC = 0x02,
17979 NM_BLTUC = 0x03,
17982 /* P.BRI instruction pool */
17983 enum {
17984 NM_BEQIC = 0x00,
17985 NM_BBEQZC = 0x01,
17986 NM_BGEIC = 0x02,
17987 NM_BGEIUC = 0x03,
17988 NM_BNEIC = 0x04,
17989 NM_BBNEZC = 0x05,
17990 NM_BLTIC = 0x06,
17991 NM_BLTIUC = 0x07,
17994 /* P16.SHIFT instruction pool */
17995 enum {
17996 NM_SLL16 = 0x00,
17997 NM_SRL16 = 0x01,
18000 /* POOL16C instruction pool */
18001 enum {
18002 NM_POOL16C_0 = 0x00,
18003 NM_LWXS16 = 0x01,
18006 /* P16.A1 instruction pool */
18007 enum {
18008 NM_ADDIUR1SP = 0x01,
18011 /* P16.A2 instruction pool */
18012 enum {
18013 NM_ADDIUR2 = 0x00,
18014 NM_P_ADDIURS5 = 0x01,
18017 /* P16.ADDU instruction pool */
18018 enum {
18019 NM_ADDU16 = 0x00,
18020 NM_SUBU16 = 0x01,
18023 /* P16.SR instruction pool */
18024 enum {
18025 NM_SAVE16 = 0x00,
18026 NM_RESTORE_JRC16 = 0x01,
18029 /* P16.4X4 instruction pool */
18030 enum {
18031 NM_ADDU4X4 = 0x00,
18032 NM_MUL4X4 = 0x01,
18035 /* P16.LB instruction pool */
18036 enum {
18037 NM_LB16 = 0x00,
18038 NM_SB16 = 0x01,
18039 NM_LBU16 = 0x02,
18042 /* P16.LH instruction pool */
18043 enum {
18044 NM_LH16 = 0x00,
18045 NM_SH16 = 0x01,
18046 NM_LHU16 = 0x02,
18049 /* P.RI instruction pool */
18050 enum {
18051 NM_SIGRIE = 0x00,
18052 NM_P_SYSCALL = 0x01,
18053 NM_BREAK = 0x02,
18054 NM_SDBBP = 0x03,
18057 /* POOL32A0 instruction pool */
18058 enum {
18059 NM_P_TRAP = 0x00,
18060 NM_SEB = 0x01,
18061 NM_SLLV = 0x02,
18062 NM_MUL = 0x03,
18063 NM_MFC0 = 0x06,
18064 NM_MFHC0 = 0x07,
18065 NM_SEH = 0x09,
18066 NM_SRLV = 0x0a,
18067 NM_MUH = 0x0b,
18068 NM_MTC0 = 0x0e,
18069 NM_MTHC0 = 0x0f,
18070 NM_SRAV = 0x12,
18071 NM_MULU = 0x13,
18072 NM_ROTRV = 0x1a,
18073 NM_MUHU = 0x1b,
18074 NM_ADD = 0x22,
18075 NM_DIV = 0x23,
18076 NM_ADDU = 0x2a,
18077 NM_MOD = 0x2b,
18078 NM_SUB = 0x32,
18079 NM_DIVU = 0x33,
18080 NM_RDHWR = 0x38,
18081 NM_SUBU = 0x3a,
18082 NM_MODU = 0x3b,
18083 NM_P_CMOVE = 0x42,
18084 NM_FORK = 0x45,
18085 NM_MFTR = 0x46,
18086 NM_MFHTR = 0x47,
18087 NM_AND = 0x4a,
18088 NM_YIELD = 0x4d,
18089 NM_MTTR = 0x4e,
18090 NM_MTHTR = 0x4f,
18091 NM_OR = 0x52,
18092 NM_D_E_MT_VPE = 0x56,
18093 NM_NOR = 0x5a,
18094 NM_XOR = 0x62,
18095 NM_SLT = 0x6a,
18096 NM_P_SLTU = 0x72,
18097 NM_SOV = 0x7a,
18100 /* CRC32 instruction pool */
18101 enum {
18102 NM_CRC32B = 0x00,
18103 NM_CRC32H = 0x01,
18104 NM_CRC32W = 0x02,
18105 NM_CRC32CB = 0x04,
18106 NM_CRC32CH = 0x05,
18107 NM_CRC32CW = 0x06,
18110 /* POOL32A5 instruction pool */
18111 enum {
18112 NM_CMP_EQ_PH = 0x00,
18113 NM_CMP_LT_PH = 0x08,
18114 NM_CMP_LE_PH = 0x10,
18115 NM_CMPGU_EQ_QB = 0x18,
18116 NM_CMPGU_LT_QB = 0x20,
18117 NM_CMPGU_LE_QB = 0x28,
18118 NM_CMPGDU_EQ_QB = 0x30,
18119 NM_CMPGDU_LT_QB = 0x38,
18120 NM_CMPGDU_LE_QB = 0x40,
18121 NM_CMPU_EQ_QB = 0x48,
18122 NM_CMPU_LT_QB = 0x50,
18123 NM_CMPU_LE_QB = 0x58,
18124 NM_ADDQ_S_W = 0x60,
18125 NM_SUBQ_S_W = 0x68,
18126 NM_ADDSC = 0x70,
18127 NM_ADDWC = 0x78,
18129 NM_ADDQ_S_PH = 0x01,
18130 NM_ADDQH_R_PH = 0x09,
18131 NM_ADDQH_R_W = 0x11,
18132 NM_ADDU_S_QB = 0x19,
18133 NM_ADDU_S_PH = 0x21,
18134 NM_ADDUH_R_QB = 0x29,
18135 NM_SHRAV_R_PH = 0x31,
18136 NM_SHRAV_R_QB = 0x39,
18137 NM_SUBQ_S_PH = 0x41,
18138 NM_SUBQH_R_PH = 0x49,
18139 NM_SUBQH_R_W = 0x51,
18140 NM_SUBU_S_QB = 0x59,
18141 NM_SUBU_S_PH = 0x61,
18142 NM_SUBUH_R_QB = 0x69,
18143 NM_SHLLV_S_PH = 0x71,
18144 NM_PRECR_SRA_R_PH_W = 0x79,
18146 NM_MULEU_S_PH_QBL = 0x12,
18147 NM_MULEU_S_PH_QBR = 0x1a,
18148 NM_MULQ_RS_PH = 0x22,
18149 NM_MULQ_S_PH = 0x2a,
18150 NM_MULQ_RS_W = 0x32,
18151 NM_MULQ_S_W = 0x3a,
18152 NM_APPEND = 0x42,
18153 NM_MODSUB = 0x52,
18154 NM_SHRAV_R_W = 0x5a,
18155 NM_SHRLV_PH = 0x62,
18156 NM_SHRLV_QB = 0x6a,
18157 NM_SHLLV_QB = 0x72,
18158 NM_SHLLV_S_W = 0x7a,
18160 NM_SHILO = 0x03,
18162 NM_MULEQ_S_W_PHL = 0x04,
18163 NM_MULEQ_S_W_PHR = 0x0c,
18165 NM_MUL_S_PH = 0x05,
18166 NM_PRECR_QB_PH = 0x0d,
18167 NM_PRECRQ_QB_PH = 0x15,
18168 NM_PRECRQ_PH_W = 0x1d,
18169 NM_PRECRQ_RS_PH_W = 0x25,
18170 NM_PRECRQU_S_QB_PH = 0x2d,
18171 NM_PACKRL_PH = 0x35,
18172 NM_PICK_QB = 0x3d,
18173 NM_PICK_PH = 0x45,
18175 NM_SHRA_R_W = 0x5e,
18176 NM_SHRA_R_PH = 0x66,
18177 NM_SHLL_S_PH = 0x76,
18178 NM_SHLL_S_W = 0x7e,
18180 NM_REPL_PH = 0x07
18183 /* POOL32A7 instruction pool */
18184 enum {
18185 NM_P_LSX = 0x00,
18186 NM_LSA = 0x01,
18187 NM_EXTW = 0x03,
18188 NM_POOL32AXF = 0x07,
18191 /* P.SR instruction pool */
18192 enum {
18193 NM_PP_SR = 0x00,
18194 NM_P_SR_F = 0x01,
18197 /* P.SHIFT instruction pool */
18198 enum {
18199 NM_P_SLL = 0x00,
18200 NM_SRL = 0x02,
18201 NM_SRA = 0x04,
18202 NM_ROTR = 0x06,
18205 /* P.ROTX instruction pool */
18206 enum {
18207 NM_ROTX = 0x00,
18210 /* P.INS instruction pool */
18211 enum {
18212 NM_INS = 0x00,
18215 /* P.EXT instruction pool */
18216 enum {
18217 NM_EXT = 0x00,
18220 /* POOL32F_0 (fmt) instruction pool */
18221 enum {
18222 NM_RINT_S = 0x04,
18223 NM_RINT_D = 0x44,
18224 NM_ADD_S = 0x06,
18225 NM_SELEQZ_S = 0x07,
18226 NM_SELEQZ_D = 0x47,
18227 NM_CLASS_S = 0x0c,
18228 NM_CLASS_D = 0x4c,
18229 NM_SUB_S = 0x0e,
18230 NM_SELNEZ_S = 0x0f,
18231 NM_SELNEZ_D = 0x4f,
18232 NM_MUL_S = 0x16,
18233 NM_SEL_S = 0x17,
18234 NM_SEL_D = 0x57,
18235 NM_DIV_S = 0x1e,
18236 NM_ADD_D = 0x26,
18237 NM_SUB_D = 0x2e,
18238 NM_MUL_D = 0x36,
18239 NM_MADDF_S = 0x37,
18240 NM_MADDF_D = 0x77,
18241 NM_DIV_D = 0x3e,
18242 NM_MSUBF_S = 0x3f,
18243 NM_MSUBF_D = 0x7f,
18246 /* POOL32F_3 instruction pool */
18247 enum {
18248 NM_MIN_FMT = 0x00,
18249 NM_MAX_FMT = 0x01,
18250 NM_MINA_FMT = 0x04,
18251 NM_MAXA_FMT = 0x05,
18252 NM_POOL32FXF = 0x07,
18255 /* POOL32F_5 instruction pool */
18256 enum {
18257 NM_CMP_CONDN_S = 0x00,
18258 NM_CMP_CONDN_D = 0x02,
18261 /* P.GP.LH instruction pool */
18262 enum {
18263 NM_LHGP = 0x00,
18264 NM_LHUGP = 0x01,
18267 /* P.GP.SH instruction pool */
18268 enum {
18269 NM_SHGP = 0x00,
18272 /* P.GP.CP1 instruction pool */
18273 enum {
18274 NM_LWC1GP = 0x00,
18275 NM_SWC1GP = 0x01,
18276 NM_LDC1GP = 0x02,
18277 NM_SDC1GP = 0x03,
18280 /* P.LS.S0 instruction pool */
18281 enum {
18282 NM_LBS9 = 0x00,
18283 NM_LHS9 = 0x04,
18284 NM_LWS9 = 0x08,
18285 NM_LDS9 = 0x0c,
18287 NM_SBS9 = 0x01,
18288 NM_SHS9 = 0x05,
18289 NM_SWS9 = 0x09,
18290 NM_SDS9 = 0x0d,
18292 NM_LBUS9 = 0x02,
18293 NM_LHUS9 = 0x06,
18294 NM_LWC1S9 = 0x0a,
18295 NM_LDC1S9 = 0x0e,
18297 NM_P_PREFS9 = 0x03,
18298 NM_LWUS9 = 0x07,
18299 NM_SWC1S9 = 0x0b,
18300 NM_SDC1S9 = 0x0f,
18303 /* P.LS.S1 instruction pool */
18304 enum {
18305 NM_ASET_ACLR = 0x02,
18306 NM_UALH = 0x04,
18307 NM_UASH = 0x05,
18308 NM_CACHE = 0x07,
18309 NM_P_LL = 0x0a,
18310 NM_P_SC = 0x0b,
18313 /* P.LS.E0 instruction pool */
18314 enum {
18315 NM_LBE = 0x00,
18316 NM_SBE = 0x01,
18317 NM_LBUE = 0x02,
18318 NM_P_PREFE = 0x03,
18319 NM_LHE = 0x04,
18320 NM_SHE = 0x05,
18321 NM_LHUE = 0x06,
18322 NM_CACHEE = 0x07,
18323 NM_LWE = 0x08,
18324 NM_SWE = 0x09,
18325 NM_P_LLE = 0x0a,
18326 NM_P_SCE = 0x0b,
18329 /* P.PREFE instruction pool */
18330 enum {
18331 NM_SYNCIE = 0x00,
18332 NM_PREFE = 0x01,
18335 /* P.LLE instruction pool */
18336 enum {
18337 NM_LLE = 0x00,
18338 NM_LLWPE = 0x01,
18341 /* P.SCE instruction pool */
18342 enum {
18343 NM_SCE = 0x00,
18344 NM_SCWPE = 0x01,
18347 /* P.LS.WM instruction pool */
18348 enum {
18349 NM_LWM = 0x00,
18350 NM_SWM = 0x01,
18353 /* P.LS.UAWM instruction pool */
18354 enum {
18355 NM_UALWM = 0x00,
18356 NM_UASWM = 0x01,
18359 /* P.BR3A instruction pool */
18360 enum {
18361 NM_BC1EQZC = 0x00,
18362 NM_BC1NEZC = 0x01,
18363 NM_BC2EQZC = 0x02,
18364 NM_BC2NEZC = 0x03,
18365 NM_BPOSGE32C = 0x04,
18368 /* P16.RI instruction pool */
18369 enum {
18370 NM_P16_SYSCALL = 0x01,
18371 NM_BREAK16 = 0x02,
18372 NM_SDBBP16 = 0x03,
18375 /* POOL16C_0 instruction pool */
18376 enum {
18377 NM_POOL16C_00 = 0x00,
18380 /* P16.JRC instruction pool */
18381 enum {
18382 NM_JRC = 0x00,
18383 NM_JALRC16 = 0x01,
18386 /* P.SYSCALL instruction pool */
18387 enum {
18388 NM_SYSCALL = 0x00,
18389 NM_HYPCALL = 0x01,
18392 /* P.TRAP instruction pool */
18393 enum {
18394 NM_TEQ = 0x00,
18395 NM_TNE = 0x01,
18398 /* P.CMOVE instruction pool */
18399 enum {
18400 NM_MOVZ = 0x00,
18401 NM_MOVN = 0x01,
18404 /* POOL32Axf instruction pool */
18405 enum {
18406 NM_POOL32AXF_1 = 0x01,
18407 NM_POOL32AXF_2 = 0x02,
18408 NM_POOL32AXF_4 = 0x04,
18409 NM_POOL32AXF_5 = 0x05,
18410 NM_POOL32AXF_7 = 0x07,
18413 /* POOL32Axf_1 instruction pool */
18414 enum {
18415 NM_POOL32AXF_1_0 = 0x00,
18416 NM_POOL32AXF_1_1 = 0x01,
18417 NM_POOL32AXF_1_3 = 0x03,
18418 NM_POOL32AXF_1_4 = 0x04,
18419 NM_POOL32AXF_1_5 = 0x05,
18420 NM_POOL32AXF_1_7 = 0x07,
18423 /* POOL32Axf_2 instruction pool */
18424 enum {
18425 NM_POOL32AXF_2_0_7 = 0x00,
18426 NM_POOL32AXF_2_8_15 = 0x01,
18427 NM_POOL32AXF_2_16_23 = 0x02,
18428 NM_POOL32AXF_2_24_31 = 0x03,
18431 /* POOL32Axf_7 instruction pool */
18432 enum {
18433 NM_SHRA_R_QB = 0x0,
18434 NM_SHRL_PH = 0x1,
18435 NM_REPL_QB = 0x2,
18438 /* POOL32Axf_1_0 instruction pool */
18439 enum {
18440 NM_MFHI = 0x0,
18441 NM_MFLO = 0x1,
18442 NM_MTHI = 0x2,
18443 NM_MTLO = 0x3,
18446 /* POOL32Axf_1_1 instruction pool */
18447 enum {
18448 NM_MTHLIP = 0x0,
18449 NM_SHILOV = 0x1,
18452 /* POOL32Axf_1_3 instruction pool */
18453 enum {
18454 NM_RDDSP = 0x0,
18455 NM_WRDSP = 0x1,
18456 NM_EXTP = 0x2,
18457 NM_EXTPDP = 0x3,
18460 /* POOL32Axf_1_4 instruction pool */
18461 enum {
18462 NM_SHLL_QB = 0x0,
18463 NM_SHRL_QB = 0x1,
18466 /* POOL32Axf_1_5 instruction pool */
18467 enum {
18468 NM_MAQ_S_W_PHR = 0x0,
18469 NM_MAQ_S_W_PHL = 0x1,
18470 NM_MAQ_SA_W_PHR = 0x2,
18471 NM_MAQ_SA_W_PHL = 0x3,
18474 /* POOL32Axf_1_7 instruction pool */
18475 enum {
18476 NM_EXTR_W = 0x0,
18477 NM_EXTR_R_W = 0x1,
18478 NM_EXTR_RS_W = 0x2,
18479 NM_EXTR_S_H = 0x3,
18482 /* POOL32Axf_2_0_7 instruction pool */
18483 enum {
18484 NM_DPA_W_PH = 0x0,
18485 NM_DPAQ_S_W_PH = 0x1,
18486 NM_DPS_W_PH = 0x2,
18487 NM_DPSQ_S_W_PH = 0x3,
18488 NM_BALIGN = 0x4,
18489 NM_MADD = 0x5,
18490 NM_MULT = 0x6,
18491 NM_EXTRV_W = 0x7,
18494 /* POOL32Axf_2_8_15 instruction pool */
18495 enum {
18496 NM_DPAX_W_PH = 0x0,
18497 NM_DPAQ_SA_L_W = 0x1,
18498 NM_DPSX_W_PH = 0x2,
18499 NM_DPSQ_SA_L_W = 0x3,
18500 NM_MADDU = 0x5,
18501 NM_MULTU = 0x6,
18502 NM_EXTRV_R_W = 0x7,
18505 /* POOL32Axf_2_16_23 instruction pool */
18506 enum {
18507 NM_DPAU_H_QBL = 0x0,
18508 NM_DPAQX_S_W_PH = 0x1,
18509 NM_DPSU_H_QBL = 0x2,
18510 NM_DPSQX_S_W_PH = 0x3,
18511 NM_EXTPV = 0x4,
18512 NM_MSUB = 0x5,
18513 NM_MULSA_W_PH = 0x6,
18514 NM_EXTRV_RS_W = 0x7,
18517 /* POOL32Axf_2_24_31 instruction pool */
18518 enum {
18519 NM_DPAU_H_QBR = 0x0,
18520 NM_DPAQX_SA_W_PH = 0x1,
18521 NM_DPSU_H_QBR = 0x2,
18522 NM_DPSQX_SA_W_PH = 0x3,
18523 NM_EXTPDPV = 0x4,
18524 NM_MSUBU = 0x5,
18525 NM_MULSAQ_S_W_PH = 0x6,
18526 NM_EXTRV_S_H = 0x7,
18529 /* POOL32Axf_{4, 5} instruction pool */
18530 enum {
18531 NM_CLO = 0x25,
18532 NM_CLZ = 0x2d,
18534 NM_TLBP = 0x01,
18535 NM_TLBR = 0x09,
18536 NM_TLBWI = 0x11,
18537 NM_TLBWR = 0x19,
18538 NM_TLBINV = 0x03,
18539 NM_TLBINVF = 0x0b,
18540 NM_DI = 0x23,
18541 NM_EI = 0x2b,
18542 NM_RDPGPR = 0x70,
18543 NM_WRPGPR = 0x78,
18544 NM_WAIT = 0x61,
18545 NM_DERET = 0x71,
18546 NM_ERETX = 0x79,
18548 /* nanoMIPS DSP instructions */
18549 NM_ABSQ_S_QB = 0x00,
18550 NM_ABSQ_S_PH = 0x08,
18551 NM_ABSQ_S_W = 0x10,
18552 NM_PRECEQ_W_PHL = 0x28,
18553 NM_PRECEQ_W_PHR = 0x30,
18554 NM_PRECEQU_PH_QBL = 0x38,
18555 NM_PRECEQU_PH_QBR = 0x48,
18556 NM_PRECEU_PH_QBL = 0x58,
18557 NM_PRECEU_PH_QBR = 0x68,
18558 NM_PRECEQU_PH_QBLA = 0x39,
18559 NM_PRECEQU_PH_QBRA = 0x49,
18560 NM_PRECEU_PH_QBLA = 0x59,
18561 NM_PRECEU_PH_QBRA = 0x69,
18562 NM_REPLV_PH = 0x01,
18563 NM_REPLV_QB = 0x09,
18564 NM_BITREV = 0x18,
18565 NM_INSV = 0x20,
18566 NM_RADDU_W_QB = 0x78,
18568 NM_BITSWAP = 0x05,
18569 NM_WSBH = 0x3d,
18572 /* PP.SR instruction pool */
18573 enum {
18574 NM_SAVE = 0x00,
18575 NM_RESTORE = 0x02,
18576 NM_RESTORE_JRC = 0x03,
18579 /* P.SR.F instruction pool */
18580 enum {
18581 NM_SAVEF = 0x00,
18582 NM_RESTOREF = 0x01,
18585 /* P16.SYSCALL instruction pool */
18586 enum {
18587 NM_SYSCALL16 = 0x00,
18588 NM_HYPCALL16 = 0x01,
18591 /* POOL16C_00 instruction pool */
18592 enum {
18593 NM_NOT16 = 0x00,
18594 NM_XOR16 = 0x01,
18595 NM_AND16 = 0x02,
18596 NM_OR16 = 0x03,
18599 /* PP.LSX and PP.LSXS instruction pool */
18600 enum {
18601 NM_LBX = 0x00,
18602 NM_LHX = 0x04,
18603 NM_LWX = 0x08,
18604 NM_LDX = 0x0c,
18606 NM_SBX = 0x01,
18607 NM_SHX = 0x05,
18608 NM_SWX = 0x09,
18609 NM_SDX = 0x0d,
18611 NM_LBUX = 0x02,
18612 NM_LHUX = 0x06,
18613 NM_LWC1X = 0x0a,
18614 NM_LDC1X = 0x0e,
18616 NM_LWUX = 0x07,
18617 NM_SWC1X = 0x0b,
18618 NM_SDC1X = 0x0f,
18620 NM_LHXS = 0x04,
18621 NM_LWXS = 0x08,
18622 NM_LDXS = 0x0c,
18624 NM_SHXS = 0x05,
18625 NM_SWXS = 0x09,
18626 NM_SDXS = 0x0d,
18628 NM_LHUXS = 0x06,
18629 NM_LWC1XS = 0x0a,
18630 NM_LDC1XS = 0x0e,
18632 NM_LWUXS = 0x07,
18633 NM_SWC1XS = 0x0b,
18634 NM_SDC1XS = 0x0f,
18637 /* ERETx instruction pool */
18638 enum {
18639 NM_ERET = 0x00,
18640 NM_ERETNC = 0x01,
18643 /* POOL32FxF_{0, 1} insturction pool */
18644 enum {
18645 NM_CFC1 = 0x40,
18646 NM_CTC1 = 0x60,
18647 NM_MFC1 = 0x80,
18648 NM_MTC1 = 0xa0,
18649 NM_MFHC1 = 0xc0,
18650 NM_MTHC1 = 0xe0,
18652 NM_CVT_S_PL = 0x84,
18653 NM_CVT_S_PU = 0xa4,
18655 NM_CVT_L_S = 0x004,
18656 NM_CVT_L_D = 0x104,
18657 NM_CVT_W_S = 0x024,
18658 NM_CVT_W_D = 0x124,
18660 NM_RSQRT_S = 0x008,
18661 NM_RSQRT_D = 0x108,
18663 NM_SQRT_S = 0x028,
18664 NM_SQRT_D = 0x128,
18666 NM_RECIP_S = 0x048,
18667 NM_RECIP_D = 0x148,
18669 NM_FLOOR_L_S = 0x00c,
18670 NM_FLOOR_L_D = 0x10c,
18672 NM_FLOOR_W_S = 0x02c,
18673 NM_FLOOR_W_D = 0x12c,
18675 NM_CEIL_L_S = 0x04c,
18676 NM_CEIL_L_D = 0x14c,
18677 NM_CEIL_W_S = 0x06c,
18678 NM_CEIL_W_D = 0x16c,
18679 NM_TRUNC_L_S = 0x08c,
18680 NM_TRUNC_L_D = 0x18c,
18681 NM_TRUNC_W_S = 0x0ac,
18682 NM_TRUNC_W_D = 0x1ac,
18683 NM_ROUND_L_S = 0x0cc,
18684 NM_ROUND_L_D = 0x1cc,
18685 NM_ROUND_W_S = 0x0ec,
18686 NM_ROUND_W_D = 0x1ec,
18688 NM_MOV_S = 0x01,
18689 NM_MOV_D = 0x81,
18690 NM_ABS_S = 0x0d,
18691 NM_ABS_D = 0x8d,
18692 NM_NEG_S = 0x2d,
18693 NM_NEG_D = 0xad,
18694 NM_CVT_D_S = 0x04d,
18695 NM_CVT_D_W = 0x0cd,
18696 NM_CVT_D_L = 0x14d,
18697 NM_CVT_S_D = 0x06d,
18698 NM_CVT_S_W = 0x0ed,
18699 NM_CVT_S_L = 0x16d,
18702 /* P.LL instruction pool */
18703 enum {
18704 NM_LL = 0x00,
18705 NM_LLWP = 0x01,
18708 /* P.SC instruction pool */
18709 enum {
18710 NM_SC = 0x00,
18711 NM_SCWP = 0x01,
18714 /* P.DVP instruction pool */
18715 enum {
18716 NM_DVP = 0x00,
18717 NM_EVP = 0x01,
18723 * nanoMIPS decoding engine
18728 /* extraction utilities */
18730 #define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7)
18731 #define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7)
18732 #define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7)
18733 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18734 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18736 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
18737 static inline int decode_gpr_gpr3(int r)
18739 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
18741 return map[r & 0x7];
18744 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
18745 static inline int decode_gpr_gpr3_src_store(int r)
18747 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
18749 return map[r & 0x7];
18752 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
18753 static inline int decode_gpr_gpr4(int r)
18755 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
18756 16, 17, 18, 19, 20, 21, 22, 23 };
18758 return map[r & 0xf];
18761 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
18762 static inline int decode_gpr_gpr4_zero(int r)
18764 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
18765 16, 17, 18, 19, 20, 21, 22, 23 };
18767 return map[r & 0xf];
18771 static void gen_adjust_sp(DisasContext *ctx, int u)
18773 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
18776 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
18777 uint8_t gp, uint16_t u)
18779 int counter = 0;
18780 TCGv va = tcg_temp_new();
18781 TCGv t0 = tcg_temp_new();
18783 while (counter != count) {
18784 bool use_gp = gp && (counter == count - 1);
18785 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18786 int this_offset = -((counter + 1) << 2);
18787 gen_base_offset_addr(ctx, va, 29, this_offset);
18788 gen_load_gpr(t0, this_rt);
18789 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
18790 (MO_TEUL | ctx->default_tcg_memop_mask));
18791 counter++;
18794 /* adjust stack pointer */
18795 gen_adjust_sp(ctx, -u);
18797 tcg_temp_free(t0);
18798 tcg_temp_free(va);
18801 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
18802 uint8_t gp, uint16_t u)
18804 int counter = 0;
18805 TCGv va = tcg_temp_new();
18806 TCGv t0 = tcg_temp_new();
18808 while (counter != count) {
18809 bool use_gp = gp && (counter == count - 1);
18810 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18811 int this_offset = u - ((counter + 1) << 2);
18812 gen_base_offset_addr(ctx, va, 29, this_offset);
18813 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
18814 ctx->default_tcg_memop_mask);
18815 tcg_gen_ext32s_tl(t0, t0);
18816 gen_store_gpr(t0, this_rt);
18817 counter++;
18820 /* adjust stack pointer */
18821 gen_adjust_sp(ctx, u);
18823 tcg_temp_free(t0);
18824 tcg_temp_free(va);
18827 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
18829 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
18830 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
18832 switch (extract32(ctx->opcode, 2, 2)) {
18833 case NM_NOT16:
18834 gen_logic(ctx, OPC_NOR, rt, rs, 0);
18835 break;
18836 case NM_AND16:
18837 gen_logic(ctx, OPC_AND, rt, rt, rs);
18838 break;
18839 case NM_XOR16:
18840 gen_logic(ctx, OPC_XOR, rt, rt, rs);
18841 break;
18842 case NM_OR16:
18843 gen_logic(ctx, OPC_OR, rt, rt, rs);
18844 break;
18848 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18850 int rt = extract32(ctx->opcode, 21, 5);
18851 int rs = extract32(ctx->opcode, 16, 5);
18852 int rd = extract32(ctx->opcode, 11, 5);
18854 switch (extract32(ctx->opcode, 3, 7)) {
18855 case NM_P_TRAP:
18856 switch (extract32(ctx->opcode, 10, 1)) {
18857 case NM_TEQ:
18858 check_nms(ctx);
18859 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
18860 break;
18861 case NM_TNE:
18862 check_nms(ctx);
18863 gen_trap(ctx, OPC_TNE, rs, rt, -1);
18864 break;
18866 break;
18867 case NM_RDHWR:
18868 check_nms(ctx);
18869 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
18870 break;
18871 case NM_SEB:
18872 check_nms(ctx);
18873 gen_bshfl(ctx, OPC_SEB, rs, rt);
18874 break;
18875 case NM_SEH:
18876 gen_bshfl(ctx, OPC_SEH, rs, rt);
18877 break;
18878 case NM_SLLV:
18879 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
18880 break;
18881 case NM_SRLV:
18882 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
18883 break;
18884 case NM_SRAV:
18885 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
18886 break;
18887 case NM_ROTRV:
18888 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
18889 break;
18890 case NM_ADD:
18891 gen_arith(ctx, OPC_ADD, rd, rs, rt);
18892 break;
18893 case NM_ADDU:
18894 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
18895 break;
18896 case NM_SUB:
18897 check_nms(ctx);
18898 gen_arith(ctx, OPC_SUB, rd, rs, rt);
18899 break;
18900 case NM_SUBU:
18901 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
18902 break;
18903 case NM_P_CMOVE:
18904 switch (extract32(ctx->opcode, 10, 1)) {
18905 case NM_MOVZ:
18906 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
18907 break;
18908 case NM_MOVN:
18909 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
18910 break;
18912 break;
18913 case NM_AND:
18914 gen_logic(ctx, OPC_AND, rd, rs, rt);
18915 break;
18916 case NM_OR:
18917 gen_logic(ctx, OPC_OR, rd, rs, rt);
18918 break;
18919 case NM_NOR:
18920 gen_logic(ctx, OPC_NOR, rd, rs, rt);
18921 break;
18922 case NM_XOR:
18923 gen_logic(ctx, OPC_XOR, rd, rs, rt);
18924 break;
18925 case NM_SLT:
18926 gen_slt(ctx, OPC_SLT, rd, rs, rt);
18927 break;
18928 case NM_P_SLTU:
18929 if (rd == 0) {
18930 /* P_DVP */
18931 #ifndef CONFIG_USER_ONLY
18932 TCGv t0 = tcg_temp_new();
18933 switch (extract32(ctx->opcode, 10, 1)) {
18934 case NM_DVP:
18935 if (ctx->vp) {
18936 check_cp0_enabled(ctx);
18937 gen_helper_dvp(t0, cpu_env);
18938 gen_store_gpr(t0, rt);
18940 break;
18941 case NM_EVP:
18942 if (ctx->vp) {
18943 check_cp0_enabled(ctx);
18944 gen_helper_evp(t0, cpu_env);
18945 gen_store_gpr(t0, rt);
18947 break;
18949 tcg_temp_free(t0);
18950 #endif
18951 } else {
18952 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
18954 break;
18955 case NM_SOV:
18957 TCGv t0 = tcg_temp_new();
18958 TCGv t1 = tcg_temp_new();
18959 TCGv t2 = tcg_temp_new();
18961 gen_load_gpr(t1, rs);
18962 gen_load_gpr(t2, rt);
18963 tcg_gen_add_tl(t0, t1, t2);
18964 tcg_gen_ext32s_tl(t0, t0);
18965 tcg_gen_xor_tl(t1, t1, t2);
18966 tcg_gen_xor_tl(t2, t0, t2);
18967 tcg_gen_andc_tl(t1, t2, t1);
18969 /* operands of same sign, result different sign */
18970 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
18971 gen_store_gpr(t0, rd);
18973 tcg_temp_free(t0);
18974 tcg_temp_free(t1);
18975 tcg_temp_free(t2);
18977 break;
18978 case NM_MUL:
18979 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
18980 break;
18981 case NM_MUH:
18982 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
18983 break;
18984 case NM_MULU:
18985 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
18986 break;
18987 case NM_MUHU:
18988 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
18989 break;
18990 case NM_DIV:
18991 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
18992 break;
18993 case NM_MOD:
18994 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
18995 break;
18996 case NM_DIVU:
18997 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
18998 break;
18999 case NM_MODU:
19000 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
19001 break;
19002 #ifndef CONFIG_USER_ONLY
19003 case NM_MFC0:
19004 check_cp0_enabled(ctx);
19005 if (rt == 0) {
19006 /* Treat as NOP. */
19007 break;
19009 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
19010 break;
19011 case NM_MTC0:
19012 check_cp0_enabled(ctx);
19014 TCGv t0 = tcg_temp_new();
19016 gen_load_gpr(t0, rt);
19017 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
19018 tcg_temp_free(t0);
19020 break;
19021 case NM_D_E_MT_VPE:
19023 uint8_t sc = extract32(ctx->opcode, 10, 1);
19024 TCGv t0 = tcg_temp_new();
19026 switch (sc) {
19027 case 0:
19028 if (rs == 1) {
19029 /* DMT */
19030 check_cp0_mt(ctx);
19031 gen_helper_dmt(t0);
19032 gen_store_gpr(t0, rt);
19033 } else if (rs == 0) {
19034 /* DVPE */
19035 check_cp0_mt(ctx);
19036 gen_helper_dvpe(t0, cpu_env);
19037 gen_store_gpr(t0, rt);
19038 } else {
19039 generate_exception_end(ctx, EXCP_RI);
19041 break;
19042 case 1:
19043 if (rs == 1) {
19044 /* EMT */
19045 check_cp0_mt(ctx);
19046 gen_helper_emt(t0);
19047 gen_store_gpr(t0, rt);
19048 } else if (rs == 0) {
19049 /* EVPE */
19050 check_cp0_mt(ctx);
19051 gen_helper_evpe(t0, cpu_env);
19052 gen_store_gpr(t0, rt);
19053 } else {
19054 generate_exception_end(ctx, EXCP_RI);
19056 break;
19059 tcg_temp_free(t0);
19061 break;
19062 case NM_FORK:
19063 check_mt(ctx);
19065 TCGv t0 = tcg_temp_new();
19066 TCGv t1 = tcg_temp_new();
19068 gen_load_gpr(t0, rt);
19069 gen_load_gpr(t1, rs);
19070 gen_helper_fork(t0, t1);
19071 tcg_temp_free(t0);
19072 tcg_temp_free(t1);
19074 break;
19075 case NM_MFTR:
19076 case NM_MFHTR:
19077 check_cp0_enabled(ctx);
19078 if (rd == 0) {
19079 /* Treat as NOP. */
19080 return;
19082 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
19083 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
19084 break;
19085 case NM_MTTR:
19086 case NM_MTHTR:
19087 check_cp0_enabled(ctx);
19088 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
19089 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
19090 break;
19091 case NM_YIELD:
19092 check_mt(ctx);
19094 TCGv t0 = tcg_temp_new();
19096 gen_load_gpr(t0, rs);
19097 gen_helper_yield(t0, cpu_env, t0);
19098 gen_store_gpr(t0, rt);
19099 tcg_temp_free(t0);
19101 break;
19102 #endif
19103 default:
19104 generate_exception_end(ctx, EXCP_RI);
19105 break;
19109 /* dsp */
19110 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
19111 int ret, int v1, int v2)
19113 TCGv_i32 t0;
19114 TCGv v0_t;
19115 TCGv v1_t;
19117 t0 = tcg_temp_new_i32();
19119 v0_t = tcg_temp_new();
19120 v1_t = tcg_temp_new();
19122 tcg_gen_movi_i32(t0, v2 >> 3);
19124 gen_load_gpr(v0_t, ret);
19125 gen_load_gpr(v1_t, v1);
19127 switch (opc) {
19128 case NM_MAQ_S_W_PHR:
19129 check_dsp(ctx);
19130 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
19131 break;
19132 case NM_MAQ_S_W_PHL:
19133 check_dsp(ctx);
19134 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
19135 break;
19136 case NM_MAQ_SA_W_PHR:
19137 check_dsp(ctx);
19138 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
19139 break;
19140 case NM_MAQ_SA_W_PHL:
19141 check_dsp(ctx);
19142 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
19143 break;
19144 default:
19145 generate_exception_end(ctx, EXCP_RI);
19146 break;
19149 tcg_temp_free_i32(t0);
19151 tcg_temp_free(v0_t);
19152 tcg_temp_free(v1_t);
19156 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
19157 int ret, int v1, int v2)
19159 int16_t imm;
19160 TCGv t0 = tcg_temp_new();
19161 TCGv t1 = tcg_temp_new();
19162 TCGv v0_t = tcg_temp_new();
19164 gen_load_gpr(v0_t, v1);
19166 switch (opc) {
19167 case NM_POOL32AXF_1_0:
19168 check_dsp(ctx);
19169 switch (extract32(ctx->opcode, 12, 2)) {
19170 case NM_MFHI:
19171 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
19172 break;
19173 case NM_MFLO:
19174 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
19175 break;
19176 case NM_MTHI:
19177 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
19178 break;
19179 case NM_MTLO:
19180 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
19181 break;
19183 break;
19184 case NM_POOL32AXF_1_1:
19185 check_dsp(ctx);
19186 switch (extract32(ctx->opcode, 12, 2)) {
19187 case NM_MTHLIP:
19188 tcg_gen_movi_tl(t0, v2);
19189 gen_helper_mthlip(t0, v0_t, cpu_env);
19190 break;
19191 case NM_SHILOV:
19192 tcg_gen_movi_tl(t0, v2 >> 3);
19193 gen_helper_shilo(t0, v0_t, cpu_env);
19194 break;
19195 default:
19196 generate_exception_end(ctx, EXCP_RI);
19197 break;
19199 break;
19200 case NM_POOL32AXF_1_3:
19201 check_dsp(ctx);
19202 imm = extract32(ctx->opcode, 14, 7);
19203 switch (extract32(ctx->opcode, 12, 2)) {
19204 case NM_RDDSP:
19205 tcg_gen_movi_tl(t0, imm);
19206 gen_helper_rddsp(t0, t0, cpu_env);
19207 gen_store_gpr(t0, ret);
19208 break;
19209 case NM_WRDSP:
19210 gen_load_gpr(t0, ret);
19211 tcg_gen_movi_tl(t1, imm);
19212 gen_helper_wrdsp(t0, t1, cpu_env);
19213 break;
19214 case NM_EXTP:
19215 tcg_gen_movi_tl(t0, v2 >> 3);
19216 tcg_gen_movi_tl(t1, v1);
19217 gen_helper_extp(t0, t0, t1, cpu_env);
19218 gen_store_gpr(t0, ret);
19219 break;
19220 case NM_EXTPDP:
19221 tcg_gen_movi_tl(t0, v2 >> 3);
19222 tcg_gen_movi_tl(t1, v1);
19223 gen_helper_extpdp(t0, t0, t1, cpu_env);
19224 gen_store_gpr(t0, ret);
19225 break;
19227 break;
19228 case NM_POOL32AXF_1_4:
19229 check_dsp(ctx);
19230 tcg_gen_movi_tl(t0, v2 >> 2);
19231 switch (extract32(ctx->opcode, 12, 1)) {
19232 case NM_SHLL_QB:
19233 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
19234 gen_store_gpr(t0, ret);
19235 break;
19236 case NM_SHRL_QB:
19237 gen_helper_shrl_qb(t0, t0, v0_t);
19238 gen_store_gpr(t0, ret);
19239 break;
19241 break;
19242 case NM_POOL32AXF_1_5:
19243 opc = extract32(ctx->opcode, 12, 2);
19244 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
19245 break;
19246 case NM_POOL32AXF_1_7:
19247 check_dsp(ctx);
19248 tcg_gen_movi_tl(t0, v2 >> 3);
19249 tcg_gen_movi_tl(t1, v1);
19250 switch (extract32(ctx->opcode, 12, 2)) {
19251 case NM_EXTR_W:
19252 gen_helper_extr_w(t0, t0, t1, cpu_env);
19253 gen_store_gpr(t0, ret);
19254 break;
19255 case NM_EXTR_R_W:
19256 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
19257 gen_store_gpr(t0, ret);
19258 break;
19259 case NM_EXTR_RS_W:
19260 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
19261 gen_store_gpr(t0, ret);
19262 break;
19263 case NM_EXTR_S_H:
19264 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
19265 gen_store_gpr(t0, ret);
19266 break;
19268 break;
19269 default:
19270 generate_exception_end(ctx, EXCP_RI);
19271 break;
19274 tcg_temp_free(t0);
19275 tcg_temp_free(t1);
19276 tcg_temp_free(v0_t);
19279 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
19280 TCGv v0, TCGv v1, int rd)
19282 TCGv_i32 t0;
19284 t0 = tcg_temp_new_i32();
19286 tcg_gen_movi_i32(t0, rd >> 3);
19288 switch (opc) {
19289 case NM_POOL32AXF_2_0_7:
19290 switch (extract32(ctx->opcode, 9, 3)) {
19291 case NM_DPA_W_PH:
19292 check_dsp_r2(ctx);
19293 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
19294 break;
19295 case NM_DPAQ_S_W_PH:
19296 check_dsp(ctx);
19297 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
19298 break;
19299 case NM_DPS_W_PH:
19300 check_dsp_r2(ctx);
19301 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
19302 break;
19303 case NM_DPSQ_S_W_PH:
19304 check_dsp(ctx);
19305 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
19306 break;
19307 default:
19308 generate_exception_end(ctx, EXCP_RI);
19309 break;
19311 break;
19312 case NM_POOL32AXF_2_8_15:
19313 switch (extract32(ctx->opcode, 9, 3)) {
19314 case NM_DPAX_W_PH:
19315 check_dsp_r2(ctx);
19316 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
19317 break;
19318 case NM_DPAQ_SA_L_W:
19319 check_dsp(ctx);
19320 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
19321 break;
19322 case NM_DPSX_W_PH:
19323 check_dsp_r2(ctx);
19324 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
19325 break;
19326 case NM_DPSQ_SA_L_W:
19327 check_dsp(ctx);
19328 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
19329 break;
19330 default:
19331 generate_exception_end(ctx, EXCP_RI);
19332 break;
19334 break;
19335 case NM_POOL32AXF_2_16_23:
19336 switch (extract32(ctx->opcode, 9, 3)) {
19337 case NM_DPAU_H_QBL:
19338 check_dsp(ctx);
19339 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
19340 break;
19341 case NM_DPAQX_S_W_PH:
19342 check_dsp_r2(ctx);
19343 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
19344 break;
19345 case NM_DPSU_H_QBL:
19346 check_dsp(ctx);
19347 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
19348 break;
19349 case NM_DPSQX_S_W_PH:
19350 check_dsp_r2(ctx);
19351 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
19352 break;
19353 case NM_MULSA_W_PH:
19354 check_dsp_r2(ctx);
19355 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
19356 break;
19357 default:
19358 generate_exception_end(ctx, EXCP_RI);
19359 break;
19361 break;
19362 case NM_POOL32AXF_2_24_31:
19363 switch (extract32(ctx->opcode, 9, 3)) {
19364 case NM_DPAU_H_QBR:
19365 check_dsp(ctx);
19366 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
19367 break;
19368 case NM_DPAQX_SA_W_PH:
19369 check_dsp_r2(ctx);
19370 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
19371 break;
19372 case NM_DPSU_H_QBR:
19373 check_dsp(ctx);
19374 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
19375 break;
19376 case NM_DPSQX_SA_W_PH:
19377 check_dsp_r2(ctx);
19378 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
19379 break;
19380 case NM_MULSAQ_S_W_PH:
19381 check_dsp(ctx);
19382 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
19383 break;
19384 default:
19385 generate_exception_end(ctx, EXCP_RI);
19386 break;
19388 break;
19389 default:
19390 generate_exception_end(ctx, EXCP_RI);
19391 break;
19394 tcg_temp_free_i32(t0);
19397 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
19398 int rt, int rs, int rd)
19400 int ret = rt;
19401 TCGv t0 = tcg_temp_new();
19402 TCGv t1 = tcg_temp_new();
19403 TCGv v0_t = tcg_temp_new();
19404 TCGv v1_t = tcg_temp_new();
19406 gen_load_gpr(v0_t, rt);
19407 gen_load_gpr(v1_t, rs);
19409 switch (opc) {
19410 case NM_POOL32AXF_2_0_7:
19411 switch (extract32(ctx->opcode, 9, 3)) {
19412 case NM_DPA_W_PH:
19413 case NM_DPAQ_S_W_PH:
19414 case NM_DPS_W_PH:
19415 case NM_DPSQ_S_W_PH:
19416 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19417 break;
19418 case NM_BALIGN:
19419 check_dsp_r2(ctx);
19420 if (rt != 0) {
19421 gen_load_gpr(t0, rs);
19422 rd &= 3;
19423 if (rd != 0 && rd != 2) {
19424 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
19425 tcg_gen_ext32u_tl(t0, t0);
19426 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
19427 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19429 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
19431 break;
19432 case NM_MADD:
19433 check_dsp(ctx);
19435 int acc = extract32(ctx->opcode, 14, 2);
19436 TCGv_i64 t2 = tcg_temp_new_i64();
19437 TCGv_i64 t3 = tcg_temp_new_i64();
19439 gen_load_gpr(t0, rt);
19440 gen_load_gpr(t1, rs);
19441 tcg_gen_ext_tl_i64(t2, t0);
19442 tcg_gen_ext_tl_i64(t3, t1);
19443 tcg_gen_mul_i64(t2, t2, t3);
19444 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19445 tcg_gen_add_i64(t2, t2, t3);
19446 tcg_temp_free_i64(t3);
19447 gen_move_low32(cpu_LO[acc], t2);
19448 gen_move_high32(cpu_HI[acc], t2);
19449 tcg_temp_free_i64(t2);
19451 break;
19452 case NM_MULT:
19453 check_dsp(ctx);
19455 int acc = extract32(ctx->opcode, 14, 2);
19456 TCGv_i32 t2 = tcg_temp_new_i32();
19457 TCGv_i32 t3 = tcg_temp_new_i32();
19459 gen_load_gpr(t0, rs);
19460 gen_load_gpr(t1, rt);
19461 tcg_gen_trunc_tl_i32(t2, t0);
19462 tcg_gen_trunc_tl_i32(t3, t1);
19463 tcg_gen_muls2_i32(t2, t3, t2, t3);
19464 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19465 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19466 tcg_temp_free_i32(t2);
19467 tcg_temp_free_i32(t3);
19469 break;
19470 case NM_EXTRV_W:
19471 check_dsp(ctx);
19472 gen_load_gpr(v1_t, rs);
19473 tcg_gen_movi_tl(t0, rd >> 3);
19474 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
19475 gen_store_gpr(t0, ret);
19476 break;
19478 break;
19479 case NM_POOL32AXF_2_8_15:
19480 switch (extract32(ctx->opcode, 9, 3)) {
19481 case NM_DPAX_W_PH:
19482 case NM_DPAQ_SA_L_W:
19483 case NM_DPSX_W_PH:
19484 case NM_DPSQ_SA_L_W:
19485 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19486 break;
19487 case NM_MADDU:
19488 check_dsp(ctx);
19490 int acc = extract32(ctx->opcode, 14, 2);
19491 TCGv_i64 t2 = tcg_temp_new_i64();
19492 TCGv_i64 t3 = tcg_temp_new_i64();
19494 gen_load_gpr(t0, rs);
19495 gen_load_gpr(t1, rt);
19496 tcg_gen_ext32u_tl(t0, t0);
19497 tcg_gen_ext32u_tl(t1, t1);
19498 tcg_gen_extu_tl_i64(t2, t0);
19499 tcg_gen_extu_tl_i64(t3, t1);
19500 tcg_gen_mul_i64(t2, t2, t3);
19501 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19502 tcg_gen_add_i64(t2, t2, t3);
19503 tcg_temp_free_i64(t3);
19504 gen_move_low32(cpu_LO[acc], t2);
19505 gen_move_high32(cpu_HI[acc], t2);
19506 tcg_temp_free_i64(t2);
19508 break;
19509 case NM_MULTU:
19510 check_dsp(ctx);
19512 int acc = extract32(ctx->opcode, 14, 2);
19513 TCGv_i32 t2 = tcg_temp_new_i32();
19514 TCGv_i32 t3 = tcg_temp_new_i32();
19516 gen_load_gpr(t0, rs);
19517 gen_load_gpr(t1, rt);
19518 tcg_gen_trunc_tl_i32(t2, t0);
19519 tcg_gen_trunc_tl_i32(t3, t1);
19520 tcg_gen_mulu2_i32(t2, t3, t2, t3);
19521 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19522 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19523 tcg_temp_free_i32(t2);
19524 tcg_temp_free_i32(t3);
19526 break;
19527 case NM_EXTRV_R_W:
19528 check_dsp(ctx);
19529 tcg_gen_movi_tl(t0, rd >> 3);
19530 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
19531 gen_store_gpr(t0, ret);
19532 break;
19533 default:
19534 generate_exception_end(ctx, EXCP_RI);
19535 break;
19537 break;
19538 case NM_POOL32AXF_2_16_23:
19539 switch (extract32(ctx->opcode, 9, 3)) {
19540 case NM_DPAU_H_QBL:
19541 case NM_DPAQX_S_W_PH:
19542 case NM_DPSU_H_QBL:
19543 case NM_DPSQX_S_W_PH:
19544 case NM_MULSA_W_PH:
19545 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19546 break;
19547 case NM_EXTPV:
19548 check_dsp(ctx);
19549 tcg_gen_movi_tl(t0, rd >> 3);
19550 gen_helper_extp(t0, t0, v1_t, cpu_env);
19551 gen_store_gpr(t0, ret);
19552 break;
19553 case NM_MSUB:
19554 check_dsp(ctx);
19556 int acc = extract32(ctx->opcode, 14, 2);
19557 TCGv_i64 t2 = tcg_temp_new_i64();
19558 TCGv_i64 t3 = tcg_temp_new_i64();
19560 gen_load_gpr(t0, rs);
19561 gen_load_gpr(t1, rt);
19562 tcg_gen_ext_tl_i64(t2, t0);
19563 tcg_gen_ext_tl_i64(t3, t1);
19564 tcg_gen_mul_i64(t2, t2, t3);
19565 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19566 tcg_gen_sub_i64(t2, t3, t2);
19567 tcg_temp_free_i64(t3);
19568 gen_move_low32(cpu_LO[acc], t2);
19569 gen_move_high32(cpu_HI[acc], t2);
19570 tcg_temp_free_i64(t2);
19572 break;
19573 case NM_EXTRV_RS_W:
19574 check_dsp(ctx);
19575 tcg_gen_movi_tl(t0, rd >> 3);
19576 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
19577 gen_store_gpr(t0, ret);
19578 break;
19580 break;
19581 case NM_POOL32AXF_2_24_31:
19582 switch (extract32(ctx->opcode, 9, 3)) {
19583 case NM_DPAU_H_QBR:
19584 case NM_DPAQX_SA_W_PH:
19585 case NM_DPSU_H_QBR:
19586 case NM_DPSQX_SA_W_PH:
19587 case NM_MULSAQ_S_W_PH:
19588 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19589 break;
19590 case NM_EXTPDPV:
19591 check_dsp(ctx);
19592 tcg_gen_movi_tl(t0, rd >> 3);
19593 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
19594 gen_store_gpr(t0, ret);
19595 break;
19596 case NM_MSUBU:
19597 check_dsp(ctx);
19599 int acc = extract32(ctx->opcode, 14, 2);
19600 TCGv_i64 t2 = tcg_temp_new_i64();
19601 TCGv_i64 t3 = tcg_temp_new_i64();
19603 gen_load_gpr(t0, rs);
19604 gen_load_gpr(t1, rt);
19605 tcg_gen_ext32u_tl(t0, t0);
19606 tcg_gen_ext32u_tl(t1, t1);
19607 tcg_gen_extu_tl_i64(t2, t0);
19608 tcg_gen_extu_tl_i64(t3, t1);
19609 tcg_gen_mul_i64(t2, t2, t3);
19610 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19611 tcg_gen_sub_i64(t2, t3, t2);
19612 tcg_temp_free_i64(t3);
19613 gen_move_low32(cpu_LO[acc], t2);
19614 gen_move_high32(cpu_HI[acc], t2);
19615 tcg_temp_free_i64(t2);
19617 break;
19618 case NM_EXTRV_S_H:
19619 check_dsp(ctx);
19620 tcg_gen_movi_tl(t0, rd >> 3);
19621 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
19622 gen_store_gpr(t0, ret);
19623 break;
19625 break;
19626 default:
19627 generate_exception_end(ctx, EXCP_RI);
19628 break;
19631 tcg_temp_free(t0);
19632 tcg_temp_free(t1);
19634 tcg_temp_free(v0_t);
19635 tcg_temp_free(v1_t);
19638 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
19639 int rt, int rs)
19641 int ret = rt;
19642 TCGv t0 = tcg_temp_new();
19643 TCGv v0_t = tcg_temp_new();
19645 gen_load_gpr(v0_t, rs);
19647 switch (opc) {
19648 case NM_ABSQ_S_QB:
19649 check_dsp_r2(ctx);
19650 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
19651 gen_store_gpr(v0_t, ret);
19652 break;
19653 case NM_ABSQ_S_PH:
19654 check_dsp(ctx);
19655 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
19656 gen_store_gpr(v0_t, ret);
19657 break;
19658 case NM_ABSQ_S_W:
19659 check_dsp(ctx);
19660 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
19661 gen_store_gpr(v0_t, ret);
19662 break;
19663 case NM_PRECEQ_W_PHL:
19664 check_dsp(ctx);
19665 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
19666 tcg_gen_ext32s_tl(v0_t, v0_t);
19667 gen_store_gpr(v0_t, ret);
19668 break;
19669 case NM_PRECEQ_W_PHR:
19670 check_dsp(ctx);
19671 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
19672 tcg_gen_shli_tl(v0_t, v0_t, 16);
19673 tcg_gen_ext32s_tl(v0_t, v0_t);
19674 gen_store_gpr(v0_t, ret);
19675 break;
19676 case NM_PRECEQU_PH_QBL:
19677 check_dsp(ctx);
19678 gen_helper_precequ_ph_qbl(v0_t, v0_t);
19679 gen_store_gpr(v0_t, ret);
19680 break;
19681 case NM_PRECEQU_PH_QBR:
19682 check_dsp(ctx);
19683 gen_helper_precequ_ph_qbr(v0_t, v0_t);
19684 gen_store_gpr(v0_t, ret);
19685 break;
19686 case NM_PRECEQU_PH_QBLA:
19687 check_dsp(ctx);
19688 gen_helper_precequ_ph_qbla(v0_t, v0_t);
19689 gen_store_gpr(v0_t, ret);
19690 break;
19691 case NM_PRECEQU_PH_QBRA:
19692 check_dsp(ctx);
19693 gen_helper_precequ_ph_qbra(v0_t, v0_t);
19694 gen_store_gpr(v0_t, ret);
19695 break;
19696 case NM_PRECEU_PH_QBL:
19697 check_dsp(ctx);
19698 gen_helper_preceu_ph_qbl(v0_t, v0_t);
19699 gen_store_gpr(v0_t, ret);
19700 break;
19701 case NM_PRECEU_PH_QBR:
19702 check_dsp(ctx);
19703 gen_helper_preceu_ph_qbr(v0_t, v0_t);
19704 gen_store_gpr(v0_t, ret);
19705 break;
19706 case NM_PRECEU_PH_QBLA:
19707 check_dsp(ctx);
19708 gen_helper_preceu_ph_qbla(v0_t, v0_t);
19709 gen_store_gpr(v0_t, ret);
19710 break;
19711 case NM_PRECEU_PH_QBRA:
19712 check_dsp(ctx);
19713 gen_helper_preceu_ph_qbra(v0_t, v0_t);
19714 gen_store_gpr(v0_t, ret);
19715 break;
19716 case NM_REPLV_PH:
19717 check_dsp(ctx);
19718 tcg_gen_ext16u_tl(v0_t, v0_t);
19719 tcg_gen_shli_tl(t0, v0_t, 16);
19720 tcg_gen_or_tl(v0_t, v0_t, t0);
19721 tcg_gen_ext32s_tl(v0_t, v0_t);
19722 gen_store_gpr(v0_t, ret);
19723 break;
19724 case NM_REPLV_QB:
19725 check_dsp(ctx);
19726 tcg_gen_ext8u_tl(v0_t, v0_t);
19727 tcg_gen_shli_tl(t0, v0_t, 8);
19728 tcg_gen_or_tl(v0_t, v0_t, t0);
19729 tcg_gen_shli_tl(t0, v0_t, 16);
19730 tcg_gen_or_tl(v0_t, v0_t, t0);
19731 tcg_gen_ext32s_tl(v0_t, v0_t);
19732 gen_store_gpr(v0_t, ret);
19733 break;
19734 case NM_BITREV:
19735 check_dsp(ctx);
19736 gen_helper_bitrev(v0_t, v0_t);
19737 gen_store_gpr(v0_t, ret);
19738 break;
19739 case NM_INSV:
19740 check_dsp(ctx);
19742 TCGv tv0 = tcg_temp_new();
19744 gen_load_gpr(tv0, rt);
19745 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
19746 gen_store_gpr(v0_t, ret);
19747 tcg_temp_free(tv0);
19749 break;
19750 case NM_RADDU_W_QB:
19751 check_dsp(ctx);
19752 gen_helper_raddu_w_qb(v0_t, v0_t);
19753 gen_store_gpr(v0_t, ret);
19754 break;
19755 case NM_BITSWAP:
19756 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
19757 break;
19758 case NM_CLO:
19759 check_nms(ctx);
19760 gen_cl(ctx, OPC_CLO, ret, rs);
19761 break;
19762 case NM_CLZ:
19763 check_nms(ctx);
19764 gen_cl(ctx, OPC_CLZ, ret, rs);
19765 break;
19766 case NM_WSBH:
19767 gen_bshfl(ctx, OPC_WSBH, ret, rs);
19768 break;
19769 default:
19770 generate_exception_end(ctx, EXCP_RI);
19771 break;
19774 tcg_temp_free(v0_t);
19775 tcg_temp_free(t0);
19778 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
19779 int rt, int rs, int rd)
19781 TCGv t0 = tcg_temp_new();
19782 TCGv rs_t = tcg_temp_new();
19784 gen_load_gpr(rs_t, rs);
19786 switch (opc) {
19787 case NM_SHRA_R_QB:
19788 check_dsp_r2(ctx);
19789 tcg_gen_movi_tl(t0, rd >> 2);
19790 switch (extract32(ctx->opcode, 12, 1)) {
19791 case 0:
19792 /* NM_SHRA_QB */
19793 gen_helper_shra_qb(t0, t0, rs_t);
19794 gen_store_gpr(t0, rt);
19795 break;
19796 case 1:
19797 /* NM_SHRA_R_QB */
19798 gen_helper_shra_r_qb(t0, t0, rs_t);
19799 gen_store_gpr(t0, rt);
19800 break;
19802 break;
19803 case NM_SHRL_PH:
19804 check_dsp_r2(ctx);
19805 tcg_gen_movi_tl(t0, rd >> 1);
19806 gen_helper_shrl_ph(t0, t0, rs_t);
19807 gen_store_gpr(t0, rt);
19808 break;
19809 case NM_REPL_QB:
19810 check_dsp(ctx);
19812 int16_t imm;
19813 target_long result;
19814 imm = extract32(ctx->opcode, 13, 8);
19815 result = (uint32_t)imm << 24 |
19816 (uint32_t)imm << 16 |
19817 (uint32_t)imm << 8 |
19818 (uint32_t)imm;
19819 result = (int32_t)result;
19820 tcg_gen_movi_tl(t0, result);
19821 gen_store_gpr(t0, rt);
19823 break;
19824 default:
19825 generate_exception_end(ctx, EXCP_RI);
19826 break;
19828 tcg_temp_free(t0);
19829 tcg_temp_free(rs_t);
19833 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19835 int rt = extract32(ctx->opcode, 21, 5);
19836 int rs = extract32(ctx->opcode, 16, 5);
19837 int rd = extract32(ctx->opcode, 11, 5);
19839 switch (extract32(ctx->opcode, 6, 3)) {
19840 case NM_POOL32AXF_1:
19842 int32_t op1 = extract32(ctx->opcode, 9, 3);
19843 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
19845 break;
19846 case NM_POOL32AXF_2:
19848 int32_t op1 = extract32(ctx->opcode, 12, 2);
19849 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
19851 break;
19852 case NM_POOL32AXF_4:
19854 int32_t op1 = extract32(ctx->opcode, 9, 7);
19855 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
19857 break;
19858 case NM_POOL32AXF_5:
19859 switch (extract32(ctx->opcode, 9, 7)) {
19860 #ifndef CONFIG_USER_ONLY
19861 case NM_TLBP:
19862 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
19863 break;
19864 case NM_TLBR:
19865 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
19866 break;
19867 case NM_TLBWI:
19868 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
19869 break;
19870 case NM_TLBWR:
19871 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
19872 break;
19873 case NM_TLBINV:
19874 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
19875 break;
19876 case NM_TLBINVF:
19877 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
19878 break;
19879 case NM_DI:
19880 check_cp0_enabled(ctx);
19882 TCGv t0 = tcg_temp_new();
19884 save_cpu_state(ctx, 1);
19885 gen_helper_di(t0, cpu_env);
19886 gen_store_gpr(t0, rt);
19887 /* Stop translation as we may have switched the execution mode */
19888 ctx->base.is_jmp = DISAS_STOP;
19889 tcg_temp_free(t0);
19891 break;
19892 case NM_EI:
19893 check_cp0_enabled(ctx);
19895 TCGv t0 = tcg_temp_new();
19897 save_cpu_state(ctx, 1);
19898 gen_helper_ei(t0, cpu_env);
19899 gen_store_gpr(t0, rt);
19900 /* Stop translation as we may have switched the execution mode */
19901 ctx->base.is_jmp = DISAS_STOP;
19902 tcg_temp_free(t0);
19904 break;
19905 case NM_RDPGPR:
19906 gen_load_srsgpr(rs, rt);
19907 break;
19908 case NM_WRPGPR:
19909 gen_store_srsgpr(rs, rt);
19910 break;
19911 case NM_WAIT:
19912 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
19913 break;
19914 case NM_DERET:
19915 gen_cp0(env, ctx, OPC_DERET, 0, 0);
19916 break;
19917 case NM_ERETX:
19918 gen_cp0(env, ctx, OPC_ERET, 0, 0);
19919 break;
19920 #endif
19921 default:
19922 generate_exception_end(ctx, EXCP_RI);
19923 break;
19925 break;
19926 case NM_POOL32AXF_7:
19928 int32_t op1 = extract32(ctx->opcode, 9, 3);
19929 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
19931 break;
19932 default:
19933 generate_exception_end(ctx, EXCP_RI);
19934 break;
19938 /* Immediate Value Compact Branches */
19939 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
19940 int rt, int32_t imm, int32_t offset)
19942 TCGCond cond;
19943 int bcond_compute = 0;
19944 TCGv t0 = tcg_temp_new();
19945 TCGv t1 = tcg_temp_new();
19947 gen_load_gpr(t0, rt);
19948 tcg_gen_movi_tl(t1, imm);
19949 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19951 /* Load needed operands and calculate btarget */
19952 switch (opc) {
19953 case NM_BEQIC:
19954 if (rt == 0 && imm == 0) {
19955 /* Unconditional branch */
19956 } else if (rt == 0 && imm != 0) {
19957 /* Treat as NOP */
19958 goto out;
19959 } else {
19960 bcond_compute = 1;
19961 cond = TCG_COND_EQ;
19963 break;
19964 case NM_BBEQZC:
19965 case NM_BBNEZC:
19966 check_nms(ctx);
19967 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
19968 generate_exception_end(ctx, EXCP_RI);
19969 goto out;
19970 } else if (rt == 0 && opc == NM_BBEQZC) {
19971 /* Unconditional branch */
19972 } else if (rt == 0 && opc == NM_BBNEZC) {
19973 /* Treat as NOP */
19974 goto out;
19975 } else {
19976 tcg_gen_shri_tl(t0, t0, imm);
19977 tcg_gen_andi_tl(t0, t0, 1);
19978 tcg_gen_movi_tl(t1, 0);
19979 bcond_compute = 1;
19980 if (opc == NM_BBEQZC) {
19981 cond = TCG_COND_EQ;
19982 } else {
19983 cond = TCG_COND_NE;
19986 break;
19987 case NM_BNEIC:
19988 if (rt == 0 && imm == 0) {
19989 /* Treat as NOP */
19990 goto out;
19991 } else if (rt == 0 && imm != 0) {
19992 /* Unconditional branch */
19993 } else {
19994 bcond_compute = 1;
19995 cond = TCG_COND_NE;
19997 break;
19998 case NM_BGEIC:
19999 if (rt == 0 && imm == 0) {
20000 /* Unconditional branch */
20001 } else {
20002 bcond_compute = 1;
20003 cond = TCG_COND_GE;
20005 break;
20006 case NM_BLTIC:
20007 bcond_compute = 1;
20008 cond = TCG_COND_LT;
20009 break;
20010 case NM_BGEIUC:
20011 if (rt == 0 && imm == 0) {
20012 /* Unconditional branch */
20013 } else {
20014 bcond_compute = 1;
20015 cond = TCG_COND_GEU;
20017 break;
20018 case NM_BLTIUC:
20019 bcond_compute = 1;
20020 cond = TCG_COND_LTU;
20021 break;
20022 default:
20023 MIPS_INVAL("Immediate Value Compact branch");
20024 generate_exception_end(ctx, EXCP_RI);
20025 goto out;
20028 /* branch completion */
20029 clear_branch_hflags(ctx);
20030 ctx->base.is_jmp = DISAS_NORETURN;
20032 if (bcond_compute == 0) {
20033 /* Uncoditional compact branch */
20034 gen_goto_tb(ctx, 0, ctx->btarget);
20035 } else {
20036 /* Conditional compact branch */
20037 TCGLabel *fs = gen_new_label();
20039 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
20041 gen_goto_tb(ctx, 1, ctx->btarget);
20042 gen_set_label(fs);
20044 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20047 out:
20048 tcg_temp_free(t0);
20049 tcg_temp_free(t1);
20052 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
20053 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
20054 int rt)
20056 TCGv t0 = tcg_temp_new();
20057 TCGv t1 = tcg_temp_new();
20059 /* load rs */
20060 gen_load_gpr(t0, rs);
20062 /* link */
20063 if (rt != 0) {
20064 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
20067 /* calculate btarget */
20068 tcg_gen_shli_tl(t0, t0, 1);
20069 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
20070 gen_op_addr_add(ctx, btarget, t1, t0);
20072 /* branch completion */
20073 clear_branch_hflags(ctx);
20074 ctx->base.is_jmp = DISAS_NORETURN;
20076 /* unconditional branch to register */
20077 tcg_gen_mov_tl(cpu_PC, btarget);
20078 tcg_gen_lookup_and_goto_ptr();
20080 tcg_temp_free(t0);
20081 tcg_temp_free(t1);
20084 /* nanoMIPS Branches */
20085 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
20086 int rs, int rt, int32_t offset)
20088 int bcond_compute = 0;
20089 TCGv t0 = tcg_temp_new();
20090 TCGv t1 = tcg_temp_new();
20092 /* Load needed operands and calculate btarget */
20093 switch (opc) {
20094 /* compact branch */
20095 case OPC_BGEC:
20096 case OPC_BLTC:
20097 gen_load_gpr(t0, rs);
20098 gen_load_gpr(t1, rt);
20099 bcond_compute = 1;
20100 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20101 break;
20102 case OPC_BGEUC:
20103 case OPC_BLTUC:
20104 if (rs == 0 || rs == rt) {
20105 /* OPC_BLEZALC, OPC_BGEZALC */
20106 /* OPC_BGTZALC, OPC_BLTZALC */
20107 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
20109 gen_load_gpr(t0, rs);
20110 gen_load_gpr(t1, rt);
20111 bcond_compute = 1;
20112 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20113 break;
20114 case OPC_BC:
20115 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20116 break;
20117 case OPC_BEQZC:
20118 if (rs != 0) {
20119 /* OPC_BEQZC, OPC_BNEZC */
20120 gen_load_gpr(t0, rs);
20121 bcond_compute = 1;
20122 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20123 } else {
20124 /* OPC_JIC, OPC_JIALC */
20125 TCGv tbase = tcg_temp_new();
20126 TCGv toffset = tcg_temp_new();
20128 gen_load_gpr(tbase, rt);
20129 tcg_gen_movi_tl(toffset, offset);
20130 gen_op_addr_add(ctx, btarget, tbase, toffset);
20131 tcg_temp_free(tbase);
20132 tcg_temp_free(toffset);
20134 break;
20135 default:
20136 MIPS_INVAL("Compact branch/jump");
20137 generate_exception_end(ctx, EXCP_RI);
20138 goto out;
20141 if (bcond_compute == 0) {
20142 /* Uncoditional compact branch */
20143 switch (opc) {
20144 case OPC_BC:
20145 gen_goto_tb(ctx, 0, ctx->btarget);
20146 break;
20147 default:
20148 MIPS_INVAL("Compact branch/jump");
20149 generate_exception_end(ctx, EXCP_RI);
20150 goto out;
20152 } else {
20153 /* Conditional compact branch */
20154 TCGLabel *fs = gen_new_label();
20156 switch (opc) {
20157 case OPC_BGEUC:
20158 if (rs == 0 && rt != 0) {
20159 /* OPC_BLEZALC */
20160 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20161 } else if (rs != 0 && rt != 0 && rs == rt) {
20162 /* OPC_BGEZALC */
20163 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20164 } else {
20165 /* OPC_BGEUC */
20166 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
20168 break;
20169 case OPC_BLTUC:
20170 if (rs == 0 && rt != 0) {
20171 /* OPC_BGTZALC */
20172 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20173 } else if (rs != 0 && rt != 0 && rs == rt) {
20174 /* OPC_BLTZALC */
20175 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20176 } else {
20177 /* OPC_BLTUC */
20178 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
20180 break;
20181 case OPC_BGEC:
20182 if (rs == 0 && rt != 0) {
20183 /* OPC_BLEZC */
20184 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20185 } else if (rs != 0 && rt != 0 && rs == rt) {
20186 /* OPC_BGEZC */
20187 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20188 } else {
20189 /* OPC_BGEC */
20190 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
20192 break;
20193 case OPC_BLTC:
20194 if (rs == 0 && rt != 0) {
20195 /* OPC_BGTZC */
20196 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20197 } else if (rs != 0 && rt != 0 && rs == rt) {
20198 /* OPC_BLTZC */
20199 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20200 } else {
20201 /* OPC_BLTC */
20202 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
20204 break;
20205 case OPC_BEQZC:
20206 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
20207 break;
20208 default:
20209 MIPS_INVAL("Compact conditional branch/jump");
20210 generate_exception_end(ctx, EXCP_RI);
20211 goto out;
20214 /* branch completion */
20215 clear_branch_hflags(ctx);
20216 ctx->base.is_jmp = DISAS_NORETURN;
20218 /* Generating branch here as compact branches don't have delay slot */
20219 gen_goto_tb(ctx, 1, ctx->btarget);
20220 gen_set_label(fs);
20222 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20225 out:
20226 tcg_temp_free(t0);
20227 tcg_temp_free(t1);
20231 /* nanoMIPS CP1 Branches */
20232 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
20233 int32_t ft, int32_t offset)
20235 target_ulong btarget;
20236 TCGv_i64 t0 = tcg_temp_new_i64();
20238 gen_load_fpr64(ctx, t0, ft);
20239 tcg_gen_andi_i64(t0, t0, 1);
20241 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20243 switch (op) {
20244 case NM_BC1EQZC:
20245 tcg_gen_xori_i64(t0, t0, 1);
20246 ctx->hflags |= MIPS_HFLAG_BC;
20247 break;
20248 case NM_BC1NEZC:
20249 /* t0 already set */
20250 ctx->hflags |= MIPS_HFLAG_BC;
20251 break;
20252 default:
20253 MIPS_INVAL("cp1 cond branch");
20254 generate_exception_end(ctx, EXCP_RI);
20255 goto out;
20258 tcg_gen_trunc_i64_tl(bcond, t0);
20260 ctx->btarget = btarget;
20262 out:
20263 tcg_temp_free_i64(t0);
20267 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
20269 TCGv t0, t1;
20270 t0 = tcg_temp_new();
20271 t1 = tcg_temp_new();
20273 gen_load_gpr(t0, rs);
20274 gen_load_gpr(t1, rt);
20276 if ((extract32(ctx->opcode, 6, 1)) == 1) {
20277 /* PP.LSXS instructions require shifting */
20278 switch (extract32(ctx->opcode, 7, 4)) {
20279 case NM_SHXS:
20280 check_nms(ctx);
20281 /* fall through */
20282 case NM_LHXS:
20283 case NM_LHUXS:
20284 tcg_gen_shli_tl(t0, t0, 1);
20285 break;
20286 case NM_SWXS:
20287 check_nms(ctx);
20288 /* fall through */
20289 case NM_LWXS:
20290 case NM_LWC1XS:
20291 case NM_SWC1XS:
20292 tcg_gen_shli_tl(t0, t0, 2);
20293 break;
20294 case NM_LDC1XS:
20295 case NM_SDC1XS:
20296 tcg_gen_shli_tl(t0, t0, 3);
20297 break;
20300 gen_op_addr_add(ctx, t0, t0, t1);
20302 switch (extract32(ctx->opcode, 7, 4)) {
20303 case NM_LBX:
20304 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20305 MO_SB);
20306 gen_store_gpr(t0, rd);
20307 break;
20308 case NM_LHX:
20309 /*case NM_LHXS:*/
20310 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20311 MO_TESW);
20312 gen_store_gpr(t0, rd);
20313 break;
20314 case NM_LWX:
20315 /*case NM_LWXS:*/
20316 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20317 MO_TESL);
20318 gen_store_gpr(t0, rd);
20319 break;
20320 case NM_LBUX:
20321 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20322 MO_UB);
20323 gen_store_gpr(t0, rd);
20324 break;
20325 case NM_LHUX:
20326 /*case NM_LHUXS:*/
20327 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20328 MO_TEUW);
20329 gen_store_gpr(t0, rd);
20330 break;
20331 case NM_SBX:
20332 check_nms(ctx);
20333 gen_load_gpr(t1, rd);
20334 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20335 MO_8);
20336 break;
20337 case NM_SHX:
20338 /*case NM_SHXS:*/
20339 check_nms(ctx);
20340 gen_load_gpr(t1, rd);
20341 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20342 MO_TEUW);
20343 break;
20344 case NM_SWX:
20345 /*case NM_SWXS:*/
20346 check_nms(ctx);
20347 gen_load_gpr(t1, rd);
20348 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20349 MO_TEUL);
20350 break;
20351 case NM_LWC1X:
20352 /*case NM_LWC1XS:*/
20353 case NM_LDC1X:
20354 /*case NM_LDC1XS:*/
20355 case NM_SWC1X:
20356 /*case NM_SWC1XS:*/
20357 case NM_SDC1X:
20358 /*case NM_SDC1XS:*/
20359 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
20360 check_cp1_enabled(ctx);
20361 switch (extract32(ctx->opcode, 7, 4)) {
20362 case NM_LWC1X:
20363 /*case NM_LWC1XS:*/
20364 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
20365 break;
20366 case NM_LDC1X:
20367 /*case NM_LDC1XS:*/
20368 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
20369 break;
20370 case NM_SWC1X:
20371 /*case NM_SWC1XS:*/
20372 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
20373 break;
20374 case NM_SDC1X:
20375 /*case NM_SDC1XS:*/
20376 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
20377 break;
20379 } else {
20380 generate_exception_err(ctx, EXCP_CpU, 1);
20382 break;
20383 default:
20384 generate_exception_end(ctx, EXCP_RI);
20385 break;
20388 tcg_temp_free(t0);
20389 tcg_temp_free(t1);
20392 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
20394 int rt, rs, rd;
20396 rt = extract32(ctx->opcode, 21, 5);
20397 rs = extract32(ctx->opcode, 16, 5);
20398 rd = extract32(ctx->opcode, 11, 5);
20400 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
20401 generate_exception_end(ctx, EXCP_RI);
20402 return;
20404 check_cp1_enabled(ctx);
20405 switch (extract32(ctx->opcode, 0, 3)) {
20406 case NM_POOL32F_0:
20407 switch (extract32(ctx->opcode, 3, 7)) {
20408 case NM_RINT_S:
20409 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
20410 break;
20411 case NM_RINT_D:
20412 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
20413 break;
20414 case NM_CLASS_S:
20415 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
20416 break;
20417 case NM_CLASS_D:
20418 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
20419 break;
20420 case NM_ADD_S:
20421 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
20422 break;
20423 case NM_ADD_D:
20424 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
20425 break;
20426 case NM_SUB_S:
20427 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
20428 break;
20429 case NM_SUB_D:
20430 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
20431 break;
20432 case NM_MUL_S:
20433 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
20434 break;
20435 case NM_MUL_D:
20436 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
20437 break;
20438 case NM_DIV_S:
20439 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
20440 break;
20441 case NM_DIV_D:
20442 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
20443 break;
20444 case NM_SELEQZ_S:
20445 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
20446 break;
20447 case NM_SELEQZ_D:
20448 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
20449 break;
20450 case NM_SELNEZ_S:
20451 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
20452 break;
20453 case NM_SELNEZ_D:
20454 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
20455 break;
20456 case NM_SEL_S:
20457 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
20458 break;
20459 case NM_SEL_D:
20460 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
20461 break;
20462 case NM_MADDF_S:
20463 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
20464 break;
20465 case NM_MADDF_D:
20466 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
20467 break;
20468 case NM_MSUBF_S:
20469 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
20470 break;
20471 case NM_MSUBF_D:
20472 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
20473 break;
20474 default:
20475 generate_exception_end(ctx, EXCP_RI);
20476 break;
20478 break;
20479 case NM_POOL32F_3:
20480 switch (extract32(ctx->opcode, 3, 3)) {
20481 case NM_MIN_FMT:
20482 switch (extract32(ctx->opcode, 9, 1)) {
20483 case FMT_SDPS_S:
20484 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
20485 break;
20486 case FMT_SDPS_D:
20487 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
20488 break;
20490 break;
20491 case NM_MAX_FMT:
20492 switch (extract32(ctx->opcode, 9, 1)) {
20493 case FMT_SDPS_S:
20494 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
20495 break;
20496 case FMT_SDPS_D:
20497 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
20498 break;
20500 break;
20501 case NM_MINA_FMT:
20502 switch (extract32(ctx->opcode, 9, 1)) {
20503 case FMT_SDPS_S:
20504 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
20505 break;
20506 case FMT_SDPS_D:
20507 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
20508 break;
20510 break;
20511 case NM_MAXA_FMT:
20512 switch (extract32(ctx->opcode, 9, 1)) {
20513 case FMT_SDPS_S:
20514 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
20515 break;
20516 case FMT_SDPS_D:
20517 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
20518 break;
20520 break;
20521 case NM_POOL32FXF:
20522 switch (extract32(ctx->opcode, 6, 8)) {
20523 case NM_CFC1:
20524 gen_cp1(ctx, OPC_CFC1, rt, rs);
20525 break;
20526 case NM_CTC1:
20527 gen_cp1(ctx, OPC_CTC1, rt, rs);
20528 break;
20529 case NM_MFC1:
20530 gen_cp1(ctx, OPC_MFC1, rt, rs);
20531 break;
20532 case NM_MTC1:
20533 gen_cp1(ctx, OPC_MTC1, rt, rs);
20534 break;
20535 case NM_MFHC1:
20536 gen_cp1(ctx, OPC_MFHC1, rt, rs);
20537 break;
20538 case NM_MTHC1:
20539 gen_cp1(ctx, OPC_MTHC1, rt, rs);
20540 break;
20541 case NM_CVT_S_PL:
20542 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
20543 break;
20544 case NM_CVT_S_PU:
20545 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
20546 break;
20547 default:
20548 switch (extract32(ctx->opcode, 6, 9)) {
20549 case NM_CVT_L_S:
20550 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
20551 break;
20552 case NM_CVT_L_D:
20553 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
20554 break;
20555 case NM_CVT_W_S:
20556 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
20557 break;
20558 case NM_CVT_W_D:
20559 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
20560 break;
20561 case NM_RSQRT_S:
20562 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
20563 break;
20564 case NM_RSQRT_D:
20565 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
20566 break;
20567 case NM_SQRT_S:
20568 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
20569 break;
20570 case NM_SQRT_D:
20571 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
20572 break;
20573 case NM_RECIP_S:
20574 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
20575 break;
20576 case NM_RECIP_D:
20577 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
20578 break;
20579 case NM_FLOOR_L_S:
20580 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
20581 break;
20582 case NM_FLOOR_L_D:
20583 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
20584 break;
20585 case NM_FLOOR_W_S:
20586 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
20587 break;
20588 case NM_FLOOR_W_D:
20589 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
20590 break;
20591 case NM_CEIL_L_S:
20592 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
20593 break;
20594 case NM_CEIL_L_D:
20595 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
20596 break;
20597 case NM_CEIL_W_S:
20598 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
20599 break;
20600 case NM_CEIL_W_D:
20601 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
20602 break;
20603 case NM_TRUNC_L_S:
20604 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
20605 break;
20606 case NM_TRUNC_L_D:
20607 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
20608 break;
20609 case NM_TRUNC_W_S:
20610 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
20611 break;
20612 case NM_TRUNC_W_D:
20613 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
20614 break;
20615 case NM_ROUND_L_S:
20616 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
20617 break;
20618 case NM_ROUND_L_D:
20619 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
20620 break;
20621 case NM_ROUND_W_S:
20622 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
20623 break;
20624 case NM_ROUND_W_D:
20625 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
20626 break;
20627 case NM_MOV_S:
20628 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
20629 break;
20630 case NM_MOV_D:
20631 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
20632 break;
20633 case NM_ABS_S:
20634 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
20635 break;
20636 case NM_ABS_D:
20637 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
20638 break;
20639 case NM_NEG_S:
20640 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
20641 break;
20642 case NM_NEG_D:
20643 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
20644 break;
20645 case NM_CVT_D_S:
20646 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
20647 break;
20648 case NM_CVT_D_W:
20649 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
20650 break;
20651 case NM_CVT_D_L:
20652 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
20653 break;
20654 case NM_CVT_S_D:
20655 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
20656 break;
20657 case NM_CVT_S_W:
20658 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
20659 break;
20660 case NM_CVT_S_L:
20661 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
20662 break;
20663 default:
20664 generate_exception_end(ctx, EXCP_RI);
20665 break;
20667 break;
20669 break;
20671 break;
20672 case NM_POOL32F_5:
20673 switch (extract32(ctx->opcode, 3, 3)) {
20674 case NM_CMP_CONDN_S:
20675 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20676 break;
20677 case NM_CMP_CONDN_D:
20678 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20679 break;
20680 default:
20681 generate_exception_end(ctx, EXCP_RI);
20682 break;
20684 break;
20685 default:
20686 generate_exception_end(ctx, EXCP_RI);
20687 break;
20691 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
20692 int rd, int rs, int rt)
20694 int ret = rd;
20695 TCGv t0 = tcg_temp_new();
20696 TCGv v1_t = tcg_temp_new();
20697 TCGv v2_t = tcg_temp_new();
20699 gen_load_gpr(v1_t, rs);
20700 gen_load_gpr(v2_t, rt);
20702 switch (opc) {
20703 case NM_CMP_EQ_PH:
20704 check_dsp(ctx);
20705 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
20706 break;
20707 case NM_CMP_LT_PH:
20708 check_dsp(ctx);
20709 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
20710 break;
20711 case NM_CMP_LE_PH:
20712 check_dsp(ctx);
20713 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
20714 break;
20715 case NM_CMPU_EQ_QB:
20716 check_dsp(ctx);
20717 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
20718 break;
20719 case NM_CMPU_LT_QB:
20720 check_dsp(ctx);
20721 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
20722 break;
20723 case NM_CMPU_LE_QB:
20724 check_dsp(ctx);
20725 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
20726 break;
20727 case NM_CMPGU_EQ_QB:
20728 check_dsp(ctx);
20729 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20730 gen_store_gpr(v1_t, ret);
20731 break;
20732 case NM_CMPGU_LT_QB:
20733 check_dsp(ctx);
20734 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20735 gen_store_gpr(v1_t, ret);
20736 break;
20737 case NM_CMPGU_LE_QB:
20738 check_dsp(ctx);
20739 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20740 gen_store_gpr(v1_t, ret);
20741 break;
20742 case NM_CMPGDU_EQ_QB:
20743 check_dsp_r2(ctx);
20744 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20745 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20746 gen_store_gpr(v1_t, ret);
20747 break;
20748 case NM_CMPGDU_LT_QB:
20749 check_dsp_r2(ctx);
20750 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20751 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20752 gen_store_gpr(v1_t, ret);
20753 break;
20754 case NM_CMPGDU_LE_QB:
20755 check_dsp_r2(ctx);
20756 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20757 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20758 gen_store_gpr(v1_t, ret);
20759 break;
20760 case NM_PACKRL_PH:
20761 check_dsp(ctx);
20762 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
20763 gen_store_gpr(v1_t, ret);
20764 break;
20765 case NM_PICK_QB:
20766 check_dsp(ctx);
20767 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
20768 gen_store_gpr(v1_t, ret);
20769 break;
20770 case NM_PICK_PH:
20771 check_dsp(ctx);
20772 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
20773 gen_store_gpr(v1_t, ret);
20774 break;
20775 case NM_ADDQ_S_W:
20776 check_dsp(ctx);
20777 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
20778 gen_store_gpr(v1_t, ret);
20779 break;
20780 case NM_SUBQ_S_W:
20781 check_dsp(ctx);
20782 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
20783 gen_store_gpr(v1_t, ret);
20784 break;
20785 case NM_ADDSC:
20786 check_dsp(ctx);
20787 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
20788 gen_store_gpr(v1_t, ret);
20789 break;
20790 case NM_ADDWC:
20791 check_dsp(ctx);
20792 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
20793 gen_store_gpr(v1_t, ret);
20794 break;
20795 case NM_ADDQ_S_PH:
20796 check_dsp(ctx);
20797 switch (extract32(ctx->opcode, 10, 1)) {
20798 case 0:
20799 /* ADDQ_PH */
20800 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
20801 gen_store_gpr(v1_t, ret);
20802 break;
20803 case 1:
20804 /* ADDQ_S_PH */
20805 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20806 gen_store_gpr(v1_t, ret);
20807 break;
20809 break;
20810 case NM_ADDQH_R_PH:
20811 check_dsp_r2(ctx);
20812 switch (extract32(ctx->opcode, 10, 1)) {
20813 case 0:
20814 /* ADDQH_PH */
20815 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
20816 gen_store_gpr(v1_t, ret);
20817 break;
20818 case 1:
20819 /* ADDQH_R_PH */
20820 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
20821 gen_store_gpr(v1_t, ret);
20822 break;
20824 break;
20825 case NM_ADDQH_R_W:
20826 check_dsp_r2(ctx);
20827 switch (extract32(ctx->opcode, 10, 1)) {
20828 case 0:
20829 /* ADDQH_W */
20830 gen_helper_addqh_w(v1_t, v1_t, v2_t);
20831 gen_store_gpr(v1_t, ret);
20832 break;
20833 case 1:
20834 /* ADDQH_R_W */
20835 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
20836 gen_store_gpr(v1_t, ret);
20837 break;
20839 break;
20840 case NM_ADDU_S_QB:
20841 check_dsp(ctx);
20842 switch (extract32(ctx->opcode, 10, 1)) {
20843 case 0:
20844 /* ADDU_QB */
20845 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
20846 gen_store_gpr(v1_t, ret);
20847 break;
20848 case 1:
20849 /* ADDU_S_QB */
20850 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20851 gen_store_gpr(v1_t, ret);
20852 break;
20854 break;
20855 case NM_ADDU_S_PH:
20856 check_dsp_r2(ctx);
20857 switch (extract32(ctx->opcode, 10, 1)) {
20858 case 0:
20859 /* ADDU_PH */
20860 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
20861 gen_store_gpr(v1_t, ret);
20862 break;
20863 case 1:
20864 /* ADDU_S_PH */
20865 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20866 gen_store_gpr(v1_t, ret);
20867 break;
20869 break;
20870 case NM_ADDUH_R_QB:
20871 check_dsp_r2(ctx);
20872 switch (extract32(ctx->opcode, 10, 1)) {
20873 case 0:
20874 /* ADDUH_QB */
20875 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
20876 gen_store_gpr(v1_t, ret);
20877 break;
20878 case 1:
20879 /* ADDUH_R_QB */
20880 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
20881 gen_store_gpr(v1_t, ret);
20882 break;
20884 break;
20885 case NM_SHRAV_R_PH:
20886 check_dsp(ctx);
20887 switch (extract32(ctx->opcode, 10, 1)) {
20888 case 0:
20889 /* SHRAV_PH */
20890 gen_helper_shra_ph(v1_t, v1_t, v2_t);
20891 gen_store_gpr(v1_t, ret);
20892 break;
20893 case 1:
20894 /* SHRAV_R_PH */
20895 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
20896 gen_store_gpr(v1_t, ret);
20897 break;
20899 break;
20900 case NM_SHRAV_R_QB:
20901 check_dsp_r2(ctx);
20902 switch (extract32(ctx->opcode, 10, 1)) {
20903 case 0:
20904 /* SHRAV_QB */
20905 gen_helper_shra_qb(v1_t, v1_t, v2_t);
20906 gen_store_gpr(v1_t, ret);
20907 break;
20908 case 1:
20909 /* SHRAV_R_QB */
20910 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
20911 gen_store_gpr(v1_t, ret);
20912 break;
20914 break;
20915 case NM_SUBQ_S_PH:
20916 check_dsp(ctx);
20917 switch (extract32(ctx->opcode, 10, 1)) {
20918 case 0:
20919 /* SUBQ_PH */
20920 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
20921 gen_store_gpr(v1_t, ret);
20922 break;
20923 case 1:
20924 /* SUBQ_S_PH */
20925 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20926 gen_store_gpr(v1_t, ret);
20927 break;
20929 break;
20930 case NM_SUBQH_R_PH:
20931 check_dsp_r2(ctx);
20932 switch (extract32(ctx->opcode, 10, 1)) {
20933 case 0:
20934 /* SUBQH_PH */
20935 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
20936 gen_store_gpr(v1_t, ret);
20937 break;
20938 case 1:
20939 /* SUBQH_R_PH */
20940 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
20941 gen_store_gpr(v1_t, ret);
20942 break;
20944 break;
20945 case NM_SUBQH_R_W:
20946 check_dsp_r2(ctx);
20947 switch (extract32(ctx->opcode, 10, 1)) {
20948 case 0:
20949 /* SUBQH_W */
20950 gen_helper_subqh_w(v1_t, v1_t, v2_t);
20951 gen_store_gpr(v1_t, ret);
20952 break;
20953 case 1:
20954 /* SUBQH_R_W */
20955 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
20956 gen_store_gpr(v1_t, ret);
20957 break;
20959 break;
20960 case NM_SUBU_S_QB:
20961 check_dsp(ctx);
20962 switch (extract32(ctx->opcode, 10, 1)) {
20963 case 0:
20964 /* SUBU_QB */
20965 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
20966 gen_store_gpr(v1_t, ret);
20967 break;
20968 case 1:
20969 /* SUBU_S_QB */
20970 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20971 gen_store_gpr(v1_t, ret);
20972 break;
20974 break;
20975 case NM_SUBU_S_PH:
20976 check_dsp_r2(ctx);
20977 switch (extract32(ctx->opcode, 10, 1)) {
20978 case 0:
20979 /* SUBU_PH */
20980 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
20981 gen_store_gpr(v1_t, ret);
20982 break;
20983 case 1:
20984 /* SUBU_S_PH */
20985 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20986 gen_store_gpr(v1_t, ret);
20987 break;
20989 break;
20990 case NM_SUBUH_R_QB:
20991 check_dsp_r2(ctx);
20992 switch (extract32(ctx->opcode, 10, 1)) {
20993 case 0:
20994 /* SUBUH_QB */
20995 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
20996 gen_store_gpr(v1_t, ret);
20997 break;
20998 case 1:
20999 /* SUBUH_R_QB */
21000 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
21001 gen_store_gpr(v1_t, ret);
21002 break;
21004 break;
21005 case NM_SHLLV_S_PH:
21006 check_dsp(ctx);
21007 switch (extract32(ctx->opcode, 10, 1)) {
21008 case 0:
21009 /* SHLLV_PH */
21010 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
21011 gen_store_gpr(v1_t, ret);
21012 break;
21013 case 1:
21014 /* SHLLV_S_PH */
21015 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
21016 gen_store_gpr(v1_t, ret);
21017 break;
21019 break;
21020 case NM_PRECR_SRA_R_PH_W:
21021 check_dsp_r2(ctx);
21022 switch (extract32(ctx->opcode, 10, 1)) {
21023 case 0:
21024 /* PRECR_SRA_PH_W */
21026 TCGv_i32 sa_t = tcg_const_i32(rd);
21027 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
21028 cpu_gpr[rt]);
21029 gen_store_gpr(v1_t, rt);
21030 tcg_temp_free_i32(sa_t);
21032 break;
21033 case 1:
21034 /* PRECR_SRA_R_PH_W */
21036 TCGv_i32 sa_t = tcg_const_i32(rd);
21037 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
21038 cpu_gpr[rt]);
21039 gen_store_gpr(v1_t, rt);
21040 tcg_temp_free_i32(sa_t);
21042 break;
21044 break;
21045 case NM_MULEU_S_PH_QBL:
21046 check_dsp(ctx);
21047 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
21048 gen_store_gpr(v1_t, ret);
21049 break;
21050 case NM_MULEU_S_PH_QBR:
21051 check_dsp(ctx);
21052 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
21053 gen_store_gpr(v1_t, ret);
21054 break;
21055 case NM_MULQ_RS_PH:
21056 check_dsp(ctx);
21057 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
21058 gen_store_gpr(v1_t, ret);
21059 break;
21060 case NM_MULQ_S_PH:
21061 check_dsp_r2(ctx);
21062 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
21063 gen_store_gpr(v1_t, ret);
21064 break;
21065 case NM_MULQ_RS_W:
21066 check_dsp_r2(ctx);
21067 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
21068 gen_store_gpr(v1_t, ret);
21069 break;
21070 case NM_MULQ_S_W:
21071 check_dsp_r2(ctx);
21072 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
21073 gen_store_gpr(v1_t, ret);
21074 break;
21075 case NM_APPEND:
21076 check_dsp_r2(ctx);
21077 gen_load_gpr(t0, rs);
21078 if (rd != 0) {
21079 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
21081 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21082 break;
21083 case NM_MODSUB:
21084 check_dsp(ctx);
21085 gen_helper_modsub(v1_t, v1_t, v2_t);
21086 gen_store_gpr(v1_t, ret);
21087 break;
21088 case NM_SHRAV_R_W:
21089 check_dsp(ctx);
21090 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
21091 gen_store_gpr(v1_t, ret);
21092 break;
21093 case NM_SHRLV_PH:
21094 check_dsp_r2(ctx);
21095 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
21096 gen_store_gpr(v1_t, ret);
21097 break;
21098 case NM_SHRLV_QB:
21099 check_dsp(ctx);
21100 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
21101 gen_store_gpr(v1_t, ret);
21102 break;
21103 case NM_SHLLV_QB:
21104 check_dsp(ctx);
21105 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
21106 gen_store_gpr(v1_t, ret);
21107 break;
21108 case NM_SHLLV_S_W:
21109 check_dsp(ctx);
21110 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
21111 gen_store_gpr(v1_t, ret);
21112 break;
21113 case NM_SHILO:
21114 check_dsp(ctx);
21116 TCGv tv0 = tcg_temp_new();
21117 TCGv tv1 = tcg_temp_new();
21118 int16_t imm = extract32(ctx->opcode, 16, 7);
21120 tcg_gen_movi_tl(tv0, rd >> 3);
21121 tcg_gen_movi_tl(tv1, imm);
21122 gen_helper_shilo(tv0, tv1, cpu_env);
21124 break;
21125 case NM_MULEQ_S_W_PHL:
21126 check_dsp(ctx);
21127 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
21128 gen_store_gpr(v1_t, ret);
21129 break;
21130 case NM_MULEQ_S_W_PHR:
21131 check_dsp(ctx);
21132 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
21133 gen_store_gpr(v1_t, ret);
21134 break;
21135 case NM_MUL_S_PH:
21136 check_dsp_r2(ctx);
21137 switch (extract32(ctx->opcode, 10, 1)) {
21138 case 0:
21139 /* MUL_PH */
21140 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
21141 gen_store_gpr(v1_t, ret);
21142 break;
21143 case 1:
21144 /* MUL_S_PH */
21145 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
21146 gen_store_gpr(v1_t, ret);
21147 break;
21149 break;
21150 case NM_PRECR_QB_PH:
21151 check_dsp_r2(ctx);
21152 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
21153 gen_store_gpr(v1_t, ret);
21154 break;
21155 case NM_PRECRQ_QB_PH:
21156 check_dsp(ctx);
21157 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
21158 gen_store_gpr(v1_t, ret);
21159 break;
21160 case NM_PRECRQ_PH_W:
21161 check_dsp(ctx);
21162 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
21163 gen_store_gpr(v1_t, ret);
21164 break;
21165 case NM_PRECRQ_RS_PH_W:
21166 check_dsp(ctx);
21167 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
21168 gen_store_gpr(v1_t, ret);
21169 break;
21170 case NM_PRECRQU_S_QB_PH:
21171 check_dsp(ctx);
21172 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
21173 gen_store_gpr(v1_t, ret);
21174 break;
21175 case NM_SHRA_R_W:
21176 check_dsp(ctx);
21177 tcg_gen_movi_tl(t0, rd);
21178 gen_helper_shra_r_w(v1_t, t0, v1_t);
21179 gen_store_gpr(v1_t, rt);
21180 break;
21181 case NM_SHRA_R_PH:
21182 check_dsp(ctx);
21183 tcg_gen_movi_tl(t0, rd >> 1);
21184 switch (extract32(ctx->opcode, 10, 1)) {
21185 case 0:
21186 /* SHRA_PH */
21187 gen_helper_shra_ph(v1_t, t0, v1_t);
21188 gen_store_gpr(v1_t, rt);
21189 break;
21190 case 1:
21191 /* SHRA_R_PH */
21192 gen_helper_shra_r_ph(v1_t, t0, v1_t);
21193 gen_store_gpr(v1_t, rt);
21194 break;
21196 break;
21197 case NM_SHLL_S_PH:
21198 check_dsp(ctx);
21199 tcg_gen_movi_tl(t0, rd >> 1);
21200 switch (extract32(ctx->opcode, 10, 2)) {
21201 case 0:
21202 /* SHLL_PH */
21203 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
21204 gen_store_gpr(v1_t, rt);
21205 break;
21206 case 2:
21207 /* SHLL_S_PH */
21208 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
21209 gen_store_gpr(v1_t, rt);
21210 break;
21211 default:
21212 generate_exception_end(ctx, EXCP_RI);
21213 break;
21215 break;
21216 case NM_SHLL_S_W:
21217 check_dsp(ctx);
21218 tcg_gen_movi_tl(t0, rd);
21219 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
21220 gen_store_gpr(v1_t, rt);
21221 break;
21222 case NM_REPL_PH:
21223 check_dsp(ctx);
21225 int16_t imm;
21226 imm = sextract32(ctx->opcode, 11, 11);
21227 imm = (int16_t)(imm << 6) >> 6;
21228 if (rt != 0) {
21229 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
21232 break;
21233 default:
21234 generate_exception_end(ctx, EXCP_RI);
21235 break;
21239 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
21241 uint16_t insn;
21242 uint32_t op;
21243 int rt, rs, rd;
21244 int offset;
21245 int imm;
21247 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
21248 ctx->opcode = (ctx->opcode << 16) | insn;
21250 rt = extract32(ctx->opcode, 21, 5);
21251 rs = extract32(ctx->opcode, 16, 5);
21252 rd = extract32(ctx->opcode, 11, 5);
21254 op = extract32(ctx->opcode, 26, 6);
21255 switch (op) {
21256 case NM_P_ADDIU:
21257 if (rt == 0) {
21258 /* P.RI */
21259 switch (extract32(ctx->opcode, 19, 2)) {
21260 case NM_SIGRIE:
21261 default:
21262 generate_exception_end(ctx, EXCP_RI);
21263 break;
21264 case NM_P_SYSCALL:
21265 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
21266 generate_exception_end(ctx, EXCP_SYSCALL);
21267 } else {
21268 generate_exception_end(ctx, EXCP_RI);
21270 break;
21271 case NM_BREAK:
21272 generate_exception_end(ctx, EXCP_BREAK);
21273 break;
21274 case NM_SDBBP:
21275 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
21276 gen_helper_do_semihosting(cpu_env);
21277 } else {
21278 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21279 generate_exception_end(ctx, EXCP_RI);
21280 } else {
21281 generate_exception_end(ctx, EXCP_DBp);
21284 break;
21286 } else {
21287 /* NM_ADDIU */
21288 imm = extract32(ctx->opcode, 0, 16);
21289 if (rs != 0) {
21290 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
21291 } else {
21292 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21294 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21296 break;
21297 case NM_ADDIUPC:
21298 if (rt != 0) {
21299 offset = sextract32(ctx->opcode, 0, 1) << 21 |
21300 extract32(ctx->opcode, 1, 20) << 1;
21301 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
21302 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21304 break;
21305 case NM_POOL32A:
21306 switch (ctx->opcode & 0x07) {
21307 case NM_POOL32A0:
21308 gen_pool32a0_nanomips_insn(env, ctx);
21309 break;
21310 case NM_POOL32A5:
21312 int32_t op1 = extract32(ctx->opcode, 3, 7);
21313 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
21315 break;
21316 case NM_POOL32A7:
21317 switch (extract32(ctx->opcode, 3, 3)) {
21318 case NM_P_LSX:
21319 gen_p_lsx(ctx, rd, rs, rt);
21320 break;
21321 case NM_LSA:
21323 * In nanoMIPS, the shift field directly encodes the shift
21324 * amount, meaning that the supported shift values are in
21325 * the range 0 to 3 (instead of 1 to 4 in MIPSR6).
21327 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
21328 extract32(ctx->opcode, 9, 2) - 1);
21329 break;
21330 case NM_EXTW:
21331 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
21332 break;
21333 case NM_POOL32AXF:
21334 gen_pool32axf_nanomips_insn(env, ctx);
21335 break;
21336 default:
21337 generate_exception_end(ctx, EXCP_RI);
21338 break;
21340 break;
21341 default:
21342 generate_exception_end(ctx, EXCP_RI);
21343 break;
21345 break;
21346 case NM_P_GP_W:
21347 switch (ctx->opcode & 0x03) {
21348 case NM_ADDIUGP_W:
21349 if (rt != 0) {
21350 offset = extract32(ctx->opcode, 0, 21);
21351 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
21353 break;
21354 case NM_LWGP:
21355 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21356 break;
21357 case NM_SWGP:
21358 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21359 break;
21360 default:
21361 generate_exception_end(ctx, EXCP_RI);
21362 break;
21364 break;
21365 case NM_P48I:
21367 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
21368 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
21369 switch (extract32(ctx->opcode, 16, 5)) {
21370 case NM_LI48:
21371 check_nms(ctx);
21372 if (rt != 0) {
21373 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
21375 break;
21376 case NM_ADDIU48:
21377 check_nms(ctx);
21378 if (rt != 0) {
21379 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
21380 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21382 break;
21383 case NM_ADDIUGP48:
21384 check_nms(ctx);
21385 if (rt != 0) {
21386 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
21388 break;
21389 case NM_ADDIUPC48:
21390 check_nms(ctx);
21391 if (rt != 0) {
21392 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21393 addr_off);
21395 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21397 break;
21398 case NM_LWPC48:
21399 check_nms(ctx);
21400 if (rt != 0) {
21401 TCGv t0;
21402 t0 = tcg_temp_new();
21404 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21405 addr_off);
21407 tcg_gen_movi_tl(t0, addr);
21408 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
21409 tcg_temp_free(t0);
21411 break;
21412 case NM_SWPC48:
21413 check_nms(ctx);
21415 TCGv t0, t1;
21416 t0 = tcg_temp_new();
21417 t1 = tcg_temp_new();
21419 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21420 addr_off);
21422 tcg_gen_movi_tl(t0, addr);
21423 gen_load_gpr(t1, rt);
21425 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
21427 tcg_temp_free(t0);
21428 tcg_temp_free(t1);
21430 break;
21431 default:
21432 generate_exception_end(ctx, EXCP_RI);
21433 break;
21435 return 6;
21437 case NM_P_U12:
21438 switch (extract32(ctx->opcode, 12, 4)) {
21439 case NM_ORI:
21440 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
21441 break;
21442 case NM_XORI:
21443 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
21444 break;
21445 case NM_ANDI:
21446 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
21447 break;
21448 case NM_P_SR:
21449 switch (extract32(ctx->opcode, 20, 1)) {
21450 case NM_PP_SR:
21451 switch (ctx->opcode & 3) {
21452 case NM_SAVE:
21453 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
21454 extract32(ctx->opcode, 2, 1),
21455 extract32(ctx->opcode, 3, 9) << 3);
21456 break;
21457 case NM_RESTORE:
21458 case NM_RESTORE_JRC:
21459 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
21460 extract32(ctx->opcode, 2, 1),
21461 extract32(ctx->opcode, 3, 9) << 3);
21462 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
21463 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21465 break;
21466 default:
21467 generate_exception_end(ctx, EXCP_RI);
21468 break;
21470 break;
21471 case NM_P_SR_F:
21472 generate_exception_end(ctx, EXCP_RI);
21473 break;
21475 break;
21476 case NM_SLTI:
21477 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
21478 break;
21479 case NM_SLTIU:
21480 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
21481 break;
21482 case NM_SEQI:
21484 TCGv t0 = tcg_temp_new();
21486 imm = extract32(ctx->opcode, 0, 12);
21487 gen_load_gpr(t0, rs);
21488 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
21489 gen_store_gpr(t0, rt);
21491 tcg_temp_free(t0);
21493 break;
21494 case NM_ADDIUNEG:
21495 imm = (int16_t) extract32(ctx->opcode, 0, 12);
21496 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
21497 break;
21498 case NM_P_SHIFT:
21500 int shift = extract32(ctx->opcode, 0, 5);
21501 switch (extract32(ctx->opcode, 5, 4)) {
21502 case NM_P_SLL:
21503 if (rt == 0 && shift == 0) {
21504 /* NOP */
21505 } else if (rt == 0 && shift == 3) {
21506 /* EHB - treat as NOP */
21507 } else if (rt == 0 && shift == 5) {
21508 /* PAUSE - treat as NOP */
21509 } else if (rt == 0 && shift == 6) {
21510 /* SYNC */
21511 gen_sync(extract32(ctx->opcode, 16, 5));
21512 } else {
21513 /* SLL */
21514 gen_shift_imm(ctx, OPC_SLL, rt, rs,
21515 extract32(ctx->opcode, 0, 5));
21517 break;
21518 case NM_SRL:
21519 gen_shift_imm(ctx, OPC_SRL, rt, rs,
21520 extract32(ctx->opcode, 0, 5));
21521 break;
21522 case NM_SRA:
21523 gen_shift_imm(ctx, OPC_SRA, rt, rs,
21524 extract32(ctx->opcode, 0, 5));
21525 break;
21526 case NM_ROTR:
21527 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
21528 extract32(ctx->opcode, 0, 5));
21529 break;
21532 break;
21533 case NM_P_ROTX:
21534 check_nms(ctx);
21535 if (rt != 0) {
21536 TCGv t0 = tcg_temp_new();
21537 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
21538 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
21539 << 1);
21540 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
21542 gen_load_gpr(t0, rs);
21543 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
21544 tcg_temp_free(t0);
21546 tcg_temp_free_i32(shift);
21547 tcg_temp_free_i32(shiftx);
21548 tcg_temp_free_i32(stripe);
21550 break;
21551 case NM_P_INS:
21552 switch (((ctx->opcode >> 10) & 2) |
21553 (extract32(ctx->opcode, 5, 1))) {
21554 case NM_INS:
21555 check_nms(ctx);
21556 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
21557 extract32(ctx->opcode, 6, 5));
21558 break;
21559 default:
21560 generate_exception_end(ctx, EXCP_RI);
21561 break;
21563 break;
21564 case NM_P_EXT:
21565 switch (((ctx->opcode >> 10) & 2) |
21566 (extract32(ctx->opcode, 5, 1))) {
21567 case NM_EXT:
21568 check_nms(ctx);
21569 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
21570 extract32(ctx->opcode, 6, 5));
21571 break;
21572 default:
21573 generate_exception_end(ctx, EXCP_RI);
21574 break;
21576 break;
21577 default:
21578 generate_exception_end(ctx, EXCP_RI);
21579 break;
21581 break;
21582 case NM_POOL32F:
21583 gen_pool32f_nanomips_insn(ctx);
21584 break;
21585 case NM_POOL32S:
21586 break;
21587 case NM_P_LUI:
21588 switch (extract32(ctx->opcode, 1, 1)) {
21589 case NM_LUI:
21590 if (rt != 0) {
21591 tcg_gen_movi_tl(cpu_gpr[rt],
21592 sextract32(ctx->opcode, 0, 1) << 31 |
21593 extract32(ctx->opcode, 2, 10) << 21 |
21594 extract32(ctx->opcode, 12, 9) << 12);
21596 break;
21597 case NM_ALUIPC:
21598 if (rt != 0) {
21599 offset = sextract32(ctx->opcode, 0, 1) << 31 |
21600 extract32(ctx->opcode, 2, 10) << 21 |
21601 extract32(ctx->opcode, 12, 9) << 12;
21602 target_long addr;
21603 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
21604 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21606 break;
21608 break;
21609 case NM_P_GP_BH:
21611 uint32_t u = extract32(ctx->opcode, 0, 18);
21613 switch (extract32(ctx->opcode, 18, 3)) {
21614 case NM_LBGP:
21615 gen_ld(ctx, OPC_LB, rt, 28, u);
21616 break;
21617 case NM_SBGP:
21618 gen_st(ctx, OPC_SB, rt, 28, u);
21619 break;
21620 case NM_LBUGP:
21621 gen_ld(ctx, OPC_LBU, rt, 28, u);
21622 break;
21623 case NM_ADDIUGP_B:
21624 if (rt != 0) {
21625 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
21627 break;
21628 case NM_P_GP_LH:
21629 u &= ~1;
21630 switch (ctx->opcode & 1) {
21631 case NM_LHGP:
21632 gen_ld(ctx, OPC_LH, rt, 28, u);
21633 break;
21634 case NM_LHUGP:
21635 gen_ld(ctx, OPC_LHU, rt, 28, u);
21636 break;
21638 break;
21639 case NM_P_GP_SH:
21640 u &= ~1;
21641 switch (ctx->opcode & 1) {
21642 case NM_SHGP:
21643 gen_st(ctx, OPC_SH, rt, 28, u);
21644 break;
21645 default:
21646 generate_exception_end(ctx, EXCP_RI);
21647 break;
21649 break;
21650 case NM_P_GP_CP1:
21651 u &= ~0x3;
21652 switch (ctx->opcode & 0x3) {
21653 case NM_LWC1GP:
21654 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
21655 break;
21656 case NM_LDC1GP:
21657 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
21658 break;
21659 case NM_SWC1GP:
21660 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
21661 break;
21662 case NM_SDC1GP:
21663 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
21664 break;
21666 break;
21667 default:
21668 generate_exception_end(ctx, EXCP_RI);
21669 break;
21672 break;
21673 case NM_P_LS_U12:
21675 uint32_t u = extract32(ctx->opcode, 0, 12);
21677 switch (extract32(ctx->opcode, 12, 4)) {
21678 case NM_P_PREFU12:
21679 if (rt == 31) {
21680 /* SYNCI */
21682 * Break the TB to be able to sync copied instructions
21683 * immediately.
21685 ctx->base.is_jmp = DISAS_STOP;
21686 } else {
21687 /* PREF */
21688 /* Treat as NOP. */
21690 break;
21691 case NM_LB:
21692 gen_ld(ctx, OPC_LB, rt, rs, u);
21693 break;
21694 case NM_LH:
21695 gen_ld(ctx, OPC_LH, rt, rs, u);
21696 break;
21697 case NM_LW:
21698 gen_ld(ctx, OPC_LW, rt, rs, u);
21699 break;
21700 case NM_LBU:
21701 gen_ld(ctx, OPC_LBU, rt, rs, u);
21702 break;
21703 case NM_LHU:
21704 gen_ld(ctx, OPC_LHU, rt, rs, u);
21705 break;
21706 case NM_SB:
21707 gen_st(ctx, OPC_SB, rt, rs, u);
21708 break;
21709 case NM_SH:
21710 gen_st(ctx, OPC_SH, rt, rs, u);
21711 break;
21712 case NM_SW:
21713 gen_st(ctx, OPC_SW, rt, rs, u);
21714 break;
21715 case NM_LWC1:
21716 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
21717 break;
21718 case NM_LDC1:
21719 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
21720 break;
21721 case NM_SWC1:
21722 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
21723 break;
21724 case NM_SDC1:
21725 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
21726 break;
21727 default:
21728 generate_exception_end(ctx, EXCP_RI);
21729 break;
21732 break;
21733 case NM_P_LS_S9:
21735 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
21736 extract32(ctx->opcode, 0, 8);
21738 switch (extract32(ctx->opcode, 8, 3)) {
21739 case NM_P_LS_S0:
21740 switch (extract32(ctx->opcode, 11, 4)) {
21741 case NM_LBS9:
21742 gen_ld(ctx, OPC_LB, rt, rs, s);
21743 break;
21744 case NM_LHS9:
21745 gen_ld(ctx, OPC_LH, rt, rs, s);
21746 break;
21747 case NM_LWS9:
21748 gen_ld(ctx, OPC_LW, rt, rs, s);
21749 break;
21750 case NM_LBUS9:
21751 gen_ld(ctx, OPC_LBU, rt, rs, s);
21752 break;
21753 case NM_LHUS9:
21754 gen_ld(ctx, OPC_LHU, rt, rs, s);
21755 break;
21756 case NM_SBS9:
21757 gen_st(ctx, OPC_SB, rt, rs, s);
21758 break;
21759 case NM_SHS9:
21760 gen_st(ctx, OPC_SH, rt, rs, s);
21761 break;
21762 case NM_SWS9:
21763 gen_st(ctx, OPC_SW, rt, rs, s);
21764 break;
21765 case NM_LWC1S9:
21766 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
21767 break;
21768 case NM_LDC1S9:
21769 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
21770 break;
21771 case NM_SWC1S9:
21772 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
21773 break;
21774 case NM_SDC1S9:
21775 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
21776 break;
21777 case NM_P_PREFS9:
21778 if (rt == 31) {
21779 /* SYNCI */
21781 * Break the TB to be able to sync copied instructions
21782 * immediately.
21784 ctx->base.is_jmp = DISAS_STOP;
21785 } else {
21786 /* PREF */
21787 /* Treat as NOP. */
21789 break;
21790 default:
21791 generate_exception_end(ctx, EXCP_RI);
21792 break;
21794 break;
21795 case NM_P_LS_S1:
21796 switch (extract32(ctx->opcode, 11, 4)) {
21797 case NM_UALH:
21798 case NM_UASH:
21799 check_nms(ctx);
21801 TCGv t0 = tcg_temp_new();
21802 TCGv t1 = tcg_temp_new();
21804 gen_base_offset_addr(ctx, t0, rs, s);
21806 switch (extract32(ctx->opcode, 11, 4)) {
21807 case NM_UALH:
21808 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
21809 MO_UNALN);
21810 gen_store_gpr(t0, rt);
21811 break;
21812 case NM_UASH:
21813 gen_load_gpr(t1, rt);
21814 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
21815 MO_UNALN);
21816 break;
21818 tcg_temp_free(t0);
21819 tcg_temp_free(t1);
21821 break;
21822 case NM_P_LL:
21823 switch (ctx->opcode & 0x03) {
21824 case NM_LL:
21825 gen_ld(ctx, OPC_LL, rt, rs, s);
21826 break;
21827 case NM_LLWP:
21828 check_xnp(ctx);
21829 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21830 break;
21832 break;
21833 case NM_P_SC:
21834 switch (ctx->opcode & 0x03) {
21835 case NM_SC:
21836 gen_st_cond(ctx, rt, rs, s, MO_TESL, false);
21837 break;
21838 case NM_SCWP:
21839 check_xnp(ctx);
21840 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21841 false);
21842 break;
21844 break;
21845 case NM_CACHE:
21846 check_cp0_enabled(ctx);
21847 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
21848 gen_cache_operation(ctx, rt, rs, s);
21850 break;
21852 break;
21853 case NM_P_LS_E0:
21854 switch (extract32(ctx->opcode, 11, 4)) {
21855 case NM_LBE:
21856 check_eva(ctx);
21857 check_cp0_enabled(ctx);
21858 gen_ld(ctx, OPC_LBE, rt, rs, s);
21859 break;
21860 case NM_SBE:
21861 check_eva(ctx);
21862 check_cp0_enabled(ctx);
21863 gen_st(ctx, OPC_SBE, rt, rs, s);
21864 break;
21865 case NM_LBUE:
21866 check_eva(ctx);
21867 check_cp0_enabled(ctx);
21868 gen_ld(ctx, OPC_LBUE, rt, rs, s);
21869 break;
21870 case NM_P_PREFE:
21871 if (rt == 31) {
21872 /* case NM_SYNCIE */
21873 check_eva(ctx);
21874 check_cp0_enabled(ctx);
21876 * Break the TB to be able to sync copied instructions
21877 * immediately.
21879 ctx->base.is_jmp = DISAS_STOP;
21880 } else {
21881 /* case NM_PREFE */
21882 check_eva(ctx);
21883 check_cp0_enabled(ctx);
21884 /* Treat as NOP. */
21886 break;
21887 case NM_LHE:
21888 check_eva(ctx);
21889 check_cp0_enabled(ctx);
21890 gen_ld(ctx, OPC_LHE, rt, rs, s);
21891 break;
21892 case NM_SHE:
21893 check_eva(ctx);
21894 check_cp0_enabled(ctx);
21895 gen_st(ctx, OPC_SHE, rt, rs, s);
21896 break;
21897 case NM_LHUE:
21898 check_eva(ctx);
21899 check_cp0_enabled(ctx);
21900 gen_ld(ctx, OPC_LHUE, rt, rs, s);
21901 break;
21902 case NM_CACHEE:
21903 check_nms_dl_il_sl_tl_l2c(ctx);
21904 gen_cache_operation(ctx, rt, rs, s);
21905 break;
21906 case NM_LWE:
21907 check_eva(ctx);
21908 check_cp0_enabled(ctx);
21909 gen_ld(ctx, OPC_LWE, rt, rs, s);
21910 break;
21911 case NM_SWE:
21912 check_eva(ctx);
21913 check_cp0_enabled(ctx);
21914 gen_st(ctx, OPC_SWE, rt, rs, s);
21915 break;
21916 case NM_P_LLE:
21917 switch (extract32(ctx->opcode, 2, 2)) {
21918 case NM_LLE:
21919 check_xnp(ctx);
21920 check_eva(ctx);
21921 check_cp0_enabled(ctx);
21922 gen_ld(ctx, OPC_LLE, rt, rs, s);
21923 break;
21924 case NM_LLWPE:
21925 check_xnp(ctx);
21926 check_eva(ctx);
21927 check_cp0_enabled(ctx);
21928 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21929 break;
21930 default:
21931 generate_exception_end(ctx, EXCP_RI);
21932 break;
21934 break;
21935 case NM_P_SCE:
21936 switch (extract32(ctx->opcode, 2, 2)) {
21937 case NM_SCE:
21938 check_xnp(ctx);
21939 check_eva(ctx);
21940 check_cp0_enabled(ctx);
21941 gen_st_cond(ctx, rt, rs, s, MO_TESL, true);
21942 break;
21943 case NM_SCWPE:
21944 check_xnp(ctx);
21945 check_eva(ctx);
21946 check_cp0_enabled(ctx);
21947 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21948 true);
21949 break;
21950 default:
21951 generate_exception_end(ctx, EXCP_RI);
21952 break;
21954 break;
21956 break;
21957 case NM_P_LS_WM:
21958 case NM_P_LS_UAWM:
21959 check_nms(ctx);
21961 int count = extract32(ctx->opcode, 12, 3);
21962 int counter = 0;
21964 offset = sextract32(ctx->opcode, 15, 1) << 8 |
21965 extract32(ctx->opcode, 0, 8);
21966 TCGv va = tcg_temp_new();
21967 TCGv t1 = tcg_temp_new();
21968 MemOp memop = (extract32(ctx->opcode, 8, 3)) ==
21969 NM_P_LS_UAWM ? MO_UNALN : 0;
21971 count = (count == 0) ? 8 : count;
21972 while (counter != count) {
21973 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
21974 int this_offset = offset + (counter << 2);
21976 gen_base_offset_addr(ctx, va, rs, this_offset);
21978 switch (extract32(ctx->opcode, 11, 1)) {
21979 case NM_LWM:
21980 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
21981 memop | MO_TESL);
21982 gen_store_gpr(t1, this_rt);
21983 if ((this_rt == rs) &&
21984 (counter != (count - 1))) {
21985 /* UNPREDICTABLE */
21987 break;
21988 case NM_SWM:
21989 this_rt = (rt == 0) ? 0 : this_rt;
21990 gen_load_gpr(t1, this_rt);
21991 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
21992 memop | MO_TEUL);
21993 break;
21995 counter++;
21997 tcg_temp_free(va);
21998 tcg_temp_free(t1);
22000 break;
22001 default:
22002 generate_exception_end(ctx, EXCP_RI);
22003 break;
22006 break;
22007 case NM_MOVE_BALC:
22008 check_nms(ctx);
22010 TCGv t0 = tcg_temp_new();
22011 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
22012 extract32(ctx->opcode, 1, 20) << 1;
22013 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
22014 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
22015 extract32(ctx->opcode, 21, 3));
22016 gen_load_gpr(t0, rt);
22017 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22018 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
22019 tcg_temp_free(t0);
22021 break;
22022 case NM_P_BAL:
22024 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
22025 extract32(ctx->opcode, 1, 24) << 1;
22027 if ((extract32(ctx->opcode, 25, 1)) == 0) {
22028 /* BC */
22029 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
22030 } else {
22031 /* BALC */
22032 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
22035 break;
22036 case NM_P_J:
22037 switch (extract32(ctx->opcode, 12, 4)) {
22038 case NM_JALRC:
22039 case NM_JALRC_HB:
22040 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
22041 break;
22042 case NM_P_BALRSC:
22043 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
22044 break;
22045 default:
22046 generate_exception_end(ctx, EXCP_RI);
22047 break;
22049 break;
22050 case NM_P_BR1:
22052 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
22053 extract32(ctx->opcode, 1, 13) << 1;
22054 switch (extract32(ctx->opcode, 14, 2)) {
22055 case NM_BEQC:
22056 check_nms(ctx);
22057 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
22058 break;
22059 case NM_P_BR3A:
22060 s = sextract32(ctx->opcode, 0, 1) << 14 |
22061 extract32(ctx->opcode, 1, 13) << 1;
22062 check_cp1_enabled(ctx);
22063 switch (extract32(ctx->opcode, 16, 5)) {
22064 case NM_BC1EQZC:
22065 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
22066 break;
22067 case NM_BC1NEZC:
22068 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
22069 break;
22070 case NM_BPOSGE32C:
22071 check_dsp_r3(ctx);
22073 int32_t imm = extract32(ctx->opcode, 1, 13) |
22074 extract32(ctx->opcode, 0, 1) << 13;
22076 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
22077 imm);
22079 break;
22080 default:
22081 generate_exception_end(ctx, EXCP_RI);
22082 break;
22084 break;
22085 case NM_BGEC:
22086 if (rs == rt) {
22087 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
22088 } else {
22089 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
22091 break;
22092 case NM_BGEUC:
22093 if (rs == rt || rt == 0) {
22094 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
22095 } else if (rs == 0) {
22096 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
22097 } else {
22098 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
22100 break;
22103 break;
22104 case NM_P_BR2:
22106 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
22107 extract32(ctx->opcode, 1, 13) << 1;
22108 switch (extract32(ctx->opcode, 14, 2)) {
22109 case NM_BNEC:
22110 check_nms(ctx);
22111 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
22112 break;
22113 case NM_BLTC:
22114 if (rs != 0 && rt != 0 && rs == rt) {
22115 /* NOP */
22116 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22117 } else {
22118 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
22120 break;
22121 case NM_BLTUC:
22122 if (rs == 0 || rs == rt) {
22123 /* NOP */
22124 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22125 } else {
22126 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
22128 break;
22129 default:
22130 generate_exception_end(ctx, EXCP_RI);
22131 break;
22134 break;
22135 case NM_P_BRI:
22137 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
22138 extract32(ctx->opcode, 1, 10) << 1;
22139 uint32_t u = extract32(ctx->opcode, 11, 7);
22141 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
22142 rt, u, s);
22144 break;
22145 default:
22146 generate_exception_end(ctx, EXCP_RI);
22147 break;
22149 return 4;
22152 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
22154 uint32_t op;
22155 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
22156 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22157 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode));
22158 int offset;
22159 int imm;
22161 /* make sure instructions are on a halfword boundary */
22162 if (ctx->base.pc_next & 0x1) {
22163 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
22164 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
22165 tcg_temp_free(tmp);
22166 generate_exception_end(ctx, EXCP_AdEL);
22167 return 2;
22170 op = extract32(ctx->opcode, 10, 6);
22171 switch (op) {
22172 case NM_P16_MV:
22173 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22174 if (rt != 0) {
22175 /* MOVE */
22176 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
22177 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
22178 } else {
22179 /* P16.RI */
22180 switch (extract32(ctx->opcode, 3, 2)) {
22181 case NM_P16_SYSCALL:
22182 if (extract32(ctx->opcode, 2, 1) == 0) {
22183 generate_exception_end(ctx, EXCP_SYSCALL);
22184 } else {
22185 generate_exception_end(ctx, EXCP_RI);
22187 break;
22188 case NM_BREAK16:
22189 generate_exception_end(ctx, EXCP_BREAK);
22190 break;
22191 case NM_SDBBP16:
22192 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
22193 gen_helper_do_semihosting(cpu_env);
22194 } else {
22195 if (ctx->hflags & MIPS_HFLAG_SBRI) {
22196 generate_exception_end(ctx, EXCP_RI);
22197 } else {
22198 generate_exception_end(ctx, EXCP_DBp);
22201 break;
22202 default:
22203 generate_exception_end(ctx, EXCP_RI);
22204 break;
22207 break;
22208 case NM_P16_SHIFT:
22210 int shift = extract32(ctx->opcode, 0, 3);
22211 uint32_t opc = 0;
22212 shift = (shift == 0) ? 8 : shift;
22214 switch (extract32(ctx->opcode, 3, 1)) {
22215 case NM_SLL16:
22216 opc = OPC_SLL;
22217 break;
22218 case NM_SRL16:
22219 opc = OPC_SRL;
22220 break;
22222 gen_shift_imm(ctx, opc, rt, rs, shift);
22224 break;
22225 case NM_P16C:
22226 switch (ctx->opcode & 1) {
22227 case NM_POOL16C_0:
22228 gen_pool16c_nanomips_insn(ctx);
22229 break;
22230 case NM_LWXS16:
22231 gen_ldxs(ctx, rt, rs, rd);
22232 break;
22234 break;
22235 case NM_P16_A1:
22236 switch (extract32(ctx->opcode, 6, 1)) {
22237 case NM_ADDIUR1SP:
22238 imm = extract32(ctx->opcode, 0, 6) << 2;
22239 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
22240 break;
22241 default:
22242 generate_exception_end(ctx, EXCP_RI);
22243 break;
22245 break;
22246 case NM_P16_A2:
22247 switch (extract32(ctx->opcode, 3, 1)) {
22248 case NM_ADDIUR2:
22249 imm = extract32(ctx->opcode, 0, 3) << 2;
22250 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
22251 break;
22252 case NM_P_ADDIURS5:
22253 rt = extract32(ctx->opcode, 5, 5);
22254 if (rt != 0) {
22255 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
22256 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
22257 (extract32(ctx->opcode, 0, 3));
22258 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
22260 break;
22262 break;
22263 case NM_P16_ADDU:
22264 switch (ctx->opcode & 0x1) {
22265 case NM_ADDU16:
22266 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
22267 break;
22268 case NM_SUBU16:
22269 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
22270 break;
22272 break;
22273 case NM_P16_4X4:
22274 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22275 extract32(ctx->opcode, 5, 3);
22276 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22277 extract32(ctx->opcode, 0, 3);
22278 rt = decode_gpr_gpr4(rt);
22279 rs = decode_gpr_gpr4(rs);
22280 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
22281 (extract32(ctx->opcode, 3, 1))) {
22282 case NM_ADDU4X4:
22283 check_nms(ctx);
22284 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
22285 break;
22286 case NM_MUL4X4:
22287 check_nms(ctx);
22288 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
22289 break;
22290 default:
22291 generate_exception_end(ctx, EXCP_RI);
22292 break;
22294 break;
22295 case NM_LI16:
22297 int imm = extract32(ctx->opcode, 0, 7);
22298 imm = (imm == 0x7f ? -1 : imm);
22299 if (rt != 0) {
22300 tcg_gen_movi_tl(cpu_gpr[rt], imm);
22303 break;
22304 case NM_ANDI16:
22306 uint32_t u = extract32(ctx->opcode, 0, 4);
22307 u = (u == 12) ? 0xff :
22308 (u == 13) ? 0xffff : u;
22309 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
22311 break;
22312 case NM_P16_LB:
22313 offset = extract32(ctx->opcode, 0, 2);
22314 switch (extract32(ctx->opcode, 2, 2)) {
22315 case NM_LB16:
22316 gen_ld(ctx, OPC_LB, rt, rs, offset);
22317 break;
22318 case NM_SB16:
22319 rt = decode_gpr_gpr3_src_store(
22320 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22321 gen_st(ctx, OPC_SB, rt, rs, offset);
22322 break;
22323 case NM_LBU16:
22324 gen_ld(ctx, OPC_LBU, rt, rs, offset);
22325 break;
22326 default:
22327 generate_exception_end(ctx, EXCP_RI);
22328 break;
22330 break;
22331 case NM_P16_LH:
22332 offset = extract32(ctx->opcode, 1, 2) << 1;
22333 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
22334 case NM_LH16:
22335 gen_ld(ctx, OPC_LH, rt, rs, offset);
22336 break;
22337 case NM_SH16:
22338 rt = decode_gpr_gpr3_src_store(
22339 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22340 gen_st(ctx, OPC_SH, rt, rs, offset);
22341 break;
22342 case NM_LHU16:
22343 gen_ld(ctx, OPC_LHU, rt, rs, offset);
22344 break;
22345 default:
22346 generate_exception_end(ctx, EXCP_RI);
22347 break;
22349 break;
22350 case NM_LW16:
22351 offset = extract32(ctx->opcode, 0, 4) << 2;
22352 gen_ld(ctx, OPC_LW, rt, rs, offset);
22353 break;
22354 case NM_LWSP16:
22355 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22356 offset = extract32(ctx->opcode, 0, 5) << 2;
22357 gen_ld(ctx, OPC_LW, rt, 29, offset);
22358 break;
22359 case NM_LW4X4:
22360 check_nms(ctx);
22361 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22362 extract32(ctx->opcode, 5, 3);
22363 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22364 extract32(ctx->opcode, 0, 3);
22365 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22366 (extract32(ctx->opcode, 8, 1) << 2);
22367 rt = decode_gpr_gpr4(rt);
22368 rs = decode_gpr_gpr4(rs);
22369 gen_ld(ctx, OPC_LW, rt, rs, offset);
22370 break;
22371 case NM_SW4X4:
22372 check_nms(ctx);
22373 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22374 extract32(ctx->opcode, 5, 3);
22375 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22376 extract32(ctx->opcode, 0, 3);
22377 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22378 (extract32(ctx->opcode, 8, 1) << 2);
22379 rt = decode_gpr_gpr4_zero(rt);
22380 rs = decode_gpr_gpr4(rs);
22381 gen_st(ctx, OPC_SW, rt, rs, offset);
22382 break;
22383 case NM_LWGP16:
22384 offset = extract32(ctx->opcode, 0, 7) << 2;
22385 gen_ld(ctx, OPC_LW, rt, 28, offset);
22386 break;
22387 case NM_SWSP16:
22388 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22389 offset = extract32(ctx->opcode, 0, 5) << 2;
22390 gen_st(ctx, OPC_SW, rt, 29, offset);
22391 break;
22392 case NM_SW16:
22393 rt = decode_gpr_gpr3_src_store(
22394 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22395 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22396 offset = extract32(ctx->opcode, 0, 4) << 2;
22397 gen_st(ctx, OPC_SW, rt, rs, offset);
22398 break;
22399 case NM_SWGP16:
22400 rt = decode_gpr_gpr3_src_store(
22401 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22402 offset = extract32(ctx->opcode, 0, 7) << 2;
22403 gen_st(ctx, OPC_SW, rt, 28, offset);
22404 break;
22405 case NM_BC16:
22406 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
22407 (sextract32(ctx->opcode, 0, 1) << 10) |
22408 (extract32(ctx->opcode, 1, 9) << 1));
22409 break;
22410 case NM_BALC16:
22411 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
22412 (sextract32(ctx->opcode, 0, 1) << 10) |
22413 (extract32(ctx->opcode, 1, 9) << 1));
22414 break;
22415 case NM_BEQZC16:
22416 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
22417 (sextract32(ctx->opcode, 0, 1) << 7) |
22418 (extract32(ctx->opcode, 1, 6) << 1));
22419 break;
22420 case NM_BNEZC16:
22421 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
22422 (sextract32(ctx->opcode, 0, 1) << 7) |
22423 (extract32(ctx->opcode, 1, 6) << 1));
22424 break;
22425 case NM_P16_BR:
22426 switch (ctx->opcode & 0xf) {
22427 case 0:
22428 /* P16.JRC */
22429 switch (extract32(ctx->opcode, 4, 1)) {
22430 case NM_JRC:
22431 gen_compute_branch_nm(ctx, OPC_JR, 2,
22432 extract32(ctx->opcode, 5, 5), 0, 0);
22433 break;
22434 case NM_JALRC16:
22435 gen_compute_branch_nm(ctx, OPC_JALR, 2,
22436 extract32(ctx->opcode, 5, 5), 31, 0);
22437 break;
22439 break;
22440 default:
22442 /* P16.BRI */
22443 uint32_t opc = extract32(ctx->opcode, 4, 3) <
22444 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
22445 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
22446 extract32(ctx->opcode, 0, 4) << 1);
22448 break;
22450 break;
22451 case NM_P16_SR:
22453 int count = extract32(ctx->opcode, 0, 4);
22454 int u = extract32(ctx->opcode, 4, 4) << 4;
22456 rt = 30 + extract32(ctx->opcode, 9, 1);
22457 switch (extract32(ctx->opcode, 8, 1)) {
22458 case NM_SAVE16:
22459 gen_save(ctx, rt, count, 0, u);
22460 break;
22461 case NM_RESTORE_JRC16:
22462 gen_restore(ctx, rt, count, 0, u);
22463 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
22464 break;
22467 break;
22468 case NM_MOVEP:
22469 case NM_MOVEPREV:
22470 check_nms(ctx);
22472 static const int gpr2reg1[] = {4, 5, 6, 7};
22473 static const int gpr2reg2[] = {5, 6, 7, 8};
22474 int re;
22475 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
22476 extract32(ctx->opcode, 8, 1);
22477 int r1 = gpr2reg1[rd2];
22478 int r2 = gpr2reg2[rd2];
22479 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
22480 extract32(ctx->opcode, 0, 3);
22481 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
22482 extract32(ctx->opcode, 5, 3);
22483 TCGv t0 = tcg_temp_new();
22484 TCGv t1 = tcg_temp_new();
22485 if (op == NM_MOVEP) {
22486 rd = r1;
22487 re = r2;
22488 rs = decode_gpr_gpr4_zero(r3);
22489 rt = decode_gpr_gpr4_zero(r4);
22490 } else {
22491 rd = decode_gpr_gpr4(r3);
22492 re = decode_gpr_gpr4(r4);
22493 rs = r1;
22494 rt = r2;
22496 gen_load_gpr(t0, rs);
22497 gen_load_gpr(t1, rt);
22498 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22499 tcg_gen_mov_tl(cpu_gpr[re], t1);
22500 tcg_temp_free(t0);
22501 tcg_temp_free(t1);
22503 break;
22504 default:
22505 return decode_nanomips_32_48_opc(env, ctx);
22508 return 2;
22512 /* SmartMIPS extension to MIPS32 */
22514 #if defined(TARGET_MIPS64)
22516 /* MDMX extension to MIPS64 */
22518 #endif
22520 /* MIPSDSP functions. */
22521 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
22522 int rd, int base, int offset)
22524 TCGv t0;
22526 check_dsp(ctx);
22527 t0 = tcg_temp_new();
22529 if (base == 0) {
22530 gen_load_gpr(t0, offset);
22531 } else if (offset == 0) {
22532 gen_load_gpr(t0, base);
22533 } else {
22534 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
22537 switch (opc) {
22538 case OPC_LBUX:
22539 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
22540 gen_store_gpr(t0, rd);
22541 break;
22542 case OPC_LHX:
22543 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
22544 gen_store_gpr(t0, rd);
22545 break;
22546 case OPC_LWX:
22547 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
22548 gen_store_gpr(t0, rd);
22549 break;
22550 #if defined(TARGET_MIPS64)
22551 case OPC_LDX:
22552 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
22553 gen_store_gpr(t0, rd);
22554 break;
22555 #endif
22557 tcg_temp_free(t0);
22560 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
22561 int ret, int v1, int v2)
22563 TCGv v1_t;
22564 TCGv v2_t;
22566 if (ret == 0) {
22567 /* Treat as NOP. */
22568 return;
22571 v1_t = tcg_temp_new();
22572 v2_t = tcg_temp_new();
22574 gen_load_gpr(v1_t, v1);
22575 gen_load_gpr(v2_t, v2);
22577 switch (op1) {
22578 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
22579 case OPC_MULT_G_2E:
22580 check_dsp_r2(ctx);
22581 switch (op2) {
22582 case OPC_ADDUH_QB:
22583 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
22584 break;
22585 case OPC_ADDUH_R_QB:
22586 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22587 break;
22588 case OPC_ADDQH_PH:
22589 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
22590 break;
22591 case OPC_ADDQH_R_PH:
22592 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22593 break;
22594 case OPC_ADDQH_W:
22595 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
22596 break;
22597 case OPC_ADDQH_R_W:
22598 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22599 break;
22600 case OPC_SUBUH_QB:
22601 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
22602 break;
22603 case OPC_SUBUH_R_QB:
22604 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22605 break;
22606 case OPC_SUBQH_PH:
22607 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
22608 break;
22609 case OPC_SUBQH_R_PH:
22610 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22611 break;
22612 case OPC_SUBQH_W:
22613 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
22614 break;
22615 case OPC_SUBQH_R_W:
22616 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22617 break;
22619 break;
22620 case OPC_ABSQ_S_PH_DSP:
22621 switch (op2) {
22622 case OPC_ABSQ_S_QB:
22623 check_dsp_r2(ctx);
22624 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
22625 break;
22626 case OPC_ABSQ_S_PH:
22627 check_dsp(ctx);
22628 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
22629 break;
22630 case OPC_ABSQ_S_W:
22631 check_dsp(ctx);
22632 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
22633 break;
22634 case OPC_PRECEQ_W_PHL:
22635 check_dsp(ctx);
22636 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
22637 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22638 break;
22639 case OPC_PRECEQ_W_PHR:
22640 check_dsp(ctx);
22641 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
22642 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
22643 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22644 break;
22645 case OPC_PRECEQU_PH_QBL:
22646 check_dsp(ctx);
22647 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
22648 break;
22649 case OPC_PRECEQU_PH_QBR:
22650 check_dsp(ctx);
22651 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
22652 break;
22653 case OPC_PRECEQU_PH_QBLA:
22654 check_dsp(ctx);
22655 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
22656 break;
22657 case OPC_PRECEQU_PH_QBRA:
22658 check_dsp(ctx);
22659 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
22660 break;
22661 case OPC_PRECEU_PH_QBL:
22662 check_dsp(ctx);
22663 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
22664 break;
22665 case OPC_PRECEU_PH_QBR:
22666 check_dsp(ctx);
22667 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
22668 break;
22669 case OPC_PRECEU_PH_QBLA:
22670 check_dsp(ctx);
22671 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
22672 break;
22673 case OPC_PRECEU_PH_QBRA:
22674 check_dsp(ctx);
22675 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
22676 break;
22678 break;
22679 case OPC_ADDU_QB_DSP:
22680 switch (op2) {
22681 case OPC_ADDQ_PH:
22682 check_dsp(ctx);
22683 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22684 break;
22685 case OPC_ADDQ_S_PH:
22686 check_dsp(ctx);
22687 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22688 break;
22689 case OPC_ADDQ_S_W:
22690 check_dsp(ctx);
22691 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22692 break;
22693 case OPC_ADDU_QB:
22694 check_dsp(ctx);
22695 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22696 break;
22697 case OPC_ADDU_S_QB:
22698 check_dsp(ctx);
22699 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22700 break;
22701 case OPC_ADDU_PH:
22702 check_dsp_r2(ctx);
22703 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22704 break;
22705 case OPC_ADDU_S_PH:
22706 check_dsp_r2(ctx);
22707 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22708 break;
22709 case OPC_SUBQ_PH:
22710 check_dsp(ctx);
22711 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22712 break;
22713 case OPC_SUBQ_S_PH:
22714 check_dsp(ctx);
22715 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22716 break;
22717 case OPC_SUBQ_S_W:
22718 check_dsp(ctx);
22719 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22720 break;
22721 case OPC_SUBU_QB:
22722 check_dsp(ctx);
22723 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22724 break;
22725 case OPC_SUBU_S_QB:
22726 check_dsp(ctx);
22727 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22728 break;
22729 case OPC_SUBU_PH:
22730 check_dsp_r2(ctx);
22731 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22732 break;
22733 case OPC_SUBU_S_PH:
22734 check_dsp_r2(ctx);
22735 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22736 break;
22737 case OPC_ADDSC:
22738 check_dsp(ctx);
22739 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22740 break;
22741 case OPC_ADDWC:
22742 check_dsp(ctx);
22743 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22744 break;
22745 case OPC_MODSUB:
22746 check_dsp(ctx);
22747 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
22748 break;
22749 case OPC_RADDU_W_QB:
22750 check_dsp(ctx);
22751 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
22752 break;
22754 break;
22755 case OPC_CMPU_EQ_QB_DSP:
22756 switch (op2) {
22757 case OPC_PRECR_QB_PH:
22758 check_dsp_r2(ctx);
22759 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22760 break;
22761 case OPC_PRECRQ_QB_PH:
22762 check_dsp(ctx);
22763 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22764 break;
22765 case OPC_PRECR_SRA_PH_W:
22766 check_dsp_r2(ctx);
22768 TCGv_i32 sa_t = tcg_const_i32(v2);
22769 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
22770 cpu_gpr[ret]);
22771 tcg_temp_free_i32(sa_t);
22772 break;
22774 case OPC_PRECR_SRA_R_PH_W:
22775 check_dsp_r2(ctx);
22777 TCGv_i32 sa_t = tcg_const_i32(v2);
22778 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
22779 cpu_gpr[ret]);
22780 tcg_temp_free_i32(sa_t);
22781 break;
22783 case OPC_PRECRQ_PH_W:
22784 check_dsp(ctx);
22785 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
22786 break;
22787 case OPC_PRECRQ_RS_PH_W:
22788 check_dsp(ctx);
22789 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22790 break;
22791 case OPC_PRECRQU_S_QB_PH:
22792 check_dsp(ctx);
22793 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22794 break;
22796 break;
22797 #ifdef TARGET_MIPS64
22798 case OPC_ABSQ_S_QH_DSP:
22799 switch (op2) {
22800 case OPC_PRECEQ_L_PWL:
22801 check_dsp(ctx);
22802 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
22803 break;
22804 case OPC_PRECEQ_L_PWR:
22805 check_dsp(ctx);
22806 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
22807 break;
22808 case OPC_PRECEQ_PW_QHL:
22809 check_dsp(ctx);
22810 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
22811 break;
22812 case OPC_PRECEQ_PW_QHR:
22813 check_dsp(ctx);
22814 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
22815 break;
22816 case OPC_PRECEQ_PW_QHLA:
22817 check_dsp(ctx);
22818 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
22819 break;
22820 case OPC_PRECEQ_PW_QHRA:
22821 check_dsp(ctx);
22822 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
22823 break;
22824 case OPC_PRECEQU_QH_OBL:
22825 check_dsp(ctx);
22826 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
22827 break;
22828 case OPC_PRECEQU_QH_OBR:
22829 check_dsp(ctx);
22830 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
22831 break;
22832 case OPC_PRECEQU_QH_OBLA:
22833 check_dsp(ctx);
22834 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
22835 break;
22836 case OPC_PRECEQU_QH_OBRA:
22837 check_dsp(ctx);
22838 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
22839 break;
22840 case OPC_PRECEU_QH_OBL:
22841 check_dsp(ctx);
22842 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
22843 break;
22844 case OPC_PRECEU_QH_OBR:
22845 check_dsp(ctx);
22846 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
22847 break;
22848 case OPC_PRECEU_QH_OBLA:
22849 check_dsp(ctx);
22850 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
22851 break;
22852 case OPC_PRECEU_QH_OBRA:
22853 check_dsp(ctx);
22854 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
22855 break;
22856 case OPC_ABSQ_S_OB:
22857 check_dsp_r2(ctx);
22858 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
22859 break;
22860 case OPC_ABSQ_S_PW:
22861 check_dsp(ctx);
22862 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
22863 break;
22864 case OPC_ABSQ_S_QH:
22865 check_dsp(ctx);
22866 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
22867 break;
22869 break;
22870 case OPC_ADDU_OB_DSP:
22871 switch (op2) {
22872 case OPC_RADDU_L_OB:
22873 check_dsp(ctx);
22874 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
22875 break;
22876 case OPC_SUBQ_PW:
22877 check_dsp(ctx);
22878 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22879 break;
22880 case OPC_SUBQ_S_PW:
22881 check_dsp(ctx);
22882 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22883 break;
22884 case OPC_SUBQ_QH:
22885 check_dsp(ctx);
22886 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22887 break;
22888 case OPC_SUBQ_S_QH:
22889 check_dsp(ctx);
22890 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22891 break;
22892 case OPC_SUBU_OB:
22893 check_dsp(ctx);
22894 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22895 break;
22896 case OPC_SUBU_S_OB:
22897 check_dsp(ctx);
22898 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22899 break;
22900 case OPC_SUBU_QH:
22901 check_dsp_r2(ctx);
22902 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22903 break;
22904 case OPC_SUBU_S_QH:
22905 check_dsp_r2(ctx);
22906 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22907 break;
22908 case OPC_SUBUH_OB:
22909 check_dsp_r2(ctx);
22910 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
22911 break;
22912 case OPC_SUBUH_R_OB:
22913 check_dsp_r2(ctx);
22914 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22915 break;
22916 case OPC_ADDQ_PW:
22917 check_dsp(ctx);
22918 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22919 break;
22920 case OPC_ADDQ_S_PW:
22921 check_dsp(ctx);
22922 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22923 break;
22924 case OPC_ADDQ_QH:
22925 check_dsp(ctx);
22926 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22927 break;
22928 case OPC_ADDQ_S_QH:
22929 check_dsp(ctx);
22930 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22931 break;
22932 case OPC_ADDU_OB:
22933 check_dsp(ctx);
22934 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22935 break;
22936 case OPC_ADDU_S_OB:
22937 check_dsp(ctx);
22938 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22939 break;
22940 case OPC_ADDU_QH:
22941 check_dsp_r2(ctx);
22942 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22943 break;
22944 case OPC_ADDU_S_QH:
22945 check_dsp_r2(ctx);
22946 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22947 break;
22948 case OPC_ADDUH_OB:
22949 check_dsp_r2(ctx);
22950 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
22951 break;
22952 case OPC_ADDUH_R_OB:
22953 check_dsp_r2(ctx);
22954 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22955 break;
22957 break;
22958 case OPC_CMPU_EQ_OB_DSP:
22959 switch (op2) {
22960 case OPC_PRECR_OB_QH:
22961 check_dsp_r2(ctx);
22962 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22963 break;
22964 case OPC_PRECR_SRA_QH_PW:
22965 check_dsp_r2(ctx);
22967 TCGv_i32 ret_t = tcg_const_i32(ret);
22968 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
22969 tcg_temp_free_i32(ret_t);
22970 break;
22972 case OPC_PRECR_SRA_R_QH_PW:
22973 check_dsp_r2(ctx);
22975 TCGv_i32 sa_v = tcg_const_i32(ret);
22976 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
22977 tcg_temp_free_i32(sa_v);
22978 break;
22980 case OPC_PRECRQ_OB_QH:
22981 check_dsp(ctx);
22982 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22983 break;
22984 case OPC_PRECRQ_PW_L:
22985 check_dsp(ctx);
22986 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
22987 break;
22988 case OPC_PRECRQ_QH_PW:
22989 check_dsp(ctx);
22990 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
22991 break;
22992 case OPC_PRECRQ_RS_QH_PW:
22993 check_dsp(ctx);
22994 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22995 break;
22996 case OPC_PRECRQU_S_OB_QH:
22997 check_dsp(ctx);
22998 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22999 break;
23001 break;
23002 #endif
23005 tcg_temp_free(v1_t);
23006 tcg_temp_free(v2_t);
23009 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
23010 int ret, int v1, int v2)
23012 uint32_t op2;
23013 TCGv t0;
23014 TCGv v1_t;
23015 TCGv v2_t;
23017 if (ret == 0) {
23018 /* Treat as NOP. */
23019 return;
23022 t0 = tcg_temp_new();
23023 v1_t = tcg_temp_new();
23024 v2_t = tcg_temp_new();
23026 tcg_gen_movi_tl(t0, v1);
23027 gen_load_gpr(v1_t, v1);
23028 gen_load_gpr(v2_t, v2);
23030 switch (opc) {
23031 case OPC_SHLL_QB_DSP:
23033 op2 = MASK_SHLL_QB(ctx->opcode);
23034 switch (op2) {
23035 case OPC_SHLL_QB:
23036 check_dsp(ctx);
23037 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
23038 break;
23039 case OPC_SHLLV_QB:
23040 check_dsp(ctx);
23041 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23042 break;
23043 case OPC_SHLL_PH:
23044 check_dsp(ctx);
23045 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
23046 break;
23047 case OPC_SHLLV_PH:
23048 check_dsp(ctx);
23049 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23050 break;
23051 case OPC_SHLL_S_PH:
23052 check_dsp(ctx);
23053 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
23054 break;
23055 case OPC_SHLLV_S_PH:
23056 check_dsp(ctx);
23057 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23058 break;
23059 case OPC_SHLL_S_W:
23060 check_dsp(ctx);
23061 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
23062 break;
23063 case OPC_SHLLV_S_W:
23064 check_dsp(ctx);
23065 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23066 break;
23067 case OPC_SHRL_QB:
23068 check_dsp(ctx);
23069 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
23070 break;
23071 case OPC_SHRLV_QB:
23072 check_dsp(ctx);
23073 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
23074 break;
23075 case OPC_SHRL_PH:
23076 check_dsp_r2(ctx);
23077 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
23078 break;
23079 case OPC_SHRLV_PH:
23080 check_dsp_r2(ctx);
23081 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
23082 break;
23083 case OPC_SHRA_QB:
23084 check_dsp_r2(ctx);
23085 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
23086 break;
23087 case OPC_SHRA_R_QB:
23088 check_dsp_r2(ctx);
23089 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
23090 break;
23091 case OPC_SHRAV_QB:
23092 check_dsp_r2(ctx);
23093 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
23094 break;
23095 case OPC_SHRAV_R_QB:
23096 check_dsp_r2(ctx);
23097 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
23098 break;
23099 case OPC_SHRA_PH:
23100 check_dsp(ctx);
23101 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
23102 break;
23103 case OPC_SHRA_R_PH:
23104 check_dsp(ctx);
23105 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
23106 break;
23107 case OPC_SHRAV_PH:
23108 check_dsp(ctx);
23109 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
23110 break;
23111 case OPC_SHRAV_R_PH:
23112 check_dsp(ctx);
23113 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
23114 break;
23115 case OPC_SHRA_R_W:
23116 check_dsp(ctx);
23117 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
23118 break;
23119 case OPC_SHRAV_R_W:
23120 check_dsp(ctx);
23121 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
23122 break;
23123 default: /* Invalid */
23124 MIPS_INVAL("MASK SHLL.QB");
23125 generate_exception_end(ctx, EXCP_RI);
23126 break;
23128 break;
23130 #ifdef TARGET_MIPS64
23131 case OPC_SHLL_OB_DSP:
23132 op2 = MASK_SHLL_OB(ctx->opcode);
23133 switch (op2) {
23134 case OPC_SHLL_PW:
23135 check_dsp(ctx);
23136 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23137 break;
23138 case OPC_SHLLV_PW:
23139 check_dsp(ctx);
23140 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23141 break;
23142 case OPC_SHLL_S_PW:
23143 check_dsp(ctx);
23144 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23145 break;
23146 case OPC_SHLLV_S_PW:
23147 check_dsp(ctx);
23148 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23149 break;
23150 case OPC_SHLL_OB:
23151 check_dsp(ctx);
23152 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
23153 break;
23154 case OPC_SHLLV_OB:
23155 check_dsp(ctx);
23156 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23157 break;
23158 case OPC_SHLL_QH:
23159 check_dsp(ctx);
23160 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23161 break;
23162 case OPC_SHLLV_QH:
23163 check_dsp(ctx);
23164 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23165 break;
23166 case OPC_SHLL_S_QH:
23167 check_dsp(ctx);
23168 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23169 break;
23170 case OPC_SHLLV_S_QH:
23171 check_dsp(ctx);
23172 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23173 break;
23174 case OPC_SHRA_OB:
23175 check_dsp_r2(ctx);
23176 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
23177 break;
23178 case OPC_SHRAV_OB:
23179 check_dsp_r2(ctx);
23180 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
23181 break;
23182 case OPC_SHRA_R_OB:
23183 check_dsp_r2(ctx);
23184 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
23185 break;
23186 case OPC_SHRAV_R_OB:
23187 check_dsp_r2(ctx);
23188 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
23189 break;
23190 case OPC_SHRA_PW:
23191 check_dsp(ctx);
23192 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
23193 break;
23194 case OPC_SHRAV_PW:
23195 check_dsp(ctx);
23196 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
23197 break;
23198 case OPC_SHRA_R_PW:
23199 check_dsp(ctx);
23200 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
23201 break;
23202 case OPC_SHRAV_R_PW:
23203 check_dsp(ctx);
23204 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
23205 break;
23206 case OPC_SHRA_QH:
23207 check_dsp(ctx);
23208 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
23209 break;
23210 case OPC_SHRAV_QH:
23211 check_dsp(ctx);
23212 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
23213 break;
23214 case OPC_SHRA_R_QH:
23215 check_dsp(ctx);
23216 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
23217 break;
23218 case OPC_SHRAV_R_QH:
23219 check_dsp(ctx);
23220 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
23221 break;
23222 case OPC_SHRL_OB:
23223 check_dsp(ctx);
23224 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
23225 break;
23226 case OPC_SHRLV_OB:
23227 check_dsp(ctx);
23228 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
23229 break;
23230 case OPC_SHRL_QH:
23231 check_dsp_r2(ctx);
23232 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
23233 break;
23234 case OPC_SHRLV_QH:
23235 check_dsp_r2(ctx);
23236 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
23237 break;
23238 default: /* Invalid */
23239 MIPS_INVAL("MASK SHLL.OB");
23240 generate_exception_end(ctx, EXCP_RI);
23241 break;
23243 break;
23244 #endif
23247 tcg_temp_free(t0);
23248 tcg_temp_free(v1_t);
23249 tcg_temp_free(v2_t);
23252 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
23253 int ret, int v1, int v2, int check_ret)
23255 TCGv_i32 t0;
23256 TCGv v1_t;
23257 TCGv v2_t;
23259 if ((ret == 0) && (check_ret == 1)) {
23260 /* Treat as NOP. */
23261 return;
23264 t0 = tcg_temp_new_i32();
23265 v1_t = tcg_temp_new();
23266 v2_t = tcg_temp_new();
23268 tcg_gen_movi_i32(t0, ret);
23269 gen_load_gpr(v1_t, v1);
23270 gen_load_gpr(v2_t, v2);
23272 switch (op1) {
23274 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
23275 * the same mask and op1.
23277 case OPC_MULT_G_2E:
23278 check_dsp_r2(ctx);
23279 switch (op2) {
23280 case OPC_MUL_PH:
23281 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23282 break;
23283 case OPC_MUL_S_PH:
23284 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23285 break;
23286 case OPC_MULQ_S_W:
23287 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23288 break;
23289 case OPC_MULQ_RS_W:
23290 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23291 break;
23293 break;
23294 case OPC_DPA_W_PH_DSP:
23295 switch (op2) {
23296 case OPC_DPAU_H_QBL:
23297 check_dsp(ctx);
23298 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
23299 break;
23300 case OPC_DPAU_H_QBR:
23301 check_dsp(ctx);
23302 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
23303 break;
23304 case OPC_DPSU_H_QBL:
23305 check_dsp(ctx);
23306 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
23307 break;
23308 case OPC_DPSU_H_QBR:
23309 check_dsp(ctx);
23310 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
23311 break;
23312 case OPC_DPA_W_PH:
23313 check_dsp_r2(ctx);
23314 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
23315 break;
23316 case OPC_DPAX_W_PH:
23317 check_dsp_r2(ctx);
23318 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
23319 break;
23320 case OPC_DPAQ_S_W_PH:
23321 check_dsp(ctx);
23322 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23323 break;
23324 case OPC_DPAQX_S_W_PH:
23325 check_dsp_r2(ctx);
23326 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23327 break;
23328 case OPC_DPAQX_SA_W_PH:
23329 check_dsp_r2(ctx);
23330 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23331 break;
23332 case OPC_DPS_W_PH:
23333 check_dsp_r2(ctx);
23334 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
23335 break;
23336 case OPC_DPSX_W_PH:
23337 check_dsp_r2(ctx);
23338 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
23339 break;
23340 case OPC_DPSQ_S_W_PH:
23341 check_dsp(ctx);
23342 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23343 break;
23344 case OPC_DPSQX_S_W_PH:
23345 check_dsp_r2(ctx);
23346 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23347 break;
23348 case OPC_DPSQX_SA_W_PH:
23349 check_dsp_r2(ctx);
23350 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23351 break;
23352 case OPC_MULSAQ_S_W_PH:
23353 check_dsp(ctx);
23354 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23355 break;
23356 case OPC_DPAQ_SA_L_W:
23357 check_dsp(ctx);
23358 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23359 break;
23360 case OPC_DPSQ_SA_L_W:
23361 check_dsp(ctx);
23362 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23363 break;
23364 case OPC_MAQ_S_W_PHL:
23365 check_dsp(ctx);
23366 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
23367 break;
23368 case OPC_MAQ_S_W_PHR:
23369 check_dsp(ctx);
23370 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
23371 break;
23372 case OPC_MAQ_SA_W_PHL:
23373 check_dsp(ctx);
23374 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
23375 break;
23376 case OPC_MAQ_SA_W_PHR:
23377 check_dsp(ctx);
23378 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
23379 break;
23380 case OPC_MULSA_W_PH:
23381 check_dsp_r2(ctx);
23382 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
23383 break;
23385 break;
23386 #ifdef TARGET_MIPS64
23387 case OPC_DPAQ_W_QH_DSP:
23389 int ac = ret & 0x03;
23390 tcg_gen_movi_i32(t0, ac);
23392 switch (op2) {
23393 case OPC_DMADD:
23394 check_dsp(ctx);
23395 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
23396 break;
23397 case OPC_DMADDU:
23398 check_dsp(ctx);
23399 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
23400 break;
23401 case OPC_DMSUB:
23402 check_dsp(ctx);
23403 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
23404 break;
23405 case OPC_DMSUBU:
23406 check_dsp(ctx);
23407 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
23408 break;
23409 case OPC_DPA_W_QH:
23410 check_dsp_r2(ctx);
23411 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
23412 break;
23413 case OPC_DPAQ_S_W_QH:
23414 check_dsp(ctx);
23415 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23416 break;
23417 case OPC_DPAQ_SA_L_PW:
23418 check_dsp(ctx);
23419 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23420 break;
23421 case OPC_DPAU_H_OBL:
23422 check_dsp(ctx);
23423 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
23424 break;
23425 case OPC_DPAU_H_OBR:
23426 check_dsp(ctx);
23427 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
23428 break;
23429 case OPC_DPS_W_QH:
23430 check_dsp_r2(ctx);
23431 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
23432 break;
23433 case OPC_DPSQ_S_W_QH:
23434 check_dsp(ctx);
23435 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23436 break;
23437 case OPC_DPSQ_SA_L_PW:
23438 check_dsp(ctx);
23439 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23440 break;
23441 case OPC_DPSU_H_OBL:
23442 check_dsp(ctx);
23443 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
23444 break;
23445 case OPC_DPSU_H_OBR:
23446 check_dsp(ctx);
23447 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
23448 break;
23449 case OPC_MAQ_S_L_PWL:
23450 check_dsp(ctx);
23451 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
23452 break;
23453 case OPC_MAQ_S_L_PWR:
23454 check_dsp(ctx);
23455 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
23456 break;
23457 case OPC_MAQ_S_W_QHLL:
23458 check_dsp(ctx);
23459 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
23460 break;
23461 case OPC_MAQ_SA_W_QHLL:
23462 check_dsp(ctx);
23463 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
23464 break;
23465 case OPC_MAQ_S_W_QHLR:
23466 check_dsp(ctx);
23467 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
23468 break;
23469 case OPC_MAQ_SA_W_QHLR:
23470 check_dsp(ctx);
23471 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
23472 break;
23473 case OPC_MAQ_S_W_QHRL:
23474 check_dsp(ctx);
23475 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
23476 break;
23477 case OPC_MAQ_SA_W_QHRL:
23478 check_dsp(ctx);
23479 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
23480 break;
23481 case OPC_MAQ_S_W_QHRR:
23482 check_dsp(ctx);
23483 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
23484 break;
23485 case OPC_MAQ_SA_W_QHRR:
23486 check_dsp(ctx);
23487 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
23488 break;
23489 case OPC_MULSAQ_S_L_PW:
23490 check_dsp(ctx);
23491 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
23492 break;
23493 case OPC_MULSAQ_S_W_QH:
23494 check_dsp(ctx);
23495 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23496 break;
23499 break;
23500 #endif
23501 case OPC_ADDU_QB_DSP:
23502 switch (op2) {
23503 case OPC_MULEU_S_PH_QBL:
23504 check_dsp(ctx);
23505 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23506 break;
23507 case OPC_MULEU_S_PH_QBR:
23508 check_dsp(ctx);
23509 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23510 break;
23511 case OPC_MULQ_RS_PH:
23512 check_dsp(ctx);
23513 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23514 break;
23515 case OPC_MULEQ_S_W_PHL:
23516 check_dsp(ctx);
23517 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23518 break;
23519 case OPC_MULEQ_S_W_PHR:
23520 check_dsp(ctx);
23521 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23522 break;
23523 case OPC_MULQ_S_PH:
23524 check_dsp_r2(ctx);
23525 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23526 break;
23528 break;
23529 #ifdef TARGET_MIPS64
23530 case OPC_ADDU_OB_DSP:
23531 switch (op2) {
23532 case OPC_MULEQ_S_PW_QHL:
23533 check_dsp(ctx);
23534 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23535 break;
23536 case OPC_MULEQ_S_PW_QHR:
23537 check_dsp(ctx);
23538 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23539 break;
23540 case OPC_MULEU_S_QH_OBL:
23541 check_dsp(ctx);
23542 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23543 break;
23544 case OPC_MULEU_S_QH_OBR:
23545 check_dsp(ctx);
23546 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23547 break;
23548 case OPC_MULQ_RS_QH:
23549 check_dsp(ctx);
23550 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23551 break;
23553 break;
23554 #endif
23557 tcg_temp_free_i32(t0);
23558 tcg_temp_free(v1_t);
23559 tcg_temp_free(v2_t);
23562 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23563 int ret, int val)
23565 int16_t imm;
23566 TCGv t0;
23567 TCGv val_t;
23569 if (ret == 0) {
23570 /* Treat as NOP. */
23571 return;
23574 t0 = tcg_temp_new();
23575 val_t = tcg_temp_new();
23576 gen_load_gpr(val_t, val);
23578 switch (op1) {
23579 case OPC_ABSQ_S_PH_DSP:
23580 switch (op2) {
23581 case OPC_BITREV:
23582 check_dsp(ctx);
23583 gen_helper_bitrev(cpu_gpr[ret], val_t);
23584 break;
23585 case OPC_REPL_QB:
23586 check_dsp(ctx);
23588 target_long result;
23589 imm = (ctx->opcode >> 16) & 0xFF;
23590 result = (uint32_t)imm << 24 |
23591 (uint32_t)imm << 16 |
23592 (uint32_t)imm << 8 |
23593 (uint32_t)imm;
23594 result = (int32_t)result;
23595 tcg_gen_movi_tl(cpu_gpr[ret], result);
23597 break;
23598 case OPC_REPLV_QB:
23599 check_dsp(ctx);
23600 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23601 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23602 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23603 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23604 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23605 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23606 break;
23607 case OPC_REPL_PH:
23608 check_dsp(ctx);
23610 imm = (ctx->opcode >> 16) & 0x03FF;
23611 imm = (int16_t)(imm << 6) >> 6;
23612 tcg_gen_movi_tl(cpu_gpr[ret], \
23613 (target_long)((int32_t)imm << 16 | \
23614 (uint16_t)imm));
23616 break;
23617 case OPC_REPLV_PH:
23618 check_dsp(ctx);
23619 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23620 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23621 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23622 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23623 break;
23625 break;
23626 #ifdef TARGET_MIPS64
23627 case OPC_ABSQ_S_QH_DSP:
23628 switch (op2) {
23629 case OPC_REPL_OB:
23630 check_dsp(ctx);
23632 target_long temp;
23634 imm = (ctx->opcode >> 16) & 0xFF;
23635 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
23636 temp = (temp << 16) | temp;
23637 temp = (temp << 32) | temp;
23638 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23639 break;
23641 case OPC_REPL_PW:
23642 check_dsp(ctx);
23644 target_long temp;
23646 imm = (ctx->opcode >> 16) & 0x03FF;
23647 imm = (int16_t)(imm << 6) >> 6;
23648 temp = ((target_long)imm << 32) \
23649 | ((target_long)imm & 0xFFFFFFFF);
23650 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23651 break;
23653 case OPC_REPL_QH:
23654 check_dsp(ctx);
23656 target_long temp;
23658 imm = (ctx->opcode >> 16) & 0x03FF;
23659 imm = (int16_t)(imm << 6) >> 6;
23661 temp = ((uint64_t)(uint16_t)imm << 48) |
23662 ((uint64_t)(uint16_t)imm << 32) |
23663 ((uint64_t)(uint16_t)imm << 16) |
23664 (uint64_t)(uint16_t)imm;
23665 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23666 break;
23668 case OPC_REPLV_OB:
23669 check_dsp(ctx);
23670 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23671 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23672 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23673 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23674 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23675 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23676 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23677 break;
23678 case OPC_REPLV_PW:
23679 check_dsp(ctx);
23680 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
23681 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23682 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23683 break;
23684 case OPC_REPLV_QH:
23685 check_dsp(ctx);
23686 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23687 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23688 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23689 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23690 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23691 break;
23693 break;
23694 #endif
23696 tcg_temp_free(t0);
23697 tcg_temp_free(val_t);
23700 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
23701 uint32_t op1, uint32_t op2,
23702 int ret, int v1, int v2, int check_ret)
23704 TCGv t1;
23705 TCGv v1_t;
23706 TCGv v2_t;
23708 if ((ret == 0) && (check_ret == 1)) {
23709 /* Treat as NOP. */
23710 return;
23713 t1 = tcg_temp_new();
23714 v1_t = tcg_temp_new();
23715 v2_t = tcg_temp_new();
23717 gen_load_gpr(v1_t, v1);
23718 gen_load_gpr(v2_t, v2);
23720 switch (op1) {
23721 case OPC_CMPU_EQ_QB_DSP:
23722 switch (op2) {
23723 case OPC_CMPU_EQ_QB:
23724 check_dsp(ctx);
23725 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
23726 break;
23727 case OPC_CMPU_LT_QB:
23728 check_dsp(ctx);
23729 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
23730 break;
23731 case OPC_CMPU_LE_QB:
23732 check_dsp(ctx);
23733 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
23734 break;
23735 case OPC_CMPGU_EQ_QB:
23736 check_dsp(ctx);
23737 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
23738 break;
23739 case OPC_CMPGU_LT_QB:
23740 check_dsp(ctx);
23741 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
23742 break;
23743 case OPC_CMPGU_LE_QB:
23744 check_dsp(ctx);
23745 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
23746 break;
23747 case OPC_CMPGDU_EQ_QB:
23748 check_dsp_r2(ctx);
23749 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
23750 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23751 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23752 tcg_gen_shli_tl(t1, t1, 24);
23753 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23754 break;
23755 case OPC_CMPGDU_LT_QB:
23756 check_dsp_r2(ctx);
23757 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
23758 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23759 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23760 tcg_gen_shli_tl(t1, t1, 24);
23761 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23762 break;
23763 case OPC_CMPGDU_LE_QB:
23764 check_dsp_r2(ctx);
23765 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
23766 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23767 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23768 tcg_gen_shli_tl(t1, t1, 24);
23769 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23770 break;
23771 case OPC_CMP_EQ_PH:
23772 check_dsp(ctx);
23773 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
23774 break;
23775 case OPC_CMP_LT_PH:
23776 check_dsp(ctx);
23777 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
23778 break;
23779 case OPC_CMP_LE_PH:
23780 check_dsp(ctx);
23781 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
23782 break;
23783 case OPC_PICK_QB:
23784 check_dsp(ctx);
23785 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23786 break;
23787 case OPC_PICK_PH:
23788 check_dsp(ctx);
23789 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23790 break;
23791 case OPC_PACKRL_PH:
23792 check_dsp(ctx);
23793 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
23794 break;
23796 break;
23797 #ifdef TARGET_MIPS64
23798 case OPC_CMPU_EQ_OB_DSP:
23799 switch (op2) {
23800 case OPC_CMP_EQ_PW:
23801 check_dsp(ctx);
23802 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
23803 break;
23804 case OPC_CMP_LT_PW:
23805 check_dsp(ctx);
23806 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
23807 break;
23808 case OPC_CMP_LE_PW:
23809 check_dsp(ctx);
23810 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
23811 break;
23812 case OPC_CMP_EQ_QH:
23813 check_dsp(ctx);
23814 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
23815 break;
23816 case OPC_CMP_LT_QH:
23817 check_dsp(ctx);
23818 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
23819 break;
23820 case OPC_CMP_LE_QH:
23821 check_dsp(ctx);
23822 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
23823 break;
23824 case OPC_CMPGDU_EQ_OB:
23825 check_dsp_r2(ctx);
23826 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23827 break;
23828 case OPC_CMPGDU_LT_OB:
23829 check_dsp_r2(ctx);
23830 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23831 break;
23832 case OPC_CMPGDU_LE_OB:
23833 check_dsp_r2(ctx);
23834 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23835 break;
23836 case OPC_CMPGU_EQ_OB:
23837 check_dsp(ctx);
23838 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
23839 break;
23840 case OPC_CMPGU_LT_OB:
23841 check_dsp(ctx);
23842 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
23843 break;
23844 case OPC_CMPGU_LE_OB:
23845 check_dsp(ctx);
23846 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
23847 break;
23848 case OPC_CMPU_EQ_OB:
23849 check_dsp(ctx);
23850 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
23851 break;
23852 case OPC_CMPU_LT_OB:
23853 check_dsp(ctx);
23854 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
23855 break;
23856 case OPC_CMPU_LE_OB:
23857 check_dsp(ctx);
23858 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
23859 break;
23860 case OPC_PACKRL_PW:
23861 check_dsp(ctx);
23862 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
23863 break;
23864 case OPC_PICK_OB:
23865 check_dsp(ctx);
23866 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23867 break;
23868 case OPC_PICK_PW:
23869 check_dsp(ctx);
23870 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23871 break;
23872 case OPC_PICK_QH:
23873 check_dsp(ctx);
23874 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23875 break;
23877 break;
23878 #endif
23881 tcg_temp_free(t1);
23882 tcg_temp_free(v1_t);
23883 tcg_temp_free(v2_t);
23886 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
23887 uint32_t op1, int rt, int rs, int sa)
23889 TCGv t0;
23891 check_dsp_r2(ctx);
23893 if (rt == 0) {
23894 /* Treat as NOP. */
23895 return;
23898 t0 = tcg_temp_new();
23899 gen_load_gpr(t0, rs);
23901 switch (op1) {
23902 case OPC_APPEND_DSP:
23903 switch (MASK_APPEND(ctx->opcode)) {
23904 case OPC_APPEND:
23905 if (sa != 0) {
23906 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
23908 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23909 break;
23910 case OPC_PREPEND:
23911 if (sa != 0) {
23912 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
23913 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23914 tcg_gen_shli_tl(t0, t0, 32 - sa);
23915 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23917 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23918 break;
23919 case OPC_BALIGN:
23920 sa &= 3;
23921 if (sa != 0 && sa != 2) {
23922 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23923 tcg_gen_ext32u_tl(t0, t0);
23924 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
23925 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23927 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23928 break;
23929 default: /* Invalid */
23930 MIPS_INVAL("MASK APPEND");
23931 generate_exception_end(ctx, EXCP_RI);
23932 break;
23934 break;
23935 #ifdef TARGET_MIPS64
23936 case OPC_DAPPEND_DSP:
23937 switch (MASK_DAPPEND(ctx->opcode)) {
23938 case OPC_DAPPEND:
23939 if (sa != 0) {
23940 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
23942 break;
23943 case OPC_PREPENDD:
23944 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
23945 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
23946 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
23947 break;
23948 case OPC_PREPENDW:
23949 if (sa != 0) {
23950 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23951 tcg_gen_shli_tl(t0, t0, 64 - sa);
23952 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23954 break;
23955 case OPC_DBALIGN:
23956 sa &= 7;
23957 if (sa != 0 && sa != 2 && sa != 4) {
23958 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23959 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
23960 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23962 break;
23963 default: /* Invalid */
23964 MIPS_INVAL("MASK DAPPEND");
23965 generate_exception_end(ctx, EXCP_RI);
23966 break;
23968 break;
23969 #endif
23971 tcg_temp_free(t0);
23974 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23975 int ret, int v1, int v2, int check_ret)
23978 TCGv t0;
23979 TCGv t1;
23980 TCGv v1_t;
23981 TCGv v2_t;
23982 int16_t imm;
23984 if ((ret == 0) && (check_ret == 1)) {
23985 /* Treat as NOP. */
23986 return;
23989 t0 = tcg_temp_new();
23990 t1 = tcg_temp_new();
23991 v1_t = tcg_temp_new();
23992 v2_t = tcg_temp_new();
23994 gen_load_gpr(v1_t, v1);
23995 gen_load_gpr(v2_t, v2);
23997 switch (op1) {
23998 case OPC_EXTR_W_DSP:
23999 check_dsp(ctx);
24000 switch (op2) {
24001 case OPC_EXTR_W:
24002 tcg_gen_movi_tl(t0, v2);
24003 tcg_gen_movi_tl(t1, v1);
24004 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
24005 break;
24006 case OPC_EXTR_R_W:
24007 tcg_gen_movi_tl(t0, v2);
24008 tcg_gen_movi_tl(t1, v1);
24009 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24010 break;
24011 case OPC_EXTR_RS_W:
24012 tcg_gen_movi_tl(t0, v2);
24013 tcg_gen_movi_tl(t1, v1);
24014 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24015 break;
24016 case OPC_EXTR_S_H:
24017 tcg_gen_movi_tl(t0, v2);
24018 tcg_gen_movi_tl(t1, v1);
24019 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24020 break;
24021 case OPC_EXTRV_S_H:
24022 tcg_gen_movi_tl(t0, v2);
24023 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
24024 break;
24025 case OPC_EXTRV_W:
24026 tcg_gen_movi_tl(t0, v2);
24027 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24028 break;
24029 case OPC_EXTRV_R_W:
24030 tcg_gen_movi_tl(t0, v2);
24031 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24032 break;
24033 case OPC_EXTRV_RS_W:
24034 tcg_gen_movi_tl(t0, v2);
24035 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24036 break;
24037 case OPC_EXTP:
24038 tcg_gen_movi_tl(t0, v2);
24039 tcg_gen_movi_tl(t1, v1);
24040 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
24041 break;
24042 case OPC_EXTPV:
24043 tcg_gen_movi_tl(t0, v2);
24044 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
24045 break;
24046 case OPC_EXTPDP:
24047 tcg_gen_movi_tl(t0, v2);
24048 tcg_gen_movi_tl(t1, v1);
24049 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
24050 break;
24051 case OPC_EXTPDPV:
24052 tcg_gen_movi_tl(t0, v2);
24053 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
24054 break;
24055 case OPC_SHILO:
24056 imm = (ctx->opcode >> 20) & 0x3F;
24057 tcg_gen_movi_tl(t0, ret);
24058 tcg_gen_movi_tl(t1, imm);
24059 gen_helper_shilo(t0, t1, cpu_env);
24060 break;
24061 case OPC_SHILOV:
24062 tcg_gen_movi_tl(t0, ret);
24063 gen_helper_shilo(t0, v1_t, cpu_env);
24064 break;
24065 case OPC_MTHLIP:
24066 tcg_gen_movi_tl(t0, ret);
24067 gen_helper_mthlip(t0, v1_t, cpu_env);
24068 break;
24069 case OPC_WRDSP:
24070 imm = (ctx->opcode >> 11) & 0x3FF;
24071 tcg_gen_movi_tl(t0, imm);
24072 gen_helper_wrdsp(v1_t, t0, cpu_env);
24073 break;
24074 case OPC_RDDSP:
24075 imm = (ctx->opcode >> 16) & 0x03FF;
24076 tcg_gen_movi_tl(t0, imm);
24077 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
24078 break;
24080 break;
24081 #ifdef TARGET_MIPS64
24082 case OPC_DEXTR_W_DSP:
24083 check_dsp(ctx);
24084 switch (op2) {
24085 case OPC_DMTHLIP:
24086 tcg_gen_movi_tl(t0, ret);
24087 gen_helper_dmthlip(v1_t, t0, cpu_env);
24088 break;
24089 case OPC_DSHILO:
24091 int shift = (ctx->opcode >> 19) & 0x7F;
24092 int ac = (ctx->opcode >> 11) & 0x03;
24093 tcg_gen_movi_tl(t0, shift);
24094 tcg_gen_movi_tl(t1, ac);
24095 gen_helper_dshilo(t0, t1, cpu_env);
24096 break;
24098 case OPC_DSHILOV:
24100 int ac = (ctx->opcode >> 11) & 0x03;
24101 tcg_gen_movi_tl(t0, ac);
24102 gen_helper_dshilo(v1_t, t0, cpu_env);
24103 break;
24105 case OPC_DEXTP:
24106 tcg_gen_movi_tl(t0, v2);
24107 tcg_gen_movi_tl(t1, v1);
24109 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
24110 break;
24111 case OPC_DEXTPV:
24112 tcg_gen_movi_tl(t0, v2);
24113 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
24114 break;
24115 case OPC_DEXTPDP:
24116 tcg_gen_movi_tl(t0, v2);
24117 tcg_gen_movi_tl(t1, v1);
24118 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
24119 break;
24120 case OPC_DEXTPDPV:
24121 tcg_gen_movi_tl(t0, v2);
24122 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
24123 break;
24124 case OPC_DEXTR_L:
24125 tcg_gen_movi_tl(t0, v2);
24126 tcg_gen_movi_tl(t1, v1);
24127 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
24128 break;
24129 case OPC_DEXTR_R_L:
24130 tcg_gen_movi_tl(t0, v2);
24131 tcg_gen_movi_tl(t1, v1);
24132 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
24133 break;
24134 case OPC_DEXTR_RS_L:
24135 tcg_gen_movi_tl(t0, v2);
24136 tcg_gen_movi_tl(t1, v1);
24137 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
24138 break;
24139 case OPC_DEXTR_W:
24140 tcg_gen_movi_tl(t0, v2);
24141 tcg_gen_movi_tl(t1, v1);
24142 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
24143 break;
24144 case OPC_DEXTR_R_W:
24145 tcg_gen_movi_tl(t0, v2);
24146 tcg_gen_movi_tl(t1, v1);
24147 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24148 break;
24149 case OPC_DEXTR_RS_W:
24150 tcg_gen_movi_tl(t0, v2);
24151 tcg_gen_movi_tl(t1, v1);
24152 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24153 break;
24154 case OPC_DEXTR_S_H:
24155 tcg_gen_movi_tl(t0, v2);
24156 tcg_gen_movi_tl(t1, v1);
24157 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24158 break;
24159 case OPC_DEXTRV_S_H:
24160 tcg_gen_movi_tl(t0, v2);
24161 tcg_gen_movi_tl(t1, v1);
24162 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24163 break;
24164 case OPC_DEXTRV_L:
24165 tcg_gen_movi_tl(t0, v2);
24166 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24167 break;
24168 case OPC_DEXTRV_R_L:
24169 tcg_gen_movi_tl(t0, v2);
24170 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24171 break;
24172 case OPC_DEXTRV_RS_L:
24173 tcg_gen_movi_tl(t0, v2);
24174 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24175 break;
24176 case OPC_DEXTRV_W:
24177 tcg_gen_movi_tl(t0, v2);
24178 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24179 break;
24180 case OPC_DEXTRV_R_W:
24181 tcg_gen_movi_tl(t0, v2);
24182 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24183 break;
24184 case OPC_DEXTRV_RS_W:
24185 tcg_gen_movi_tl(t0, v2);
24186 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24187 break;
24189 break;
24190 #endif
24193 tcg_temp_free(t0);
24194 tcg_temp_free(t1);
24195 tcg_temp_free(v1_t);
24196 tcg_temp_free(v2_t);
24199 /* End MIPSDSP functions. */
24201 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
24203 int rs, rt, rd, sa;
24204 uint32_t op1, op2;
24206 rs = (ctx->opcode >> 21) & 0x1f;
24207 rt = (ctx->opcode >> 16) & 0x1f;
24208 rd = (ctx->opcode >> 11) & 0x1f;
24209 sa = (ctx->opcode >> 6) & 0x1f;
24211 op1 = MASK_SPECIAL(ctx->opcode);
24212 switch (op1) {
24213 case OPC_LSA:
24214 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
24215 break;
24216 case OPC_MULT:
24217 case OPC_MULTU:
24218 case OPC_DIV:
24219 case OPC_DIVU:
24220 op2 = MASK_R6_MULDIV(ctx->opcode);
24221 switch (op2) {
24222 case R6_OPC_MUL:
24223 case R6_OPC_MUH:
24224 case R6_OPC_MULU:
24225 case R6_OPC_MUHU:
24226 case R6_OPC_DIV:
24227 case R6_OPC_MOD:
24228 case R6_OPC_DIVU:
24229 case R6_OPC_MODU:
24230 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24231 break;
24232 default:
24233 MIPS_INVAL("special_r6 muldiv");
24234 generate_exception_end(ctx, EXCP_RI);
24235 break;
24237 break;
24238 case OPC_SELEQZ:
24239 case OPC_SELNEZ:
24240 gen_cond_move(ctx, op1, rd, rs, rt);
24241 break;
24242 case R6_OPC_CLO:
24243 case R6_OPC_CLZ:
24244 if (rt == 0 && sa == 1) {
24246 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24247 * We need additionally to check other fields.
24249 gen_cl(ctx, op1, rd, rs);
24250 } else {
24251 generate_exception_end(ctx, EXCP_RI);
24253 break;
24254 case R6_OPC_SDBBP:
24255 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
24256 gen_helper_do_semihosting(cpu_env);
24257 } else {
24258 if (ctx->hflags & MIPS_HFLAG_SBRI) {
24259 generate_exception_end(ctx, EXCP_RI);
24260 } else {
24261 generate_exception_end(ctx, EXCP_DBp);
24264 break;
24265 #if defined(TARGET_MIPS64)
24266 case OPC_DLSA:
24267 check_mips_64(ctx);
24268 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
24269 break;
24270 case R6_OPC_DCLO:
24271 case R6_OPC_DCLZ:
24272 if (rt == 0 && sa == 1) {
24274 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24275 * We need additionally to check other fields.
24277 check_mips_64(ctx);
24278 gen_cl(ctx, op1, rd, rs);
24279 } else {
24280 generate_exception_end(ctx, EXCP_RI);
24282 break;
24283 case OPC_DMULT:
24284 case OPC_DMULTU:
24285 case OPC_DDIV:
24286 case OPC_DDIVU:
24288 op2 = MASK_R6_MULDIV(ctx->opcode);
24289 switch (op2) {
24290 case R6_OPC_DMUL:
24291 case R6_OPC_DMUH:
24292 case R6_OPC_DMULU:
24293 case R6_OPC_DMUHU:
24294 case R6_OPC_DDIV:
24295 case R6_OPC_DMOD:
24296 case R6_OPC_DDIVU:
24297 case R6_OPC_DMODU:
24298 check_mips_64(ctx);
24299 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24300 break;
24301 default:
24302 MIPS_INVAL("special_r6 muldiv");
24303 generate_exception_end(ctx, EXCP_RI);
24304 break;
24306 break;
24307 #endif
24308 default: /* Invalid */
24309 MIPS_INVAL("special_r6");
24310 generate_exception_end(ctx, EXCP_RI);
24311 break;
24315 static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
24317 int rs = extract32(ctx->opcode, 21, 5);
24318 int rt = extract32(ctx->opcode, 16, 5);
24319 int rd = extract32(ctx->opcode, 11, 5);
24320 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
24322 switch (op1) {
24323 case OPC_MOVN: /* Conditional move */
24324 case OPC_MOVZ:
24325 gen_cond_move(ctx, op1, rd, rs, rt);
24326 break;
24327 case OPC_MFHI: /* Move from HI/LO */
24328 case OPC_MFLO:
24329 gen_HILO(ctx, op1, 0, rd);
24330 break;
24331 case OPC_MTHI:
24332 case OPC_MTLO: /* Move to HI/LO */
24333 gen_HILO(ctx, op1, 0, rs);
24334 break;
24335 case OPC_MULT:
24336 case OPC_MULTU:
24337 gen_mul_txx9(ctx, op1, rd, rs, rt);
24338 break;
24339 case OPC_DIV:
24340 case OPC_DIVU:
24341 gen_muldiv(ctx, op1, 0, rs, rt);
24342 break;
24343 #if defined(TARGET_MIPS64)
24344 case OPC_DMULT:
24345 case OPC_DMULTU:
24346 case OPC_DDIV:
24347 case OPC_DDIVU:
24348 check_insn_opc_user_only(ctx, INSN_R5900);
24349 gen_muldiv(ctx, op1, 0, rs, rt);
24350 break;
24351 #endif
24352 case OPC_JR:
24353 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
24354 break;
24355 default: /* Invalid */
24356 MIPS_INVAL("special_tx79");
24357 generate_exception_end(ctx, EXCP_RI);
24358 break;
24362 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
24364 int rs, rt, rd, sa;
24365 uint32_t op1;
24367 rs = (ctx->opcode >> 21) & 0x1f;
24368 rt = (ctx->opcode >> 16) & 0x1f;
24369 rd = (ctx->opcode >> 11) & 0x1f;
24370 sa = (ctx->opcode >> 6) & 0x1f;
24372 op1 = MASK_SPECIAL(ctx->opcode);
24373 switch (op1) {
24374 case OPC_MOVN: /* Conditional move */
24375 case OPC_MOVZ:
24376 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
24377 INSN_LOONGSON2E | INSN_LOONGSON2F);
24378 gen_cond_move(ctx, op1, rd, rs, rt);
24379 break;
24380 case OPC_MFHI: /* Move from HI/LO */
24381 case OPC_MFLO:
24382 gen_HILO(ctx, op1, rs & 3, rd);
24383 break;
24384 case OPC_MTHI:
24385 case OPC_MTLO: /* Move to HI/LO */
24386 gen_HILO(ctx, op1, rd & 3, rs);
24387 break;
24388 case OPC_MOVCI:
24389 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
24390 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
24391 check_cp1_enabled(ctx);
24392 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
24393 (ctx->opcode >> 16) & 1);
24394 } else {
24395 generate_exception_err(ctx, EXCP_CpU, 1);
24397 break;
24398 case OPC_MULT:
24399 case OPC_MULTU:
24400 if (sa) {
24401 check_insn(ctx, INSN_VR54XX);
24402 op1 = MASK_MUL_VR54XX(ctx->opcode);
24403 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
24404 } else {
24405 gen_muldiv(ctx, op1, rd & 3, rs, rt);
24407 break;
24408 case OPC_DIV:
24409 case OPC_DIVU:
24410 gen_muldiv(ctx, op1, 0, rs, rt);
24411 break;
24412 #if defined(TARGET_MIPS64)
24413 case OPC_DMULT:
24414 case OPC_DMULTU:
24415 case OPC_DDIV:
24416 case OPC_DDIVU:
24417 check_insn(ctx, ISA_MIPS3);
24418 check_mips_64(ctx);
24419 gen_muldiv(ctx, op1, 0, rs, rt);
24420 break;
24421 #endif
24422 case OPC_JR:
24423 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24424 break;
24425 case OPC_SPIM:
24426 #ifdef MIPS_STRICT_STANDARD
24427 MIPS_INVAL("SPIM");
24428 generate_exception_end(ctx, EXCP_RI);
24429 #else
24430 /* Implemented as RI exception for now. */
24431 MIPS_INVAL("spim (unofficial)");
24432 generate_exception_end(ctx, EXCP_RI);
24433 #endif
24434 break;
24435 default: /* Invalid */
24436 MIPS_INVAL("special_legacy");
24437 generate_exception_end(ctx, EXCP_RI);
24438 break;
24442 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
24444 int rs, rt, rd, sa;
24445 uint32_t op1;
24447 rs = (ctx->opcode >> 21) & 0x1f;
24448 rt = (ctx->opcode >> 16) & 0x1f;
24449 rd = (ctx->opcode >> 11) & 0x1f;
24450 sa = (ctx->opcode >> 6) & 0x1f;
24452 op1 = MASK_SPECIAL(ctx->opcode);
24453 switch (op1) {
24454 case OPC_SLL: /* Shift with immediate */
24455 if (sa == 5 && rd == 0 &&
24456 rs == 0 && rt == 0) { /* PAUSE */
24457 if ((ctx->insn_flags & ISA_MIPS32R6) &&
24458 (ctx->hflags & MIPS_HFLAG_BMASK)) {
24459 generate_exception_end(ctx, EXCP_RI);
24460 break;
24463 /* Fallthrough */
24464 case OPC_SRA:
24465 gen_shift_imm(ctx, op1, rd, rt, sa);
24466 break;
24467 case OPC_SRL:
24468 switch ((ctx->opcode >> 21) & 0x1f) {
24469 case 1:
24470 /* rotr is decoded as srl on non-R2 CPUs */
24471 if (ctx->insn_flags & ISA_MIPS32R2) {
24472 op1 = OPC_ROTR;
24474 /* Fallthrough */
24475 case 0:
24476 gen_shift_imm(ctx, op1, rd, rt, sa);
24477 break;
24478 default:
24479 generate_exception_end(ctx, EXCP_RI);
24480 break;
24482 break;
24483 case OPC_ADD:
24484 case OPC_ADDU:
24485 case OPC_SUB:
24486 case OPC_SUBU:
24487 gen_arith(ctx, op1, rd, rs, rt);
24488 break;
24489 case OPC_SLLV: /* Shifts */
24490 case OPC_SRAV:
24491 gen_shift(ctx, op1, rd, rs, rt);
24492 break;
24493 case OPC_SRLV:
24494 switch ((ctx->opcode >> 6) & 0x1f) {
24495 case 1:
24496 /* rotrv is decoded as srlv on non-R2 CPUs */
24497 if (ctx->insn_flags & ISA_MIPS32R2) {
24498 op1 = OPC_ROTRV;
24500 /* Fallthrough */
24501 case 0:
24502 gen_shift(ctx, op1, rd, rs, rt);
24503 break;
24504 default:
24505 generate_exception_end(ctx, EXCP_RI);
24506 break;
24508 break;
24509 case OPC_SLT: /* Set on less than */
24510 case OPC_SLTU:
24511 gen_slt(ctx, op1, rd, rs, rt);
24512 break;
24513 case OPC_AND: /* Logic*/
24514 case OPC_OR:
24515 case OPC_NOR:
24516 case OPC_XOR:
24517 gen_logic(ctx, op1, rd, rs, rt);
24518 break;
24519 case OPC_JALR:
24520 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24521 break;
24522 case OPC_TGE: /* Traps */
24523 case OPC_TGEU:
24524 case OPC_TLT:
24525 case OPC_TLTU:
24526 case OPC_TEQ:
24527 case OPC_TNE:
24528 check_insn(ctx, ISA_MIPS2);
24529 gen_trap(ctx, op1, rs, rt, -1);
24530 break;
24531 case OPC_LSA: /* OPC_PMON */
24532 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24533 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
24534 decode_opc_special_r6(env, ctx);
24535 } else {
24536 /* Pmon entry point, also R4010 selsl */
24537 #ifdef MIPS_STRICT_STANDARD
24538 MIPS_INVAL("PMON / selsl");
24539 generate_exception_end(ctx, EXCP_RI);
24540 #else
24541 gen_helper_0e0i(pmon, sa);
24542 #endif
24544 break;
24545 case OPC_SYSCALL:
24546 generate_exception_end(ctx, EXCP_SYSCALL);
24547 break;
24548 case OPC_BREAK:
24549 generate_exception_end(ctx, EXCP_BREAK);
24550 break;
24551 case OPC_SYNC:
24552 check_insn(ctx, ISA_MIPS2);
24553 gen_sync(extract32(ctx->opcode, 6, 5));
24554 break;
24556 #if defined(TARGET_MIPS64)
24557 /* MIPS64 specific opcodes */
24558 case OPC_DSLL:
24559 case OPC_DSRA:
24560 case OPC_DSLL32:
24561 case OPC_DSRA32:
24562 check_insn(ctx, ISA_MIPS3);
24563 check_mips_64(ctx);
24564 gen_shift_imm(ctx, op1, rd, rt, sa);
24565 break;
24566 case OPC_DSRL:
24567 switch ((ctx->opcode >> 21) & 0x1f) {
24568 case 1:
24569 /* drotr is decoded as dsrl on non-R2 CPUs */
24570 if (ctx->insn_flags & ISA_MIPS32R2) {
24571 op1 = OPC_DROTR;
24573 /* Fallthrough */
24574 case 0:
24575 check_insn(ctx, ISA_MIPS3);
24576 check_mips_64(ctx);
24577 gen_shift_imm(ctx, op1, rd, rt, sa);
24578 break;
24579 default:
24580 generate_exception_end(ctx, EXCP_RI);
24581 break;
24583 break;
24584 case OPC_DSRL32:
24585 switch ((ctx->opcode >> 21) & 0x1f) {
24586 case 1:
24587 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
24588 if (ctx->insn_flags & ISA_MIPS32R2) {
24589 op1 = OPC_DROTR32;
24591 /* Fallthrough */
24592 case 0:
24593 check_insn(ctx, ISA_MIPS3);
24594 check_mips_64(ctx);
24595 gen_shift_imm(ctx, op1, rd, rt, sa);
24596 break;
24597 default:
24598 generate_exception_end(ctx, EXCP_RI);
24599 break;
24601 break;
24602 case OPC_DADD:
24603 case OPC_DADDU:
24604 case OPC_DSUB:
24605 case OPC_DSUBU:
24606 check_insn(ctx, ISA_MIPS3);
24607 check_mips_64(ctx);
24608 gen_arith(ctx, op1, rd, rs, rt);
24609 break;
24610 case OPC_DSLLV:
24611 case OPC_DSRAV:
24612 check_insn(ctx, ISA_MIPS3);
24613 check_mips_64(ctx);
24614 gen_shift(ctx, op1, rd, rs, rt);
24615 break;
24616 case OPC_DSRLV:
24617 switch ((ctx->opcode >> 6) & 0x1f) {
24618 case 1:
24619 /* drotrv is decoded as dsrlv on non-R2 CPUs */
24620 if (ctx->insn_flags & ISA_MIPS32R2) {
24621 op1 = OPC_DROTRV;
24623 /* Fallthrough */
24624 case 0:
24625 check_insn(ctx, ISA_MIPS3);
24626 check_mips_64(ctx);
24627 gen_shift(ctx, op1, rd, rs, rt);
24628 break;
24629 default:
24630 generate_exception_end(ctx, EXCP_RI);
24631 break;
24633 break;
24634 case OPC_DLSA:
24635 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24636 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
24637 decode_opc_special_r6(env, ctx);
24639 break;
24640 #endif
24641 default:
24642 if (ctx->insn_flags & ISA_MIPS32R6) {
24643 decode_opc_special_r6(env, ctx);
24644 } else if (ctx->insn_flags & INSN_R5900) {
24645 decode_opc_special_tx79(env, ctx);
24646 } else {
24647 decode_opc_special_legacy(env, ctx);
24653 #if defined(TARGET_MIPS64)
24657 * MMI (MultiMedia Interface) ASE instructions
24658 * ===========================================
24662 * MMI instructions category: data communication
24663 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24665 * PCPYH PEXCH PEXTLB PINTH PPACB PEXT5 PREVH
24666 * PCPYLD PEXCW PEXTLH PINTEH PPACH PPAC5 PROT3W
24667 * PCPYUD PEXEH PEXTLW PPACW
24668 * PEXEW PEXTUB
24669 * PEXTUH
24670 * PEXTUW
24674 * PCPYH rd, rt
24676 * Parallel Copy Halfword
24678 * 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
24679 * +-----------+---------+---------+---------+---------+-----------+
24680 * | MMI |0 0 0 0 0| rt | rd | PCPYH | MMI3 |
24681 * +-----------+---------+---------+---------+---------+-----------+
24683 static void gen_mmi_pcpyh(DisasContext *ctx)
24685 uint32_t pd, rt, rd;
24686 uint32_t opcode;
24688 opcode = ctx->opcode;
24690 pd = extract32(opcode, 21, 5);
24691 rt = extract32(opcode, 16, 5);
24692 rd = extract32(opcode, 11, 5);
24694 if (unlikely(pd != 0)) {
24695 generate_exception_end(ctx, EXCP_RI);
24696 } else if (rd == 0) {
24697 /* nop */
24698 } else if (rt == 0) {
24699 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24700 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24701 } else {
24702 TCGv_i64 t0 = tcg_temp_new();
24703 TCGv_i64 t1 = tcg_temp_new();
24704 uint64_t mask = (1ULL << 16) - 1;
24706 tcg_gen_andi_i64(t0, cpu_gpr[rt], mask);
24707 tcg_gen_movi_i64(t1, 0);
24708 tcg_gen_or_i64(t1, t0, t1);
24709 tcg_gen_shli_i64(t0, t0, 16);
24710 tcg_gen_or_i64(t1, t0, t1);
24711 tcg_gen_shli_i64(t0, t0, 16);
24712 tcg_gen_or_i64(t1, t0, t1);
24713 tcg_gen_shli_i64(t0, t0, 16);
24714 tcg_gen_or_i64(t1, t0, t1);
24716 tcg_gen_mov_i64(cpu_gpr[rd], t1);
24718 tcg_gen_andi_i64(t0, cpu_mmr[rt], mask);
24719 tcg_gen_movi_i64(t1, 0);
24720 tcg_gen_or_i64(t1, t0, t1);
24721 tcg_gen_shli_i64(t0, t0, 16);
24722 tcg_gen_or_i64(t1, t0, t1);
24723 tcg_gen_shli_i64(t0, t0, 16);
24724 tcg_gen_or_i64(t1, t0, t1);
24725 tcg_gen_shli_i64(t0, t0, 16);
24726 tcg_gen_or_i64(t1, t0, t1);
24728 tcg_gen_mov_i64(cpu_mmr[rd], t1);
24730 tcg_temp_free(t0);
24731 tcg_temp_free(t1);
24736 * PCPYLD rd, rs, rt
24738 * Parallel Copy Lower Doubleword
24740 * 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
24741 * +-----------+---------+---------+---------+---------+-----------+
24742 * | MMI | rs | rt | rd | PCPYLD | MMI2 |
24743 * +-----------+---------+---------+---------+---------+-----------+
24745 static void gen_mmi_pcpyld(DisasContext *ctx)
24747 uint32_t rs, rt, rd;
24748 uint32_t opcode;
24750 opcode = ctx->opcode;
24752 rs = extract32(opcode, 21, 5);
24753 rt = extract32(opcode, 16, 5);
24754 rd = extract32(opcode, 11, 5);
24756 if (rd == 0) {
24757 /* nop */
24758 } else {
24759 if (rs == 0) {
24760 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24761 } else {
24762 tcg_gen_mov_i64(cpu_mmr[rd], cpu_gpr[rs]);
24764 if (rt == 0) {
24765 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24766 } else {
24767 if (rd != rt) {
24768 tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr[rt]);
24775 * PCPYUD rd, rs, rt
24777 * Parallel Copy Upper Doubleword
24779 * 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
24780 * +-----------+---------+---------+---------+---------+-----------+
24781 * | MMI | rs | rt | rd | PCPYUD | MMI3 |
24782 * +-----------+---------+---------+---------+---------+-----------+
24784 static void gen_mmi_pcpyud(DisasContext *ctx)
24786 uint32_t rs, rt, rd;
24787 uint32_t opcode;
24789 opcode = ctx->opcode;
24791 rs = extract32(opcode, 21, 5);
24792 rt = extract32(opcode, 16, 5);
24793 rd = extract32(opcode, 11, 5);
24795 if (rd == 0) {
24796 /* nop */
24797 } else {
24798 if (rs == 0) {
24799 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24800 } else {
24801 tcg_gen_mov_i64(cpu_gpr[rd], cpu_mmr[rs]);
24803 if (rt == 0) {
24804 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24805 } else {
24806 if (rd != rt) {
24807 tcg_gen_mov_i64(cpu_mmr[rd], cpu_mmr[rt]);
24813 #endif
24816 #if !defined(TARGET_MIPS64)
24818 /* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
24819 #define MXU_APTN1_A 0
24820 #define MXU_APTN1_S 1
24822 /* MXU accumulate add/subtract 2-bit pattern 'aptn2' */
24823 #define MXU_APTN2_AA 0
24824 #define MXU_APTN2_AS 1
24825 #define MXU_APTN2_SA 2
24826 #define MXU_APTN2_SS 3
24828 /* MXU execute add/subtract 2-bit pattern 'eptn2' */
24829 #define MXU_EPTN2_AA 0
24830 #define MXU_EPTN2_AS 1
24831 #define MXU_EPTN2_SA 2
24832 #define MXU_EPTN2_SS 3
24834 /* MXU operand getting pattern 'optn2' */
24835 #define MXU_OPTN2_PTN0 0
24836 #define MXU_OPTN2_PTN1 1
24837 #define MXU_OPTN2_PTN2 2
24838 #define MXU_OPTN2_PTN3 3
24839 /* alternative naming scheme for 'optn2' */
24840 #define MXU_OPTN2_WW 0
24841 #define MXU_OPTN2_LW 1
24842 #define MXU_OPTN2_HW 2
24843 #define MXU_OPTN2_XW 3
24845 /* MXU operand getting pattern 'optn3' */
24846 #define MXU_OPTN3_PTN0 0
24847 #define MXU_OPTN3_PTN1 1
24848 #define MXU_OPTN3_PTN2 2
24849 #define MXU_OPTN3_PTN3 3
24850 #define MXU_OPTN3_PTN4 4
24851 #define MXU_OPTN3_PTN5 5
24852 #define MXU_OPTN3_PTN6 6
24853 #define MXU_OPTN3_PTN7 7
24857 * S32I2M XRa, rb - Register move from GRF to XRF
24859 static void gen_mxu_s32i2m(DisasContext *ctx)
24861 TCGv t0;
24862 uint32_t XRa, Rb;
24864 t0 = tcg_temp_new();
24866 XRa = extract32(ctx->opcode, 6, 5);
24867 Rb = extract32(ctx->opcode, 16, 5);
24869 gen_load_gpr(t0, Rb);
24870 if (XRa <= 15) {
24871 gen_store_mxu_gpr(t0, XRa);
24872 } else if (XRa == 16) {
24873 gen_store_mxu_cr(t0);
24876 tcg_temp_free(t0);
24880 * S32M2I XRa, rb - Register move from XRF to GRF
24882 static void gen_mxu_s32m2i(DisasContext *ctx)
24884 TCGv t0;
24885 uint32_t XRa, Rb;
24887 t0 = tcg_temp_new();
24889 XRa = extract32(ctx->opcode, 6, 5);
24890 Rb = extract32(ctx->opcode, 16, 5);
24892 if (XRa <= 15) {
24893 gen_load_mxu_gpr(t0, XRa);
24894 } else if (XRa == 16) {
24895 gen_load_mxu_cr(t0);
24898 gen_store_gpr(t0, Rb);
24900 tcg_temp_free(t0);
24904 * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF
24906 static void gen_mxu_s8ldd(DisasContext *ctx)
24908 TCGv t0, t1;
24909 uint32_t XRa, Rb, s8, optn3;
24911 t0 = tcg_temp_new();
24912 t1 = tcg_temp_new();
24914 XRa = extract32(ctx->opcode, 6, 4);
24915 s8 = extract32(ctx->opcode, 10, 8);
24916 optn3 = extract32(ctx->opcode, 18, 3);
24917 Rb = extract32(ctx->opcode, 21, 5);
24919 gen_load_gpr(t0, Rb);
24920 tcg_gen_addi_tl(t0, t0, (int8_t)s8);
24922 switch (optn3) {
24923 /* XRa[7:0] = tmp8 */
24924 case MXU_OPTN3_PTN0:
24925 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24926 gen_load_mxu_gpr(t0, XRa);
24927 tcg_gen_deposit_tl(t0, t0, t1, 0, 8);
24928 break;
24929 /* XRa[15:8] = tmp8 */
24930 case MXU_OPTN3_PTN1:
24931 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24932 gen_load_mxu_gpr(t0, XRa);
24933 tcg_gen_deposit_tl(t0, t0, t1, 8, 8);
24934 break;
24935 /* XRa[23:16] = tmp8 */
24936 case MXU_OPTN3_PTN2:
24937 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24938 gen_load_mxu_gpr(t0, XRa);
24939 tcg_gen_deposit_tl(t0, t0, t1, 16, 8);
24940 break;
24941 /* XRa[31:24] = tmp8 */
24942 case MXU_OPTN3_PTN3:
24943 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24944 gen_load_mxu_gpr(t0, XRa);
24945 tcg_gen_deposit_tl(t0, t0, t1, 24, 8);
24946 break;
24947 /* XRa = {8'b0, tmp8, 8'b0, tmp8} */
24948 case MXU_OPTN3_PTN4:
24949 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24950 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24951 break;
24952 /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */
24953 case MXU_OPTN3_PTN5:
24954 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24955 tcg_gen_shli_tl(t1, t1, 8);
24956 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24957 break;
24958 /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */
24959 case MXU_OPTN3_PTN6:
24960 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB);
24961 tcg_gen_mov_tl(t0, t1);
24962 tcg_gen_andi_tl(t0, t0, 0xFF00FFFF);
24963 tcg_gen_shli_tl(t1, t1, 16);
24964 tcg_gen_or_tl(t0, t0, t1);
24965 break;
24966 /* XRa = {tmp8, tmp8, tmp8, tmp8} */
24967 case MXU_OPTN3_PTN7:
24968 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24969 tcg_gen_deposit_tl(t1, t1, t1, 8, 8);
24970 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24971 break;
24974 gen_store_mxu_gpr(t0, XRa);
24976 tcg_temp_free(t0);
24977 tcg_temp_free(t1);
24981 * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication
24983 static void gen_mxu_d16mul(DisasContext *ctx)
24985 TCGv t0, t1, t2, t3;
24986 uint32_t XRa, XRb, XRc, XRd, optn2;
24988 t0 = tcg_temp_new();
24989 t1 = tcg_temp_new();
24990 t2 = tcg_temp_new();
24991 t3 = tcg_temp_new();
24993 XRa = extract32(ctx->opcode, 6, 4);
24994 XRb = extract32(ctx->opcode, 10, 4);
24995 XRc = extract32(ctx->opcode, 14, 4);
24996 XRd = extract32(ctx->opcode, 18, 4);
24997 optn2 = extract32(ctx->opcode, 22, 2);
24999 gen_load_mxu_gpr(t1, XRb);
25000 tcg_gen_sextract_tl(t0, t1, 0, 16);
25001 tcg_gen_sextract_tl(t1, t1, 16, 16);
25002 gen_load_mxu_gpr(t3, XRc);
25003 tcg_gen_sextract_tl(t2, t3, 0, 16);
25004 tcg_gen_sextract_tl(t3, t3, 16, 16);
25006 switch (optn2) {
25007 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
25008 tcg_gen_mul_tl(t3, t1, t3);
25009 tcg_gen_mul_tl(t2, t0, t2);
25010 break;
25011 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
25012 tcg_gen_mul_tl(t3, t0, t3);
25013 tcg_gen_mul_tl(t2, t0, t2);
25014 break;
25015 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
25016 tcg_gen_mul_tl(t3, t1, t3);
25017 tcg_gen_mul_tl(t2, t1, t2);
25018 break;
25019 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
25020 tcg_gen_mul_tl(t3, t0, t3);
25021 tcg_gen_mul_tl(t2, t1, t2);
25022 break;
25024 gen_store_mxu_gpr(t3, XRa);
25025 gen_store_mxu_gpr(t2, XRd);
25027 tcg_temp_free(t0);
25028 tcg_temp_free(t1);
25029 tcg_temp_free(t2);
25030 tcg_temp_free(t3);
25034 * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply
25035 * and accumulate
25037 static void gen_mxu_d16mac(DisasContext *ctx)
25039 TCGv t0, t1, t2, t3;
25040 uint32_t XRa, XRb, XRc, XRd, optn2, aptn2;
25042 t0 = tcg_temp_new();
25043 t1 = tcg_temp_new();
25044 t2 = tcg_temp_new();
25045 t3 = tcg_temp_new();
25047 XRa = extract32(ctx->opcode, 6, 4);
25048 XRb = extract32(ctx->opcode, 10, 4);
25049 XRc = extract32(ctx->opcode, 14, 4);
25050 XRd = extract32(ctx->opcode, 18, 4);
25051 optn2 = extract32(ctx->opcode, 22, 2);
25052 aptn2 = extract32(ctx->opcode, 24, 2);
25054 gen_load_mxu_gpr(t1, XRb);
25055 tcg_gen_sextract_tl(t0, t1, 0, 16);
25056 tcg_gen_sextract_tl(t1, t1, 16, 16);
25058 gen_load_mxu_gpr(t3, XRc);
25059 tcg_gen_sextract_tl(t2, t3, 0, 16);
25060 tcg_gen_sextract_tl(t3, t3, 16, 16);
25062 switch (optn2) {
25063 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
25064 tcg_gen_mul_tl(t3, t1, t3);
25065 tcg_gen_mul_tl(t2, t0, t2);
25066 break;
25067 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
25068 tcg_gen_mul_tl(t3, t0, t3);
25069 tcg_gen_mul_tl(t2, t0, t2);
25070 break;
25071 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
25072 tcg_gen_mul_tl(t3, t1, t3);
25073 tcg_gen_mul_tl(t2, t1, t2);
25074 break;
25075 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
25076 tcg_gen_mul_tl(t3, t0, t3);
25077 tcg_gen_mul_tl(t2, t1, t2);
25078 break;
25080 gen_load_mxu_gpr(t0, XRa);
25081 gen_load_mxu_gpr(t1, XRd);
25083 switch (aptn2) {
25084 case MXU_APTN2_AA:
25085 tcg_gen_add_tl(t3, t0, t3);
25086 tcg_gen_add_tl(t2, t1, t2);
25087 break;
25088 case MXU_APTN2_AS:
25089 tcg_gen_add_tl(t3, t0, t3);
25090 tcg_gen_sub_tl(t2, t1, t2);
25091 break;
25092 case MXU_APTN2_SA:
25093 tcg_gen_sub_tl(t3, t0, t3);
25094 tcg_gen_add_tl(t2, t1, t2);
25095 break;
25096 case MXU_APTN2_SS:
25097 tcg_gen_sub_tl(t3, t0, t3);
25098 tcg_gen_sub_tl(t2, t1, t2);
25099 break;
25101 gen_store_mxu_gpr(t3, XRa);
25102 gen_store_mxu_gpr(t2, XRd);
25104 tcg_temp_free(t0);
25105 tcg_temp_free(t1);
25106 tcg_temp_free(t2);
25107 tcg_temp_free(t3);
25111 * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply
25112 * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply
25114 static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx)
25116 TCGv t0, t1, t2, t3, t4, t5, t6, t7;
25117 uint32_t XRa, XRb, XRc, XRd, sel;
25119 t0 = tcg_temp_new();
25120 t1 = tcg_temp_new();
25121 t2 = tcg_temp_new();
25122 t3 = tcg_temp_new();
25123 t4 = tcg_temp_new();
25124 t5 = tcg_temp_new();
25125 t6 = tcg_temp_new();
25126 t7 = tcg_temp_new();
25128 XRa = extract32(ctx->opcode, 6, 4);
25129 XRb = extract32(ctx->opcode, 10, 4);
25130 XRc = extract32(ctx->opcode, 14, 4);
25131 XRd = extract32(ctx->opcode, 18, 4);
25132 sel = extract32(ctx->opcode, 22, 2);
25134 gen_load_mxu_gpr(t3, XRb);
25135 gen_load_mxu_gpr(t7, XRc);
25137 if (sel == 0x2) {
25138 /* Q8MULSU */
25139 tcg_gen_ext8s_tl(t0, t3);
25140 tcg_gen_shri_tl(t3, t3, 8);
25141 tcg_gen_ext8s_tl(t1, t3);
25142 tcg_gen_shri_tl(t3, t3, 8);
25143 tcg_gen_ext8s_tl(t2, t3);
25144 tcg_gen_shri_tl(t3, t3, 8);
25145 tcg_gen_ext8s_tl(t3, t3);
25146 } else {
25147 /* Q8MUL */
25148 tcg_gen_ext8u_tl(t0, t3);
25149 tcg_gen_shri_tl(t3, t3, 8);
25150 tcg_gen_ext8u_tl(t1, t3);
25151 tcg_gen_shri_tl(t3, t3, 8);
25152 tcg_gen_ext8u_tl(t2, t3);
25153 tcg_gen_shri_tl(t3, t3, 8);
25154 tcg_gen_ext8u_tl(t3, t3);
25157 tcg_gen_ext8u_tl(t4, t7);
25158 tcg_gen_shri_tl(t7, t7, 8);
25159 tcg_gen_ext8u_tl(t5, t7);
25160 tcg_gen_shri_tl(t7, t7, 8);
25161 tcg_gen_ext8u_tl(t6, t7);
25162 tcg_gen_shri_tl(t7, t7, 8);
25163 tcg_gen_ext8u_tl(t7, t7);
25165 tcg_gen_mul_tl(t0, t0, t4);
25166 tcg_gen_mul_tl(t1, t1, t5);
25167 tcg_gen_mul_tl(t2, t2, t6);
25168 tcg_gen_mul_tl(t3, t3, t7);
25170 tcg_gen_andi_tl(t0, t0, 0xFFFF);
25171 tcg_gen_andi_tl(t1, t1, 0xFFFF);
25172 tcg_gen_andi_tl(t2, t2, 0xFFFF);
25173 tcg_gen_andi_tl(t3, t3, 0xFFFF);
25175 tcg_gen_shli_tl(t1, t1, 16);
25176 tcg_gen_shli_tl(t3, t3, 16);
25178 tcg_gen_or_tl(t0, t0, t1);
25179 tcg_gen_or_tl(t1, t2, t3);
25181 gen_store_mxu_gpr(t0, XRd);
25182 gen_store_mxu_gpr(t1, XRa);
25184 tcg_temp_free(t0);
25185 tcg_temp_free(t1);
25186 tcg_temp_free(t2);
25187 tcg_temp_free(t3);
25188 tcg_temp_free(t4);
25189 tcg_temp_free(t5);
25190 tcg_temp_free(t6);
25191 tcg_temp_free(t7);
25195 * S32LDD XRa, Rb, S12 - Load a word from memory to XRF
25196 * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte seq.
25198 static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx)
25200 TCGv t0, t1;
25201 uint32_t XRa, Rb, s12, sel;
25203 t0 = tcg_temp_new();
25204 t1 = tcg_temp_new();
25206 XRa = extract32(ctx->opcode, 6, 4);
25207 s12 = extract32(ctx->opcode, 10, 10);
25208 sel = extract32(ctx->opcode, 20, 1);
25209 Rb = extract32(ctx->opcode, 21, 5);
25211 gen_load_gpr(t0, Rb);
25213 tcg_gen_movi_tl(t1, s12);
25214 tcg_gen_shli_tl(t1, t1, 2);
25215 if (s12 & 0x200) {
25216 tcg_gen_ori_tl(t1, t1, 0xFFFFF000);
25218 tcg_gen_add_tl(t1, t0, t1);
25219 tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL);
25221 if (sel == 1) {
25222 /* S32LDDR */
25223 tcg_gen_bswap32_tl(t1, t1);
25225 gen_store_mxu_gpr(t1, XRa);
25227 tcg_temp_free(t0);
25228 tcg_temp_free(t1);
25233 * MXU instruction category: logic
25234 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25236 * S32NOR S32AND S32OR S32XOR
25240 * S32NOR XRa, XRb, XRc
25241 * Update XRa with the result of logical bitwise 'nor' operation
25242 * applied to the content of XRb and XRc.
25244 * 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
25245 * +-----------+---------+-----+-------+-------+-------+-----------+
25246 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25247 * +-----------+---------+-----+-------+-------+-------+-----------+
25249 static void gen_mxu_S32NOR(DisasContext *ctx)
25251 uint32_t pad, XRc, XRb, XRa;
25253 pad = extract32(ctx->opcode, 21, 5);
25254 XRc = extract32(ctx->opcode, 14, 4);
25255 XRb = extract32(ctx->opcode, 10, 4);
25256 XRa = extract32(ctx->opcode, 6, 4);
25258 if (unlikely(pad != 0)) {
25259 /* opcode padding incorrect -> do nothing */
25260 } else if (unlikely(XRa == 0)) {
25261 /* destination is zero register -> do nothing */
25262 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25263 /* both operands zero registers -> just set destination to all 1s */
25264 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF);
25265 } else if (unlikely(XRb == 0)) {
25266 /* XRb zero register -> just set destination to the negation of XRc */
25267 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25268 } else if (unlikely(XRc == 0)) {
25269 /* XRa zero register -> just set destination to the negation of XRb */
25270 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25271 } else if (unlikely(XRb == XRc)) {
25272 /* both operands same -> just set destination to the negation of XRb */
25273 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25274 } else {
25275 /* the most general case */
25276 tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25281 * S32AND XRa, XRb, XRc
25282 * Update XRa with the result of logical bitwise 'and' operation
25283 * applied to the content of XRb and XRc.
25285 * 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
25286 * +-----------+---------+-----+-------+-------+-------+-----------+
25287 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25288 * +-----------+---------+-----+-------+-------+-------+-----------+
25290 static void gen_mxu_S32AND(DisasContext *ctx)
25292 uint32_t pad, XRc, XRb, XRa;
25294 pad = extract32(ctx->opcode, 21, 5);
25295 XRc = extract32(ctx->opcode, 14, 4);
25296 XRb = extract32(ctx->opcode, 10, 4);
25297 XRa = extract32(ctx->opcode, 6, 4);
25299 if (unlikely(pad != 0)) {
25300 /* opcode padding incorrect -> do nothing */
25301 } else if (unlikely(XRa == 0)) {
25302 /* destination is zero register -> do nothing */
25303 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25304 /* one of operands zero register -> just set destination to all 0s */
25305 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25306 } else if (unlikely(XRb == XRc)) {
25307 /* both operands same -> just set destination to one of them */
25308 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25309 } else {
25310 /* the most general case */
25311 tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25316 * S32OR XRa, XRb, XRc
25317 * Update XRa with the result of logical bitwise 'or' operation
25318 * applied to the content of XRb and XRc.
25320 * 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
25321 * +-----------+---------+-----+-------+-------+-------+-----------+
25322 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25323 * +-----------+---------+-----+-------+-------+-------+-----------+
25325 static void gen_mxu_S32OR(DisasContext *ctx)
25327 uint32_t pad, XRc, XRb, XRa;
25329 pad = extract32(ctx->opcode, 21, 5);
25330 XRc = extract32(ctx->opcode, 14, 4);
25331 XRb = extract32(ctx->opcode, 10, 4);
25332 XRa = extract32(ctx->opcode, 6, 4);
25334 if (unlikely(pad != 0)) {
25335 /* opcode padding incorrect -> do nothing */
25336 } else if (unlikely(XRa == 0)) {
25337 /* destination is zero register -> do nothing */
25338 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25339 /* both operands zero registers -> just set destination to all 0s */
25340 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25341 } else if (unlikely(XRb == 0)) {
25342 /* XRb zero register -> just set destination to the content of XRc */
25343 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25344 } else if (unlikely(XRc == 0)) {
25345 /* XRc zero register -> just set destination to the content of XRb */
25346 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25347 } else if (unlikely(XRb == XRc)) {
25348 /* both operands same -> just set destination to one of them */
25349 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25350 } else {
25351 /* the most general case */
25352 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25357 * S32XOR XRa, XRb, XRc
25358 * Update XRa with the result of logical bitwise 'xor' operation
25359 * applied to the content of XRb and XRc.
25361 * 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
25362 * +-----------+---------+-----+-------+-------+-------+-----------+
25363 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25364 * +-----------+---------+-----+-------+-------+-------+-----------+
25366 static void gen_mxu_S32XOR(DisasContext *ctx)
25368 uint32_t pad, XRc, XRb, XRa;
25370 pad = extract32(ctx->opcode, 21, 5);
25371 XRc = extract32(ctx->opcode, 14, 4);
25372 XRb = extract32(ctx->opcode, 10, 4);
25373 XRa = extract32(ctx->opcode, 6, 4);
25375 if (unlikely(pad != 0)) {
25376 /* opcode padding incorrect -> do nothing */
25377 } else if (unlikely(XRa == 0)) {
25378 /* destination is zero register -> do nothing */
25379 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25380 /* both operands zero registers -> just set destination to all 0s */
25381 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25382 } else if (unlikely(XRb == 0)) {
25383 /* XRb zero register -> just set destination to the content of XRc */
25384 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25385 } else if (unlikely(XRc == 0)) {
25386 /* XRc zero register -> just set destination to the content of XRb */
25387 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25388 } else if (unlikely(XRb == XRc)) {
25389 /* both operands same -> just set destination to all 0s */
25390 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25391 } else {
25392 /* the most general case */
25393 tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25399 * MXU instruction category max/min
25400 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25402 * S32MAX D16MAX Q8MAX
25403 * S32MIN D16MIN Q8MIN
25407 * S32MAX XRa, XRb, XRc
25408 * Update XRa with the maximum of signed 32-bit integers contained
25409 * in XRb and XRc.
25411 * S32MIN XRa, XRb, XRc
25412 * Update XRa with the minimum of signed 32-bit integers contained
25413 * in XRb and XRc.
25415 * 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
25416 * +-----------+---------+-----+-------+-------+-------+-----------+
25417 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25418 * +-----------+---------+-----+-------+-------+-------+-----------+
25420 static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx)
25422 uint32_t pad, opc, XRc, XRb, XRa;
25424 pad = extract32(ctx->opcode, 21, 5);
25425 opc = extract32(ctx->opcode, 18, 3);
25426 XRc = extract32(ctx->opcode, 14, 4);
25427 XRb = extract32(ctx->opcode, 10, 4);
25428 XRa = extract32(ctx->opcode, 6, 4);
25430 if (unlikely(pad != 0)) {
25431 /* opcode padding incorrect -> do nothing */
25432 } else if (unlikely(XRa == 0)) {
25433 /* destination is zero register -> do nothing */
25434 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25435 /* both operands zero registers -> just set destination to zero */
25436 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25437 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25438 /* exactly one operand is zero register - find which one is not...*/
25439 uint32_t XRx = XRb ? XRb : XRc;
25440 /* ...and do max/min operation with one operand 0 */
25441 if (opc == OPC_MXU_S32MAX) {
25442 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25443 } else {
25444 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25446 } else if (unlikely(XRb == XRc)) {
25447 /* both operands same -> just set destination to one of them */
25448 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25449 } else {
25450 /* the most general case */
25451 if (opc == OPC_MXU_S32MAX) {
25452 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25453 mxu_gpr[XRc - 1]);
25454 } else {
25455 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25456 mxu_gpr[XRc - 1]);
25462 * D16MAX
25463 * Update XRa with the 16-bit-wise maximums of signed integers
25464 * contained in XRb and XRc.
25466 * D16MIN
25467 * Update XRa with the 16-bit-wise minimums of signed integers
25468 * contained in XRb and XRc.
25470 * 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
25471 * +-----------+---------+-----+-------+-------+-------+-----------+
25472 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25473 * +-----------+---------+-----+-------+-------+-------+-----------+
25475 static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx)
25477 uint32_t pad, opc, XRc, XRb, XRa;
25479 pad = extract32(ctx->opcode, 21, 5);
25480 opc = extract32(ctx->opcode, 18, 3);
25481 XRc = extract32(ctx->opcode, 14, 4);
25482 XRb = extract32(ctx->opcode, 10, 4);
25483 XRa = extract32(ctx->opcode, 6, 4);
25485 if (unlikely(pad != 0)) {
25486 /* opcode padding incorrect -> do nothing */
25487 } else if (unlikely(XRc == 0)) {
25488 /* destination is zero register -> do nothing */
25489 } else if (unlikely((XRb == 0) && (XRa == 0))) {
25490 /* both operands zero registers -> just set destination to zero */
25491 tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0);
25492 } else if (unlikely((XRb == 0) || (XRa == 0))) {
25493 /* exactly one operand is zero register - find which one is not...*/
25494 uint32_t XRx = XRb ? XRb : XRc;
25495 /* ...and do half-word-wise max/min with one operand 0 */
25496 TCGv_i32 t0 = tcg_temp_new();
25497 TCGv_i32 t1 = tcg_const_i32(0);
25499 /* the left half-word first */
25500 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000);
25501 if (opc == OPC_MXU_D16MAX) {
25502 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25503 } else {
25504 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25507 /* the right half-word */
25508 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF);
25509 /* move half-words to the leftmost position */
25510 tcg_gen_shli_i32(t0, t0, 16);
25511 /* t0 will be max/min of t0 and t1 */
25512 if (opc == OPC_MXU_D16MAX) {
25513 tcg_gen_smax_i32(t0, t0, t1);
25514 } else {
25515 tcg_gen_smin_i32(t0, t0, t1);
25517 /* return resulting half-words to its original position */
25518 tcg_gen_shri_i32(t0, t0, 16);
25519 /* finaly update the destination */
25520 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25522 tcg_temp_free(t1);
25523 tcg_temp_free(t0);
25524 } else if (unlikely(XRb == XRc)) {
25525 /* both operands same -> just set destination to one of them */
25526 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25527 } else {
25528 /* the most general case */
25529 TCGv_i32 t0 = tcg_temp_new();
25530 TCGv_i32 t1 = tcg_temp_new();
25532 /* the left half-word first */
25533 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000);
25534 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25535 if (opc == OPC_MXU_D16MAX) {
25536 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25537 } else {
25538 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25541 /* the right half-word */
25542 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25543 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF);
25544 /* move half-words to the leftmost position */
25545 tcg_gen_shli_i32(t0, t0, 16);
25546 tcg_gen_shli_i32(t1, t1, 16);
25547 /* t0 will be max/min of t0 and t1 */
25548 if (opc == OPC_MXU_D16MAX) {
25549 tcg_gen_smax_i32(t0, t0, t1);
25550 } else {
25551 tcg_gen_smin_i32(t0, t0, t1);
25553 /* return resulting half-words to its original position */
25554 tcg_gen_shri_i32(t0, t0, 16);
25555 /* finaly update the destination */
25556 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25558 tcg_temp_free(t1);
25559 tcg_temp_free(t0);
25564 * Q8MAX
25565 * Update XRa with the 8-bit-wise maximums of signed integers
25566 * contained in XRb and XRc.
25568 * Q8MIN
25569 * Update XRa with the 8-bit-wise minimums of signed integers
25570 * contained in XRb and XRc.
25572 * 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
25573 * +-----------+---------+-----+-------+-------+-------+-----------+
25574 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25575 * +-----------+---------+-----+-------+-------+-------+-----------+
25577 static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx)
25579 uint32_t pad, opc, XRc, XRb, XRa;
25581 pad = extract32(ctx->opcode, 21, 5);
25582 opc = extract32(ctx->opcode, 18, 3);
25583 XRc = extract32(ctx->opcode, 14, 4);
25584 XRb = extract32(ctx->opcode, 10, 4);
25585 XRa = extract32(ctx->opcode, 6, 4);
25587 if (unlikely(pad != 0)) {
25588 /* opcode padding incorrect -> do nothing */
25589 } else if (unlikely(XRa == 0)) {
25590 /* destination is zero register -> do nothing */
25591 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25592 /* both operands zero registers -> just set destination to zero */
25593 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25594 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25595 /* exactly one operand is zero register - make it be the first...*/
25596 uint32_t XRx = XRb ? XRb : XRc;
25597 /* ...and do byte-wise max/min with one operand 0 */
25598 TCGv_i32 t0 = tcg_temp_new();
25599 TCGv_i32 t1 = tcg_const_i32(0);
25600 int32_t i;
25602 /* the leftmost byte (byte 3) first */
25603 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000);
25604 if (opc == OPC_MXU_Q8MAX) {
25605 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25606 } else {
25607 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25610 /* bytes 2, 1, 0 */
25611 for (i = 2; i >= 0; i--) {
25612 /* extract the byte */
25613 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i));
25614 /* move the byte to the leftmost position */
25615 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25616 /* t0 will be max/min of t0 and t1 */
25617 if (opc == OPC_MXU_Q8MAX) {
25618 tcg_gen_smax_i32(t0, t0, t1);
25619 } else {
25620 tcg_gen_smin_i32(t0, t0, t1);
25622 /* return resulting byte to its original position */
25623 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25624 /* finaly update the destination */
25625 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25628 tcg_temp_free(t1);
25629 tcg_temp_free(t0);
25630 } else if (unlikely(XRb == XRc)) {
25631 /* both operands same -> just set destination to one of them */
25632 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25633 } else {
25634 /* the most general case */
25635 TCGv_i32 t0 = tcg_temp_new();
25636 TCGv_i32 t1 = tcg_temp_new();
25637 int32_t i;
25639 /* the leftmost bytes (bytes 3) first */
25640 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000);
25641 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25642 if (opc == OPC_MXU_Q8MAX) {
25643 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25644 } else {
25645 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25648 /* bytes 2, 1, 0 */
25649 for (i = 2; i >= 0; i--) {
25650 /* extract corresponding bytes */
25651 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i));
25652 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i));
25653 /* move the bytes to the leftmost position */
25654 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25655 tcg_gen_shli_i32(t1, t1, 8 * (3 - i));
25656 /* t0 will be max/min of t0 and t1 */
25657 if (opc == OPC_MXU_Q8MAX) {
25658 tcg_gen_smax_i32(t0, t0, t1);
25659 } else {
25660 tcg_gen_smin_i32(t0, t0, t1);
25662 /* return resulting byte to its original position */
25663 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25664 /* finaly update the destination */
25665 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25668 tcg_temp_free(t1);
25669 tcg_temp_free(t0);
25675 * MXU instruction category: align
25676 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25678 * S32ALN S32ALNI
25682 * S32ALNI XRc, XRb, XRa, optn3
25683 * Arrange bytes from XRb and XRc according to one of five sets of
25684 * rules determined by optn3, and place the result in XRa.
25686 * 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
25687 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25688 * | SPECIAL2 |optn3|0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
25689 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25692 static void gen_mxu_S32ALNI(DisasContext *ctx)
25694 uint32_t optn3, pad, XRc, XRb, XRa;
25696 optn3 = extract32(ctx->opcode, 23, 3);
25697 pad = extract32(ctx->opcode, 21, 2);
25698 XRc = extract32(ctx->opcode, 14, 4);
25699 XRb = extract32(ctx->opcode, 10, 4);
25700 XRa = extract32(ctx->opcode, 6, 4);
25702 if (unlikely(pad != 0)) {
25703 /* opcode padding incorrect -> do nothing */
25704 } else if (unlikely(XRa == 0)) {
25705 /* destination is zero register -> do nothing */
25706 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25707 /* both operands zero registers -> just set destination to all 0s */
25708 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25709 } else if (unlikely(XRb == 0)) {
25710 /* XRb zero register -> just appropriatelly shift XRc into XRa */
25711 switch (optn3) {
25712 case MXU_OPTN3_PTN0:
25713 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25714 break;
25715 case MXU_OPTN3_PTN1:
25716 case MXU_OPTN3_PTN2:
25717 case MXU_OPTN3_PTN3:
25718 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1],
25719 8 * (4 - optn3));
25720 break;
25721 case MXU_OPTN3_PTN4:
25722 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25723 break;
25725 } else if (unlikely(XRc == 0)) {
25726 /* XRc zero register -> just appropriatelly shift XRb into XRa */
25727 switch (optn3) {
25728 case MXU_OPTN3_PTN0:
25729 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25730 break;
25731 case MXU_OPTN3_PTN1:
25732 case MXU_OPTN3_PTN2:
25733 case MXU_OPTN3_PTN3:
25734 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25735 break;
25736 case MXU_OPTN3_PTN4:
25737 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25738 break;
25740 } else if (unlikely(XRb == XRc)) {
25741 /* both operands same -> just rotation or moving from any of them */
25742 switch (optn3) {
25743 case MXU_OPTN3_PTN0:
25744 case MXU_OPTN3_PTN4:
25745 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25746 break;
25747 case MXU_OPTN3_PTN1:
25748 case MXU_OPTN3_PTN2:
25749 case MXU_OPTN3_PTN3:
25750 tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25751 break;
25753 } else {
25754 /* the most general case */
25755 switch (optn3) {
25756 case MXU_OPTN3_PTN0:
25758 /* */
25759 /* XRb XRc */
25760 /* +---------------+ */
25761 /* | A B C D | E F G H */
25762 /* +-------+-------+ */
25763 /* | */
25764 /* XRa */
25765 /* */
25767 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25769 break;
25770 case MXU_OPTN3_PTN1:
25772 /* */
25773 /* XRb XRc */
25774 /* +-------------------+ */
25775 /* A | B C D E | F G H */
25776 /* +---------+---------+ */
25777 /* | */
25778 /* XRa */
25779 /* */
25781 TCGv_i32 t0 = tcg_temp_new();
25782 TCGv_i32 t1 = tcg_temp_new();
25784 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF);
25785 tcg_gen_shli_i32(t0, t0, 8);
25787 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25788 tcg_gen_shri_i32(t1, t1, 24);
25790 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25792 tcg_temp_free(t1);
25793 tcg_temp_free(t0);
25795 break;
25796 case MXU_OPTN3_PTN2:
25798 /* */
25799 /* XRb XRc */
25800 /* +-------------------+ */
25801 /* A B | C D E F | G H */
25802 /* +---------+---------+ */
25803 /* | */
25804 /* XRa */
25805 /* */
25807 TCGv_i32 t0 = tcg_temp_new();
25808 TCGv_i32 t1 = tcg_temp_new();
25810 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25811 tcg_gen_shli_i32(t0, t0, 16);
25813 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25814 tcg_gen_shri_i32(t1, t1, 16);
25816 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25818 tcg_temp_free(t1);
25819 tcg_temp_free(t0);
25821 break;
25822 case MXU_OPTN3_PTN3:
25824 /* */
25825 /* XRb XRc */
25826 /* +-------------------+ */
25827 /* A B C | D E F G | H */
25828 /* +---------+---------+ */
25829 /* | */
25830 /* XRa */
25831 /* */
25833 TCGv_i32 t0 = tcg_temp_new();
25834 TCGv_i32 t1 = tcg_temp_new();
25836 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF);
25837 tcg_gen_shli_i32(t0, t0, 24);
25839 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00);
25840 tcg_gen_shri_i32(t1, t1, 8);
25842 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25844 tcg_temp_free(t1);
25845 tcg_temp_free(t0);
25847 break;
25848 case MXU_OPTN3_PTN4:
25850 /* */
25851 /* XRb XRc */
25852 /* +---------------+ */
25853 /* A B C D | E F G H | */
25854 /* +-------+-------+ */
25855 /* | */
25856 /* XRa */
25857 /* */
25859 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25861 break;
25868 * Decoding engine for MXU
25869 * =======================
25874 * Decode MXU pool00
25876 * 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
25877 * +-----------+---------+-----+-------+-------+-------+-----------+
25878 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL00|
25879 * +-----------+---------+-----+-------+-------+-------+-----------+
25882 static void decode_opc_mxu__pool00(CPUMIPSState *env, DisasContext *ctx)
25884 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25886 switch (opcode) {
25887 case OPC_MXU_S32MAX:
25888 case OPC_MXU_S32MIN:
25889 gen_mxu_S32MAX_S32MIN(ctx);
25890 break;
25891 case OPC_MXU_D16MAX:
25892 case OPC_MXU_D16MIN:
25893 gen_mxu_D16MAX_D16MIN(ctx);
25894 break;
25895 case OPC_MXU_Q8MAX:
25896 case OPC_MXU_Q8MIN:
25897 gen_mxu_Q8MAX_Q8MIN(ctx);
25898 break;
25899 case OPC_MXU_Q8SLT:
25900 /* TODO: Implement emulation of Q8SLT instruction. */
25901 MIPS_INVAL("OPC_MXU_Q8SLT");
25902 generate_exception_end(ctx, EXCP_RI);
25903 break;
25904 case OPC_MXU_Q8SLTU:
25905 /* TODO: Implement emulation of Q8SLTU instruction. */
25906 MIPS_INVAL("OPC_MXU_Q8SLTU");
25907 generate_exception_end(ctx, EXCP_RI);
25908 break;
25909 default:
25910 MIPS_INVAL("decode_opc_mxu");
25911 generate_exception_end(ctx, EXCP_RI);
25912 break;
25918 * Decode MXU pool01
25920 * S32SLT, D16SLT, D16AVG, D16AVGR, Q8AVG, Q8AVGR:
25921 * 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
25922 * +-----------+---------+-----+-------+-------+-------+-----------+
25923 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
25924 * +-----------+---------+-----+-------+-------+-------+-----------+
25926 * Q8ADD:
25927 * 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
25928 * +-----------+---+-----+-----+-------+-------+-------+-----------+
25929 * | SPECIAL2 |en2|0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
25930 * +-----------+---+-----+-----+-------+-------+-------+-----------+
25933 static void decode_opc_mxu__pool01(CPUMIPSState *env, DisasContext *ctx)
25935 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25937 switch (opcode) {
25938 case OPC_MXU_S32SLT:
25939 /* TODO: Implement emulation of S32SLT instruction. */
25940 MIPS_INVAL("OPC_MXU_S32SLT");
25941 generate_exception_end(ctx, EXCP_RI);
25942 break;
25943 case OPC_MXU_D16SLT:
25944 /* TODO: Implement emulation of D16SLT instruction. */
25945 MIPS_INVAL("OPC_MXU_D16SLT");
25946 generate_exception_end(ctx, EXCP_RI);
25947 break;
25948 case OPC_MXU_D16AVG:
25949 /* TODO: Implement emulation of D16AVG instruction. */
25950 MIPS_INVAL("OPC_MXU_D16AVG");
25951 generate_exception_end(ctx, EXCP_RI);
25952 break;
25953 case OPC_MXU_D16AVGR:
25954 /* TODO: Implement emulation of D16AVGR instruction. */
25955 MIPS_INVAL("OPC_MXU_D16AVGR");
25956 generate_exception_end(ctx, EXCP_RI);
25957 break;
25958 case OPC_MXU_Q8AVG:
25959 /* TODO: Implement emulation of Q8AVG instruction. */
25960 MIPS_INVAL("OPC_MXU_Q8AVG");
25961 generate_exception_end(ctx, EXCP_RI);
25962 break;
25963 case OPC_MXU_Q8AVGR:
25964 /* TODO: Implement emulation of Q8AVGR instruction. */
25965 MIPS_INVAL("OPC_MXU_Q8AVGR");
25966 generate_exception_end(ctx, EXCP_RI);
25967 break;
25968 case OPC_MXU_Q8ADD:
25969 /* TODO: Implement emulation of Q8ADD instruction. */
25970 MIPS_INVAL("OPC_MXU_Q8ADD");
25971 generate_exception_end(ctx, EXCP_RI);
25972 break;
25973 default:
25974 MIPS_INVAL("decode_opc_mxu");
25975 generate_exception_end(ctx, EXCP_RI);
25976 break;
25982 * Decode MXU pool02
25984 * 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
25985 * +-----------+---------+-----+-------+-------+-------+-----------+
25986 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL02|
25987 * +-----------+---------+-----+-------+-------+-------+-----------+
25990 static void decode_opc_mxu__pool02(CPUMIPSState *env, DisasContext *ctx)
25992 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25994 switch (opcode) {
25995 case OPC_MXU_S32CPS:
25996 /* TODO: Implement emulation of S32CPS instruction. */
25997 MIPS_INVAL("OPC_MXU_S32CPS");
25998 generate_exception_end(ctx, EXCP_RI);
25999 break;
26000 case OPC_MXU_D16CPS:
26001 /* TODO: Implement emulation of D16CPS instruction. */
26002 MIPS_INVAL("OPC_MXU_D16CPS");
26003 generate_exception_end(ctx, EXCP_RI);
26004 break;
26005 case OPC_MXU_Q8ABD:
26006 /* TODO: Implement emulation of Q8ABD instruction. */
26007 MIPS_INVAL("OPC_MXU_Q8ABD");
26008 generate_exception_end(ctx, EXCP_RI);
26009 break;
26010 case OPC_MXU_Q16SAT:
26011 /* TODO: Implement emulation of Q16SAT instruction. */
26012 MIPS_INVAL("OPC_MXU_Q16SAT");
26013 generate_exception_end(ctx, EXCP_RI);
26014 break;
26015 default:
26016 MIPS_INVAL("decode_opc_mxu");
26017 generate_exception_end(ctx, EXCP_RI);
26018 break;
26024 * Decode MXU pool03
26026 * D16MULF:
26027 * 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
26028 * +-----------+---+---+-------+-------+-------+-------+-----------+
26029 * | SPECIAL2 |x x|on2|0 0 0 0| XRc | XRb | XRa |MXU__POOL03|
26030 * +-----------+---+---+-------+-------+-------+-------+-----------+
26032 * D16MULE:
26033 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26034 * +-----------+---+---+-------+-------+-------+-------+-----------+
26035 * | SPECIAL2 |x x|on2| Xd | XRc | XRb | XRa |MXU__POOL03|
26036 * +-----------+---+---+-------+-------+-------+-------+-----------+
26039 static void decode_opc_mxu__pool03(CPUMIPSState *env, DisasContext *ctx)
26041 uint32_t opcode = extract32(ctx->opcode, 24, 2);
26043 switch (opcode) {
26044 case OPC_MXU_D16MULF:
26045 /* TODO: Implement emulation of D16MULF instruction. */
26046 MIPS_INVAL("OPC_MXU_D16MULF");
26047 generate_exception_end(ctx, EXCP_RI);
26048 break;
26049 case OPC_MXU_D16MULE:
26050 /* TODO: Implement emulation of D16MULE instruction. */
26051 MIPS_INVAL("OPC_MXU_D16MULE");
26052 generate_exception_end(ctx, EXCP_RI);
26053 break;
26054 default:
26055 MIPS_INVAL("decode_opc_mxu");
26056 generate_exception_end(ctx, EXCP_RI);
26057 break;
26063 * Decode MXU pool04
26065 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26066 * +-----------+---------+-+-------------------+-------+-----------+
26067 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL04|
26068 * +-----------+---------+-+-------------------+-------+-----------+
26071 static void decode_opc_mxu__pool04(CPUMIPSState *env, DisasContext *ctx)
26073 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26075 switch (opcode) {
26076 case OPC_MXU_S32LDD:
26077 case OPC_MXU_S32LDDR:
26078 gen_mxu_s32ldd_s32lddr(ctx);
26079 break;
26080 default:
26081 MIPS_INVAL("decode_opc_mxu");
26082 generate_exception_end(ctx, EXCP_RI);
26083 break;
26089 * Decode MXU pool05
26091 * 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
26092 * +-----------+---------+-+-------------------+-------+-----------+
26093 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL05|
26094 * +-----------+---------+-+-------------------+-------+-----------+
26097 static void decode_opc_mxu__pool05(CPUMIPSState *env, DisasContext *ctx)
26099 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26101 switch (opcode) {
26102 case OPC_MXU_S32STD:
26103 /* TODO: Implement emulation of S32STD instruction. */
26104 MIPS_INVAL("OPC_MXU_S32STD");
26105 generate_exception_end(ctx, EXCP_RI);
26106 break;
26107 case OPC_MXU_S32STDR:
26108 /* TODO: Implement emulation of S32STDR instruction. */
26109 MIPS_INVAL("OPC_MXU_S32STDR");
26110 generate_exception_end(ctx, EXCP_RI);
26111 break;
26112 default:
26113 MIPS_INVAL("decode_opc_mxu");
26114 generate_exception_end(ctx, EXCP_RI);
26115 break;
26121 * Decode MXU pool06
26123 * 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
26124 * +-----------+---------+---------+---+-------+-------+-----------+
26125 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL06|
26126 * +-----------+---------+---------+---+-------+-------+-----------+
26129 static void decode_opc_mxu__pool06(CPUMIPSState *env, DisasContext *ctx)
26131 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26133 switch (opcode) {
26134 case OPC_MXU_S32LDDV:
26135 /* TODO: Implement emulation of S32LDDV instruction. */
26136 MIPS_INVAL("OPC_MXU_S32LDDV");
26137 generate_exception_end(ctx, EXCP_RI);
26138 break;
26139 case OPC_MXU_S32LDDVR:
26140 /* TODO: Implement emulation of S32LDDVR instruction. */
26141 MIPS_INVAL("OPC_MXU_S32LDDVR");
26142 generate_exception_end(ctx, EXCP_RI);
26143 break;
26144 default:
26145 MIPS_INVAL("decode_opc_mxu");
26146 generate_exception_end(ctx, EXCP_RI);
26147 break;
26153 * Decode MXU pool07
26155 * 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
26156 * +-----------+---------+---------+---+-------+-------+-----------+
26157 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL07|
26158 * +-----------+---------+---------+---+-------+-------+-----------+
26161 static void decode_opc_mxu__pool07(CPUMIPSState *env, DisasContext *ctx)
26163 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26165 switch (opcode) {
26166 case OPC_MXU_S32STDV:
26167 /* TODO: Implement emulation of S32TDV instruction. */
26168 MIPS_INVAL("OPC_MXU_S32TDV");
26169 generate_exception_end(ctx, EXCP_RI);
26170 break;
26171 case OPC_MXU_S32STDVR:
26172 /* TODO: Implement emulation of S32TDVR instruction. */
26173 MIPS_INVAL("OPC_MXU_S32TDVR");
26174 generate_exception_end(ctx, EXCP_RI);
26175 break;
26176 default:
26177 MIPS_INVAL("decode_opc_mxu");
26178 generate_exception_end(ctx, EXCP_RI);
26179 break;
26185 * Decode MXU pool08
26187 * 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
26188 * +-----------+---------+-+-------------------+-------+-----------+
26189 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL08|
26190 * +-----------+---------+-+-------------------+-------+-----------+
26193 static void decode_opc_mxu__pool08(CPUMIPSState *env, DisasContext *ctx)
26195 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26197 switch (opcode) {
26198 case OPC_MXU_S32LDI:
26199 /* TODO: Implement emulation of S32LDI instruction. */
26200 MIPS_INVAL("OPC_MXU_S32LDI");
26201 generate_exception_end(ctx, EXCP_RI);
26202 break;
26203 case OPC_MXU_S32LDIR:
26204 /* TODO: Implement emulation of S32LDIR instruction. */
26205 MIPS_INVAL("OPC_MXU_S32LDIR");
26206 generate_exception_end(ctx, EXCP_RI);
26207 break;
26208 default:
26209 MIPS_INVAL("decode_opc_mxu");
26210 generate_exception_end(ctx, EXCP_RI);
26211 break;
26217 * Decode MXU pool09
26219 * 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
26220 * +-----------+---------+-+-------------------+-------+-----------+
26221 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL09|
26222 * +-----------+---------+-+-------------------+-------+-----------+
26225 static void decode_opc_mxu__pool09(CPUMIPSState *env, DisasContext *ctx)
26227 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26229 switch (opcode) {
26230 case OPC_MXU_S32SDI:
26231 /* TODO: Implement emulation of S32SDI instruction. */
26232 MIPS_INVAL("OPC_MXU_S32SDI");
26233 generate_exception_end(ctx, EXCP_RI);
26234 break;
26235 case OPC_MXU_S32SDIR:
26236 /* TODO: Implement emulation of S32SDIR instruction. */
26237 MIPS_INVAL("OPC_MXU_S32SDIR");
26238 generate_exception_end(ctx, EXCP_RI);
26239 break;
26240 default:
26241 MIPS_INVAL("decode_opc_mxu");
26242 generate_exception_end(ctx, EXCP_RI);
26243 break;
26249 * Decode MXU pool10
26251 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26252 * +-----------+---------+---------+---+-------+-------+-----------+
26253 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL10|
26254 * +-----------+---------+---------+---+-------+-------+-----------+
26257 static void decode_opc_mxu__pool10(CPUMIPSState *env, DisasContext *ctx)
26259 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26261 switch (opcode) {
26262 case OPC_MXU_S32LDIV:
26263 /* TODO: Implement emulation of S32LDIV instruction. */
26264 MIPS_INVAL("OPC_MXU_S32LDIV");
26265 generate_exception_end(ctx, EXCP_RI);
26266 break;
26267 case OPC_MXU_S32LDIVR:
26268 /* TODO: Implement emulation of S32LDIVR instruction. */
26269 MIPS_INVAL("OPC_MXU_S32LDIVR");
26270 generate_exception_end(ctx, EXCP_RI);
26271 break;
26272 default:
26273 MIPS_INVAL("decode_opc_mxu");
26274 generate_exception_end(ctx, EXCP_RI);
26275 break;
26281 * Decode MXU pool11
26283 * 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
26284 * +-----------+---------+---------+---+-------+-------+-----------+
26285 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL11|
26286 * +-----------+---------+---------+---+-------+-------+-----------+
26289 static void decode_opc_mxu__pool11(CPUMIPSState *env, DisasContext *ctx)
26291 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26293 switch (opcode) {
26294 case OPC_MXU_S32SDIV:
26295 /* TODO: Implement emulation of S32SDIV instruction. */
26296 MIPS_INVAL("OPC_MXU_S32SDIV");
26297 generate_exception_end(ctx, EXCP_RI);
26298 break;
26299 case OPC_MXU_S32SDIVR:
26300 /* TODO: Implement emulation of S32SDIVR instruction. */
26301 MIPS_INVAL("OPC_MXU_S32SDIVR");
26302 generate_exception_end(ctx, EXCP_RI);
26303 break;
26304 default:
26305 MIPS_INVAL("decode_opc_mxu");
26306 generate_exception_end(ctx, EXCP_RI);
26307 break;
26313 * Decode MXU pool12
26315 * 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
26316 * +-----------+---+---+-------+-------+-------+-------+-----------+
26317 * | SPECIAL2 |an2|x x| Xd | XRc | XRb | XRa |MXU__POOL12|
26318 * +-----------+---+---+-------+-------+-------+-------+-----------+
26321 static void decode_opc_mxu__pool12(CPUMIPSState *env, DisasContext *ctx)
26323 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26325 switch (opcode) {
26326 case OPC_MXU_D32ACC:
26327 /* TODO: Implement emulation of D32ACC instruction. */
26328 MIPS_INVAL("OPC_MXU_D32ACC");
26329 generate_exception_end(ctx, EXCP_RI);
26330 break;
26331 case OPC_MXU_D32ACCM:
26332 /* TODO: Implement emulation of D32ACCM instruction. */
26333 MIPS_INVAL("OPC_MXU_D32ACCM");
26334 generate_exception_end(ctx, EXCP_RI);
26335 break;
26336 case OPC_MXU_D32ASUM:
26337 /* TODO: Implement emulation of D32ASUM instruction. */
26338 MIPS_INVAL("OPC_MXU_D32ASUM");
26339 generate_exception_end(ctx, EXCP_RI);
26340 break;
26341 default:
26342 MIPS_INVAL("decode_opc_mxu");
26343 generate_exception_end(ctx, EXCP_RI);
26344 break;
26350 * Decode MXU pool13
26352 * 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
26353 * +-----------+---+---+-------+-------+-------+-------+-----------+
26354 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL13|
26355 * +-----------+---+---+-------+-------+-------+-------+-----------+
26358 static void decode_opc_mxu__pool13(CPUMIPSState *env, DisasContext *ctx)
26360 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26362 switch (opcode) {
26363 case OPC_MXU_Q16ACC:
26364 /* TODO: Implement emulation of Q16ACC instruction. */
26365 MIPS_INVAL("OPC_MXU_Q16ACC");
26366 generate_exception_end(ctx, EXCP_RI);
26367 break;
26368 case OPC_MXU_Q16ACCM:
26369 /* TODO: Implement emulation of Q16ACCM instruction. */
26370 MIPS_INVAL("OPC_MXU_Q16ACCM");
26371 generate_exception_end(ctx, EXCP_RI);
26372 break;
26373 case OPC_MXU_Q16ASUM:
26374 /* TODO: Implement emulation of Q16ASUM instruction. */
26375 MIPS_INVAL("OPC_MXU_Q16ASUM");
26376 generate_exception_end(ctx, EXCP_RI);
26377 break;
26378 default:
26379 MIPS_INVAL("decode_opc_mxu");
26380 generate_exception_end(ctx, EXCP_RI);
26381 break;
26387 * Decode MXU pool14
26389 * Q8ADDE, Q8ACCE:
26390 * 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
26391 * +-----------+---+---+-------+-------+-------+-------+-----------+
26392 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL14|
26393 * +-----------+---+---+-------+-------+-------+-------+-----------+
26395 * D8SUM, D8SUMC:
26396 * 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
26397 * +-----------+---+---+-------+-------+-------+-------+-----------+
26398 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL14|
26399 * +-----------+---+---+-------+-------+-------+-------+-----------+
26402 static void decode_opc_mxu__pool14(CPUMIPSState *env, DisasContext *ctx)
26404 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26406 switch (opcode) {
26407 case OPC_MXU_Q8ADDE:
26408 /* TODO: Implement emulation of Q8ADDE instruction. */
26409 MIPS_INVAL("OPC_MXU_Q8ADDE");
26410 generate_exception_end(ctx, EXCP_RI);
26411 break;
26412 case OPC_MXU_D8SUM:
26413 /* TODO: Implement emulation of D8SUM instruction. */
26414 MIPS_INVAL("OPC_MXU_D8SUM");
26415 generate_exception_end(ctx, EXCP_RI);
26416 break;
26417 case OPC_MXU_D8SUMC:
26418 /* TODO: Implement emulation of D8SUMC instruction. */
26419 MIPS_INVAL("OPC_MXU_D8SUMC");
26420 generate_exception_end(ctx, EXCP_RI);
26421 break;
26422 default:
26423 MIPS_INVAL("decode_opc_mxu");
26424 generate_exception_end(ctx, EXCP_RI);
26425 break;
26431 * Decode MXU pool15
26433 * S32MUL, S32MULU, S32EXTRV:
26434 * 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
26435 * +-----------+---------+---------+---+-------+-------+-----------+
26436 * | SPECIAL2 | rs | rt |x x| XRd | XRa |MXU__POOL15|
26437 * +-----------+---------+---------+---+-------+-------+-----------+
26439 * S32EXTR:
26440 * 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
26441 * +-----------+---------+---------+---+-------+-------+-----------+
26442 * | SPECIAL2 | rb | sft5 |x x| XRd | XRa |MXU__POOL15|
26443 * +-----------+---------+---------+---+-------+-------+-----------+
26446 static void decode_opc_mxu__pool15(CPUMIPSState *env, DisasContext *ctx)
26448 uint32_t opcode = extract32(ctx->opcode, 14, 2);
26450 switch (opcode) {
26451 case OPC_MXU_S32MUL:
26452 /* TODO: Implement emulation of S32MUL instruction. */
26453 MIPS_INVAL("OPC_MXU_S32MUL");
26454 generate_exception_end(ctx, EXCP_RI);
26455 break;
26456 case OPC_MXU_S32MULU:
26457 /* TODO: Implement emulation of S32MULU instruction. */
26458 MIPS_INVAL("OPC_MXU_S32MULU");
26459 generate_exception_end(ctx, EXCP_RI);
26460 break;
26461 case OPC_MXU_S32EXTR:
26462 /* TODO: Implement emulation of S32EXTR instruction. */
26463 MIPS_INVAL("OPC_MXU_S32EXTR");
26464 generate_exception_end(ctx, EXCP_RI);
26465 break;
26466 case OPC_MXU_S32EXTRV:
26467 /* TODO: Implement emulation of S32EXTRV instruction. */
26468 MIPS_INVAL("OPC_MXU_S32EXTRV");
26469 generate_exception_end(ctx, EXCP_RI);
26470 break;
26471 default:
26472 MIPS_INVAL("decode_opc_mxu");
26473 generate_exception_end(ctx, EXCP_RI);
26474 break;
26480 * Decode MXU pool16
26482 * D32SARW:
26483 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26484 * +-----------+---------+-----+-------+-------+-------+-----------+
26485 * | SPECIAL2 | rb |x x x| XRc | XRb | XRa |MXU__POOL16|
26486 * +-----------+---------+-----+-------+-------+-------+-----------+
26488 * S32ALN:
26489 * 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
26490 * +-----------+---------+-----+-------+-------+-------+-----------+
26491 * | SPECIAL2 | rs |x x x| XRc | XRb | XRa |MXU__POOL16|
26492 * +-----------+---------+-----+-------+-------+-------+-----------+
26494 * S32ALNI:
26495 * 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
26496 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26497 * | SPECIAL2 | s3 |0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26498 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26500 * S32LUI:
26501 * 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
26502 * +-----------+-----+---+-----+-------+---------------+-----------+
26503 * | SPECIAL2 |optn3|0 0|x x x| XRc | s8 |MXU__POOL16|
26504 * +-----------+-----+---+-----+-------+---------------+-----------+
26506 * S32NOR, S32AND, S32OR, S32XOR:
26507 * 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
26508 * +-----------+---------+-----+-------+-------+-------+-----------+
26509 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26510 * +-----------+---------+-----+-------+-------+-------+-----------+
26513 static void decode_opc_mxu__pool16(CPUMIPSState *env, DisasContext *ctx)
26515 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26517 switch (opcode) {
26518 case OPC_MXU_D32SARW:
26519 /* TODO: Implement emulation of D32SARW instruction. */
26520 MIPS_INVAL("OPC_MXU_D32SARW");
26521 generate_exception_end(ctx, EXCP_RI);
26522 break;
26523 case OPC_MXU_S32ALN:
26524 /* TODO: Implement emulation of S32ALN instruction. */
26525 MIPS_INVAL("OPC_MXU_S32ALN");
26526 generate_exception_end(ctx, EXCP_RI);
26527 break;
26528 case OPC_MXU_S32ALNI:
26529 gen_mxu_S32ALNI(ctx);
26530 break;
26531 case OPC_MXU_S32LUI:
26532 /* TODO: Implement emulation of S32LUI instruction. */
26533 MIPS_INVAL("OPC_MXU_S32LUI");
26534 generate_exception_end(ctx, EXCP_RI);
26535 break;
26536 case OPC_MXU_S32NOR:
26537 gen_mxu_S32NOR(ctx);
26538 break;
26539 case OPC_MXU_S32AND:
26540 gen_mxu_S32AND(ctx);
26541 break;
26542 case OPC_MXU_S32OR:
26543 gen_mxu_S32OR(ctx);
26544 break;
26545 case OPC_MXU_S32XOR:
26546 gen_mxu_S32XOR(ctx);
26547 break;
26548 default:
26549 MIPS_INVAL("decode_opc_mxu");
26550 generate_exception_end(ctx, EXCP_RI);
26551 break;
26557 * Decode MXU pool17
26559 * 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
26560 * +-----------+---------+---------+---+---------+-----+-----------+
26561 * | SPECIAL2 | rs | rt |0 0| rd |x x x|MXU__POOL15|
26562 * +-----------+---------+---------+---+---------+-----+-----------+
26565 static void decode_opc_mxu__pool17(CPUMIPSState *env, DisasContext *ctx)
26567 uint32_t opcode = extract32(ctx->opcode, 6, 2);
26569 switch (opcode) {
26570 case OPC_MXU_LXW:
26571 /* TODO: Implement emulation of LXW instruction. */
26572 MIPS_INVAL("OPC_MXU_LXW");
26573 generate_exception_end(ctx, EXCP_RI);
26574 break;
26575 case OPC_MXU_LXH:
26576 /* TODO: Implement emulation of LXH instruction. */
26577 MIPS_INVAL("OPC_MXU_LXH");
26578 generate_exception_end(ctx, EXCP_RI);
26579 break;
26580 case OPC_MXU_LXHU:
26581 /* TODO: Implement emulation of LXHU instruction. */
26582 MIPS_INVAL("OPC_MXU_LXHU");
26583 generate_exception_end(ctx, EXCP_RI);
26584 break;
26585 case OPC_MXU_LXB:
26586 /* TODO: Implement emulation of LXB instruction. */
26587 MIPS_INVAL("OPC_MXU_LXB");
26588 generate_exception_end(ctx, EXCP_RI);
26589 break;
26590 case OPC_MXU_LXBU:
26591 /* TODO: Implement emulation of LXBU instruction. */
26592 MIPS_INVAL("OPC_MXU_LXBU");
26593 generate_exception_end(ctx, EXCP_RI);
26594 break;
26595 default:
26596 MIPS_INVAL("decode_opc_mxu");
26597 generate_exception_end(ctx, EXCP_RI);
26598 break;
26603 * Decode MXU pool18
26605 * 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
26606 * +-----------+---------+-----+-------+-------+-------+-----------+
26607 * | SPECIAL2 | rb |x x x| XRd | XRa |0 0 0 0|MXU__POOL18|
26608 * +-----------+---------+-----+-------+-------+-------+-----------+
26611 static void decode_opc_mxu__pool18(CPUMIPSState *env, DisasContext *ctx)
26613 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26615 switch (opcode) {
26616 case OPC_MXU_D32SLLV:
26617 /* TODO: Implement emulation of D32SLLV instruction. */
26618 MIPS_INVAL("OPC_MXU_D32SLLV");
26619 generate_exception_end(ctx, EXCP_RI);
26620 break;
26621 case OPC_MXU_D32SLRV:
26622 /* TODO: Implement emulation of D32SLRV instruction. */
26623 MIPS_INVAL("OPC_MXU_D32SLRV");
26624 generate_exception_end(ctx, EXCP_RI);
26625 break;
26626 case OPC_MXU_D32SARV:
26627 /* TODO: Implement emulation of D32SARV instruction. */
26628 MIPS_INVAL("OPC_MXU_D32SARV");
26629 generate_exception_end(ctx, EXCP_RI);
26630 break;
26631 case OPC_MXU_Q16SLLV:
26632 /* TODO: Implement emulation of Q16SLLV instruction. */
26633 MIPS_INVAL("OPC_MXU_Q16SLLV");
26634 generate_exception_end(ctx, EXCP_RI);
26635 break;
26636 case OPC_MXU_Q16SLRV:
26637 /* TODO: Implement emulation of Q16SLRV instruction. */
26638 MIPS_INVAL("OPC_MXU_Q16SLRV");
26639 generate_exception_end(ctx, EXCP_RI);
26640 break;
26641 case OPC_MXU_Q16SARV:
26642 /* TODO: Implement emulation of Q16SARV instruction. */
26643 MIPS_INVAL("OPC_MXU_Q16SARV");
26644 generate_exception_end(ctx, EXCP_RI);
26645 break;
26646 default:
26647 MIPS_INVAL("decode_opc_mxu");
26648 generate_exception_end(ctx, EXCP_RI);
26649 break;
26655 * Decode MXU pool19
26657 * 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
26658 * +-----------+---+---+-------+-------+-------+-------+-----------+
26659 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL19|
26660 * +-----------+---+---+-------+-------+-------+-------+-----------+
26663 static void decode_opc_mxu__pool19(CPUMIPSState *env, DisasContext *ctx)
26665 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26667 switch (opcode) {
26668 case OPC_MXU_Q8MUL:
26669 case OPC_MXU_Q8MULSU:
26670 gen_mxu_q8mul_q8mulsu(ctx);
26671 break;
26672 default:
26673 MIPS_INVAL("decode_opc_mxu");
26674 generate_exception_end(ctx, EXCP_RI);
26675 break;
26681 * Decode MXU pool20
26683 * 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
26684 * +-----------+---------+-----+-------+-------+-------+-----------+
26685 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL20|
26686 * +-----------+---------+-----+-------+-------+-------+-----------+
26689 static void decode_opc_mxu__pool20(CPUMIPSState *env, DisasContext *ctx)
26691 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26693 switch (opcode) {
26694 case OPC_MXU_Q8MOVZ:
26695 /* TODO: Implement emulation of Q8MOVZ instruction. */
26696 MIPS_INVAL("OPC_MXU_Q8MOVZ");
26697 generate_exception_end(ctx, EXCP_RI);
26698 break;
26699 case OPC_MXU_Q8MOVN:
26700 /* TODO: Implement emulation of Q8MOVN instruction. */
26701 MIPS_INVAL("OPC_MXU_Q8MOVN");
26702 generate_exception_end(ctx, EXCP_RI);
26703 break;
26704 case OPC_MXU_D16MOVZ:
26705 /* TODO: Implement emulation of D16MOVZ instruction. */
26706 MIPS_INVAL("OPC_MXU_D16MOVZ");
26707 generate_exception_end(ctx, EXCP_RI);
26708 break;
26709 case OPC_MXU_D16MOVN:
26710 /* TODO: Implement emulation of D16MOVN instruction. */
26711 MIPS_INVAL("OPC_MXU_D16MOVN");
26712 generate_exception_end(ctx, EXCP_RI);
26713 break;
26714 case OPC_MXU_S32MOVZ:
26715 /* TODO: Implement emulation of S32MOVZ instruction. */
26716 MIPS_INVAL("OPC_MXU_S32MOVZ");
26717 generate_exception_end(ctx, EXCP_RI);
26718 break;
26719 case OPC_MXU_S32MOVN:
26720 /* TODO: Implement emulation of S32MOVN instruction. */
26721 MIPS_INVAL("OPC_MXU_S32MOVN");
26722 generate_exception_end(ctx, EXCP_RI);
26723 break;
26724 default:
26725 MIPS_INVAL("decode_opc_mxu");
26726 generate_exception_end(ctx, EXCP_RI);
26727 break;
26733 * Decode MXU pool21
26735 * 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
26736 * +-----------+---+---+-------+-------+-------+-------+-----------+
26737 * | SPECIAL2 |an2|x x| XRd | XRc | XRb | XRa |MXU__POOL21|
26738 * +-----------+---+---+-------+-------+-------+-------+-----------+
26741 static void decode_opc_mxu__pool21(CPUMIPSState *env, DisasContext *ctx)
26743 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26745 switch (opcode) {
26746 case OPC_MXU_Q8MAC:
26747 /* TODO: Implement emulation of Q8MAC instruction. */
26748 MIPS_INVAL("OPC_MXU_Q8MAC");
26749 generate_exception_end(ctx, EXCP_RI);
26750 break;
26751 case OPC_MXU_Q8MACSU:
26752 /* TODO: Implement emulation of Q8MACSU instruction. */
26753 MIPS_INVAL("OPC_MXU_Q8MACSU");
26754 generate_exception_end(ctx, EXCP_RI);
26755 break;
26756 default:
26757 MIPS_INVAL("decode_opc_mxu");
26758 generate_exception_end(ctx, EXCP_RI);
26759 break;
26765 * Main MXU decoding function
26767 * 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
26768 * +-----------+---------------------------------------+-----------+
26769 * | SPECIAL2 | |x x x x x x|
26770 * +-----------+---------------------------------------+-----------+
26773 static void decode_opc_mxu(CPUMIPSState *env, DisasContext *ctx)
26776 * TODO: Investigate necessity of including handling of
26777 * CLZ, CLO, SDBB in this function, as they belong to
26778 * SPECIAL2 opcode space for regular pre-R6 MIPS ISAs.
26780 uint32_t opcode = extract32(ctx->opcode, 0, 6);
26782 if (opcode == OPC__MXU_MUL) {
26783 uint32_t rs, rt, rd, op1;
26785 rs = extract32(ctx->opcode, 21, 5);
26786 rt = extract32(ctx->opcode, 16, 5);
26787 rd = extract32(ctx->opcode, 11, 5);
26788 op1 = MASK_SPECIAL2(ctx->opcode);
26790 gen_arith(ctx, op1, rd, rs, rt);
26792 return;
26795 if (opcode == OPC_MXU_S32M2I) {
26796 gen_mxu_s32m2i(ctx);
26797 return;
26800 if (opcode == OPC_MXU_S32I2M) {
26801 gen_mxu_s32i2m(ctx);
26802 return;
26806 TCGv t_mxu_cr = tcg_temp_new();
26807 TCGLabel *l_exit = gen_new_label();
26809 gen_load_mxu_cr(t_mxu_cr);
26810 tcg_gen_andi_tl(t_mxu_cr, t_mxu_cr, MXU_CR_MXU_EN);
26811 tcg_gen_brcondi_tl(TCG_COND_NE, t_mxu_cr, MXU_CR_MXU_EN, l_exit);
26813 switch (opcode) {
26814 case OPC_MXU_S32MADD:
26815 /* TODO: Implement emulation of S32MADD instruction. */
26816 MIPS_INVAL("OPC_MXU_S32MADD");
26817 generate_exception_end(ctx, EXCP_RI);
26818 break;
26819 case OPC_MXU_S32MADDU:
26820 /* TODO: Implement emulation of S32MADDU instruction. */
26821 MIPS_INVAL("OPC_MXU_S32MADDU");
26822 generate_exception_end(ctx, EXCP_RI);
26823 break;
26824 case OPC_MXU__POOL00:
26825 decode_opc_mxu__pool00(env, ctx);
26826 break;
26827 case OPC_MXU_S32MSUB:
26828 /* TODO: Implement emulation of S32MSUB instruction. */
26829 MIPS_INVAL("OPC_MXU_S32MSUB");
26830 generate_exception_end(ctx, EXCP_RI);
26831 break;
26832 case OPC_MXU_S32MSUBU:
26833 /* TODO: Implement emulation of S32MSUBU instruction. */
26834 MIPS_INVAL("OPC_MXU_S32MSUBU");
26835 generate_exception_end(ctx, EXCP_RI);
26836 break;
26837 case OPC_MXU__POOL01:
26838 decode_opc_mxu__pool01(env, ctx);
26839 break;
26840 case OPC_MXU__POOL02:
26841 decode_opc_mxu__pool02(env, ctx);
26842 break;
26843 case OPC_MXU_D16MUL:
26844 gen_mxu_d16mul(ctx);
26845 break;
26846 case OPC_MXU__POOL03:
26847 decode_opc_mxu__pool03(env, ctx);
26848 break;
26849 case OPC_MXU_D16MAC:
26850 gen_mxu_d16mac(ctx);
26851 break;
26852 case OPC_MXU_D16MACF:
26853 /* TODO: Implement emulation of D16MACF instruction. */
26854 MIPS_INVAL("OPC_MXU_D16MACF");
26855 generate_exception_end(ctx, EXCP_RI);
26856 break;
26857 case OPC_MXU_D16MADL:
26858 /* TODO: Implement emulation of D16MADL instruction. */
26859 MIPS_INVAL("OPC_MXU_D16MADL");
26860 generate_exception_end(ctx, EXCP_RI);
26861 break;
26862 case OPC_MXU_S16MAD:
26863 /* TODO: Implement emulation of S16MAD instruction. */
26864 MIPS_INVAL("OPC_MXU_S16MAD");
26865 generate_exception_end(ctx, EXCP_RI);
26866 break;
26867 case OPC_MXU_Q16ADD:
26868 /* TODO: Implement emulation of Q16ADD instruction. */
26869 MIPS_INVAL("OPC_MXU_Q16ADD");
26870 generate_exception_end(ctx, EXCP_RI);
26871 break;
26872 case OPC_MXU_D16MACE:
26873 /* TODO: Implement emulation of D16MACE instruction. */
26874 MIPS_INVAL("OPC_MXU_D16MACE");
26875 generate_exception_end(ctx, EXCP_RI);
26876 break;
26877 case OPC_MXU__POOL04:
26878 decode_opc_mxu__pool04(env, ctx);
26879 break;
26880 case OPC_MXU__POOL05:
26881 decode_opc_mxu__pool05(env, ctx);
26882 break;
26883 case OPC_MXU__POOL06:
26884 decode_opc_mxu__pool06(env, ctx);
26885 break;
26886 case OPC_MXU__POOL07:
26887 decode_opc_mxu__pool07(env, ctx);
26888 break;
26889 case OPC_MXU__POOL08:
26890 decode_opc_mxu__pool08(env, ctx);
26891 break;
26892 case OPC_MXU__POOL09:
26893 decode_opc_mxu__pool09(env, ctx);
26894 break;
26895 case OPC_MXU__POOL10:
26896 decode_opc_mxu__pool10(env, ctx);
26897 break;
26898 case OPC_MXU__POOL11:
26899 decode_opc_mxu__pool11(env, ctx);
26900 break;
26901 case OPC_MXU_D32ADD:
26902 /* TODO: Implement emulation of D32ADD instruction. */
26903 MIPS_INVAL("OPC_MXU_D32ADD");
26904 generate_exception_end(ctx, EXCP_RI);
26905 break;
26906 case OPC_MXU__POOL12:
26907 decode_opc_mxu__pool12(env, ctx);
26908 break;
26909 case OPC_MXU__POOL13:
26910 decode_opc_mxu__pool13(env, ctx);
26911 break;
26912 case OPC_MXU__POOL14:
26913 decode_opc_mxu__pool14(env, ctx);
26914 break;
26915 case OPC_MXU_Q8ACCE:
26916 /* TODO: Implement emulation of Q8ACCE instruction. */
26917 MIPS_INVAL("OPC_MXU_Q8ACCE");
26918 generate_exception_end(ctx, EXCP_RI);
26919 break;
26920 case OPC_MXU_S8LDD:
26921 gen_mxu_s8ldd(ctx);
26922 break;
26923 case OPC_MXU_S8STD:
26924 /* TODO: Implement emulation of S8STD instruction. */
26925 MIPS_INVAL("OPC_MXU_S8STD");
26926 generate_exception_end(ctx, EXCP_RI);
26927 break;
26928 case OPC_MXU_S8LDI:
26929 /* TODO: Implement emulation of S8LDI instruction. */
26930 MIPS_INVAL("OPC_MXU_S8LDI");
26931 generate_exception_end(ctx, EXCP_RI);
26932 break;
26933 case OPC_MXU_S8SDI:
26934 /* TODO: Implement emulation of S8SDI instruction. */
26935 MIPS_INVAL("OPC_MXU_S8SDI");
26936 generate_exception_end(ctx, EXCP_RI);
26937 break;
26938 case OPC_MXU__POOL15:
26939 decode_opc_mxu__pool15(env, ctx);
26940 break;
26941 case OPC_MXU__POOL16:
26942 decode_opc_mxu__pool16(env, ctx);
26943 break;
26944 case OPC_MXU__POOL17:
26945 decode_opc_mxu__pool17(env, ctx);
26946 break;
26947 case OPC_MXU_S16LDD:
26948 /* TODO: Implement emulation of S16LDD instruction. */
26949 MIPS_INVAL("OPC_MXU_S16LDD");
26950 generate_exception_end(ctx, EXCP_RI);
26951 break;
26952 case OPC_MXU_S16STD:
26953 /* TODO: Implement emulation of S16STD instruction. */
26954 MIPS_INVAL("OPC_MXU_S16STD");
26955 generate_exception_end(ctx, EXCP_RI);
26956 break;
26957 case OPC_MXU_S16LDI:
26958 /* TODO: Implement emulation of S16LDI instruction. */
26959 MIPS_INVAL("OPC_MXU_S16LDI");
26960 generate_exception_end(ctx, EXCP_RI);
26961 break;
26962 case OPC_MXU_S16SDI:
26963 /* TODO: Implement emulation of S16SDI instruction. */
26964 MIPS_INVAL("OPC_MXU_S16SDI");
26965 generate_exception_end(ctx, EXCP_RI);
26966 break;
26967 case OPC_MXU_D32SLL:
26968 /* TODO: Implement emulation of D32SLL instruction. */
26969 MIPS_INVAL("OPC_MXU_D32SLL");
26970 generate_exception_end(ctx, EXCP_RI);
26971 break;
26972 case OPC_MXU_D32SLR:
26973 /* TODO: Implement emulation of D32SLR instruction. */
26974 MIPS_INVAL("OPC_MXU_D32SLR");
26975 generate_exception_end(ctx, EXCP_RI);
26976 break;
26977 case OPC_MXU_D32SARL:
26978 /* TODO: Implement emulation of D32SARL instruction. */
26979 MIPS_INVAL("OPC_MXU_D32SARL");
26980 generate_exception_end(ctx, EXCP_RI);
26981 break;
26982 case OPC_MXU_D32SAR:
26983 /* TODO: Implement emulation of D32SAR instruction. */
26984 MIPS_INVAL("OPC_MXU_D32SAR");
26985 generate_exception_end(ctx, EXCP_RI);
26986 break;
26987 case OPC_MXU_Q16SLL:
26988 /* TODO: Implement emulation of Q16SLL instruction. */
26989 MIPS_INVAL("OPC_MXU_Q16SLL");
26990 generate_exception_end(ctx, EXCP_RI);
26991 break;
26992 case OPC_MXU_Q16SLR:
26993 /* TODO: Implement emulation of Q16SLR instruction. */
26994 MIPS_INVAL("OPC_MXU_Q16SLR");
26995 generate_exception_end(ctx, EXCP_RI);
26996 break;
26997 case OPC_MXU__POOL18:
26998 decode_opc_mxu__pool18(env, ctx);
26999 break;
27000 case OPC_MXU_Q16SAR:
27001 /* TODO: Implement emulation of Q16SAR instruction. */
27002 MIPS_INVAL("OPC_MXU_Q16SAR");
27003 generate_exception_end(ctx, EXCP_RI);
27004 break;
27005 case OPC_MXU__POOL19:
27006 decode_opc_mxu__pool19(env, ctx);
27007 break;
27008 case OPC_MXU__POOL20:
27009 decode_opc_mxu__pool20(env, ctx);
27010 break;
27011 case OPC_MXU__POOL21:
27012 decode_opc_mxu__pool21(env, ctx);
27013 break;
27014 case OPC_MXU_Q16SCOP:
27015 /* TODO: Implement emulation of Q16SCOP instruction. */
27016 MIPS_INVAL("OPC_MXU_Q16SCOP");
27017 generate_exception_end(ctx, EXCP_RI);
27018 break;
27019 case OPC_MXU_Q8MADL:
27020 /* TODO: Implement emulation of Q8MADL instruction. */
27021 MIPS_INVAL("OPC_MXU_Q8MADL");
27022 generate_exception_end(ctx, EXCP_RI);
27023 break;
27024 case OPC_MXU_S32SFL:
27025 /* TODO: Implement emulation of S32SFL instruction. */
27026 MIPS_INVAL("OPC_MXU_S32SFL");
27027 generate_exception_end(ctx, EXCP_RI);
27028 break;
27029 case OPC_MXU_Q8SAD:
27030 /* TODO: Implement emulation of Q8SAD instruction. */
27031 MIPS_INVAL("OPC_MXU_Q8SAD");
27032 generate_exception_end(ctx, EXCP_RI);
27033 break;
27034 default:
27035 MIPS_INVAL("decode_opc_mxu");
27036 generate_exception_end(ctx, EXCP_RI);
27039 gen_set_label(l_exit);
27040 tcg_temp_free(t_mxu_cr);
27044 #endif /* !defined(TARGET_MIPS64) */
27047 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
27049 int rs, rt, rd;
27050 uint32_t op1;
27052 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27054 rs = (ctx->opcode >> 21) & 0x1f;
27055 rt = (ctx->opcode >> 16) & 0x1f;
27056 rd = (ctx->opcode >> 11) & 0x1f;
27058 op1 = MASK_SPECIAL2(ctx->opcode);
27059 switch (op1) {
27060 case OPC_MADD: /* Multiply and add/sub */
27061 case OPC_MADDU:
27062 case OPC_MSUB:
27063 case OPC_MSUBU:
27064 check_insn(ctx, ISA_MIPS32);
27065 gen_muldiv(ctx, op1, rd & 3, rs, rt);
27066 break;
27067 case OPC_MUL:
27068 gen_arith(ctx, op1, rd, rs, rt);
27069 break;
27070 case OPC_DIV_G_2F:
27071 case OPC_DIVU_G_2F:
27072 case OPC_MULT_G_2F:
27073 case OPC_MULTU_G_2F:
27074 case OPC_MOD_G_2F:
27075 case OPC_MODU_G_2F:
27076 check_insn(ctx, INSN_LOONGSON2F);
27077 gen_loongson_integer(ctx, op1, rd, rs, rt);
27078 break;
27079 case OPC_CLO:
27080 case OPC_CLZ:
27081 check_insn(ctx, ISA_MIPS32);
27082 gen_cl(ctx, op1, rd, rs);
27083 break;
27084 case OPC_SDBBP:
27085 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
27086 gen_helper_do_semihosting(cpu_env);
27087 } else {
27089 * XXX: not clear which exception should be raised
27090 * when in debug mode...
27092 check_insn(ctx, ISA_MIPS32);
27093 generate_exception_end(ctx, EXCP_DBp);
27095 break;
27096 #if defined(TARGET_MIPS64)
27097 case OPC_DCLO:
27098 case OPC_DCLZ:
27099 check_insn(ctx, ISA_MIPS64);
27100 check_mips_64(ctx);
27101 gen_cl(ctx, op1, rd, rs);
27102 break;
27103 case OPC_DMULT_G_2F:
27104 case OPC_DMULTU_G_2F:
27105 case OPC_DDIV_G_2F:
27106 case OPC_DDIVU_G_2F:
27107 case OPC_DMOD_G_2F:
27108 case OPC_DMODU_G_2F:
27109 check_insn(ctx, INSN_LOONGSON2F);
27110 gen_loongson_integer(ctx, op1, rd, rs, rt);
27111 break;
27112 #endif
27113 default: /* Invalid */
27114 MIPS_INVAL("special2_legacy");
27115 generate_exception_end(ctx, EXCP_RI);
27116 break;
27120 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
27122 int rs, rt, rd, sa;
27123 uint32_t op1, op2;
27124 int16_t imm;
27126 rs = (ctx->opcode >> 21) & 0x1f;
27127 rt = (ctx->opcode >> 16) & 0x1f;
27128 rd = (ctx->opcode >> 11) & 0x1f;
27129 sa = (ctx->opcode >> 6) & 0x1f;
27130 imm = (int16_t)ctx->opcode >> 7;
27132 op1 = MASK_SPECIAL3(ctx->opcode);
27133 switch (op1) {
27134 case R6_OPC_PREF:
27135 if (rt >= 24) {
27136 /* hint codes 24-31 are reserved and signal RI */
27137 generate_exception_end(ctx, EXCP_RI);
27139 /* Treat as NOP. */
27140 break;
27141 case R6_OPC_CACHE:
27142 check_cp0_enabled(ctx);
27143 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
27144 gen_cache_operation(ctx, rt, rs, imm);
27146 break;
27147 case R6_OPC_SC:
27148 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
27149 break;
27150 case R6_OPC_LL:
27151 gen_ld(ctx, op1, rt, rs, imm);
27152 break;
27153 case OPC_BSHFL:
27155 if (rd == 0) {
27156 /* Treat as NOP. */
27157 break;
27159 op2 = MASK_BSHFL(ctx->opcode);
27160 switch (op2) {
27161 case OPC_ALIGN:
27162 case OPC_ALIGN_1:
27163 case OPC_ALIGN_2:
27164 case OPC_ALIGN_3:
27165 gen_align(ctx, 32, rd, rs, rt, sa & 3);
27166 break;
27167 case OPC_BITSWAP:
27168 gen_bitswap(ctx, op2, rd, rt);
27169 break;
27172 break;
27173 #if defined(TARGET_MIPS64)
27174 case R6_OPC_SCD:
27175 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
27176 break;
27177 case R6_OPC_LLD:
27178 gen_ld(ctx, op1, rt, rs, imm);
27179 break;
27180 case OPC_DBSHFL:
27181 check_mips_64(ctx);
27183 if (rd == 0) {
27184 /* Treat as NOP. */
27185 break;
27187 op2 = MASK_DBSHFL(ctx->opcode);
27188 switch (op2) {
27189 case OPC_DALIGN:
27190 case OPC_DALIGN_1:
27191 case OPC_DALIGN_2:
27192 case OPC_DALIGN_3:
27193 case OPC_DALIGN_4:
27194 case OPC_DALIGN_5:
27195 case OPC_DALIGN_6:
27196 case OPC_DALIGN_7:
27197 gen_align(ctx, 64, rd, rs, rt, sa & 7);
27198 break;
27199 case OPC_DBITSWAP:
27200 gen_bitswap(ctx, op2, rd, rt);
27201 break;
27205 break;
27206 #endif
27207 default: /* Invalid */
27208 MIPS_INVAL("special3_r6");
27209 generate_exception_end(ctx, EXCP_RI);
27210 break;
27214 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
27216 int rs, rt, rd;
27217 uint32_t op1, op2;
27219 rs = (ctx->opcode >> 21) & 0x1f;
27220 rt = (ctx->opcode >> 16) & 0x1f;
27221 rd = (ctx->opcode >> 11) & 0x1f;
27223 op1 = MASK_SPECIAL3(ctx->opcode);
27224 switch (op1) {
27225 case OPC_DIV_G_2E:
27226 case OPC_DIVU_G_2E:
27227 case OPC_MOD_G_2E:
27228 case OPC_MODU_G_2E:
27229 case OPC_MULT_G_2E:
27230 case OPC_MULTU_G_2E:
27232 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
27233 * the same mask and op1.
27235 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
27236 op2 = MASK_ADDUH_QB(ctx->opcode);
27237 switch (op2) {
27238 case OPC_ADDUH_QB:
27239 case OPC_ADDUH_R_QB:
27240 case OPC_ADDQH_PH:
27241 case OPC_ADDQH_R_PH:
27242 case OPC_ADDQH_W:
27243 case OPC_ADDQH_R_W:
27244 case OPC_SUBUH_QB:
27245 case OPC_SUBUH_R_QB:
27246 case OPC_SUBQH_PH:
27247 case OPC_SUBQH_R_PH:
27248 case OPC_SUBQH_W:
27249 case OPC_SUBQH_R_W:
27250 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27251 break;
27252 case OPC_MUL_PH:
27253 case OPC_MUL_S_PH:
27254 case OPC_MULQ_S_W:
27255 case OPC_MULQ_RS_W:
27256 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27257 break;
27258 default:
27259 MIPS_INVAL("MASK ADDUH.QB");
27260 generate_exception_end(ctx, EXCP_RI);
27261 break;
27263 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
27264 gen_loongson_integer(ctx, op1, rd, rs, rt);
27265 } else {
27266 generate_exception_end(ctx, EXCP_RI);
27268 break;
27269 case OPC_LX_DSP:
27270 op2 = MASK_LX(ctx->opcode);
27271 switch (op2) {
27272 #if defined(TARGET_MIPS64)
27273 case OPC_LDX:
27274 #endif
27275 case OPC_LBUX:
27276 case OPC_LHX:
27277 case OPC_LWX:
27278 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
27279 break;
27280 default: /* Invalid */
27281 MIPS_INVAL("MASK LX");
27282 generate_exception_end(ctx, EXCP_RI);
27283 break;
27285 break;
27286 case OPC_ABSQ_S_PH_DSP:
27287 op2 = MASK_ABSQ_S_PH(ctx->opcode);
27288 switch (op2) {
27289 case OPC_ABSQ_S_QB:
27290 case OPC_ABSQ_S_PH:
27291 case OPC_ABSQ_S_W:
27292 case OPC_PRECEQ_W_PHL:
27293 case OPC_PRECEQ_W_PHR:
27294 case OPC_PRECEQU_PH_QBL:
27295 case OPC_PRECEQU_PH_QBR:
27296 case OPC_PRECEQU_PH_QBLA:
27297 case OPC_PRECEQU_PH_QBRA:
27298 case OPC_PRECEU_PH_QBL:
27299 case OPC_PRECEU_PH_QBR:
27300 case OPC_PRECEU_PH_QBLA:
27301 case OPC_PRECEU_PH_QBRA:
27302 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27303 break;
27304 case OPC_BITREV:
27305 case OPC_REPL_QB:
27306 case OPC_REPLV_QB:
27307 case OPC_REPL_PH:
27308 case OPC_REPLV_PH:
27309 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27310 break;
27311 default:
27312 MIPS_INVAL("MASK ABSQ_S.PH");
27313 generate_exception_end(ctx, EXCP_RI);
27314 break;
27316 break;
27317 case OPC_ADDU_QB_DSP:
27318 op2 = MASK_ADDU_QB(ctx->opcode);
27319 switch (op2) {
27320 case OPC_ADDQ_PH:
27321 case OPC_ADDQ_S_PH:
27322 case OPC_ADDQ_S_W:
27323 case OPC_ADDU_QB:
27324 case OPC_ADDU_S_QB:
27325 case OPC_ADDU_PH:
27326 case OPC_ADDU_S_PH:
27327 case OPC_SUBQ_PH:
27328 case OPC_SUBQ_S_PH:
27329 case OPC_SUBQ_S_W:
27330 case OPC_SUBU_QB:
27331 case OPC_SUBU_S_QB:
27332 case OPC_SUBU_PH:
27333 case OPC_SUBU_S_PH:
27334 case OPC_ADDSC:
27335 case OPC_ADDWC:
27336 case OPC_MODSUB:
27337 case OPC_RADDU_W_QB:
27338 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27339 break;
27340 case OPC_MULEU_S_PH_QBL:
27341 case OPC_MULEU_S_PH_QBR:
27342 case OPC_MULQ_RS_PH:
27343 case OPC_MULEQ_S_W_PHL:
27344 case OPC_MULEQ_S_W_PHR:
27345 case OPC_MULQ_S_PH:
27346 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27347 break;
27348 default: /* Invalid */
27349 MIPS_INVAL("MASK ADDU.QB");
27350 generate_exception_end(ctx, EXCP_RI);
27351 break;
27354 break;
27355 case OPC_CMPU_EQ_QB_DSP:
27356 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
27357 switch (op2) {
27358 case OPC_PRECR_SRA_PH_W:
27359 case OPC_PRECR_SRA_R_PH_W:
27360 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
27361 break;
27362 case OPC_PRECR_QB_PH:
27363 case OPC_PRECRQ_QB_PH:
27364 case OPC_PRECRQ_PH_W:
27365 case OPC_PRECRQ_RS_PH_W:
27366 case OPC_PRECRQU_S_QB_PH:
27367 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27368 break;
27369 case OPC_CMPU_EQ_QB:
27370 case OPC_CMPU_LT_QB:
27371 case OPC_CMPU_LE_QB:
27372 case OPC_CMP_EQ_PH:
27373 case OPC_CMP_LT_PH:
27374 case OPC_CMP_LE_PH:
27375 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
27376 break;
27377 case OPC_CMPGU_EQ_QB:
27378 case OPC_CMPGU_LT_QB:
27379 case OPC_CMPGU_LE_QB:
27380 case OPC_CMPGDU_EQ_QB:
27381 case OPC_CMPGDU_LT_QB:
27382 case OPC_CMPGDU_LE_QB:
27383 case OPC_PICK_QB:
27384 case OPC_PICK_PH:
27385 case OPC_PACKRL_PH:
27386 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27387 break;
27388 default: /* Invalid */
27389 MIPS_INVAL("MASK CMPU.EQ.QB");
27390 generate_exception_end(ctx, EXCP_RI);
27391 break;
27393 break;
27394 case OPC_SHLL_QB_DSP:
27395 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27396 break;
27397 case OPC_DPA_W_PH_DSP:
27398 op2 = MASK_DPA_W_PH(ctx->opcode);
27399 switch (op2) {
27400 case OPC_DPAU_H_QBL:
27401 case OPC_DPAU_H_QBR:
27402 case OPC_DPSU_H_QBL:
27403 case OPC_DPSU_H_QBR:
27404 case OPC_DPA_W_PH:
27405 case OPC_DPAX_W_PH:
27406 case OPC_DPAQ_S_W_PH:
27407 case OPC_DPAQX_S_W_PH:
27408 case OPC_DPAQX_SA_W_PH:
27409 case OPC_DPS_W_PH:
27410 case OPC_DPSX_W_PH:
27411 case OPC_DPSQ_S_W_PH:
27412 case OPC_DPSQX_S_W_PH:
27413 case OPC_DPSQX_SA_W_PH:
27414 case OPC_MULSAQ_S_W_PH:
27415 case OPC_DPAQ_SA_L_W:
27416 case OPC_DPSQ_SA_L_W:
27417 case OPC_MAQ_S_W_PHL:
27418 case OPC_MAQ_S_W_PHR:
27419 case OPC_MAQ_SA_W_PHL:
27420 case OPC_MAQ_SA_W_PHR:
27421 case OPC_MULSA_W_PH:
27422 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27423 break;
27424 default: /* Invalid */
27425 MIPS_INVAL("MASK DPAW.PH");
27426 generate_exception_end(ctx, EXCP_RI);
27427 break;
27429 break;
27430 case OPC_INSV_DSP:
27431 op2 = MASK_INSV(ctx->opcode);
27432 switch (op2) {
27433 case OPC_INSV:
27434 check_dsp(ctx);
27436 TCGv t0, t1;
27438 if (rt == 0) {
27439 break;
27442 t0 = tcg_temp_new();
27443 t1 = tcg_temp_new();
27445 gen_load_gpr(t0, rt);
27446 gen_load_gpr(t1, rs);
27448 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
27450 tcg_temp_free(t0);
27451 tcg_temp_free(t1);
27452 break;
27454 default: /* Invalid */
27455 MIPS_INVAL("MASK INSV");
27456 generate_exception_end(ctx, EXCP_RI);
27457 break;
27459 break;
27460 case OPC_APPEND_DSP:
27461 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27462 break;
27463 case OPC_EXTR_W_DSP:
27464 op2 = MASK_EXTR_W(ctx->opcode);
27465 switch (op2) {
27466 case OPC_EXTR_W:
27467 case OPC_EXTR_R_W:
27468 case OPC_EXTR_RS_W:
27469 case OPC_EXTR_S_H:
27470 case OPC_EXTRV_S_H:
27471 case OPC_EXTRV_W:
27472 case OPC_EXTRV_R_W:
27473 case OPC_EXTRV_RS_W:
27474 case OPC_EXTP:
27475 case OPC_EXTPV:
27476 case OPC_EXTPDP:
27477 case OPC_EXTPDPV:
27478 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27479 break;
27480 case OPC_RDDSP:
27481 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
27482 break;
27483 case OPC_SHILO:
27484 case OPC_SHILOV:
27485 case OPC_MTHLIP:
27486 case OPC_WRDSP:
27487 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27488 break;
27489 default: /* Invalid */
27490 MIPS_INVAL("MASK EXTR.W");
27491 generate_exception_end(ctx, EXCP_RI);
27492 break;
27494 break;
27495 #if defined(TARGET_MIPS64)
27496 case OPC_DDIV_G_2E:
27497 case OPC_DDIVU_G_2E:
27498 case OPC_DMULT_G_2E:
27499 case OPC_DMULTU_G_2E:
27500 case OPC_DMOD_G_2E:
27501 case OPC_DMODU_G_2E:
27502 check_insn(ctx, INSN_LOONGSON2E);
27503 gen_loongson_integer(ctx, op1, rd, rs, rt);
27504 break;
27505 case OPC_ABSQ_S_QH_DSP:
27506 op2 = MASK_ABSQ_S_QH(ctx->opcode);
27507 switch (op2) {
27508 case OPC_PRECEQ_L_PWL:
27509 case OPC_PRECEQ_L_PWR:
27510 case OPC_PRECEQ_PW_QHL:
27511 case OPC_PRECEQ_PW_QHR:
27512 case OPC_PRECEQ_PW_QHLA:
27513 case OPC_PRECEQ_PW_QHRA:
27514 case OPC_PRECEQU_QH_OBL:
27515 case OPC_PRECEQU_QH_OBR:
27516 case OPC_PRECEQU_QH_OBLA:
27517 case OPC_PRECEQU_QH_OBRA:
27518 case OPC_PRECEU_QH_OBL:
27519 case OPC_PRECEU_QH_OBR:
27520 case OPC_PRECEU_QH_OBLA:
27521 case OPC_PRECEU_QH_OBRA:
27522 case OPC_ABSQ_S_OB:
27523 case OPC_ABSQ_S_PW:
27524 case OPC_ABSQ_S_QH:
27525 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27526 break;
27527 case OPC_REPL_OB:
27528 case OPC_REPL_PW:
27529 case OPC_REPL_QH:
27530 case OPC_REPLV_OB:
27531 case OPC_REPLV_PW:
27532 case OPC_REPLV_QH:
27533 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27534 break;
27535 default: /* Invalid */
27536 MIPS_INVAL("MASK ABSQ_S.QH");
27537 generate_exception_end(ctx, EXCP_RI);
27538 break;
27540 break;
27541 case OPC_ADDU_OB_DSP:
27542 op2 = MASK_ADDU_OB(ctx->opcode);
27543 switch (op2) {
27544 case OPC_RADDU_L_OB:
27545 case OPC_SUBQ_PW:
27546 case OPC_SUBQ_S_PW:
27547 case OPC_SUBQ_QH:
27548 case OPC_SUBQ_S_QH:
27549 case OPC_SUBU_OB:
27550 case OPC_SUBU_S_OB:
27551 case OPC_SUBU_QH:
27552 case OPC_SUBU_S_QH:
27553 case OPC_SUBUH_OB:
27554 case OPC_SUBUH_R_OB:
27555 case OPC_ADDQ_PW:
27556 case OPC_ADDQ_S_PW:
27557 case OPC_ADDQ_QH:
27558 case OPC_ADDQ_S_QH:
27559 case OPC_ADDU_OB:
27560 case OPC_ADDU_S_OB:
27561 case OPC_ADDU_QH:
27562 case OPC_ADDU_S_QH:
27563 case OPC_ADDUH_OB:
27564 case OPC_ADDUH_R_OB:
27565 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27566 break;
27567 case OPC_MULEQ_S_PW_QHL:
27568 case OPC_MULEQ_S_PW_QHR:
27569 case OPC_MULEU_S_QH_OBL:
27570 case OPC_MULEU_S_QH_OBR:
27571 case OPC_MULQ_RS_QH:
27572 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27573 break;
27574 default: /* Invalid */
27575 MIPS_INVAL("MASK ADDU.OB");
27576 generate_exception_end(ctx, EXCP_RI);
27577 break;
27579 break;
27580 case OPC_CMPU_EQ_OB_DSP:
27581 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
27582 switch (op2) {
27583 case OPC_PRECR_SRA_QH_PW:
27584 case OPC_PRECR_SRA_R_QH_PW:
27585 /* Return value is rt. */
27586 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
27587 break;
27588 case OPC_PRECR_OB_QH:
27589 case OPC_PRECRQ_OB_QH:
27590 case OPC_PRECRQ_PW_L:
27591 case OPC_PRECRQ_QH_PW:
27592 case OPC_PRECRQ_RS_QH_PW:
27593 case OPC_PRECRQU_S_OB_QH:
27594 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27595 break;
27596 case OPC_CMPU_EQ_OB:
27597 case OPC_CMPU_LT_OB:
27598 case OPC_CMPU_LE_OB:
27599 case OPC_CMP_EQ_QH:
27600 case OPC_CMP_LT_QH:
27601 case OPC_CMP_LE_QH:
27602 case OPC_CMP_EQ_PW:
27603 case OPC_CMP_LT_PW:
27604 case OPC_CMP_LE_PW:
27605 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
27606 break;
27607 case OPC_CMPGDU_EQ_OB:
27608 case OPC_CMPGDU_LT_OB:
27609 case OPC_CMPGDU_LE_OB:
27610 case OPC_CMPGU_EQ_OB:
27611 case OPC_CMPGU_LT_OB:
27612 case OPC_CMPGU_LE_OB:
27613 case OPC_PACKRL_PW:
27614 case OPC_PICK_OB:
27615 case OPC_PICK_PW:
27616 case OPC_PICK_QH:
27617 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27618 break;
27619 default: /* Invalid */
27620 MIPS_INVAL("MASK CMPU_EQ.OB");
27621 generate_exception_end(ctx, EXCP_RI);
27622 break;
27624 break;
27625 case OPC_DAPPEND_DSP:
27626 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27627 break;
27628 case OPC_DEXTR_W_DSP:
27629 op2 = MASK_DEXTR_W(ctx->opcode);
27630 switch (op2) {
27631 case OPC_DEXTP:
27632 case OPC_DEXTPDP:
27633 case OPC_DEXTPDPV:
27634 case OPC_DEXTPV:
27635 case OPC_DEXTR_L:
27636 case OPC_DEXTR_R_L:
27637 case OPC_DEXTR_RS_L:
27638 case OPC_DEXTR_W:
27639 case OPC_DEXTR_R_W:
27640 case OPC_DEXTR_RS_W:
27641 case OPC_DEXTR_S_H:
27642 case OPC_DEXTRV_L:
27643 case OPC_DEXTRV_R_L:
27644 case OPC_DEXTRV_RS_L:
27645 case OPC_DEXTRV_S_H:
27646 case OPC_DEXTRV_W:
27647 case OPC_DEXTRV_R_W:
27648 case OPC_DEXTRV_RS_W:
27649 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27650 break;
27651 case OPC_DMTHLIP:
27652 case OPC_DSHILO:
27653 case OPC_DSHILOV:
27654 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27655 break;
27656 default: /* Invalid */
27657 MIPS_INVAL("MASK EXTR.W");
27658 generate_exception_end(ctx, EXCP_RI);
27659 break;
27661 break;
27662 case OPC_DPAQ_W_QH_DSP:
27663 op2 = MASK_DPAQ_W_QH(ctx->opcode);
27664 switch (op2) {
27665 case OPC_DPAU_H_OBL:
27666 case OPC_DPAU_H_OBR:
27667 case OPC_DPSU_H_OBL:
27668 case OPC_DPSU_H_OBR:
27669 case OPC_DPA_W_QH:
27670 case OPC_DPAQ_S_W_QH:
27671 case OPC_DPS_W_QH:
27672 case OPC_DPSQ_S_W_QH:
27673 case OPC_MULSAQ_S_W_QH:
27674 case OPC_DPAQ_SA_L_PW:
27675 case OPC_DPSQ_SA_L_PW:
27676 case OPC_MULSAQ_S_L_PW:
27677 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27678 break;
27679 case OPC_MAQ_S_W_QHLL:
27680 case OPC_MAQ_S_W_QHLR:
27681 case OPC_MAQ_S_W_QHRL:
27682 case OPC_MAQ_S_W_QHRR:
27683 case OPC_MAQ_SA_W_QHLL:
27684 case OPC_MAQ_SA_W_QHLR:
27685 case OPC_MAQ_SA_W_QHRL:
27686 case OPC_MAQ_SA_W_QHRR:
27687 case OPC_MAQ_S_L_PWL:
27688 case OPC_MAQ_S_L_PWR:
27689 case OPC_DMADD:
27690 case OPC_DMADDU:
27691 case OPC_DMSUB:
27692 case OPC_DMSUBU:
27693 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27694 break;
27695 default: /* Invalid */
27696 MIPS_INVAL("MASK DPAQ.W.QH");
27697 generate_exception_end(ctx, EXCP_RI);
27698 break;
27700 break;
27701 case OPC_DINSV_DSP:
27702 op2 = MASK_INSV(ctx->opcode);
27703 switch (op2) {
27704 case OPC_DINSV:
27706 TCGv t0, t1;
27708 if (rt == 0) {
27709 break;
27711 check_dsp(ctx);
27713 t0 = tcg_temp_new();
27714 t1 = tcg_temp_new();
27716 gen_load_gpr(t0, rt);
27717 gen_load_gpr(t1, rs);
27719 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
27721 tcg_temp_free(t0);
27722 tcg_temp_free(t1);
27723 break;
27725 default: /* Invalid */
27726 MIPS_INVAL("MASK DINSV");
27727 generate_exception_end(ctx, EXCP_RI);
27728 break;
27730 break;
27731 case OPC_SHLL_OB_DSP:
27732 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27733 break;
27734 #endif
27735 default: /* Invalid */
27736 MIPS_INVAL("special3_legacy");
27737 generate_exception_end(ctx, EXCP_RI);
27738 break;
27743 #if defined(TARGET_MIPS64)
27745 static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx)
27747 uint32_t opc = MASK_MMI0(ctx->opcode);
27749 switch (opc) {
27750 case MMI_OPC_0_PADDW: /* TODO: MMI_OPC_0_PADDW */
27751 case MMI_OPC_0_PSUBW: /* TODO: MMI_OPC_0_PSUBW */
27752 case MMI_OPC_0_PCGTW: /* TODO: MMI_OPC_0_PCGTW */
27753 case MMI_OPC_0_PMAXW: /* TODO: MMI_OPC_0_PMAXW */
27754 case MMI_OPC_0_PADDH: /* TODO: MMI_OPC_0_PADDH */
27755 case MMI_OPC_0_PSUBH: /* TODO: MMI_OPC_0_PSUBH */
27756 case MMI_OPC_0_PCGTH: /* TODO: MMI_OPC_0_PCGTH */
27757 case MMI_OPC_0_PMAXH: /* TODO: MMI_OPC_0_PMAXH */
27758 case MMI_OPC_0_PADDB: /* TODO: MMI_OPC_0_PADDB */
27759 case MMI_OPC_0_PSUBB: /* TODO: MMI_OPC_0_PSUBB */
27760 case MMI_OPC_0_PCGTB: /* TODO: MMI_OPC_0_PCGTB */
27761 case MMI_OPC_0_PADDSW: /* TODO: MMI_OPC_0_PADDSW */
27762 case MMI_OPC_0_PSUBSW: /* TODO: MMI_OPC_0_PSUBSW */
27763 case MMI_OPC_0_PEXTLW: /* TODO: MMI_OPC_0_PEXTLW */
27764 case MMI_OPC_0_PPACW: /* TODO: MMI_OPC_0_PPACW */
27765 case MMI_OPC_0_PADDSH: /* TODO: MMI_OPC_0_PADDSH */
27766 case MMI_OPC_0_PSUBSH: /* TODO: MMI_OPC_0_PSUBSH */
27767 case MMI_OPC_0_PEXTLH: /* TODO: MMI_OPC_0_PEXTLH */
27768 case MMI_OPC_0_PPACH: /* TODO: MMI_OPC_0_PPACH */
27769 case MMI_OPC_0_PADDSB: /* TODO: MMI_OPC_0_PADDSB */
27770 case MMI_OPC_0_PSUBSB: /* TODO: MMI_OPC_0_PSUBSB */
27771 case MMI_OPC_0_PEXTLB: /* TODO: MMI_OPC_0_PEXTLB */
27772 case MMI_OPC_0_PPACB: /* TODO: MMI_OPC_0_PPACB */
27773 case MMI_OPC_0_PEXT5: /* TODO: MMI_OPC_0_PEXT5 */
27774 case MMI_OPC_0_PPAC5: /* TODO: MMI_OPC_0_PPAC5 */
27775 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI0 */
27776 break;
27777 default:
27778 MIPS_INVAL("TX79 MMI class MMI0");
27779 generate_exception_end(ctx, EXCP_RI);
27780 break;
27784 static void decode_mmi1(CPUMIPSState *env, DisasContext *ctx)
27786 uint32_t opc = MASK_MMI1(ctx->opcode);
27788 switch (opc) {
27789 case MMI_OPC_1_PABSW: /* TODO: MMI_OPC_1_PABSW */
27790 case MMI_OPC_1_PCEQW: /* TODO: MMI_OPC_1_PCEQW */
27791 case MMI_OPC_1_PMINW: /* TODO: MMI_OPC_1_PMINW */
27792 case MMI_OPC_1_PADSBH: /* TODO: MMI_OPC_1_PADSBH */
27793 case MMI_OPC_1_PABSH: /* TODO: MMI_OPC_1_PABSH */
27794 case MMI_OPC_1_PCEQH: /* TODO: MMI_OPC_1_PCEQH */
27795 case MMI_OPC_1_PMINH: /* TODO: MMI_OPC_1_PMINH */
27796 case MMI_OPC_1_PCEQB: /* TODO: MMI_OPC_1_PCEQB */
27797 case MMI_OPC_1_PADDUW: /* TODO: MMI_OPC_1_PADDUW */
27798 case MMI_OPC_1_PSUBUW: /* TODO: MMI_OPC_1_PSUBUW */
27799 case MMI_OPC_1_PEXTUW: /* TODO: MMI_OPC_1_PEXTUW */
27800 case MMI_OPC_1_PADDUH: /* TODO: MMI_OPC_1_PADDUH */
27801 case MMI_OPC_1_PSUBUH: /* TODO: MMI_OPC_1_PSUBUH */
27802 case MMI_OPC_1_PEXTUH: /* TODO: MMI_OPC_1_PEXTUH */
27803 case MMI_OPC_1_PADDUB: /* TODO: MMI_OPC_1_PADDUB */
27804 case MMI_OPC_1_PSUBUB: /* TODO: MMI_OPC_1_PSUBUB */
27805 case MMI_OPC_1_PEXTUB: /* TODO: MMI_OPC_1_PEXTUB */
27806 case MMI_OPC_1_QFSRV: /* TODO: MMI_OPC_1_QFSRV */
27807 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI1 */
27808 break;
27809 default:
27810 MIPS_INVAL("TX79 MMI class MMI1");
27811 generate_exception_end(ctx, EXCP_RI);
27812 break;
27816 static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx)
27818 uint32_t opc = MASK_MMI2(ctx->opcode);
27820 switch (opc) {
27821 case MMI_OPC_2_PMADDW: /* TODO: MMI_OPC_2_PMADDW */
27822 case MMI_OPC_2_PSLLVW: /* TODO: MMI_OPC_2_PSLLVW */
27823 case MMI_OPC_2_PSRLVW: /* TODO: MMI_OPC_2_PSRLVW */
27824 case MMI_OPC_2_PMSUBW: /* TODO: MMI_OPC_2_PMSUBW */
27825 case MMI_OPC_2_PMFHI: /* TODO: MMI_OPC_2_PMFHI */
27826 case MMI_OPC_2_PMFLO: /* TODO: MMI_OPC_2_PMFLO */
27827 case MMI_OPC_2_PINTH: /* TODO: MMI_OPC_2_PINTH */
27828 case MMI_OPC_2_PMULTW: /* TODO: MMI_OPC_2_PMULTW */
27829 case MMI_OPC_2_PDIVW: /* TODO: MMI_OPC_2_PDIVW */
27830 case MMI_OPC_2_PMADDH: /* TODO: MMI_OPC_2_PMADDH */
27831 case MMI_OPC_2_PHMADH: /* TODO: MMI_OPC_2_PHMADH */
27832 case MMI_OPC_2_PAND: /* TODO: MMI_OPC_2_PAND */
27833 case MMI_OPC_2_PXOR: /* TODO: MMI_OPC_2_PXOR */
27834 case MMI_OPC_2_PMSUBH: /* TODO: MMI_OPC_2_PMSUBH */
27835 case MMI_OPC_2_PHMSBH: /* TODO: MMI_OPC_2_PHMSBH */
27836 case MMI_OPC_2_PEXEH: /* TODO: MMI_OPC_2_PEXEH */
27837 case MMI_OPC_2_PREVH: /* TODO: MMI_OPC_2_PREVH */
27838 case MMI_OPC_2_PMULTH: /* TODO: MMI_OPC_2_PMULTH */
27839 case MMI_OPC_2_PDIVBW: /* TODO: MMI_OPC_2_PDIVBW */
27840 case MMI_OPC_2_PEXEW: /* TODO: MMI_OPC_2_PEXEW */
27841 case MMI_OPC_2_PROT3W: /* TODO: MMI_OPC_2_PROT3W */
27842 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI2 */
27843 break;
27844 case MMI_OPC_2_PCPYLD:
27845 gen_mmi_pcpyld(ctx);
27846 break;
27847 default:
27848 MIPS_INVAL("TX79 MMI class MMI2");
27849 generate_exception_end(ctx, EXCP_RI);
27850 break;
27854 static void decode_mmi3(CPUMIPSState *env, DisasContext *ctx)
27856 uint32_t opc = MASK_MMI3(ctx->opcode);
27858 switch (opc) {
27859 case MMI_OPC_3_PMADDUW: /* TODO: MMI_OPC_3_PMADDUW */
27860 case MMI_OPC_3_PSRAVW: /* TODO: MMI_OPC_3_PSRAVW */
27861 case MMI_OPC_3_PMTHI: /* TODO: MMI_OPC_3_PMTHI */
27862 case MMI_OPC_3_PMTLO: /* TODO: MMI_OPC_3_PMTLO */
27863 case MMI_OPC_3_PINTEH: /* TODO: MMI_OPC_3_PINTEH */
27864 case MMI_OPC_3_PMULTUW: /* TODO: MMI_OPC_3_PMULTUW */
27865 case MMI_OPC_3_PDIVUW: /* TODO: MMI_OPC_3_PDIVUW */
27866 case MMI_OPC_3_POR: /* TODO: MMI_OPC_3_POR */
27867 case MMI_OPC_3_PNOR: /* TODO: MMI_OPC_3_PNOR */
27868 case MMI_OPC_3_PEXCH: /* TODO: MMI_OPC_3_PEXCH */
27869 case MMI_OPC_3_PEXCW: /* TODO: MMI_OPC_3_PEXCW */
27870 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI3 */
27871 break;
27872 case MMI_OPC_3_PCPYH:
27873 gen_mmi_pcpyh(ctx);
27874 break;
27875 case MMI_OPC_3_PCPYUD:
27876 gen_mmi_pcpyud(ctx);
27877 break;
27878 default:
27879 MIPS_INVAL("TX79 MMI class MMI3");
27880 generate_exception_end(ctx, EXCP_RI);
27881 break;
27885 static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
27887 uint32_t opc = MASK_MMI(ctx->opcode);
27888 int rs = extract32(ctx->opcode, 21, 5);
27889 int rt = extract32(ctx->opcode, 16, 5);
27890 int rd = extract32(ctx->opcode, 11, 5);
27892 switch (opc) {
27893 case MMI_OPC_CLASS_MMI0:
27894 decode_mmi0(env, ctx);
27895 break;
27896 case MMI_OPC_CLASS_MMI1:
27897 decode_mmi1(env, ctx);
27898 break;
27899 case MMI_OPC_CLASS_MMI2:
27900 decode_mmi2(env, ctx);
27901 break;
27902 case MMI_OPC_CLASS_MMI3:
27903 decode_mmi3(env, ctx);
27904 break;
27905 case MMI_OPC_MULT1:
27906 case MMI_OPC_MULTU1:
27907 case MMI_OPC_MADD:
27908 case MMI_OPC_MADDU:
27909 case MMI_OPC_MADD1:
27910 case MMI_OPC_MADDU1:
27911 gen_mul_txx9(ctx, opc, rd, rs, rt);
27912 break;
27913 case MMI_OPC_DIV1:
27914 case MMI_OPC_DIVU1:
27915 gen_div1_tx79(ctx, opc, rs, rt);
27916 break;
27917 case MMI_OPC_MTLO1:
27918 case MMI_OPC_MTHI1:
27919 gen_HILO1_tx79(ctx, opc, rs);
27920 break;
27921 case MMI_OPC_MFLO1:
27922 case MMI_OPC_MFHI1:
27923 gen_HILO1_tx79(ctx, opc, rd);
27924 break;
27925 case MMI_OPC_PLZCW: /* TODO: MMI_OPC_PLZCW */
27926 case MMI_OPC_PMFHL: /* TODO: MMI_OPC_PMFHL */
27927 case MMI_OPC_PMTHL: /* TODO: MMI_OPC_PMTHL */
27928 case MMI_OPC_PSLLH: /* TODO: MMI_OPC_PSLLH */
27929 case MMI_OPC_PSRLH: /* TODO: MMI_OPC_PSRLH */
27930 case MMI_OPC_PSRAH: /* TODO: MMI_OPC_PSRAH */
27931 case MMI_OPC_PSLLW: /* TODO: MMI_OPC_PSLLW */
27932 case MMI_OPC_PSRLW: /* TODO: MMI_OPC_PSRLW */
27933 case MMI_OPC_PSRAW: /* TODO: MMI_OPC_PSRAW */
27934 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI */
27935 break;
27936 default:
27937 MIPS_INVAL("TX79 MMI class");
27938 generate_exception_end(ctx, EXCP_RI);
27939 break;
27943 static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
27945 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_LQ */
27948 static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
27950 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_SQ */
27954 * The TX79-specific instruction Store Quadword
27956 * +--------+-------+-------+------------------------+
27957 * | 011111 | base | rt | offset | SQ
27958 * +--------+-------+-------+------------------------+
27959 * 6 5 5 16
27961 * has the same opcode as the Read Hardware Register instruction
27963 * +--------+-------+-------+-------+-------+--------+
27964 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
27965 * +--------+-------+-------+-------+-------+--------+
27966 * 6 5 5 5 5 6
27968 * that is required, trapped and emulated by the Linux kernel. However, all
27969 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
27970 * offset is odd. Therefore all valid SQ instructions can execute normally.
27971 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
27972 * between SQ and RDHWR, as the Linux kernel does.
27974 static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
27976 int base = extract32(ctx->opcode, 21, 5);
27977 int rt = extract32(ctx->opcode, 16, 5);
27978 int offset = extract32(ctx->opcode, 0, 16);
27980 #ifdef CONFIG_USER_ONLY
27981 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
27982 uint32_t op2 = extract32(ctx->opcode, 6, 5);
27984 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
27985 int rd = extract32(ctx->opcode, 11, 5);
27987 gen_rdhwr(ctx, rt, rd, 0);
27988 return;
27990 #endif
27992 gen_mmi_sq(ctx, base, rt, offset);
27995 #endif
27997 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
27999 int rs, rt, rd, sa;
28000 uint32_t op1, op2;
28001 int16_t imm;
28003 rs = (ctx->opcode >> 21) & 0x1f;
28004 rt = (ctx->opcode >> 16) & 0x1f;
28005 rd = (ctx->opcode >> 11) & 0x1f;
28006 sa = (ctx->opcode >> 6) & 0x1f;
28007 imm = sextract32(ctx->opcode, 7, 9);
28009 op1 = MASK_SPECIAL3(ctx->opcode);
28012 * EVA loads and stores overlap Loongson 2E instructions decoded by
28013 * decode_opc_special3_legacy(), so be careful to allow their decoding when
28014 * EVA is absent.
28016 if (ctx->eva) {
28017 switch (op1) {
28018 case OPC_LWLE:
28019 case OPC_LWRE:
28020 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28021 /* fall through */
28022 case OPC_LBUE:
28023 case OPC_LHUE:
28024 case OPC_LBE:
28025 case OPC_LHE:
28026 case OPC_LLE:
28027 case OPC_LWE:
28028 check_cp0_enabled(ctx);
28029 gen_ld(ctx, op1, rt, rs, imm);
28030 return;
28031 case OPC_SWLE:
28032 case OPC_SWRE:
28033 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28034 /* fall through */
28035 case OPC_SBE:
28036 case OPC_SHE:
28037 case OPC_SWE:
28038 check_cp0_enabled(ctx);
28039 gen_st(ctx, op1, rt, rs, imm);
28040 return;
28041 case OPC_SCE:
28042 check_cp0_enabled(ctx);
28043 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
28044 return;
28045 case OPC_CACHEE:
28046 check_cp0_enabled(ctx);
28047 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
28048 gen_cache_operation(ctx, rt, rs, imm);
28050 /* Treat as NOP. */
28051 return;
28052 case OPC_PREFE:
28053 check_cp0_enabled(ctx);
28054 /* Treat as NOP. */
28055 return;
28059 switch (op1) {
28060 case OPC_EXT:
28061 case OPC_INS:
28062 check_insn(ctx, ISA_MIPS32R2);
28063 gen_bitops(ctx, op1, rt, rs, sa, rd);
28064 break;
28065 case OPC_BSHFL:
28066 op2 = MASK_BSHFL(ctx->opcode);
28067 switch (op2) {
28068 case OPC_ALIGN:
28069 case OPC_ALIGN_1:
28070 case OPC_ALIGN_2:
28071 case OPC_ALIGN_3:
28072 case OPC_BITSWAP:
28073 check_insn(ctx, ISA_MIPS32R6);
28074 decode_opc_special3_r6(env, ctx);
28075 break;
28076 default:
28077 check_insn(ctx, ISA_MIPS32R2);
28078 gen_bshfl(ctx, op2, rt, rd);
28079 break;
28081 break;
28082 #if defined(TARGET_MIPS64)
28083 case OPC_DEXTM:
28084 case OPC_DEXTU:
28085 case OPC_DEXT:
28086 case OPC_DINSM:
28087 case OPC_DINSU:
28088 case OPC_DINS:
28089 check_insn(ctx, ISA_MIPS64R2);
28090 check_mips_64(ctx);
28091 gen_bitops(ctx, op1, rt, rs, sa, rd);
28092 break;
28093 case OPC_DBSHFL:
28094 op2 = MASK_DBSHFL(ctx->opcode);
28095 switch (op2) {
28096 case OPC_DALIGN:
28097 case OPC_DALIGN_1:
28098 case OPC_DALIGN_2:
28099 case OPC_DALIGN_3:
28100 case OPC_DALIGN_4:
28101 case OPC_DALIGN_5:
28102 case OPC_DALIGN_6:
28103 case OPC_DALIGN_7:
28104 case OPC_DBITSWAP:
28105 check_insn(ctx, ISA_MIPS32R6);
28106 decode_opc_special3_r6(env, ctx);
28107 break;
28108 default:
28109 check_insn(ctx, ISA_MIPS64R2);
28110 check_mips_64(ctx);
28111 op2 = MASK_DBSHFL(ctx->opcode);
28112 gen_bshfl(ctx, op2, rt, rd);
28113 break;
28115 break;
28116 #endif
28117 case OPC_RDHWR:
28118 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
28119 break;
28120 case OPC_FORK:
28121 check_mt(ctx);
28123 TCGv t0 = tcg_temp_new();
28124 TCGv t1 = tcg_temp_new();
28126 gen_load_gpr(t0, rt);
28127 gen_load_gpr(t1, rs);
28128 gen_helper_fork(t0, t1);
28129 tcg_temp_free(t0);
28130 tcg_temp_free(t1);
28132 break;
28133 case OPC_YIELD:
28134 check_mt(ctx);
28136 TCGv t0 = tcg_temp_new();
28138 gen_load_gpr(t0, rs);
28139 gen_helper_yield(t0, cpu_env, t0);
28140 gen_store_gpr(t0, rd);
28141 tcg_temp_free(t0);
28143 break;
28144 default:
28145 if (ctx->insn_flags & ISA_MIPS32R6) {
28146 decode_opc_special3_r6(env, ctx);
28147 } else {
28148 decode_opc_special3_legacy(env, ctx);
28153 /* MIPS SIMD Architecture (MSA) */
28154 static inline int check_msa_access(DisasContext *ctx)
28156 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
28157 !(ctx->hflags & MIPS_HFLAG_F64))) {
28158 generate_exception_end(ctx, EXCP_RI);
28159 return 0;
28162 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
28163 if (ctx->insn_flags & ASE_MSA) {
28164 generate_exception_end(ctx, EXCP_MSADIS);
28165 return 0;
28166 } else {
28167 generate_exception_end(ctx, EXCP_RI);
28168 return 0;
28171 return 1;
28174 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
28176 /* generates tcg ops to check if any element is 0 */
28177 /* Note this function only works with MSA_WRLEN = 128 */
28178 uint64_t eval_zero_or_big = 0;
28179 uint64_t eval_big = 0;
28180 TCGv_i64 t0 = tcg_temp_new_i64();
28181 TCGv_i64 t1 = tcg_temp_new_i64();
28182 switch (df) {
28183 case DF_BYTE:
28184 eval_zero_or_big = 0x0101010101010101ULL;
28185 eval_big = 0x8080808080808080ULL;
28186 break;
28187 case DF_HALF:
28188 eval_zero_or_big = 0x0001000100010001ULL;
28189 eval_big = 0x8000800080008000ULL;
28190 break;
28191 case DF_WORD:
28192 eval_zero_or_big = 0x0000000100000001ULL;
28193 eval_big = 0x8000000080000000ULL;
28194 break;
28195 case DF_DOUBLE:
28196 eval_zero_or_big = 0x0000000000000001ULL;
28197 eval_big = 0x8000000000000000ULL;
28198 break;
28200 tcg_gen_subi_i64(t0, msa_wr_d[wt << 1], eval_zero_or_big);
28201 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt << 1]);
28202 tcg_gen_andi_i64(t0, t0, eval_big);
28203 tcg_gen_subi_i64(t1, msa_wr_d[(wt << 1) + 1], eval_zero_or_big);
28204 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt << 1) + 1]);
28205 tcg_gen_andi_i64(t1, t1, eval_big);
28206 tcg_gen_or_i64(t0, t0, t1);
28207 /* if all bits are zero then all elements are not zero */
28208 /* if some bit is non-zero then some element is zero */
28209 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
28210 tcg_gen_trunc_i64_tl(tresult, t0);
28211 tcg_temp_free_i64(t0);
28212 tcg_temp_free_i64(t1);
28215 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
28217 uint8_t df = (ctx->opcode >> 21) & 0x3;
28218 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28219 int64_t s16 = (int16_t)ctx->opcode;
28221 check_msa_access(ctx);
28223 if (ctx->hflags & MIPS_HFLAG_BMASK) {
28224 generate_exception_end(ctx, EXCP_RI);
28225 return;
28227 switch (op1) {
28228 case OPC_BZ_V:
28229 case OPC_BNZ_V:
28231 TCGv_i64 t0 = tcg_temp_new_i64();
28232 tcg_gen_or_i64(t0, msa_wr_d[wt << 1], msa_wr_d[(wt << 1) + 1]);
28233 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
28234 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
28235 tcg_gen_trunc_i64_tl(bcond, t0);
28236 tcg_temp_free_i64(t0);
28238 break;
28239 case OPC_BZ_B:
28240 case OPC_BZ_H:
28241 case OPC_BZ_W:
28242 case OPC_BZ_D:
28243 gen_check_zero_element(bcond, df, wt);
28244 break;
28245 case OPC_BNZ_B:
28246 case OPC_BNZ_H:
28247 case OPC_BNZ_W:
28248 case OPC_BNZ_D:
28249 gen_check_zero_element(bcond, df, wt);
28250 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
28251 break;
28254 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
28256 ctx->hflags |= MIPS_HFLAG_BC;
28257 ctx->hflags |= MIPS_HFLAG_BDS32;
28260 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
28262 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
28263 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
28264 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28265 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28267 TCGv_i32 twd = tcg_const_i32(wd);
28268 TCGv_i32 tws = tcg_const_i32(ws);
28269 TCGv_i32 ti8 = tcg_const_i32(i8);
28271 switch (MASK_MSA_I8(ctx->opcode)) {
28272 case OPC_ANDI_B:
28273 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
28274 break;
28275 case OPC_ORI_B:
28276 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
28277 break;
28278 case OPC_NORI_B:
28279 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
28280 break;
28281 case OPC_XORI_B:
28282 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
28283 break;
28284 case OPC_BMNZI_B:
28285 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
28286 break;
28287 case OPC_BMZI_B:
28288 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
28289 break;
28290 case OPC_BSELI_B:
28291 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
28292 break;
28293 case OPC_SHF_B:
28294 case OPC_SHF_H:
28295 case OPC_SHF_W:
28297 uint8_t df = (ctx->opcode >> 24) & 0x3;
28298 if (df == DF_DOUBLE) {
28299 generate_exception_end(ctx, EXCP_RI);
28300 } else {
28301 TCGv_i32 tdf = tcg_const_i32(df);
28302 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
28303 tcg_temp_free_i32(tdf);
28306 break;
28307 default:
28308 MIPS_INVAL("MSA instruction");
28309 generate_exception_end(ctx, EXCP_RI);
28310 break;
28313 tcg_temp_free_i32(twd);
28314 tcg_temp_free_i32(tws);
28315 tcg_temp_free_i32(ti8);
28318 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
28320 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28321 uint8_t df = (ctx->opcode >> 21) & 0x3;
28322 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
28323 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
28324 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28325 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28327 TCGv_i32 tdf = tcg_const_i32(df);
28328 TCGv_i32 twd = tcg_const_i32(wd);
28329 TCGv_i32 tws = tcg_const_i32(ws);
28330 TCGv_i32 timm = tcg_temp_new_i32();
28331 tcg_gen_movi_i32(timm, u5);
28333 switch (MASK_MSA_I5(ctx->opcode)) {
28334 case OPC_ADDVI_df:
28335 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
28336 break;
28337 case OPC_SUBVI_df:
28338 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
28339 break;
28340 case OPC_MAXI_S_df:
28341 tcg_gen_movi_i32(timm, s5);
28342 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
28343 break;
28344 case OPC_MAXI_U_df:
28345 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
28346 break;
28347 case OPC_MINI_S_df:
28348 tcg_gen_movi_i32(timm, s5);
28349 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
28350 break;
28351 case OPC_MINI_U_df:
28352 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
28353 break;
28354 case OPC_CEQI_df:
28355 tcg_gen_movi_i32(timm, s5);
28356 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
28357 break;
28358 case OPC_CLTI_S_df:
28359 tcg_gen_movi_i32(timm, s5);
28360 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
28361 break;
28362 case OPC_CLTI_U_df:
28363 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
28364 break;
28365 case OPC_CLEI_S_df:
28366 tcg_gen_movi_i32(timm, s5);
28367 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
28368 break;
28369 case OPC_CLEI_U_df:
28370 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
28371 break;
28372 case OPC_LDI_df:
28374 int32_t s10 = sextract32(ctx->opcode, 11, 10);
28375 tcg_gen_movi_i32(timm, s10);
28376 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
28378 break;
28379 default:
28380 MIPS_INVAL("MSA instruction");
28381 generate_exception_end(ctx, EXCP_RI);
28382 break;
28385 tcg_temp_free_i32(tdf);
28386 tcg_temp_free_i32(twd);
28387 tcg_temp_free_i32(tws);
28388 tcg_temp_free_i32(timm);
28391 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
28393 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28394 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
28395 uint32_t df = 0, m = 0;
28396 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28397 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28399 TCGv_i32 tdf;
28400 TCGv_i32 tm;
28401 TCGv_i32 twd;
28402 TCGv_i32 tws;
28404 if ((dfm & 0x40) == 0x00) {
28405 m = dfm & 0x3f;
28406 df = DF_DOUBLE;
28407 } else if ((dfm & 0x60) == 0x40) {
28408 m = dfm & 0x1f;
28409 df = DF_WORD;
28410 } else if ((dfm & 0x70) == 0x60) {
28411 m = dfm & 0x0f;
28412 df = DF_HALF;
28413 } else if ((dfm & 0x78) == 0x70) {
28414 m = dfm & 0x7;
28415 df = DF_BYTE;
28416 } else {
28417 generate_exception_end(ctx, EXCP_RI);
28418 return;
28421 tdf = tcg_const_i32(df);
28422 tm = tcg_const_i32(m);
28423 twd = tcg_const_i32(wd);
28424 tws = tcg_const_i32(ws);
28426 switch (MASK_MSA_BIT(ctx->opcode)) {
28427 case OPC_SLLI_df:
28428 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
28429 break;
28430 case OPC_SRAI_df:
28431 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
28432 break;
28433 case OPC_SRLI_df:
28434 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
28435 break;
28436 case OPC_BCLRI_df:
28437 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
28438 break;
28439 case OPC_BSETI_df:
28440 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
28441 break;
28442 case OPC_BNEGI_df:
28443 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
28444 break;
28445 case OPC_BINSLI_df:
28446 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
28447 break;
28448 case OPC_BINSRI_df:
28449 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
28450 break;
28451 case OPC_SAT_S_df:
28452 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
28453 break;
28454 case OPC_SAT_U_df:
28455 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
28456 break;
28457 case OPC_SRARI_df:
28458 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
28459 break;
28460 case OPC_SRLRI_df:
28461 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
28462 break;
28463 default:
28464 MIPS_INVAL("MSA instruction");
28465 generate_exception_end(ctx, EXCP_RI);
28466 break;
28469 tcg_temp_free_i32(tdf);
28470 tcg_temp_free_i32(tm);
28471 tcg_temp_free_i32(twd);
28472 tcg_temp_free_i32(tws);
28475 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
28477 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28478 uint8_t df = (ctx->opcode >> 21) & 0x3;
28479 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28480 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28481 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28483 TCGv_i32 tdf = tcg_const_i32(df);
28484 TCGv_i32 twd = tcg_const_i32(wd);
28485 TCGv_i32 tws = tcg_const_i32(ws);
28486 TCGv_i32 twt = tcg_const_i32(wt);
28488 switch (MASK_MSA_3R(ctx->opcode)) {
28489 case OPC_BINSL_df:
28490 switch (df) {
28491 case DF_BYTE:
28492 gen_helper_msa_binsl_b(cpu_env, twd, tws, twt);
28493 break;
28494 case DF_HALF:
28495 gen_helper_msa_binsl_h(cpu_env, twd, tws, twt);
28496 break;
28497 case DF_WORD:
28498 gen_helper_msa_binsl_w(cpu_env, twd, tws, twt);
28499 break;
28500 case DF_DOUBLE:
28501 gen_helper_msa_binsl_d(cpu_env, twd, tws, twt);
28502 break;
28504 break;
28505 case OPC_BINSR_df:
28506 switch (df) {
28507 case DF_BYTE:
28508 gen_helper_msa_binsr_b(cpu_env, twd, tws, twt);
28509 break;
28510 case DF_HALF:
28511 gen_helper_msa_binsr_h(cpu_env, twd, tws, twt);
28512 break;
28513 case DF_WORD:
28514 gen_helper_msa_binsr_w(cpu_env, twd, tws, twt);
28515 break;
28516 case DF_DOUBLE:
28517 gen_helper_msa_binsr_d(cpu_env, twd, tws, twt);
28518 break;
28520 break;
28521 case OPC_BCLR_df:
28522 switch (df) {
28523 case DF_BYTE:
28524 gen_helper_msa_bclr_b(cpu_env, twd, tws, twt);
28525 break;
28526 case DF_HALF:
28527 gen_helper_msa_bclr_h(cpu_env, twd, tws, twt);
28528 break;
28529 case DF_WORD:
28530 gen_helper_msa_bclr_w(cpu_env, twd, tws, twt);
28531 break;
28532 case DF_DOUBLE:
28533 gen_helper_msa_bclr_d(cpu_env, twd, tws, twt);
28534 break;
28536 break;
28537 case OPC_BNEG_df:
28538 switch (df) {
28539 case DF_BYTE:
28540 gen_helper_msa_bneg_b(cpu_env, twd, tws, twt);
28541 break;
28542 case DF_HALF:
28543 gen_helper_msa_bneg_h(cpu_env, twd, tws, twt);
28544 break;
28545 case DF_WORD:
28546 gen_helper_msa_bneg_w(cpu_env, twd, tws, twt);
28547 break;
28548 case DF_DOUBLE:
28549 gen_helper_msa_bneg_d(cpu_env, twd, tws, twt);
28550 break;
28552 break;
28553 case OPC_BSET_df:
28554 switch (df) {
28555 case DF_BYTE:
28556 gen_helper_msa_bset_b(cpu_env, twd, tws, twt);
28557 break;
28558 case DF_HALF:
28559 gen_helper_msa_bset_h(cpu_env, twd, tws, twt);
28560 break;
28561 case DF_WORD:
28562 gen_helper_msa_bset_w(cpu_env, twd, tws, twt);
28563 break;
28564 case DF_DOUBLE:
28565 gen_helper_msa_bset_d(cpu_env, twd, tws, twt);
28566 break;
28568 break;
28569 case OPC_ADD_A_df:
28570 switch (df) {
28571 case DF_BYTE:
28572 gen_helper_msa_add_a_b(cpu_env, twd, tws, twt);
28573 break;
28574 case DF_HALF:
28575 gen_helper_msa_add_a_h(cpu_env, twd, tws, twt);
28576 break;
28577 case DF_WORD:
28578 gen_helper_msa_add_a_w(cpu_env, twd, tws, twt);
28579 break;
28580 case DF_DOUBLE:
28581 gen_helper_msa_add_a_d(cpu_env, twd, tws, twt);
28582 break;
28584 break;
28585 case OPC_ADDS_A_df:
28586 switch (df) {
28587 case DF_BYTE:
28588 gen_helper_msa_adds_a_b(cpu_env, twd, tws, twt);
28589 break;
28590 case DF_HALF:
28591 gen_helper_msa_adds_a_h(cpu_env, twd, tws, twt);
28592 break;
28593 case DF_WORD:
28594 gen_helper_msa_adds_a_w(cpu_env, twd, tws, twt);
28595 break;
28596 case DF_DOUBLE:
28597 gen_helper_msa_adds_a_d(cpu_env, twd, tws, twt);
28598 break;
28600 break;
28601 case OPC_ADDS_S_df:
28602 switch (df) {
28603 case DF_BYTE:
28604 gen_helper_msa_adds_s_b(cpu_env, twd, tws, twt);
28605 break;
28606 case DF_HALF:
28607 gen_helper_msa_adds_s_h(cpu_env, twd, tws, twt);
28608 break;
28609 case DF_WORD:
28610 gen_helper_msa_adds_s_w(cpu_env, twd, tws, twt);
28611 break;
28612 case DF_DOUBLE:
28613 gen_helper_msa_adds_s_d(cpu_env, twd, tws, twt);
28614 break;
28616 break;
28617 case OPC_ADDS_U_df:
28618 switch (df) {
28619 case DF_BYTE:
28620 gen_helper_msa_adds_u_b(cpu_env, twd, tws, twt);
28621 break;
28622 case DF_HALF:
28623 gen_helper_msa_adds_u_h(cpu_env, twd, tws, twt);
28624 break;
28625 case DF_WORD:
28626 gen_helper_msa_adds_u_w(cpu_env, twd, tws, twt);
28627 break;
28628 case DF_DOUBLE:
28629 gen_helper_msa_adds_u_d(cpu_env, twd, tws, twt);
28630 break;
28632 break;
28633 case OPC_ADDV_df:
28634 switch (df) {
28635 case DF_BYTE:
28636 gen_helper_msa_addv_b(cpu_env, twd, tws, twt);
28637 break;
28638 case DF_HALF:
28639 gen_helper_msa_addv_h(cpu_env, twd, tws, twt);
28640 break;
28641 case DF_WORD:
28642 gen_helper_msa_addv_w(cpu_env, twd, tws, twt);
28643 break;
28644 case DF_DOUBLE:
28645 gen_helper_msa_addv_d(cpu_env, twd, tws, twt);
28646 break;
28648 break;
28649 case OPC_AVE_S_df:
28650 switch (df) {
28651 case DF_BYTE:
28652 gen_helper_msa_ave_s_b(cpu_env, twd, tws, twt);
28653 break;
28654 case DF_HALF:
28655 gen_helper_msa_ave_s_h(cpu_env, twd, tws, twt);
28656 break;
28657 case DF_WORD:
28658 gen_helper_msa_ave_s_w(cpu_env, twd, tws, twt);
28659 break;
28660 case DF_DOUBLE:
28661 gen_helper_msa_ave_s_d(cpu_env, twd, tws, twt);
28662 break;
28664 break;
28665 case OPC_AVE_U_df:
28666 switch (df) {
28667 case DF_BYTE:
28668 gen_helper_msa_ave_u_b(cpu_env, twd, tws, twt);
28669 break;
28670 case DF_HALF:
28671 gen_helper_msa_ave_u_h(cpu_env, twd, tws, twt);
28672 break;
28673 case DF_WORD:
28674 gen_helper_msa_ave_u_w(cpu_env, twd, tws, twt);
28675 break;
28676 case DF_DOUBLE:
28677 gen_helper_msa_ave_u_d(cpu_env, twd, tws, twt);
28678 break;
28680 break;
28681 case OPC_AVER_S_df:
28682 switch (df) {
28683 case DF_BYTE:
28684 gen_helper_msa_aver_s_b(cpu_env, twd, tws, twt);
28685 break;
28686 case DF_HALF:
28687 gen_helper_msa_aver_s_h(cpu_env, twd, tws, twt);
28688 break;
28689 case DF_WORD:
28690 gen_helper_msa_aver_s_w(cpu_env, twd, tws, twt);
28691 break;
28692 case DF_DOUBLE:
28693 gen_helper_msa_aver_s_d(cpu_env, twd, tws, twt);
28694 break;
28696 break;
28697 case OPC_AVER_U_df:
28698 switch (df) {
28699 case DF_BYTE:
28700 gen_helper_msa_aver_u_b(cpu_env, twd, tws, twt);
28701 break;
28702 case DF_HALF:
28703 gen_helper_msa_aver_u_h(cpu_env, twd, tws, twt);
28704 break;
28705 case DF_WORD:
28706 gen_helper_msa_aver_u_w(cpu_env, twd, tws, twt);
28707 break;
28708 case DF_DOUBLE:
28709 gen_helper_msa_aver_u_d(cpu_env, twd, tws, twt);
28710 break;
28712 break;
28713 case OPC_CEQ_df:
28714 switch (df) {
28715 case DF_BYTE:
28716 gen_helper_msa_ceq_b(cpu_env, twd, tws, twt);
28717 break;
28718 case DF_HALF:
28719 gen_helper_msa_ceq_h(cpu_env, twd, tws, twt);
28720 break;
28721 case DF_WORD:
28722 gen_helper_msa_ceq_w(cpu_env, twd, tws, twt);
28723 break;
28724 case DF_DOUBLE:
28725 gen_helper_msa_ceq_d(cpu_env, twd, tws, twt);
28726 break;
28728 break;
28729 case OPC_CLE_S_df:
28730 switch (df) {
28731 case DF_BYTE:
28732 gen_helper_msa_cle_s_b(cpu_env, twd, tws, twt);
28733 break;
28734 case DF_HALF:
28735 gen_helper_msa_cle_s_h(cpu_env, twd, tws, twt);
28736 break;
28737 case DF_WORD:
28738 gen_helper_msa_cle_s_w(cpu_env, twd, tws, twt);
28739 break;
28740 case DF_DOUBLE:
28741 gen_helper_msa_cle_s_d(cpu_env, twd, tws, twt);
28742 break;
28744 break;
28745 case OPC_CLE_U_df:
28746 switch (df) {
28747 case DF_BYTE:
28748 gen_helper_msa_cle_u_b(cpu_env, twd, tws, twt);
28749 break;
28750 case DF_HALF:
28751 gen_helper_msa_cle_u_h(cpu_env, twd, tws, twt);
28752 break;
28753 case DF_WORD:
28754 gen_helper_msa_cle_u_w(cpu_env, twd, tws, twt);
28755 break;
28756 case DF_DOUBLE:
28757 gen_helper_msa_cle_u_d(cpu_env, twd, tws, twt);
28758 break;
28760 break;
28761 case OPC_CLT_S_df:
28762 switch (df) {
28763 case DF_BYTE:
28764 gen_helper_msa_clt_s_b(cpu_env, twd, tws, twt);
28765 break;
28766 case DF_HALF:
28767 gen_helper_msa_clt_s_h(cpu_env, twd, tws, twt);
28768 break;
28769 case DF_WORD:
28770 gen_helper_msa_clt_s_w(cpu_env, twd, tws, twt);
28771 break;
28772 case DF_DOUBLE:
28773 gen_helper_msa_clt_s_d(cpu_env, twd, tws, twt);
28774 break;
28776 break;
28777 case OPC_CLT_U_df:
28778 switch (df) {
28779 case DF_BYTE:
28780 gen_helper_msa_clt_u_b(cpu_env, twd, tws, twt);
28781 break;
28782 case DF_HALF:
28783 gen_helper_msa_clt_u_h(cpu_env, twd, tws, twt);
28784 break;
28785 case DF_WORD:
28786 gen_helper_msa_clt_u_w(cpu_env, twd, tws, twt);
28787 break;
28788 case DF_DOUBLE:
28789 gen_helper_msa_clt_u_d(cpu_env, twd, tws, twt);
28790 break;
28792 break;
28793 case OPC_DIV_S_df:
28794 switch (df) {
28795 case DF_BYTE:
28796 gen_helper_msa_div_s_b(cpu_env, twd, tws, twt);
28797 break;
28798 case DF_HALF:
28799 gen_helper_msa_div_s_h(cpu_env, twd, tws, twt);
28800 break;
28801 case DF_WORD:
28802 gen_helper_msa_div_s_w(cpu_env, twd, tws, twt);
28803 break;
28804 case DF_DOUBLE:
28805 gen_helper_msa_div_s_d(cpu_env, twd, tws, twt);
28806 break;
28808 break;
28809 case OPC_DIV_U_df:
28810 switch (df) {
28811 case DF_BYTE:
28812 gen_helper_msa_div_u_b(cpu_env, twd, tws, twt);
28813 break;
28814 case DF_HALF:
28815 gen_helper_msa_div_u_h(cpu_env, twd, tws, twt);
28816 break;
28817 case DF_WORD:
28818 gen_helper_msa_div_u_w(cpu_env, twd, tws, twt);
28819 break;
28820 case DF_DOUBLE:
28821 gen_helper_msa_div_u_d(cpu_env, twd, tws, twt);
28822 break;
28824 break;
28825 case OPC_MAX_A_df:
28826 switch (df) {
28827 case DF_BYTE:
28828 gen_helper_msa_max_a_b(cpu_env, twd, tws, twt);
28829 break;
28830 case DF_HALF:
28831 gen_helper_msa_max_a_h(cpu_env, twd, tws, twt);
28832 break;
28833 case DF_WORD:
28834 gen_helper_msa_max_a_w(cpu_env, twd, tws, twt);
28835 break;
28836 case DF_DOUBLE:
28837 gen_helper_msa_max_a_d(cpu_env, twd, tws, twt);
28838 break;
28840 break;
28841 case OPC_MAX_S_df:
28842 switch (df) {
28843 case DF_BYTE:
28844 gen_helper_msa_max_s_b(cpu_env, twd, tws, twt);
28845 break;
28846 case DF_HALF:
28847 gen_helper_msa_max_s_h(cpu_env, twd, tws, twt);
28848 break;
28849 case DF_WORD:
28850 gen_helper_msa_max_s_w(cpu_env, twd, tws, twt);
28851 break;
28852 case DF_DOUBLE:
28853 gen_helper_msa_max_s_d(cpu_env, twd, tws, twt);
28854 break;
28856 break;
28857 case OPC_MAX_U_df:
28858 switch (df) {
28859 case DF_BYTE:
28860 gen_helper_msa_max_u_b(cpu_env, twd, tws, twt);
28861 break;
28862 case DF_HALF:
28863 gen_helper_msa_max_u_h(cpu_env, twd, tws, twt);
28864 break;
28865 case DF_WORD:
28866 gen_helper_msa_max_u_w(cpu_env, twd, tws, twt);
28867 break;
28868 case DF_DOUBLE:
28869 gen_helper_msa_max_u_d(cpu_env, twd, tws, twt);
28870 break;
28872 break;
28873 case OPC_MIN_A_df:
28874 switch (df) {
28875 case DF_BYTE:
28876 gen_helper_msa_min_a_b(cpu_env, twd, tws, twt);
28877 break;
28878 case DF_HALF:
28879 gen_helper_msa_min_a_h(cpu_env, twd, tws, twt);
28880 break;
28881 case DF_WORD:
28882 gen_helper_msa_min_a_w(cpu_env, twd, tws, twt);
28883 break;
28884 case DF_DOUBLE:
28885 gen_helper_msa_min_a_d(cpu_env, twd, tws, twt);
28886 break;
28888 break;
28889 case OPC_MIN_S_df:
28890 switch (df) {
28891 case DF_BYTE:
28892 gen_helper_msa_min_s_b(cpu_env, twd, tws, twt);
28893 break;
28894 case DF_HALF:
28895 gen_helper_msa_min_s_h(cpu_env, twd, tws, twt);
28896 break;
28897 case DF_WORD:
28898 gen_helper_msa_min_s_w(cpu_env, twd, tws, twt);
28899 break;
28900 case DF_DOUBLE:
28901 gen_helper_msa_min_s_d(cpu_env, twd, tws, twt);
28902 break;
28904 break;
28905 case OPC_MIN_U_df:
28906 switch (df) {
28907 case DF_BYTE:
28908 gen_helper_msa_min_u_b(cpu_env, twd, tws, twt);
28909 break;
28910 case DF_HALF:
28911 gen_helper_msa_min_u_h(cpu_env, twd, tws, twt);
28912 break;
28913 case DF_WORD:
28914 gen_helper_msa_min_u_w(cpu_env, twd, tws, twt);
28915 break;
28916 case DF_DOUBLE:
28917 gen_helper_msa_min_u_d(cpu_env, twd, tws, twt);
28918 break;
28920 break;
28921 case OPC_MOD_S_df:
28922 switch (df) {
28923 case DF_BYTE:
28924 gen_helper_msa_mod_s_b(cpu_env, twd, tws, twt);
28925 break;
28926 case DF_HALF:
28927 gen_helper_msa_mod_s_h(cpu_env, twd, tws, twt);
28928 break;
28929 case DF_WORD:
28930 gen_helper_msa_mod_s_w(cpu_env, twd, tws, twt);
28931 break;
28932 case DF_DOUBLE:
28933 gen_helper_msa_mod_s_d(cpu_env, twd, tws, twt);
28934 break;
28936 break;
28937 case OPC_MOD_U_df:
28938 switch (df) {
28939 case DF_BYTE:
28940 gen_helper_msa_mod_u_b(cpu_env, twd, tws, twt);
28941 break;
28942 case DF_HALF:
28943 gen_helper_msa_mod_u_h(cpu_env, twd, tws, twt);
28944 break;
28945 case DF_WORD:
28946 gen_helper_msa_mod_u_w(cpu_env, twd, tws, twt);
28947 break;
28948 case DF_DOUBLE:
28949 gen_helper_msa_mod_u_d(cpu_env, twd, tws, twt);
28950 break;
28952 break;
28953 case OPC_ASUB_S_df:
28954 switch (df) {
28955 case DF_BYTE:
28956 gen_helper_msa_asub_s_b(cpu_env, twd, tws, twt);
28957 break;
28958 case DF_HALF:
28959 gen_helper_msa_asub_s_h(cpu_env, twd, tws, twt);
28960 break;
28961 case DF_WORD:
28962 gen_helper_msa_asub_s_w(cpu_env, twd, tws, twt);
28963 break;
28964 case DF_DOUBLE:
28965 gen_helper_msa_asub_s_d(cpu_env, twd, tws, twt);
28966 break;
28968 break;
28969 case OPC_ASUB_U_df:
28970 switch (df) {
28971 case DF_BYTE:
28972 gen_helper_msa_asub_u_b(cpu_env, twd, tws, twt);
28973 break;
28974 case DF_HALF:
28975 gen_helper_msa_asub_u_h(cpu_env, twd, tws, twt);
28976 break;
28977 case DF_WORD:
28978 gen_helper_msa_asub_u_w(cpu_env, twd, tws, twt);
28979 break;
28980 case DF_DOUBLE:
28981 gen_helper_msa_asub_u_d(cpu_env, twd, tws, twt);
28982 break;
28984 break;
28985 case OPC_ILVEV_df:
28986 switch (df) {
28987 case DF_BYTE:
28988 gen_helper_msa_ilvev_b(cpu_env, twd, tws, twt);
28989 break;
28990 case DF_HALF:
28991 gen_helper_msa_ilvev_h(cpu_env, twd, tws, twt);
28992 break;
28993 case DF_WORD:
28994 gen_helper_msa_ilvev_w(cpu_env, twd, tws, twt);
28995 break;
28996 case DF_DOUBLE:
28997 gen_helper_msa_ilvev_d(cpu_env, twd, tws, twt);
28998 break;
29000 break;
29001 case OPC_ILVOD_df:
29002 switch (df) {
29003 case DF_BYTE:
29004 gen_helper_msa_ilvod_b(cpu_env, twd, tws, twt);
29005 break;
29006 case DF_HALF:
29007 gen_helper_msa_ilvod_h(cpu_env, twd, tws, twt);
29008 break;
29009 case DF_WORD:
29010 gen_helper_msa_ilvod_w(cpu_env, twd, tws, twt);
29011 break;
29012 case DF_DOUBLE:
29013 gen_helper_msa_ilvod_d(cpu_env, twd, tws, twt);
29014 break;
29016 break;
29017 case OPC_ILVL_df:
29018 switch (df) {
29019 case DF_BYTE:
29020 gen_helper_msa_ilvl_b(cpu_env, twd, tws, twt);
29021 break;
29022 case DF_HALF:
29023 gen_helper_msa_ilvl_h(cpu_env, twd, tws, twt);
29024 break;
29025 case DF_WORD:
29026 gen_helper_msa_ilvl_w(cpu_env, twd, tws, twt);
29027 break;
29028 case DF_DOUBLE:
29029 gen_helper_msa_ilvl_d(cpu_env, twd, tws, twt);
29030 break;
29032 break;
29033 case OPC_ILVR_df:
29034 switch (df) {
29035 case DF_BYTE:
29036 gen_helper_msa_ilvr_b(cpu_env, twd, tws, twt);
29037 break;
29038 case DF_HALF:
29039 gen_helper_msa_ilvr_h(cpu_env, twd, tws, twt);
29040 break;
29041 case DF_WORD:
29042 gen_helper_msa_ilvr_w(cpu_env, twd, tws, twt);
29043 break;
29044 case DF_DOUBLE:
29045 gen_helper_msa_ilvr_d(cpu_env, twd, tws, twt);
29046 break;
29048 break;
29049 case OPC_PCKEV_df:
29050 switch (df) {
29051 case DF_BYTE:
29052 gen_helper_msa_pckev_b(cpu_env, twd, tws, twt);
29053 break;
29054 case DF_HALF:
29055 gen_helper_msa_pckev_h(cpu_env, twd, tws, twt);
29056 break;
29057 case DF_WORD:
29058 gen_helper_msa_pckev_w(cpu_env, twd, tws, twt);
29059 break;
29060 case DF_DOUBLE:
29061 gen_helper_msa_pckev_d(cpu_env, twd, tws, twt);
29062 break;
29064 break;
29065 case OPC_PCKOD_df:
29066 switch (df) {
29067 case DF_BYTE:
29068 gen_helper_msa_pckod_b(cpu_env, twd, tws, twt);
29069 break;
29070 case DF_HALF:
29071 gen_helper_msa_pckod_h(cpu_env, twd, tws, twt);
29072 break;
29073 case DF_WORD:
29074 gen_helper_msa_pckod_w(cpu_env, twd, tws, twt);
29075 break;
29076 case DF_DOUBLE:
29077 gen_helper_msa_pckod_d(cpu_env, twd, tws, twt);
29078 break;
29080 break;
29081 case OPC_SLL_df:
29082 switch (df) {
29083 case DF_BYTE:
29084 gen_helper_msa_sll_b(cpu_env, twd, tws, twt);
29085 break;
29086 case DF_HALF:
29087 gen_helper_msa_sll_h(cpu_env, twd, tws, twt);
29088 break;
29089 case DF_WORD:
29090 gen_helper_msa_sll_w(cpu_env, twd, tws, twt);
29091 break;
29092 case DF_DOUBLE:
29093 gen_helper_msa_sll_d(cpu_env, twd, tws, twt);
29094 break;
29096 break;
29097 case OPC_SRA_df:
29098 switch (df) {
29099 case DF_BYTE:
29100 gen_helper_msa_sra_b(cpu_env, twd, tws, twt);
29101 break;
29102 case DF_HALF:
29103 gen_helper_msa_sra_h(cpu_env, twd, tws, twt);
29104 break;
29105 case DF_WORD:
29106 gen_helper_msa_sra_w(cpu_env, twd, tws, twt);
29107 break;
29108 case DF_DOUBLE:
29109 gen_helper_msa_sra_d(cpu_env, twd, tws, twt);
29110 break;
29112 break;
29113 case OPC_SRAR_df:
29114 switch (df) {
29115 case DF_BYTE:
29116 gen_helper_msa_srar_b(cpu_env, twd, tws, twt);
29117 break;
29118 case DF_HALF:
29119 gen_helper_msa_srar_h(cpu_env, twd, tws, twt);
29120 break;
29121 case DF_WORD:
29122 gen_helper_msa_srar_w(cpu_env, twd, tws, twt);
29123 break;
29124 case DF_DOUBLE:
29125 gen_helper_msa_srar_d(cpu_env, twd, tws, twt);
29126 break;
29128 break;
29129 case OPC_SRL_df:
29130 switch (df) {
29131 case DF_BYTE:
29132 gen_helper_msa_srl_b(cpu_env, twd, tws, twt);
29133 break;
29134 case DF_HALF:
29135 gen_helper_msa_srl_h(cpu_env, twd, tws, twt);
29136 break;
29137 case DF_WORD:
29138 gen_helper_msa_srl_w(cpu_env, twd, tws, twt);
29139 break;
29140 case DF_DOUBLE:
29141 gen_helper_msa_srl_d(cpu_env, twd, tws, twt);
29142 break;
29144 break;
29145 case OPC_SRLR_df:
29146 switch (df) {
29147 case DF_BYTE:
29148 gen_helper_msa_srlr_b(cpu_env, twd, tws, twt);
29149 break;
29150 case DF_HALF:
29151 gen_helper_msa_srlr_h(cpu_env, twd, tws, twt);
29152 break;
29153 case DF_WORD:
29154 gen_helper_msa_srlr_w(cpu_env, twd, tws, twt);
29155 break;
29156 case DF_DOUBLE:
29157 gen_helper_msa_srlr_d(cpu_env, twd, tws, twt);
29158 break;
29160 break;
29161 case OPC_SUBS_S_df:
29162 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
29163 break;
29164 case OPC_MULV_df:
29165 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
29166 break;
29167 case OPC_SLD_df:
29168 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
29169 break;
29170 case OPC_VSHF_df:
29171 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
29172 break;
29173 case OPC_SUBV_df:
29174 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
29175 break;
29176 case OPC_SUBS_U_df:
29177 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
29178 break;
29179 case OPC_MADDV_df:
29180 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
29181 break;
29182 case OPC_SPLAT_df:
29183 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
29184 break;
29185 case OPC_SUBSUS_U_df:
29186 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
29187 break;
29188 case OPC_MSUBV_df:
29189 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
29190 break;
29191 case OPC_SUBSUU_S_df:
29192 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
29193 break;
29195 case OPC_DOTP_S_df:
29196 case OPC_DOTP_U_df:
29197 case OPC_DPADD_S_df:
29198 case OPC_DPADD_U_df:
29199 case OPC_DPSUB_S_df:
29200 case OPC_HADD_S_df:
29201 case OPC_DPSUB_U_df:
29202 case OPC_HADD_U_df:
29203 case OPC_HSUB_S_df:
29204 case OPC_HSUB_U_df:
29205 if (df == DF_BYTE) {
29206 generate_exception_end(ctx, EXCP_RI);
29207 break;
29209 switch (MASK_MSA_3R(ctx->opcode)) {
29210 case OPC_HADD_S_df:
29211 switch (df) {
29212 case DF_HALF:
29213 gen_helper_msa_hadd_s_h(cpu_env, twd, tws, twt);
29214 break;
29215 case DF_WORD:
29216 gen_helper_msa_hadd_s_w(cpu_env, twd, tws, twt);
29217 break;
29218 case DF_DOUBLE:
29219 gen_helper_msa_hadd_s_d(cpu_env, twd, tws, twt);
29220 break;
29222 break;
29223 case OPC_HADD_U_df:
29224 switch (df) {
29225 case DF_HALF:
29226 gen_helper_msa_hadd_u_h(cpu_env, twd, tws, twt);
29227 break;
29228 case DF_WORD:
29229 gen_helper_msa_hadd_u_w(cpu_env, twd, tws, twt);
29230 break;
29231 case DF_DOUBLE:
29232 gen_helper_msa_hadd_u_d(cpu_env, twd, tws, twt);
29233 break;
29235 break;
29236 case OPC_HSUB_S_df:
29237 switch (df) {
29238 case DF_HALF:
29239 gen_helper_msa_hsub_s_h(cpu_env, twd, tws, twt);
29240 break;
29241 case DF_WORD:
29242 gen_helper_msa_hsub_s_w(cpu_env, twd, tws, twt);
29243 break;
29244 case DF_DOUBLE:
29245 gen_helper_msa_hsub_s_d(cpu_env, twd, tws, twt);
29246 break;
29248 break;
29249 case OPC_HSUB_U_df:
29250 switch (df) {
29251 case DF_HALF:
29252 gen_helper_msa_hsub_u_h(cpu_env, twd, tws, twt);
29253 break;
29254 case DF_WORD:
29255 gen_helper_msa_hsub_u_w(cpu_env, twd, tws, twt);
29256 break;
29257 case DF_DOUBLE:
29258 gen_helper_msa_hsub_u_d(cpu_env, twd, tws, twt);
29259 break;
29261 break;
29262 case OPC_DOTP_S_df:
29263 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
29264 break;
29265 case OPC_DOTP_U_df:
29266 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
29267 break;
29268 case OPC_DPADD_S_df:
29269 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
29270 break;
29271 case OPC_DPADD_U_df:
29272 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
29273 break;
29274 case OPC_DPSUB_S_df:
29275 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
29276 break;
29277 case OPC_DPSUB_U_df:
29278 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
29279 break;
29281 break;
29282 default:
29283 MIPS_INVAL("MSA instruction");
29284 generate_exception_end(ctx, EXCP_RI);
29285 break;
29287 tcg_temp_free_i32(twd);
29288 tcg_temp_free_i32(tws);
29289 tcg_temp_free_i32(twt);
29290 tcg_temp_free_i32(tdf);
29293 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
29295 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
29296 uint8_t source = (ctx->opcode >> 11) & 0x1f;
29297 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
29298 TCGv telm = tcg_temp_new();
29299 TCGv_i32 tsr = tcg_const_i32(source);
29300 TCGv_i32 tdt = tcg_const_i32(dest);
29302 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
29303 case OPC_CTCMSA:
29304 gen_load_gpr(telm, source);
29305 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
29306 break;
29307 case OPC_CFCMSA:
29308 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
29309 gen_store_gpr(telm, dest);
29310 break;
29311 case OPC_MOVE_V:
29312 gen_helper_msa_move_v(cpu_env, tdt, tsr);
29313 break;
29314 default:
29315 MIPS_INVAL("MSA instruction");
29316 generate_exception_end(ctx, EXCP_RI);
29317 break;
29320 tcg_temp_free(telm);
29321 tcg_temp_free_i32(tdt);
29322 tcg_temp_free_i32(tsr);
29325 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
29326 uint32_t n)
29328 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
29329 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29330 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29332 TCGv_i32 tws = tcg_const_i32(ws);
29333 TCGv_i32 twd = tcg_const_i32(wd);
29334 TCGv_i32 tn = tcg_const_i32(n);
29335 TCGv_i32 tdf = tcg_const_i32(df);
29337 switch (MASK_MSA_ELM(ctx->opcode)) {
29338 case OPC_SLDI_df:
29339 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
29340 break;
29341 case OPC_SPLATI_df:
29342 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
29343 break;
29344 case OPC_INSVE_df:
29345 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
29346 break;
29347 case OPC_COPY_S_df:
29348 case OPC_COPY_U_df:
29349 case OPC_INSERT_df:
29350 #if !defined(TARGET_MIPS64)
29351 /* Double format valid only for MIPS64 */
29352 if (df == DF_DOUBLE) {
29353 generate_exception_end(ctx, EXCP_RI);
29354 break;
29356 if ((MASK_MSA_ELM(ctx->opcode) == OPC_COPY_U_df) &&
29357 (df == DF_WORD)) {
29358 generate_exception_end(ctx, EXCP_RI);
29359 break;
29361 #endif
29362 switch (MASK_MSA_ELM(ctx->opcode)) {
29363 case OPC_COPY_S_df:
29364 if (likely(wd != 0)) {
29365 switch (df) {
29366 case DF_BYTE:
29367 gen_helper_msa_copy_s_b(cpu_env, twd, tws, tn);
29368 break;
29369 case DF_HALF:
29370 gen_helper_msa_copy_s_h(cpu_env, twd, tws, tn);
29371 break;
29372 case DF_WORD:
29373 gen_helper_msa_copy_s_w(cpu_env, twd, tws, tn);
29374 break;
29375 #if defined(TARGET_MIPS64)
29376 case DF_DOUBLE:
29377 gen_helper_msa_copy_s_d(cpu_env, twd, tws, tn);
29378 break;
29379 #endif
29380 default:
29381 assert(0);
29384 break;
29385 case OPC_COPY_U_df:
29386 if (likely(wd != 0)) {
29387 switch (df) {
29388 case DF_BYTE:
29389 gen_helper_msa_copy_u_b(cpu_env, twd, tws, tn);
29390 break;
29391 case DF_HALF:
29392 gen_helper_msa_copy_u_h(cpu_env, twd, tws, tn);
29393 break;
29394 #if defined(TARGET_MIPS64)
29395 case DF_WORD:
29396 gen_helper_msa_copy_u_w(cpu_env, twd, tws, tn);
29397 break;
29398 #endif
29399 default:
29400 assert(0);
29403 break;
29404 case OPC_INSERT_df:
29405 switch (df) {
29406 case DF_BYTE:
29407 gen_helper_msa_insert_b(cpu_env, twd, tws, tn);
29408 break;
29409 case DF_HALF:
29410 gen_helper_msa_insert_h(cpu_env, twd, tws, tn);
29411 break;
29412 case DF_WORD:
29413 gen_helper_msa_insert_w(cpu_env, twd, tws, tn);
29414 break;
29415 #if defined(TARGET_MIPS64)
29416 case DF_DOUBLE:
29417 gen_helper_msa_insert_d(cpu_env, twd, tws, tn);
29418 break;
29419 #endif
29420 default:
29421 assert(0);
29423 break;
29425 break;
29426 default:
29427 MIPS_INVAL("MSA instruction");
29428 generate_exception_end(ctx, EXCP_RI);
29430 tcg_temp_free_i32(twd);
29431 tcg_temp_free_i32(tws);
29432 tcg_temp_free_i32(tn);
29433 tcg_temp_free_i32(tdf);
29436 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
29438 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
29439 uint32_t df = 0, n = 0;
29441 if ((dfn & 0x30) == 0x00) {
29442 n = dfn & 0x0f;
29443 df = DF_BYTE;
29444 } else if ((dfn & 0x38) == 0x20) {
29445 n = dfn & 0x07;
29446 df = DF_HALF;
29447 } else if ((dfn & 0x3c) == 0x30) {
29448 n = dfn & 0x03;
29449 df = DF_WORD;
29450 } else if ((dfn & 0x3e) == 0x38) {
29451 n = dfn & 0x01;
29452 df = DF_DOUBLE;
29453 } else if (dfn == 0x3E) {
29454 /* CTCMSA, CFCMSA, MOVE.V */
29455 gen_msa_elm_3e(env, ctx);
29456 return;
29457 } else {
29458 generate_exception_end(ctx, EXCP_RI);
29459 return;
29462 gen_msa_elm_df(env, ctx, df, n);
29465 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
29467 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
29468 uint8_t df = (ctx->opcode >> 21) & 0x1;
29469 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
29470 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29471 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29473 TCGv_i32 twd = tcg_const_i32(wd);
29474 TCGv_i32 tws = tcg_const_i32(ws);
29475 TCGv_i32 twt = tcg_const_i32(wt);
29476 TCGv_i32 tdf = tcg_temp_new_i32();
29478 /* adjust df value for floating-point instruction */
29479 tcg_gen_movi_i32(tdf, df + 2);
29481 switch (MASK_MSA_3RF(ctx->opcode)) {
29482 case OPC_FCAF_df:
29483 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
29484 break;
29485 case OPC_FADD_df:
29486 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
29487 break;
29488 case OPC_FCUN_df:
29489 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
29490 break;
29491 case OPC_FSUB_df:
29492 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
29493 break;
29494 case OPC_FCOR_df:
29495 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
29496 break;
29497 case OPC_FCEQ_df:
29498 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
29499 break;
29500 case OPC_FMUL_df:
29501 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
29502 break;
29503 case OPC_FCUNE_df:
29504 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
29505 break;
29506 case OPC_FCUEQ_df:
29507 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
29508 break;
29509 case OPC_FDIV_df:
29510 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
29511 break;
29512 case OPC_FCNE_df:
29513 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
29514 break;
29515 case OPC_FCLT_df:
29516 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
29517 break;
29518 case OPC_FMADD_df:
29519 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
29520 break;
29521 case OPC_MUL_Q_df:
29522 tcg_gen_movi_i32(tdf, df + 1);
29523 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
29524 break;
29525 case OPC_FCULT_df:
29526 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
29527 break;
29528 case OPC_FMSUB_df:
29529 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
29530 break;
29531 case OPC_MADD_Q_df:
29532 tcg_gen_movi_i32(tdf, df + 1);
29533 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
29534 break;
29535 case OPC_FCLE_df:
29536 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
29537 break;
29538 case OPC_MSUB_Q_df:
29539 tcg_gen_movi_i32(tdf, df + 1);
29540 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
29541 break;
29542 case OPC_FCULE_df:
29543 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
29544 break;
29545 case OPC_FEXP2_df:
29546 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
29547 break;
29548 case OPC_FSAF_df:
29549 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
29550 break;
29551 case OPC_FEXDO_df:
29552 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
29553 break;
29554 case OPC_FSUN_df:
29555 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
29556 break;
29557 case OPC_FSOR_df:
29558 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
29559 break;
29560 case OPC_FSEQ_df:
29561 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
29562 break;
29563 case OPC_FTQ_df:
29564 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
29565 break;
29566 case OPC_FSUNE_df:
29567 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
29568 break;
29569 case OPC_FSUEQ_df:
29570 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
29571 break;
29572 case OPC_FSNE_df:
29573 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
29574 break;
29575 case OPC_FSLT_df:
29576 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
29577 break;
29578 case OPC_FMIN_df:
29579 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
29580 break;
29581 case OPC_MULR_Q_df:
29582 tcg_gen_movi_i32(tdf, df + 1);
29583 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
29584 break;
29585 case OPC_FSULT_df:
29586 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
29587 break;
29588 case OPC_FMIN_A_df:
29589 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
29590 break;
29591 case OPC_MADDR_Q_df:
29592 tcg_gen_movi_i32(tdf, df + 1);
29593 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
29594 break;
29595 case OPC_FSLE_df:
29596 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
29597 break;
29598 case OPC_FMAX_df:
29599 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
29600 break;
29601 case OPC_MSUBR_Q_df:
29602 tcg_gen_movi_i32(tdf, df + 1);
29603 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
29604 break;
29605 case OPC_FSULE_df:
29606 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
29607 break;
29608 case OPC_FMAX_A_df:
29609 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
29610 break;
29611 default:
29612 MIPS_INVAL("MSA instruction");
29613 generate_exception_end(ctx, EXCP_RI);
29614 break;
29617 tcg_temp_free_i32(twd);
29618 tcg_temp_free_i32(tws);
29619 tcg_temp_free_i32(twt);
29620 tcg_temp_free_i32(tdf);
29623 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
29625 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
29626 (op & (0x7 << 18)))
29627 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
29628 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29629 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29630 uint8_t df = (ctx->opcode >> 16) & 0x3;
29631 TCGv_i32 twd = tcg_const_i32(wd);
29632 TCGv_i32 tws = tcg_const_i32(ws);
29633 TCGv_i32 twt = tcg_const_i32(wt);
29634 TCGv_i32 tdf = tcg_const_i32(df);
29636 switch (MASK_MSA_2R(ctx->opcode)) {
29637 case OPC_FILL_df:
29638 #if !defined(TARGET_MIPS64)
29639 /* Double format valid only for MIPS64 */
29640 if (df == DF_DOUBLE) {
29641 generate_exception_end(ctx, EXCP_RI);
29642 break;
29644 #endif
29645 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
29646 break;
29647 case OPC_NLOC_df:
29648 switch (df) {
29649 case DF_BYTE:
29650 gen_helper_msa_nloc_b(cpu_env, twd, tws);
29651 break;
29652 case DF_HALF:
29653 gen_helper_msa_nloc_h(cpu_env, twd, tws);
29654 break;
29655 case DF_WORD:
29656 gen_helper_msa_nloc_w(cpu_env, twd, tws);
29657 break;
29658 case DF_DOUBLE:
29659 gen_helper_msa_nloc_d(cpu_env, twd, tws);
29660 break;
29662 break;
29663 case OPC_NLZC_df:
29664 switch (df) {
29665 case DF_BYTE:
29666 gen_helper_msa_nlzc_b(cpu_env, twd, tws);
29667 break;
29668 case DF_HALF:
29669 gen_helper_msa_nlzc_h(cpu_env, twd, tws);
29670 break;
29671 case DF_WORD:
29672 gen_helper_msa_nlzc_w(cpu_env, twd, tws);
29673 break;
29674 case DF_DOUBLE:
29675 gen_helper_msa_nlzc_d(cpu_env, twd, tws);
29676 break;
29678 break;
29679 case OPC_PCNT_df:
29680 switch (df) {
29681 case DF_BYTE:
29682 gen_helper_msa_pcnt_b(cpu_env, twd, tws);
29683 break;
29684 case DF_HALF:
29685 gen_helper_msa_pcnt_h(cpu_env, twd, tws);
29686 break;
29687 case DF_WORD:
29688 gen_helper_msa_pcnt_w(cpu_env, twd, tws);
29689 break;
29690 case DF_DOUBLE:
29691 gen_helper_msa_pcnt_d(cpu_env, twd, tws);
29692 break;
29694 break;
29695 default:
29696 MIPS_INVAL("MSA instruction");
29697 generate_exception_end(ctx, EXCP_RI);
29698 break;
29701 tcg_temp_free_i32(twd);
29702 tcg_temp_free_i32(tws);
29703 tcg_temp_free_i32(twt);
29704 tcg_temp_free_i32(tdf);
29707 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
29709 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
29710 (op & (0xf << 17)))
29711 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
29712 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29713 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29714 uint8_t df = (ctx->opcode >> 16) & 0x1;
29715 TCGv_i32 twd = tcg_const_i32(wd);
29716 TCGv_i32 tws = tcg_const_i32(ws);
29717 TCGv_i32 twt = tcg_const_i32(wt);
29718 /* adjust df value for floating-point instruction */
29719 TCGv_i32 tdf = tcg_const_i32(df + 2);
29721 switch (MASK_MSA_2RF(ctx->opcode)) {
29722 case OPC_FCLASS_df:
29723 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
29724 break;
29725 case OPC_FTRUNC_S_df:
29726 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
29727 break;
29728 case OPC_FTRUNC_U_df:
29729 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
29730 break;
29731 case OPC_FSQRT_df:
29732 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
29733 break;
29734 case OPC_FRSQRT_df:
29735 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
29736 break;
29737 case OPC_FRCP_df:
29738 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
29739 break;
29740 case OPC_FRINT_df:
29741 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
29742 break;
29743 case OPC_FLOG2_df:
29744 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
29745 break;
29746 case OPC_FEXUPL_df:
29747 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
29748 break;
29749 case OPC_FEXUPR_df:
29750 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
29751 break;
29752 case OPC_FFQL_df:
29753 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
29754 break;
29755 case OPC_FFQR_df:
29756 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
29757 break;
29758 case OPC_FTINT_S_df:
29759 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
29760 break;
29761 case OPC_FTINT_U_df:
29762 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
29763 break;
29764 case OPC_FFINT_S_df:
29765 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
29766 break;
29767 case OPC_FFINT_U_df:
29768 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
29769 break;
29772 tcg_temp_free_i32(twd);
29773 tcg_temp_free_i32(tws);
29774 tcg_temp_free_i32(twt);
29775 tcg_temp_free_i32(tdf);
29778 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
29780 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
29781 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
29782 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29783 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29784 TCGv_i32 twd = tcg_const_i32(wd);
29785 TCGv_i32 tws = tcg_const_i32(ws);
29786 TCGv_i32 twt = tcg_const_i32(wt);
29788 switch (MASK_MSA_VEC(ctx->opcode)) {
29789 case OPC_AND_V:
29790 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
29791 break;
29792 case OPC_OR_V:
29793 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
29794 break;
29795 case OPC_NOR_V:
29796 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
29797 break;
29798 case OPC_XOR_V:
29799 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
29800 break;
29801 case OPC_BMNZ_V:
29802 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
29803 break;
29804 case OPC_BMZ_V:
29805 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
29806 break;
29807 case OPC_BSEL_V:
29808 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
29809 break;
29810 default:
29811 MIPS_INVAL("MSA instruction");
29812 generate_exception_end(ctx, EXCP_RI);
29813 break;
29816 tcg_temp_free_i32(twd);
29817 tcg_temp_free_i32(tws);
29818 tcg_temp_free_i32(twt);
29821 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
29823 switch (MASK_MSA_VEC(ctx->opcode)) {
29824 case OPC_AND_V:
29825 case OPC_OR_V:
29826 case OPC_NOR_V:
29827 case OPC_XOR_V:
29828 case OPC_BMNZ_V:
29829 case OPC_BMZ_V:
29830 case OPC_BSEL_V:
29831 gen_msa_vec_v(env, ctx);
29832 break;
29833 case OPC_MSA_2R:
29834 gen_msa_2r(env, ctx);
29835 break;
29836 case OPC_MSA_2RF:
29837 gen_msa_2rf(env, ctx);
29838 break;
29839 default:
29840 MIPS_INVAL("MSA instruction");
29841 generate_exception_end(ctx, EXCP_RI);
29842 break;
29846 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
29848 uint32_t opcode = ctx->opcode;
29849 check_insn(ctx, ASE_MSA);
29850 check_msa_access(ctx);
29852 switch (MASK_MSA_MINOR(opcode)) {
29853 case OPC_MSA_I8_00:
29854 case OPC_MSA_I8_01:
29855 case OPC_MSA_I8_02:
29856 gen_msa_i8(env, ctx);
29857 break;
29858 case OPC_MSA_I5_06:
29859 case OPC_MSA_I5_07:
29860 gen_msa_i5(env, ctx);
29861 break;
29862 case OPC_MSA_BIT_09:
29863 case OPC_MSA_BIT_0A:
29864 gen_msa_bit(env, ctx);
29865 break;
29866 case OPC_MSA_3R_0D:
29867 case OPC_MSA_3R_0E:
29868 case OPC_MSA_3R_0F:
29869 case OPC_MSA_3R_10:
29870 case OPC_MSA_3R_11:
29871 case OPC_MSA_3R_12:
29872 case OPC_MSA_3R_13:
29873 case OPC_MSA_3R_14:
29874 case OPC_MSA_3R_15:
29875 gen_msa_3r(env, ctx);
29876 break;
29877 case OPC_MSA_ELM:
29878 gen_msa_elm(env, ctx);
29879 break;
29880 case OPC_MSA_3RF_1A:
29881 case OPC_MSA_3RF_1B:
29882 case OPC_MSA_3RF_1C:
29883 gen_msa_3rf(env, ctx);
29884 break;
29885 case OPC_MSA_VEC:
29886 gen_msa_vec(env, ctx);
29887 break;
29888 case OPC_LD_B:
29889 case OPC_LD_H:
29890 case OPC_LD_W:
29891 case OPC_LD_D:
29892 case OPC_ST_B:
29893 case OPC_ST_H:
29894 case OPC_ST_W:
29895 case OPC_ST_D:
29897 int32_t s10 = sextract32(ctx->opcode, 16, 10);
29898 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
29899 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29900 uint8_t df = (ctx->opcode >> 0) & 0x3;
29902 TCGv_i32 twd = tcg_const_i32(wd);
29903 TCGv taddr = tcg_temp_new();
29904 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
29906 switch (MASK_MSA_MINOR(opcode)) {
29907 case OPC_LD_B:
29908 gen_helper_msa_ld_b(cpu_env, twd, taddr);
29909 break;
29910 case OPC_LD_H:
29911 gen_helper_msa_ld_h(cpu_env, twd, taddr);
29912 break;
29913 case OPC_LD_W:
29914 gen_helper_msa_ld_w(cpu_env, twd, taddr);
29915 break;
29916 case OPC_LD_D:
29917 gen_helper_msa_ld_d(cpu_env, twd, taddr);
29918 break;
29919 case OPC_ST_B:
29920 gen_helper_msa_st_b(cpu_env, twd, taddr);
29921 break;
29922 case OPC_ST_H:
29923 gen_helper_msa_st_h(cpu_env, twd, taddr);
29924 break;
29925 case OPC_ST_W:
29926 gen_helper_msa_st_w(cpu_env, twd, taddr);
29927 break;
29928 case OPC_ST_D:
29929 gen_helper_msa_st_d(cpu_env, twd, taddr);
29930 break;
29933 tcg_temp_free_i32(twd);
29934 tcg_temp_free(taddr);
29936 break;
29937 default:
29938 MIPS_INVAL("MSA instruction");
29939 generate_exception_end(ctx, EXCP_RI);
29940 break;
29945 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
29947 int32_t offset;
29948 int rs, rt, rd, sa;
29949 uint32_t op, op1;
29950 int16_t imm;
29952 /* make sure instructions are on a word boundary */
29953 if (ctx->base.pc_next & 0x3) {
29954 env->CP0_BadVAddr = ctx->base.pc_next;
29955 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
29956 return;
29959 /* Handle blikely not taken case */
29960 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
29961 TCGLabel *l1 = gen_new_label();
29963 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
29964 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
29965 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
29966 gen_set_label(l1);
29969 op = MASK_OP_MAJOR(ctx->opcode);
29970 rs = (ctx->opcode >> 21) & 0x1f;
29971 rt = (ctx->opcode >> 16) & 0x1f;
29972 rd = (ctx->opcode >> 11) & 0x1f;
29973 sa = (ctx->opcode >> 6) & 0x1f;
29974 imm = (int16_t)ctx->opcode;
29975 switch (op) {
29976 case OPC_SPECIAL:
29977 decode_opc_special(env, ctx);
29978 break;
29979 case OPC_SPECIAL2:
29980 #if defined(TARGET_MIPS64)
29981 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
29982 decode_mmi(env, ctx);
29983 #else
29984 if (ctx->insn_flags & ASE_MXU) {
29985 decode_opc_mxu(env, ctx);
29986 #endif
29987 } else {
29988 decode_opc_special2_legacy(env, ctx);
29990 break;
29991 case OPC_SPECIAL3:
29992 #if defined(TARGET_MIPS64)
29993 if (ctx->insn_flags & INSN_R5900) {
29994 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
29995 } else {
29996 decode_opc_special3(env, ctx);
29998 #else
29999 decode_opc_special3(env, ctx);
30000 #endif
30001 break;
30002 case OPC_REGIMM:
30003 op1 = MASK_REGIMM(ctx->opcode);
30004 switch (op1) {
30005 case OPC_BLTZL: /* REGIMM branches */
30006 case OPC_BGEZL:
30007 case OPC_BLTZALL:
30008 case OPC_BGEZALL:
30009 check_insn(ctx, ISA_MIPS2);
30010 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30011 /* Fallthrough */
30012 case OPC_BLTZ:
30013 case OPC_BGEZ:
30014 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
30015 break;
30016 case OPC_BLTZAL:
30017 case OPC_BGEZAL:
30018 if (ctx->insn_flags & ISA_MIPS32R6) {
30019 if (rs == 0) {
30020 /* OPC_NAL, OPC_BAL */
30021 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
30022 } else {
30023 generate_exception_end(ctx, EXCP_RI);
30025 } else {
30026 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
30028 break;
30029 case OPC_TGEI: /* REGIMM traps */
30030 case OPC_TGEIU:
30031 case OPC_TLTI:
30032 case OPC_TLTIU:
30033 case OPC_TEQI:
30035 case OPC_TNEI:
30036 check_insn(ctx, ISA_MIPS2);
30037 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30038 gen_trap(ctx, op1, rs, -1, imm);
30039 break;
30040 case OPC_SIGRIE:
30041 check_insn(ctx, ISA_MIPS32R6);
30042 generate_exception_end(ctx, EXCP_RI);
30043 break;
30044 case OPC_SYNCI:
30045 check_insn(ctx, ISA_MIPS32R2);
30047 * Break the TB to be able to sync copied instructions
30048 * immediately.
30050 ctx->base.is_jmp = DISAS_STOP;
30051 break;
30052 case OPC_BPOSGE32: /* MIPS DSP branch */
30053 #if defined(TARGET_MIPS64)
30054 case OPC_BPOSGE64:
30055 #endif
30056 check_dsp(ctx);
30057 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
30058 break;
30059 #if defined(TARGET_MIPS64)
30060 case OPC_DAHI:
30061 check_insn(ctx, ISA_MIPS32R6);
30062 check_mips_64(ctx);
30063 if (rs != 0) {
30064 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
30066 break;
30067 case OPC_DATI:
30068 check_insn(ctx, ISA_MIPS32R6);
30069 check_mips_64(ctx);
30070 if (rs != 0) {
30071 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
30073 break;
30074 #endif
30075 default: /* Invalid */
30076 MIPS_INVAL("regimm");
30077 generate_exception_end(ctx, EXCP_RI);
30078 break;
30080 break;
30081 case OPC_CP0:
30082 check_cp0_enabled(ctx);
30083 op1 = MASK_CP0(ctx->opcode);
30084 switch (op1) {
30085 case OPC_MFC0:
30086 case OPC_MTC0:
30087 case OPC_MFTR:
30088 case OPC_MTTR:
30089 case OPC_MFHC0:
30090 case OPC_MTHC0:
30091 #if defined(TARGET_MIPS64)
30092 case OPC_DMFC0:
30093 case OPC_DMTC0:
30094 #endif
30095 #ifndef CONFIG_USER_ONLY
30096 gen_cp0(env, ctx, op1, rt, rd);
30097 #endif /* !CONFIG_USER_ONLY */
30098 break;
30099 case OPC_C0:
30100 case OPC_C0_1:
30101 case OPC_C0_2:
30102 case OPC_C0_3:
30103 case OPC_C0_4:
30104 case OPC_C0_5:
30105 case OPC_C0_6:
30106 case OPC_C0_7:
30107 case OPC_C0_8:
30108 case OPC_C0_9:
30109 case OPC_C0_A:
30110 case OPC_C0_B:
30111 case OPC_C0_C:
30112 case OPC_C0_D:
30113 case OPC_C0_E:
30114 case OPC_C0_F:
30115 #ifndef CONFIG_USER_ONLY
30116 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
30117 #endif /* !CONFIG_USER_ONLY */
30118 break;
30119 case OPC_MFMC0:
30120 #ifndef CONFIG_USER_ONLY
30122 uint32_t op2;
30123 TCGv t0 = tcg_temp_new();
30125 op2 = MASK_MFMC0(ctx->opcode);
30126 switch (op2) {
30127 case OPC_DMT:
30128 check_cp0_mt(ctx);
30129 gen_helper_dmt(t0);
30130 gen_store_gpr(t0, rt);
30131 break;
30132 case OPC_EMT:
30133 check_cp0_mt(ctx);
30134 gen_helper_emt(t0);
30135 gen_store_gpr(t0, rt);
30136 break;
30137 case OPC_DVPE:
30138 check_cp0_mt(ctx);
30139 gen_helper_dvpe(t0, cpu_env);
30140 gen_store_gpr(t0, rt);
30141 break;
30142 case OPC_EVPE:
30143 check_cp0_mt(ctx);
30144 gen_helper_evpe(t0, cpu_env);
30145 gen_store_gpr(t0, rt);
30146 break;
30147 case OPC_DVP:
30148 check_insn(ctx, ISA_MIPS32R6);
30149 if (ctx->vp) {
30150 gen_helper_dvp(t0, cpu_env);
30151 gen_store_gpr(t0, rt);
30153 break;
30154 case OPC_EVP:
30155 check_insn(ctx, ISA_MIPS32R6);
30156 if (ctx->vp) {
30157 gen_helper_evp(t0, cpu_env);
30158 gen_store_gpr(t0, rt);
30160 break;
30161 case OPC_DI:
30162 check_insn(ctx, ISA_MIPS32R2);
30163 save_cpu_state(ctx, 1);
30164 gen_helper_di(t0, cpu_env);
30165 gen_store_gpr(t0, rt);
30167 * Stop translation as we may have switched
30168 * the execution mode.
30170 ctx->base.is_jmp = DISAS_STOP;
30171 break;
30172 case OPC_EI:
30173 check_insn(ctx, ISA_MIPS32R2);
30174 save_cpu_state(ctx, 1);
30175 gen_helper_ei(t0, cpu_env);
30176 gen_store_gpr(t0, rt);
30178 * DISAS_STOP isn't sufficient, we need to ensure we break
30179 * out of translated code to check for pending interrupts.
30181 gen_save_pc(ctx->base.pc_next + 4);
30182 ctx->base.is_jmp = DISAS_EXIT;
30183 break;
30184 default: /* Invalid */
30185 MIPS_INVAL("mfmc0");
30186 generate_exception_end(ctx, EXCP_RI);
30187 break;
30189 tcg_temp_free(t0);
30191 #endif /* !CONFIG_USER_ONLY */
30192 break;
30193 case OPC_RDPGPR:
30194 check_insn(ctx, ISA_MIPS32R2);
30195 gen_load_srsgpr(rt, rd);
30196 break;
30197 case OPC_WRPGPR:
30198 check_insn(ctx, ISA_MIPS32R2);
30199 gen_store_srsgpr(rt, rd);
30200 break;
30201 default:
30202 MIPS_INVAL("cp0");
30203 generate_exception_end(ctx, EXCP_RI);
30204 break;
30206 break;
30207 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
30208 if (ctx->insn_flags & ISA_MIPS32R6) {
30209 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
30210 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30211 } else {
30212 /* OPC_ADDI */
30213 /* Arithmetic with immediate opcode */
30214 gen_arith_imm(ctx, op, rt, rs, imm);
30216 break;
30217 case OPC_ADDIU:
30218 gen_arith_imm(ctx, op, rt, rs, imm);
30219 break;
30220 case OPC_SLTI: /* Set on less than with immediate opcode */
30221 case OPC_SLTIU:
30222 gen_slt_imm(ctx, op, rt, rs, imm);
30223 break;
30224 case OPC_ANDI: /* Arithmetic with immediate opcode */
30225 case OPC_LUI: /* OPC_AUI */
30226 case OPC_ORI:
30227 case OPC_XORI:
30228 gen_logic_imm(ctx, op, rt, rs, imm);
30229 break;
30230 case OPC_J: /* Jump */
30231 case OPC_JAL:
30232 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
30233 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
30234 break;
30235 /* Branch */
30236 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
30237 if (ctx->insn_flags & ISA_MIPS32R6) {
30238 if (rt == 0) {
30239 generate_exception_end(ctx, EXCP_RI);
30240 break;
30242 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
30243 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30244 } else {
30245 /* OPC_BLEZL */
30246 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30248 break;
30249 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
30250 if (ctx->insn_flags & ISA_MIPS32R6) {
30251 if (rt == 0) {
30252 generate_exception_end(ctx, EXCP_RI);
30253 break;
30255 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
30256 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30257 } else {
30258 /* OPC_BGTZL */
30259 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30261 break;
30262 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
30263 if (rt == 0) {
30264 /* OPC_BLEZ */
30265 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30266 } else {
30267 check_insn(ctx, ISA_MIPS32R6);
30268 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
30269 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30271 break;
30272 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
30273 if (rt == 0) {
30274 /* OPC_BGTZ */
30275 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30276 } else {
30277 check_insn(ctx, ISA_MIPS32R6);
30278 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
30279 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30281 break;
30282 case OPC_BEQL:
30283 case OPC_BNEL:
30284 check_insn(ctx, ISA_MIPS2);
30285 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30286 /* Fallthrough */
30287 case OPC_BEQ:
30288 case OPC_BNE:
30289 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30290 break;
30291 case OPC_LL: /* Load and stores */
30292 check_insn(ctx, ISA_MIPS2);
30293 if (ctx->insn_flags & INSN_R5900) {
30294 check_insn_opc_user_only(ctx, INSN_R5900);
30296 /* Fallthrough */
30297 case OPC_LWL:
30298 case OPC_LWR:
30299 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30300 /* Fallthrough */
30301 case OPC_LB:
30302 case OPC_LH:
30303 case OPC_LW:
30304 case OPC_LWPC:
30305 case OPC_LBU:
30306 case OPC_LHU:
30307 gen_ld(ctx, op, rt, rs, imm);
30308 break;
30309 case OPC_SWL:
30310 case OPC_SWR:
30311 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30312 /* fall through */
30313 case OPC_SB:
30314 case OPC_SH:
30315 case OPC_SW:
30316 gen_st(ctx, op, rt, rs, imm);
30317 break;
30318 case OPC_SC:
30319 check_insn(ctx, ISA_MIPS2);
30320 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30321 if (ctx->insn_flags & INSN_R5900) {
30322 check_insn_opc_user_only(ctx, INSN_R5900);
30324 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
30325 break;
30326 case OPC_CACHE:
30327 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30328 check_cp0_enabled(ctx);
30329 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
30330 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
30331 gen_cache_operation(ctx, rt, rs, imm);
30333 /* Treat as NOP. */
30334 break;
30335 case OPC_PREF:
30336 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30337 if (ctx->insn_flags & INSN_R5900) {
30338 /* Treat as NOP. */
30339 } else {
30340 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
30341 /* Treat as NOP. */
30343 break;
30345 /* Floating point (COP1). */
30346 case OPC_LWC1:
30347 case OPC_LDC1:
30348 case OPC_SWC1:
30349 case OPC_SDC1:
30350 gen_cop1_ldst(ctx, op, rt, rs, imm);
30351 break;
30353 case OPC_CP1:
30354 op1 = MASK_CP1(ctx->opcode);
30356 switch (op1) {
30357 case OPC_MFHC1:
30358 case OPC_MTHC1:
30359 check_cp1_enabled(ctx);
30360 check_insn(ctx, ISA_MIPS32R2);
30361 /* fall through */
30362 case OPC_MFC1:
30363 case OPC_CFC1:
30364 case OPC_MTC1:
30365 case OPC_CTC1:
30366 check_cp1_enabled(ctx);
30367 gen_cp1(ctx, op1, rt, rd);
30368 break;
30369 #if defined(TARGET_MIPS64)
30370 case OPC_DMFC1:
30371 case OPC_DMTC1:
30372 check_cp1_enabled(ctx);
30373 check_insn(ctx, ISA_MIPS3);
30374 check_mips_64(ctx);
30375 gen_cp1(ctx, op1, rt, rd);
30376 break;
30377 #endif
30378 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
30379 check_cp1_enabled(ctx);
30380 if (ctx->insn_flags & ISA_MIPS32R6) {
30381 /* OPC_BC1EQZ */
30382 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
30383 rt, imm << 2, 4);
30384 } else {
30385 /* OPC_BC1ANY2 */
30386 check_cop1x(ctx);
30387 check_insn(ctx, ASE_MIPS3D);
30388 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
30389 (rt >> 2) & 0x7, imm << 2);
30391 break;
30392 case OPC_BC1NEZ:
30393 check_cp1_enabled(ctx);
30394 check_insn(ctx, ISA_MIPS32R6);
30395 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
30396 rt, imm << 2, 4);
30397 break;
30398 case OPC_BC1ANY4:
30399 check_cp1_enabled(ctx);
30400 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30401 check_cop1x(ctx);
30402 check_insn(ctx, ASE_MIPS3D);
30403 /* fall through */
30404 case OPC_BC1:
30405 check_cp1_enabled(ctx);
30406 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30407 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
30408 (rt >> 2) & 0x7, imm << 2);
30409 break;
30410 case OPC_PS_FMT:
30411 check_ps(ctx);
30412 /* fall through */
30413 case OPC_S_FMT:
30414 case OPC_D_FMT:
30415 check_cp1_enabled(ctx);
30416 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
30417 (imm >> 8) & 0x7);
30418 break;
30419 case OPC_W_FMT:
30420 case OPC_L_FMT:
30422 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
30423 check_cp1_enabled(ctx);
30424 if (ctx->insn_flags & ISA_MIPS32R6) {
30425 switch (r6_op) {
30426 case R6_OPC_CMP_AF_S:
30427 case R6_OPC_CMP_UN_S:
30428 case R6_OPC_CMP_EQ_S:
30429 case R6_OPC_CMP_UEQ_S:
30430 case R6_OPC_CMP_LT_S:
30431 case R6_OPC_CMP_ULT_S:
30432 case R6_OPC_CMP_LE_S:
30433 case R6_OPC_CMP_ULE_S:
30434 case R6_OPC_CMP_SAF_S:
30435 case R6_OPC_CMP_SUN_S:
30436 case R6_OPC_CMP_SEQ_S:
30437 case R6_OPC_CMP_SEUQ_S:
30438 case R6_OPC_CMP_SLT_S:
30439 case R6_OPC_CMP_SULT_S:
30440 case R6_OPC_CMP_SLE_S:
30441 case R6_OPC_CMP_SULE_S:
30442 case R6_OPC_CMP_OR_S:
30443 case R6_OPC_CMP_UNE_S:
30444 case R6_OPC_CMP_NE_S:
30445 case R6_OPC_CMP_SOR_S:
30446 case R6_OPC_CMP_SUNE_S:
30447 case R6_OPC_CMP_SNE_S:
30448 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
30449 break;
30450 case R6_OPC_CMP_AF_D:
30451 case R6_OPC_CMP_UN_D:
30452 case R6_OPC_CMP_EQ_D:
30453 case R6_OPC_CMP_UEQ_D:
30454 case R6_OPC_CMP_LT_D:
30455 case R6_OPC_CMP_ULT_D:
30456 case R6_OPC_CMP_LE_D:
30457 case R6_OPC_CMP_ULE_D:
30458 case R6_OPC_CMP_SAF_D:
30459 case R6_OPC_CMP_SUN_D:
30460 case R6_OPC_CMP_SEQ_D:
30461 case R6_OPC_CMP_SEUQ_D:
30462 case R6_OPC_CMP_SLT_D:
30463 case R6_OPC_CMP_SULT_D:
30464 case R6_OPC_CMP_SLE_D:
30465 case R6_OPC_CMP_SULE_D:
30466 case R6_OPC_CMP_OR_D:
30467 case R6_OPC_CMP_UNE_D:
30468 case R6_OPC_CMP_NE_D:
30469 case R6_OPC_CMP_SOR_D:
30470 case R6_OPC_CMP_SUNE_D:
30471 case R6_OPC_CMP_SNE_D:
30472 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
30473 break;
30474 default:
30475 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
30476 rt, rd, sa, (imm >> 8) & 0x7);
30478 break;
30480 } else {
30481 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
30482 (imm >> 8) & 0x7);
30484 break;
30486 case OPC_BZ_V:
30487 case OPC_BNZ_V:
30488 case OPC_BZ_B:
30489 case OPC_BZ_H:
30490 case OPC_BZ_W:
30491 case OPC_BZ_D:
30492 case OPC_BNZ_B:
30493 case OPC_BNZ_H:
30494 case OPC_BNZ_W:
30495 case OPC_BNZ_D:
30496 check_insn(ctx, ASE_MSA);
30497 gen_msa_branch(env, ctx, op1);
30498 break;
30499 default:
30500 MIPS_INVAL("cp1");
30501 generate_exception_end(ctx, EXCP_RI);
30502 break;
30504 break;
30506 /* Compact branches [R6] and COP2 [non-R6] */
30507 case OPC_BC: /* OPC_LWC2 */
30508 case OPC_BALC: /* OPC_SWC2 */
30509 if (ctx->insn_flags & ISA_MIPS32R6) {
30510 /* OPC_BC, OPC_BALC */
30511 gen_compute_compact_branch(ctx, op, 0, 0,
30512 sextract32(ctx->opcode << 2, 0, 28));
30513 } else {
30514 /* OPC_LWC2, OPC_SWC2 */
30515 /* COP2: Not implemented. */
30516 generate_exception_err(ctx, EXCP_CpU, 2);
30518 break;
30519 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
30520 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
30521 if (ctx->insn_flags & ISA_MIPS32R6) {
30522 if (rs != 0) {
30523 /* OPC_BEQZC, OPC_BNEZC */
30524 gen_compute_compact_branch(ctx, op, rs, 0,
30525 sextract32(ctx->opcode << 2, 0, 23));
30526 } else {
30527 /* OPC_JIC, OPC_JIALC */
30528 gen_compute_compact_branch(ctx, op, 0, rt, imm);
30530 } else {
30531 /* OPC_LWC2, OPC_SWC2 */
30532 /* COP2: Not implemented. */
30533 generate_exception_err(ctx, EXCP_CpU, 2);
30535 break;
30536 case OPC_CP2:
30537 check_insn(ctx, INSN_LOONGSON2F);
30538 /* Note that these instructions use different fields. */
30539 gen_loongson_multimedia(ctx, sa, rd, rt);
30540 break;
30542 case OPC_CP3:
30543 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30544 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
30545 check_cp1_enabled(ctx);
30546 op1 = MASK_CP3(ctx->opcode);
30547 switch (op1) {
30548 case OPC_LUXC1:
30549 case OPC_SUXC1:
30550 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
30551 /* Fallthrough */
30552 case OPC_LWXC1:
30553 case OPC_LDXC1:
30554 case OPC_SWXC1:
30555 case OPC_SDXC1:
30556 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
30557 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
30558 break;
30559 case OPC_PREFX:
30560 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
30561 /* Treat as NOP. */
30562 break;
30563 case OPC_ALNV_PS:
30564 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
30565 /* Fallthrough */
30566 case OPC_MADD_S:
30567 case OPC_MADD_D:
30568 case OPC_MADD_PS:
30569 case OPC_MSUB_S:
30570 case OPC_MSUB_D:
30571 case OPC_MSUB_PS:
30572 case OPC_NMADD_S:
30573 case OPC_NMADD_D:
30574 case OPC_NMADD_PS:
30575 case OPC_NMSUB_S:
30576 case OPC_NMSUB_D:
30577 case OPC_NMSUB_PS:
30578 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
30579 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
30580 break;
30581 default:
30582 MIPS_INVAL("cp3");
30583 generate_exception_end(ctx, EXCP_RI);
30584 break;
30586 } else {
30587 generate_exception_err(ctx, EXCP_CpU, 1);
30589 break;
30591 #if defined(TARGET_MIPS64)
30592 /* MIPS64 opcodes */
30593 case OPC_LLD:
30594 if (ctx->insn_flags & INSN_R5900) {
30595 check_insn_opc_user_only(ctx, INSN_R5900);
30597 /* fall through */
30598 case OPC_LDL:
30599 case OPC_LDR:
30600 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30601 /* fall through */
30602 case OPC_LWU:
30603 case OPC_LD:
30604 check_insn(ctx, ISA_MIPS3);
30605 check_mips_64(ctx);
30606 gen_ld(ctx, op, rt, rs, imm);
30607 break;
30608 case OPC_SDL:
30609 case OPC_SDR:
30610 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30611 /* fall through */
30612 case OPC_SD:
30613 check_insn(ctx, ISA_MIPS3);
30614 check_mips_64(ctx);
30615 gen_st(ctx, op, rt, rs, imm);
30616 break;
30617 case OPC_SCD:
30618 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30619 check_insn(ctx, ISA_MIPS3);
30620 if (ctx->insn_flags & INSN_R5900) {
30621 check_insn_opc_user_only(ctx, INSN_R5900);
30623 check_mips_64(ctx);
30624 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
30625 break;
30626 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
30627 if (ctx->insn_flags & ISA_MIPS32R6) {
30628 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
30629 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30630 } else {
30631 /* OPC_DADDI */
30632 check_insn(ctx, ISA_MIPS3);
30633 check_mips_64(ctx);
30634 gen_arith_imm(ctx, op, rt, rs, imm);
30636 break;
30637 case OPC_DADDIU:
30638 check_insn(ctx, ISA_MIPS3);
30639 check_mips_64(ctx);
30640 gen_arith_imm(ctx, op, rt, rs, imm);
30641 break;
30642 #else
30643 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
30644 if (ctx->insn_flags & ISA_MIPS32R6) {
30645 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30646 } else {
30647 MIPS_INVAL("major opcode");
30648 generate_exception_end(ctx, EXCP_RI);
30650 break;
30651 #endif
30652 case OPC_DAUI: /* OPC_JALX */
30653 if (ctx->insn_flags & ISA_MIPS32R6) {
30654 #if defined(TARGET_MIPS64)
30655 /* OPC_DAUI */
30656 check_mips_64(ctx);
30657 if (rs == 0) {
30658 generate_exception(ctx, EXCP_RI);
30659 } else if (rt != 0) {
30660 TCGv t0 = tcg_temp_new();
30661 gen_load_gpr(t0, rs);
30662 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
30663 tcg_temp_free(t0);
30665 #else
30666 generate_exception_end(ctx, EXCP_RI);
30667 MIPS_INVAL("major opcode");
30668 #endif
30669 } else {
30670 /* OPC_JALX */
30671 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
30672 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
30673 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
30675 break;
30676 case OPC_MSA: /* OPC_MDMX */
30677 if (ctx->insn_flags & INSN_R5900) {
30678 #if defined(TARGET_MIPS64)
30679 gen_mmi_lq(env, ctx); /* MMI_OPC_LQ */
30680 #endif
30681 } else {
30682 /* MDMX: Not implemented. */
30683 gen_msa(env, ctx);
30685 break;
30686 case OPC_PCREL:
30687 check_insn(ctx, ISA_MIPS32R6);
30688 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
30689 break;
30690 default: /* Invalid */
30691 MIPS_INVAL("major opcode");
30692 generate_exception_end(ctx, EXCP_RI);
30693 break;
30697 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
30699 DisasContext *ctx = container_of(dcbase, DisasContext, base);
30700 CPUMIPSState *env = cs->env_ptr;
30702 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
30703 ctx->saved_pc = -1;
30704 ctx->insn_flags = env->insn_flags;
30705 ctx->CP0_Config1 = env->CP0_Config1;
30706 ctx->CP0_Config2 = env->CP0_Config2;
30707 ctx->CP0_Config3 = env->CP0_Config3;
30708 ctx->CP0_Config5 = env->CP0_Config5;
30709 ctx->btarget = 0;
30710 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
30711 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
30712 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
30713 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
30714 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
30715 ctx->PAMask = env->PAMask;
30716 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
30717 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
30718 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
30719 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
30720 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
30721 /* Restore delay slot state from the tb context. */
30722 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
30723 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
30724 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
30725 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
30726 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
30727 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
30728 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
30729 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
30730 restore_cpu_state(env, ctx);
30731 #ifdef CONFIG_USER_ONLY
30732 ctx->mem_idx = MIPS_HFLAG_UM;
30733 #else
30734 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
30735 #endif
30736 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
30737 MO_UNALN : MO_ALIGN;
30739 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
30740 ctx->hflags);
30743 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
30747 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
30749 DisasContext *ctx = container_of(dcbase, DisasContext, base);
30751 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
30752 ctx->btarget);
30755 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
30756 const CPUBreakpoint *bp)
30758 DisasContext *ctx = container_of(dcbase, DisasContext, base);
30760 save_cpu_state(ctx, 1);
30761 ctx->base.is_jmp = DISAS_NORETURN;
30762 gen_helper_raise_exception_debug(cpu_env);
30764 * The address covered by the breakpoint must be included in
30765 * [tb->pc, tb->pc + tb->size) in order to for it to be
30766 * properly cleared -- thus we increment the PC here so that
30767 * the logic setting tb->size below does the right thing.
30769 ctx->base.pc_next += 4;
30770 return true;
30773 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
30775 CPUMIPSState *env = cs->env_ptr;
30776 DisasContext *ctx = container_of(dcbase, DisasContext, base);
30777 int insn_bytes;
30778 int is_slot;
30780 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
30781 if (ctx->insn_flags & ISA_NANOMIPS32) {
30782 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
30783 insn_bytes = decode_nanomips_opc(env, ctx);
30784 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
30785 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
30786 insn_bytes = 4;
30787 decode_opc(env, ctx);
30788 } else if (ctx->insn_flags & ASE_MICROMIPS) {
30789 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
30790 insn_bytes = decode_micromips_opc(env, ctx);
30791 } else if (ctx->insn_flags & ASE_MIPS16) {
30792 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
30793 insn_bytes = decode_mips16_opc(env, ctx);
30794 } else {
30795 generate_exception_end(ctx, EXCP_RI);
30796 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
30797 return;
30800 if (ctx->hflags & MIPS_HFLAG_BMASK) {
30801 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
30802 MIPS_HFLAG_FBNSLOT))) {
30804 * Force to generate branch as there is neither delay nor
30805 * forbidden slot.
30807 is_slot = 1;
30809 if ((ctx->hflags & MIPS_HFLAG_M16) &&
30810 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
30812 * Force to generate branch as microMIPS R6 doesn't restrict
30813 * branches in the forbidden slot.
30815 is_slot = 1;
30818 if (is_slot) {
30819 gen_branch(ctx, insn_bytes);
30821 ctx->base.pc_next += insn_bytes;
30823 if (ctx->base.is_jmp != DISAS_NEXT) {
30824 return;
30827 * Execute a branch and its delay slot as a single instruction.
30828 * This is what GDB expects and is consistent with what the
30829 * hardware does (e.g. if a delay slot instruction faults, the
30830 * reported PC is the PC of the branch).
30832 if (ctx->base.singlestep_enabled &&
30833 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
30834 ctx->base.is_jmp = DISAS_TOO_MANY;
30836 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
30837 ctx->base.is_jmp = DISAS_TOO_MANY;
30841 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
30843 DisasContext *ctx = container_of(dcbase, DisasContext, base);
30845 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
30846 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
30847 gen_helper_raise_exception_debug(cpu_env);
30848 } else {
30849 switch (ctx->base.is_jmp) {
30850 case DISAS_STOP:
30851 gen_save_pc(ctx->base.pc_next);
30852 tcg_gen_lookup_and_goto_ptr();
30853 break;
30854 case DISAS_NEXT:
30855 case DISAS_TOO_MANY:
30856 save_cpu_state(ctx, 0);
30857 gen_goto_tb(ctx, 0, ctx->base.pc_next);
30858 break;
30859 case DISAS_EXIT:
30860 tcg_gen_exit_tb(NULL, 0);
30861 break;
30862 case DISAS_NORETURN:
30863 break;
30864 default:
30865 g_assert_not_reached();
30870 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
30872 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
30873 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
30876 static const TranslatorOps mips_tr_ops = {
30877 .init_disas_context = mips_tr_init_disas_context,
30878 .tb_start = mips_tr_tb_start,
30879 .insn_start = mips_tr_insn_start,
30880 .breakpoint_check = mips_tr_breakpoint_check,
30881 .translate_insn = mips_tr_translate_insn,
30882 .tb_stop = mips_tr_tb_stop,
30883 .disas_log = mips_tr_disas_log,
30886 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
30888 DisasContext ctx;
30890 translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
30893 static void fpu_dump_state(CPUMIPSState *env, FILE * f, int flags)
30895 int i;
30896 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
30898 #define printfpr(fp) \
30899 do { \
30900 if (is_fpu64) \
30901 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
30902 " fd:%13g fs:%13g psu: %13g\n", \
30903 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
30904 (double)(fp)->fd, \
30905 (double)(fp)->fs[FP_ENDIAN_IDX], \
30906 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
30907 else { \
30908 fpr_t tmp; \
30909 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
30910 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
30911 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
30912 " fd:%13g fs:%13g psu:%13g\n", \
30913 tmp.w[FP_ENDIAN_IDX], tmp.d, \
30914 (double)tmp.fd, \
30915 (double)tmp.fs[FP_ENDIAN_IDX], \
30916 (double)tmp.fs[!FP_ENDIAN_IDX]); \
30918 } while (0)
30921 qemu_fprintf(f,
30922 "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
30923 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
30924 get_float_exception_flags(&env->active_fpu.fp_status));
30925 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
30926 qemu_fprintf(f, "%3s: ", fregnames[i]);
30927 printfpr(&env->active_fpu.fpr[i]);
30930 #undef printfpr
30933 void mips_cpu_dump_state(CPUState *cs, FILE *f, int flags)
30935 MIPSCPU *cpu = MIPS_CPU(cs);
30936 CPUMIPSState *env = &cpu->env;
30937 int i;
30939 qemu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
30940 " LO=0x" TARGET_FMT_lx " ds %04x "
30941 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
30942 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
30943 env->hflags, env->btarget, env->bcond);
30944 for (i = 0; i < 32; i++) {
30945 if ((i & 3) == 0) {
30946 qemu_fprintf(f, "GPR%02d:", i);
30948 qemu_fprintf(f, " %s " TARGET_FMT_lx,
30949 regnames[i], env->active_tc.gpr[i]);
30950 if ((i & 3) == 3) {
30951 qemu_fprintf(f, "\n");
30955 qemu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x"
30956 TARGET_FMT_lx "\n",
30957 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
30958 qemu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
30959 PRIx64 "\n",
30960 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
30961 qemu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
30962 env->CP0_Config2, env->CP0_Config3);
30963 qemu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
30964 env->CP0_Config4, env->CP0_Config5);
30965 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
30966 fpu_dump_state(env, f, flags);
30970 void mips_tcg_init(void)
30972 int i;
30974 cpu_gpr[0] = NULL;
30975 for (i = 1; i < 32; i++)
30976 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
30977 offsetof(CPUMIPSState,
30978 active_tc.gpr[i]),
30979 regnames[i]);
30981 for (i = 0; i < 32; i++) {
30982 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
30983 msa_wr_d[i * 2] =
30984 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
30986 * The scalar floating-point unit (FPU) registers are mapped on
30987 * the MSA vector registers.
30989 fpu_f64[i] = msa_wr_d[i * 2];
30990 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
30991 msa_wr_d[i * 2 + 1] =
30992 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
30995 cpu_PC = tcg_global_mem_new(cpu_env,
30996 offsetof(CPUMIPSState, active_tc.PC), "PC");
30997 for (i = 0; i < MIPS_DSP_ACC; i++) {
30998 cpu_HI[i] = tcg_global_mem_new(cpu_env,
30999 offsetof(CPUMIPSState, active_tc.HI[i]),
31000 regnames_HI[i]);
31001 cpu_LO[i] = tcg_global_mem_new(cpu_env,
31002 offsetof(CPUMIPSState, active_tc.LO[i]),
31003 regnames_LO[i]);
31005 cpu_dspctrl = tcg_global_mem_new(cpu_env,
31006 offsetof(CPUMIPSState,
31007 active_tc.DSPControl),
31008 "DSPControl");
31009 bcond = tcg_global_mem_new(cpu_env,
31010 offsetof(CPUMIPSState, bcond), "bcond");
31011 btarget = tcg_global_mem_new(cpu_env,
31012 offsetof(CPUMIPSState, btarget), "btarget");
31013 hflags = tcg_global_mem_new_i32(cpu_env,
31014 offsetof(CPUMIPSState, hflags), "hflags");
31016 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
31017 offsetof(CPUMIPSState, active_fpu.fcr0),
31018 "fcr0");
31019 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
31020 offsetof(CPUMIPSState, active_fpu.fcr31),
31021 "fcr31");
31022 cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
31023 "lladdr");
31024 cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
31025 "llval");
31027 #if defined(TARGET_MIPS64)
31028 cpu_mmr[0] = NULL;
31029 for (i = 1; i < 32; i++) {
31030 cpu_mmr[i] = tcg_global_mem_new_i64(cpu_env,
31031 offsetof(CPUMIPSState,
31032 active_tc.mmr[i]),
31033 regnames[i]);
31035 #endif
31037 #if !defined(TARGET_MIPS64)
31038 for (i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
31039 mxu_gpr[i] = tcg_global_mem_new(cpu_env,
31040 offsetof(CPUMIPSState,
31041 active_tc.mxu_gpr[i]),
31042 mxuregnames[i]);
31045 mxu_CR = tcg_global_mem_new(cpu_env,
31046 offsetof(CPUMIPSState, active_tc.mxu_cr),
31047 mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
31048 #endif
31051 #include "translate_init.inc.c"
31053 void cpu_mips_realize_env(CPUMIPSState *env)
31055 env->exception_base = (int32_t)0xBFC00000;
31057 #ifndef CONFIG_USER_ONLY
31058 mmu_init(env, env->cpu_model);
31059 #endif
31060 fpu_init(env, env->cpu_model);
31061 mvp_init(env, env->cpu_model);
31064 bool cpu_supports_cps_smp(const char *cpu_type)
31066 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
31067 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
31070 bool cpu_supports_isa(const char *cpu_type, uint64_t isa)
31072 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
31073 return (mcc->cpu_def->insn_flags & isa) != 0;
31076 void cpu_set_exception_base(int vp_index, target_ulong address)
31078 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
31079 vp->env.exception_base = address;
31082 void cpu_state_reset(CPUMIPSState *env)
31084 CPUState *cs = env_cpu(env);
31086 /* Reset registers to their default values */
31087 env->CP0_PRid = env->cpu_model->CP0_PRid;
31088 env->CP0_Config0 = env->cpu_model->CP0_Config0;
31089 #ifdef TARGET_WORDS_BIGENDIAN
31090 env->CP0_Config0 |= (1 << CP0C0_BE);
31091 #endif
31092 env->CP0_Config1 = env->cpu_model->CP0_Config1;
31093 env->CP0_Config2 = env->cpu_model->CP0_Config2;
31094 env->CP0_Config3 = env->cpu_model->CP0_Config3;
31095 env->CP0_Config4 = env->cpu_model->CP0_Config4;
31096 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
31097 env->CP0_Config5 = env->cpu_model->CP0_Config5;
31098 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
31099 env->CP0_Config6 = env->cpu_model->CP0_Config6;
31100 env->CP0_Config7 = env->cpu_model->CP0_Config7;
31101 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
31102 << env->cpu_model->CP0_LLAddr_shift;
31103 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
31104 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
31105 env->CCRes = env->cpu_model->CCRes;
31106 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
31107 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
31108 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
31109 env->current_tc = 0;
31110 env->SEGBITS = env->cpu_model->SEGBITS;
31111 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
31112 #if defined(TARGET_MIPS64)
31113 if (env->cpu_model->insn_flags & ISA_MIPS3) {
31114 env->SEGMask |= 3ULL << 62;
31116 #endif
31117 env->PABITS = env->cpu_model->PABITS;
31118 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
31119 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
31120 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
31121 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
31122 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
31123 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
31124 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
31125 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
31126 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
31127 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
31128 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
31129 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
31130 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
31131 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
31132 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
31133 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
31134 env->msair = env->cpu_model->MSAIR;
31135 env->insn_flags = env->cpu_model->insn_flags;
31137 #if defined(CONFIG_USER_ONLY)
31138 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
31139 # ifdef TARGET_MIPS64
31140 /* Enable 64-bit register mode. */
31141 env->CP0_Status |= (1 << CP0St_PX);
31142 # endif
31143 # ifdef TARGET_ABI_MIPSN64
31144 /* Enable 64-bit address mode. */
31145 env->CP0_Status |= (1 << CP0St_UX);
31146 # endif
31148 * Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
31149 * hardware registers.
31151 env->CP0_HWREna |= 0x0000000F;
31152 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
31153 env->CP0_Status |= (1 << CP0St_CU1);
31155 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
31156 env->CP0_Status |= (1 << CP0St_MX);
31158 # if defined(TARGET_MIPS64)
31159 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
31160 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
31161 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
31162 env->CP0_Status |= (1 << CP0St_FR);
31164 # endif
31165 #else
31166 if (env->hflags & MIPS_HFLAG_BMASK) {
31168 * If the exception was raised from a delay slot,
31169 * come back to the jump.
31171 env->CP0_ErrorEPC = (env->active_tc.PC
31172 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
31173 } else {
31174 env->CP0_ErrorEPC = env->active_tc.PC;
31176 env->active_tc.PC = env->exception_base;
31177 env->CP0_Random = env->tlb->nb_tlb - 1;
31178 env->tlb->tlb_in_use = env->tlb->nb_tlb;
31179 env->CP0_Wired = 0;
31180 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
31181 env->CP0_EBase = (cs->cpu_index & 0x3FF);
31182 if (mips_um_ksegs_enabled()) {
31183 env->CP0_EBase |= 0x40000000;
31184 } else {
31185 env->CP0_EBase |= (int32_t)0x80000000;
31187 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
31188 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
31190 env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
31191 0x3ff : 0xff;
31192 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
31194 * Vectored interrupts not implemented, timer on int 7,
31195 * no performance counters.
31197 env->CP0_IntCtl = 0xe0000000;
31199 int i;
31201 for (i = 0; i < 7; i++) {
31202 env->CP0_WatchLo[i] = 0;
31203 env->CP0_WatchHi[i] = 0x80000000;
31205 env->CP0_WatchLo[7] = 0;
31206 env->CP0_WatchHi[7] = 0;
31208 /* Count register increments in debug mode, EJTAG version 1 */
31209 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
31211 cpu_mips_store_count(env, 1);
31213 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
31214 int i;
31216 /* Only TC0 on VPE 0 starts as active. */
31217 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
31218 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
31219 env->tcs[i].CP0_TCHalt = 1;
31221 env->active_tc.CP0_TCHalt = 1;
31222 cs->halted = 1;
31224 if (cs->cpu_index == 0) {
31225 /* VPE0 starts up enabled. */
31226 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
31227 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
31229 /* TC0 starts up unhalted. */
31230 cs->halted = 0;
31231 env->active_tc.CP0_TCHalt = 0;
31232 env->tcs[0].CP0_TCHalt = 0;
31233 /* With thread 0 active. */
31234 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
31235 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
31240 * Configure default legacy segmentation control. We use this regardless of
31241 * whether segmentation control is presented to the guest.
31243 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
31244 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
31245 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
31246 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
31247 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
31248 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
31249 (2 << CP0SC_C);
31250 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
31251 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
31252 (3 << CP0SC_C)) << 16;
31253 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
31254 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
31255 (1 << CP0SC_EU) | (2 << CP0SC_C);
31256 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
31257 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
31258 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
31259 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
31260 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
31261 #endif
31262 if ((env->insn_flags & ISA_MIPS32R6) &&
31263 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
31264 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
31265 env->CP0_Status |= (1 << CP0St_FR);
31268 if (env->insn_flags & ISA_MIPS32R6) {
31269 /* PTW = 1 */
31270 env->CP0_PWSize = 0x40;
31271 /* GDI = 12 */
31272 /* UDI = 12 */
31273 /* MDI = 12 */
31274 /* PRI = 12 */
31275 /* PTEI = 2 */
31276 env->CP0_PWField = 0x0C30C302;
31277 } else {
31278 /* GDI = 0 */
31279 /* UDI = 0 */
31280 /* MDI = 0 */
31281 /* PRI = 0 */
31282 /* PTEI = 2 */
31283 env->CP0_PWField = 0x02;
31286 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
31287 /* microMIPS on reset when Config3.ISA is 3 */
31288 env->hflags |= MIPS_HFLAG_M16;
31291 /* MSA */
31292 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
31293 msa_reset(env);
31296 compute_hflags(env);
31297 restore_fp_status(env);
31298 restore_pamask(env);
31299 cs->exception_index = EXCP_NONE;
31301 if (semihosting_get_argc()) {
31302 /* UHI interface can be used to obtain argc and argv */
31303 env->active_tc.gpr[4] = -1;
31307 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
31308 target_ulong *data)
31310 env->active_tc.PC = data[0];
31311 env->hflags &= ~MIPS_HFLAG_BMASK;
31312 env->hflags |= data[1];
31313 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
31314 case MIPS_HFLAG_BR:
31315 break;
31316 case MIPS_HFLAG_BC:
31317 case MIPS_HFLAG_BL:
31318 case MIPS_HFLAG_B:
31319 env->btarget = data[2];
31320 break;