target/s390x: Fix typo
[qemu/ar7.git] / target / mips / translate.c
blob8b4a072ecb8eca662d8c292fc73354a47a6a93e4
1 /*
2 * MIPS32 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 "disas/disas.h"
27 #include "exec/exec-all.h"
28 #include "tcg-op.h"
29 #include "exec/cpu_ldst.h"
31 #include "exec/helper-proto.h"
32 #include "exec/helper-gen.h"
33 #include "sysemu/kvm.h"
34 #include "exec/semihost.h"
36 #include "trace-tcg.h"
37 #include "exec/log.h"
39 #define MIPS_DEBUG_DISAS 0
41 /* MIPS major opcodes */
42 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
44 enum {
45 /* indirect opcode tables */
46 OPC_SPECIAL = (0x00 << 26),
47 OPC_REGIMM = (0x01 << 26),
48 OPC_CP0 = (0x10 << 26),
49 OPC_CP1 = (0x11 << 26),
50 OPC_CP2 = (0x12 << 26),
51 OPC_CP3 = (0x13 << 26),
52 OPC_SPECIAL2 = (0x1C << 26),
53 OPC_SPECIAL3 = (0x1F << 26),
54 /* arithmetic with immediate */
55 OPC_ADDI = (0x08 << 26),
56 OPC_ADDIU = (0x09 << 26),
57 OPC_SLTI = (0x0A << 26),
58 OPC_SLTIU = (0x0B << 26),
59 /* logic with immediate */
60 OPC_ANDI = (0x0C << 26),
61 OPC_ORI = (0x0D << 26),
62 OPC_XORI = (0x0E << 26),
63 OPC_LUI = (0x0F << 26),
64 /* arithmetic with immediate */
65 OPC_DADDI = (0x18 << 26),
66 OPC_DADDIU = (0x19 << 26),
67 /* Jump and branches */
68 OPC_J = (0x02 << 26),
69 OPC_JAL = (0x03 << 26),
70 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
71 OPC_BEQL = (0x14 << 26),
72 OPC_BNE = (0x05 << 26),
73 OPC_BNEL = (0x15 << 26),
74 OPC_BLEZ = (0x06 << 26),
75 OPC_BLEZL = (0x16 << 26),
76 OPC_BGTZ = (0x07 << 26),
77 OPC_BGTZL = (0x17 << 26),
78 OPC_JALX = (0x1D << 26),
79 OPC_DAUI = (0x1D << 26),
80 /* Load and stores */
81 OPC_LDL = (0x1A << 26),
82 OPC_LDR = (0x1B << 26),
83 OPC_LB = (0x20 << 26),
84 OPC_LH = (0x21 << 26),
85 OPC_LWL = (0x22 << 26),
86 OPC_LW = (0x23 << 26),
87 OPC_LWPC = OPC_LW | 0x5,
88 OPC_LBU = (0x24 << 26),
89 OPC_LHU = (0x25 << 26),
90 OPC_LWR = (0x26 << 26),
91 OPC_LWU = (0x27 << 26),
92 OPC_SB = (0x28 << 26),
93 OPC_SH = (0x29 << 26),
94 OPC_SWL = (0x2A << 26),
95 OPC_SW = (0x2B << 26),
96 OPC_SDL = (0x2C << 26),
97 OPC_SDR = (0x2D << 26),
98 OPC_SWR = (0x2E << 26),
99 OPC_LL = (0x30 << 26),
100 OPC_LLD = (0x34 << 26),
101 OPC_LD = (0x37 << 26),
102 OPC_LDPC = OPC_LD | 0x5,
103 OPC_SC = (0x38 << 26),
104 OPC_SCD = (0x3C << 26),
105 OPC_SD = (0x3F << 26),
106 /* Floating point load/store */
107 OPC_LWC1 = (0x31 << 26),
108 OPC_LWC2 = (0x32 << 26),
109 OPC_LDC1 = (0x35 << 26),
110 OPC_LDC2 = (0x36 << 26),
111 OPC_SWC1 = (0x39 << 26),
112 OPC_SWC2 = (0x3A << 26),
113 OPC_SDC1 = (0x3D << 26),
114 OPC_SDC2 = (0x3E << 26),
115 /* Compact Branches */
116 OPC_BLEZALC = (0x06 << 26),
117 OPC_BGEZALC = (0x06 << 26),
118 OPC_BGEUC = (0x06 << 26),
119 OPC_BGTZALC = (0x07 << 26),
120 OPC_BLTZALC = (0x07 << 26),
121 OPC_BLTUC = (0x07 << 26),
122 OPC_BOVC = (0x08 << 26),
123 OPC_BEQZALC = (0x08 << 26),
124 OPC_BEQC = (0x08 << 26),
125 OPC_BLEZC = (0x16 << 26),
126 OPC_BGEZC = (0x16 << 26),
127 OPC_BGEC = (0x16 << 26),
128 OPC_BGTZC = (0x17 << 26),
129 OPC_BLTZC = (0x17 << 26),
130 OPC_BLTC = (0x17 << 26),
131 OPC_BNVC = (0x18 << 26),
132 OPC_BNEZALC = (0x18 << 26),
133 OPC_BNEC = (0x18 << 26),
134 OPC_BC = (0x32 << 26),
135 OPC_BEQZC = (0x36 << 26),
136 OPC_JIC = (0x36 << 26),
137 OPC_BALC = (0x3A << 26),
138 OPC_BNEZC = (0x3E << 26),
139 OPC_JIALC = (0x3E << 26),
140 /* MDMX ASE specific */
141 OPC_MDMX = (0x1E << 26),
142 /* MSA ASE, same as MDMX */
143 OPC_MSA = OPC_MDMX,
144 /* Cache and prefetch */
145 OPC_CACHE = (0x2F << 26),
146 OPC_PREF = (0x33 << 26),
147 /* PC-relative address computation / loads */
148 OPC_PCREL = (0x3B << 26),
151 /* PC-relative address computation / loads */
152 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
153 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
154 enum {
155 /* Instructions determined by bits 19 and 20 */
156 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
157 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
158 OPC_LWUPC = OPC_PCREL | (2 << 19),
160 /* Instructions determined by bits 16 ... 20 */
161 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
162 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
164 /* Other */
165 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
168 /* MIPS special opcodes */
169 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
171 enum {
172 /* Shifts */
173 OPC_SLL = 0x00 | OPC_SPECIAL,
174 /* NOP is SLL r0, r0, 0 */
175 /* SSNOP is SLL r0, r0, 1 */
176 /* EHB is SLL r0, r0, 3 */
177 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
178 OPC_ROTR = OPC_SRL | (1 << 21),
179 OPC_SRA = 0x03 | OPC_SPECIAL,
180 OPC_SLLV = 0x04 | OPC_SPECIAL,
181 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
182 OPC_ROTRV = OPC_SRLV | (1 << 6),
183 OPC_SRAV = 0x07 | OPC_SPECIAL,
184 OPC_DSLLV = 0x14 | OPC_SPECIAL,
185 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
186 OPC_DROTRV = OPC_DSRLV | (1 << 6),
187 OPC_DSRAV = 0x17 | OPC_SPECIAL,
188 OPC_DSLL = 0x38 | OPC_SPECIAL,
189 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
190 OPC_DROTR = OPC_DSRL | (1 << 21),
191 OPC_DSRA = 0x3B | OPC_SPECIAL,
192 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
193 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
194 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
195 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
196 /* Multiplication / division */
197 OPC_MULT = 0x18 | OPC_SPECIAL,
198 OPC_MULTU = 0x19 | OPC_SPECIAL,
199 OPC_DIV = 0x1A | OPC_SPECIAL,
200 OPC_DIVU = 0x1B | OPC_SPECIAL,
201 OPC_DMULT = 0x1C | OPC_SPECIAL,
202 OPC_DMULTU = 0x1D | OPC_SPECIAL,
203 OPC_DDIV = 0x1E | OPC_SPECIAL,
204 OPC_DDIVU = 0x1F | OPC_SPECIAL,
206 /* 2 registers arithmetic / logic */
207 OPC_ADD = 0x20 | OPC_SPECIAL,
208 OPC_ADDU = 0x21 | OPC_SPECIAL,
209 OPC_SUB = 0x22 | OPC_SPECIAL,
210 OPC_SUBU = 0x23 | OPC_SPECIAL,
211 OPC_AND = 0x24 | OPC_SPECIAL,
212 OPC_OR = 0x25 | OPC_SPECIAL,
213 OPC_XOR = 0x26 | OPC_SPECIAL,
214 OPC_NOR = 0x27 | OPC_SPECIAL,
215 OPC_SLT = 0x2A | OPC_SPECIAL,
216 OPC_SLTU = 0x2B | OPC_SPECIAL,
217 OPC_DADD = 0x2C | OPC_SPECIAL,
218 OPC_DADDU = 0x2D | OPC_SPECIAL,
219 OPC_DSUB = 0x2E | OPC_SPECIAL,
220 OPC_DSUBU = 0x2F | OPC_SPECIAL,
221 /* Jumps */
222 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
223 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
224 /* Traps */
225 OPC_TGE = 0x30 | OPC_SPECIAL,
226 OPC_TGEU = 0x31 | OPC_SPECIAL,
227 OPC_TLT = 0x32 | OPC_SPECIAL,
228 OPC_TLTU = 0x33 | OPC_SPECIAL,
229 OPC_TEQ = 0x34 | OPC_SPECIAL,
230 OPC_TNE = 0x36 | OPC_SPECIAL,
231 /* HI / LO registers load & stores */
232 OPC_MFHI = 0x10 | OPC_SPECIAL,
233 OPC_MTHI = 0x11 | OPC_SPECIAL,
234 OPC_MFLO = 0x12 | OPC_SPECIAL,
235 OPC_MTLO = 0x13 | OPC_SPECIAL,
236 /* Conditional moves */
237 OPC_MOVZ = 0x0A | OPC_SPECIAL,
238 OPC_MOVN = 0x0B | OPC_SPECIAL,
240 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
241 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
243 OPC_MOVCI = 0x01 | OPC_SPECIAL,
245 /* Special */
246 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
247 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
248 OPC_BREAK = 0x0D | OPC_SPECIAL,
249 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
250 OPC_SYNC = 0x0F | OPC_SPECIAL,
252 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
253 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
254 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
255 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
258 /* R6 Multiply and Divide instructions have the same Opcode
259 and function field as legacy OPC_MULT[U]/OPC_DIV[U] */
260 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
262 enum {
263 R6_OPC_MUL = OPC_MULT | (2 << 6),
264 R6_OPC_MUH = OPC_MULT | (3 << 6),
265 R6_OPC_MULU = OPC_MULTU | (2 << 6),
266 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
267 R6_OPC_DIV = OPC_DIV | (2 << 6),
268 R6_OPC_MOD = OPC_DIV | (3 << 6),
269 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
270 R6_OPC_MODU = OPC_DIVU | (3 << 6),
272 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
273 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
274 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
275 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
276 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
277 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
278 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
279 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
281 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
282 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
283 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
284 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
285 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
287 OPC_LSA = 0x05 | OPC_SPECIAL,
288 OPC_DLSA = 0x15 | OPC_SPECIAL,
291 /* Multiplication variants of the vr54xx. */
292 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
294 enum {
295 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
296 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
297 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
298 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
299 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
300 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
301 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
302 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
303 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
304 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
305 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
306 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
307 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
308 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
311 /* REGIMM (rt field) opcodes */
312 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
314 enum {
315 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
316 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
317 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
318 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
319 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
320 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
321 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
322 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
323 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
324 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
325 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
326 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
327 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
328 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
329 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
330 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
332 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
333 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
336 /* Special2 opcodes */
337 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
339 enum {
340 /* Multiply & xxx operations */
341 OPC_MADD = 0x00 | OPC_SPECIAL2,
342 OPC_MADDU = 0x01 | OPC_SPECIAL2,
343 OPC_MUL = 0x02 | OPC_SPECIAL2,
344 OPC_MSUB = 0x04 | OPC_SPECIAL2,
345 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
346 /* Loongson 2F */
347 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
348 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
349 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
350 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
351 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
352 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
353 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
354 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
355 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
356 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
357 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
358 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
359 /* Misc */
360 OPC_CLZ = 0x20 | OPC_SPECIAL2,
361 OPC_CLO = 0x21 | OPC_SPECIAL2,
362 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
363 OPC_DCLO = 0x25 | OPC_SPECIAL2,
364 /* Special */
365 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
368 /* Special3 opcodes */
369 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
371 enum {
372 OPC_EXT = 0x00 | OPC_SPECIAL3,
373 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
374 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
375 OPC_DEXT = 0x03 | OPC_SPECIAL3,
376 OPC_INS = 0x04 | OPC_SPECIAL3,
377 OPC_DINSM = 0x05 | OPC_SPECIAL3,
378 OPC_DINSU = 0x06 | OPC_SPECIAL3,
379 OPC_DINS = 0x07 | OPC_SPECIAL3,
380 OPC_FORK = 0x08 | OPC_SPECIAL3,
381 OPC_YIELD = 0x09 | OPC_SPECIAL3,
382 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
383 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
384 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
386 /* Loongson 2E */
387 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
388 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
389 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
390 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
391 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
392 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
393 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
394 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
395 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
396 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
397 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
398 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
400 /* MIPS DSP Load */
401 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
402 /* MIPS DSP Arithmetic */
403 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
404 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
405 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
406 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
407 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
408 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
409 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
410 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
411 /* MIPS DSP GPR-Based Shift Sub-class */
412 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
413 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
414 /* MIPS DSP Multiply Sub-class insns */
415 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
416 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
417 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
418 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
419 /* DSP Bit/Manipulation Sub-class */
420 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
421 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
422 /* MIPS DSP Append Sub-class */
423 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
424 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
425 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
426 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
427 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
429 /* R6 */
430 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
431 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
432 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
433 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
434 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
435 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
438 /* BSHFL opcodes */
439 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
441 enum {
442 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
443 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
444 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
445 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp */
446 OPC_ALIGN_END = (0x0B << 6) | OPC_BSHFL, /* 010.00 to 010.11 */
447 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
450 /* DBSHFL opcodes */
451 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
453 enum {
454 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
455 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
456 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp */
457 OPC_DALIGN_END = (0x0F << 6) | OPC_DBSHFL, /* 01.000 to 01.111 */
458 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
461 /* MIPS DSP REGIMM opcodes */
462 enum {
463 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
464 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
467 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
468 /* MIPS DSP Load */
469 enum {
470 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
471 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
472 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
473 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
476 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
477 enum {
478 /* MIPS DSP Arithmetic Sub-class */
479 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
480 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
481 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
482 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
483 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
484 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
485 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
486 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
487 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
488 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
489 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
490 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
491 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
492 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
493 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
494 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
495 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
496 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
497 /* MIPS DSP Multiply Sub-class insns */
498 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
499 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
500 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
501 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
502 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
503 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
506 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
507 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
508 enum {
509 /* MIPS DSP Arithmetic Sub-class */
510 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
511 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
512 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
513 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
514 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
515 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
516 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
517 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
518 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
519 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
520 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
521 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
522 /* MIPS DSP Multiply Sub-class insns */
523 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
524 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
525 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
526 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
529 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
530 enum {
531 /* MIPS DSP Arithmetic Sub-class */
532 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
533 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
534 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
535 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
536 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
537 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
538 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
539 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
540 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
541 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
542 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
543 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
544 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
545 /* DSP Bit/Manipulation Sub-class */
546 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
547 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
548 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
549 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
550 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
553 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
554 enum {
555 /* MIPS DSP Arithmetic Sub-class */
556 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
557 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
558 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
559 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
560 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
561 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
562 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
563 /* DSP Compare-Pick Sub-class */
564 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
565 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
566 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
567 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
568 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
569 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
570 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
571 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
572 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
573 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
574 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
575 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
576 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
577 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
578 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
581 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
582 enum {
583 /* MIPS DSP GPR-Based Shift Sub-class */
584 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
585 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
586 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
587 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
588 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
589 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
590 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
591 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
592 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
593 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
594 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
595 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
596 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
597 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
598 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
599 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
600 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
601 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
602 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
603 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
604 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
605 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
608 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
609 enum {
610 /* MIPS DSP Multiply Sub-class insns */
611 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
612 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
613 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
614 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
615 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
616 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
617 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
618 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
619 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
620 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
621 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
622 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
623 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
624 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
625 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
626 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
627 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
628 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
629 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
630 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
631 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
632 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
635 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
636 enum {
637 /* DSP Bit/Manipulation Sub-class */
638 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
641 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
642 enum {
643 /* MIPS DSP Append Sub-class */
644 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
645 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
646 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
649 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
650 enum {
651 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
652 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
653 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
654 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
655 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
656 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
657 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
658 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
659 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
660 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
661 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
662 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
663 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
664 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
665 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
666 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
667 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
668 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
671 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
672 enum {
673 /* MIPS DSP Arithmetic Sub-class */
674 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
675 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
676 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
677 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
678 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
679 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
680 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
681 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
682 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
683 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
684 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
685 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
686 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
687 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
688 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
689 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
690 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
691 /* DSP Bit/Manipulation Sub-class */
692 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
693 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
694 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
695 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
696 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
697 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
700 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
701 enum {
702 /* MIPS DSP Multiply Sub-class insns */
703 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
704 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
705 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
706 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
707 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
708 /* MIPS DSP Arithmetic Sub-class */
709 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
710 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
711 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
712 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
713 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
714 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
715 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
716 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
717 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
718 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
719 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
720 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
721 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
722 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
723 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
724 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
725 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
726 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
727 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
728 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
729 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
732 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
733 enum {
734 /* DSP Compare-Pick Sub-class */
735 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
736 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
737 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
738 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
739 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
740 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
741 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
742 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
743 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
744 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
745 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
746 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
747 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
748 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
749 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
750 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
751 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
752 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
753 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
754 /* MIPS DSP Arithmetic Sub-class */
755 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
756 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
757 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
758 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
759 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
760 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
761 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
762 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
765 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
766 enum {
767 /* DSP Append Sub-class */
768 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
769 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
770 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
771 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
774 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
775 enum {
776 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
777 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
778 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
779 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
780 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
781 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
782 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
783 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
784 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
785 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
786 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
787 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
788 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
789 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
790 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
791 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
792 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
793 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
794 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
795 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
796 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
797 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
800 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
801 enum {
802 /* DSP Bit/Manipulation Sub-class */
803 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
806 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
807 enum {
808 /* MIPS DSP Multiply Sub-class insns */
809 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
810 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
811 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
812 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
813 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
814 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
815 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
816 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
817 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
818 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
819 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
820 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
821 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
822 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
823 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
824 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
825 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
826 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
827 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
828 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
829 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
830 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
831 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
832 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
833 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
834 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
837 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
838 enum {
839 /* MIPS DSP GPR-Based Shift Sub-class */
840 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
841 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
842 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
843 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
844 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
845 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
846 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
847 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
848 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
849 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
850 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
851 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
852 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
853 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
854 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
855 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
856 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
857 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
858 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
859 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
860 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
861 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
862 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
863 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
864 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
865 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
868 /* Coprocessor 0 (rs field) */
869 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
871 enum {
872 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
873 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
874 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
875 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
876 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
877 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
878 OPC_MFTR = (0x08 << 21) | OPC_CP0,
879 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
880 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
881 OPC_MTTR = (0x0C << 21) | OPC_CP0,
882 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
883 OPC_C0 = (0x10 << 21) | OPC_CP0,
884 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
885 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
888 /* MFMC0 opcodes */
889 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
891 enum {
892 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
893 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
894 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
895 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
896 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
897 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
898 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
899 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
902 /* Coprocessor 0 (with rs == C0) */
903 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
905 enum {
906 OPC_TLBR = 0x01 | OPC_C0,
907 OPC_TLBWI = 0x02 | OPC_C0,
908 OPC_TLBINV = 0x03 | OPC_C0,
909 OPC_TLBINVF = 0x04 | OPC_C0,
910 OPC_TLBWR = 0x06 | OPC_C0,
911 OPC_TLBP = 0x08 | OPC_C0,
912 OPC_RFE = 0x10 | OPC_C0,
913 OPC_ERET = 0x18 | OPC_C0,
914 OPC_DERET = 0x1F | OPC_C0,
915 OPC_WAIT = 0x20 | OPC_C0,
918 /* Coprocessor 1 (rs field) */
919 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
921 /* Values for the fmt field in FP instructions */
922 enum {
923 /* 0 - 15 are reserved */
924 FMT_S = 16, /* single fp */
925 FMT_D = 17, /* double fp */
926 FMT_E = 18, /* extended fp */
927 FMT_Q = 19, /* quad fp */
928 FMT_W = 20, /* 32-bit fixed */
929 FMT_L = 21, /* 64-bit fixed */
930 FMT_PS = 22, /* paired single fp */
931 /* 23 - 31 are reserved */
934 enum {
935 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
936 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
937 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
938 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
939 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
940 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
941 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
942 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
943 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
944 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
945 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
946 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
947 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
948 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
949 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
950 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
951 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
952 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
953 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
954 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
955 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
956 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
957 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
958 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
959 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
960 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
961 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
962 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
963 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
964 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
967 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
968 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
970 enum {
971 OPC_BC1F = (0x00 << 16) | OPC_BC1,
972 OPC_BC1T = (0x01 << 16) | OPC_BC1,
973 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
974 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
977 enum {
978 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
979 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
982 enum {
983 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
984 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
987 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
989 enum {
990 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
991 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
992 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
993 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
994 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
995 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
996 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
997 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
998 OPC_BC2 = (0x08 << 21) | OPC_CP2,
999 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1000 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1003 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1005 enum {
1006 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1007 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1008 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1009 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1010 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1011 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1012 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1013 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1015 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1016 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1017 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1018 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1019 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1020 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1021 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1022 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1024 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1025 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1026 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1027 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1028 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1029 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1030 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1031 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1033 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1034 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1035 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1036 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1037 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1038 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1039 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1040 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1042 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1043 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1044 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1045 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1046 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1047 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1049 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1050 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1051 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1052 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1053 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1054 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1056 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1057 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1058 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1059 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1060 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1061 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1063 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1064 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1065 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1066 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1067 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1068 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1070 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1071 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1072 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1073 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1074 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1075 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1077 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1078 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1079 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1080 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1081 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1082 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1084 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1085 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1086 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1087 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1088 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1089 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1091 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1092 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1093 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1094 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1095 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1096 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1100 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
1102 enum {
1103 OPC_LWXC1 = 0x00 | OPC_CP3,
1104 OPC_LDXC1 = 0x01 | OPC_CP3,
1105 OPC_LUXC1 = 0x05 | OPC_CP3,
1106 OPC_SWXC1 = 0x08 | OPC_CP3,
1107 OPC_SDXC1 = 0x09 | OPC_CP3,
1108 OPC_SUXC1 = 0x0D | OPC_CP3,
1109 OPC_PREFX = 0x0F | OPC_CP3,
1110 OPC_ALNV_PS = 0x1E | OPC_CP3,
1111 OPC_MADD_S = 0x20 | OPC_CP3,
1112 OPC_MADD_D = 0x21 | OPC_CP3,
1113 OPC_MADD_PS = 0x26 | OPC_CP3,
1114 OPC_MSUB_S = 0x28 | OPC_CP3,
1115 OPC_MSUB_D = 0x29 | OPC_CP3,
1116 OPC_MSUB_PS = 0x2E | OPC_CP3,
1117 OPC_NMADD_S = 0x30 | OPC_CP3,
1118 OPC_NMADD_D = 0x31 | OPC_CP3,
1119 OPC_NMADD_PS= 0x36 | OPC_CP3,
1120 OPC_NMSUB_S = 0x38 | OPC_CP3,
1121 OPC_NMSUB_D = 0x39 | OPC_CP3,
1122 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1125 /* MSA Opcodes */
1126 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1127 enum {
1128 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1129 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1130 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1131 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1132 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1133 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1134 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1135 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1136 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1137 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1138 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1139 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1140 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1141 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1142 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1143 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1144 OPC_MSA_ELM = 0x19 | OPC_MSA,
1145 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1146 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1147 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1148 OPC_MSA_VEC = 0x1E | OPC_MSA,
1150 /* MI10 instruction */
1151 OPC_LD_B = (0x20) | OPC_MSA,
1152 OPC_LD_H = (0x21) | OPC_MSA,
1153 OPC_LD_W = (0x22) | OPC_MSA,
1154 OPC_LD_D = (0x23) | OPC_MSA,
1155 OPC_ST_B = (0x24) | OPC_MSA,
1156 OPC_ST_H = (0x25) | OPC_MSA,
1157 OPC_ST_W = (0x26) | OPC_MSA,
1158 OPC_ST_D = (0x27) | OPC_MSA,
1161 enum {
1162 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1163 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1164 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1165 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1166 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1167 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1168 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1169 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1170 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1171 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1172 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1173 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1174 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1176 /* I8 instruction */
1177 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1178 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1179 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1180 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1181 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1182 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1183 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1184 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1185 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1186 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1188 /* VEC/2R/2RF instruction */
1189 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1190 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1191 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1192 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1193 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1194 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1195 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1197 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1198 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1200 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1201 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1202 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1203 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1204 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1206 /* 2RF instruction df(bit 16) = _w, _d */
1207 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1208 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1209 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1210 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1211 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1212 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1213 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1214 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1215 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1216 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1217 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1218 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1219 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1220 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1221 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1222 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1224 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1225 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1226 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1227 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1228 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1229 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1230 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1231 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1232 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1233 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1234 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1235 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1236 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1237 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1238 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1239 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1240 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1241 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1242 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1243 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1244 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1245 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1246 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1247 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1248 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1249 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1250 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1251 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1252 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1253 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1254 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1255 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1256 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1257 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1258 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1259 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1260 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1261 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1262 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1263 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1264 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1265 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1266 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1267 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1268 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1269 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1270 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1271 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1272 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1273 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1274 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1275 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1276 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1277 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1278 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1279 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1280 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1281 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1282 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1283 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1284 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1285 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1286 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1287 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1289 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1290 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1291 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1292 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1293 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1294 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1295 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1296 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1297 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1298 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1300 /* 3RF instruction _df(bit 21) = _w, _d */
1301 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1302 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1303 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1304 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1305 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1306 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1307 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1308 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1309 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1310 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1311 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1312 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1313 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1314 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1315 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1316 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1317 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1318 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1319 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1320 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1321 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1322 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1323 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1324 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1325 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1326 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1327 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1328 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1329 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1330 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1331 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1332 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1333 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1334 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1335 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1336 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1337 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1338 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1339 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1340 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1341 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1343 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1344 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1345 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1346 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1347 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1348 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1349 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1350 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1351 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1352 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1353 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1354 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1355 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1358 /* global register indices */
1359 static TCGv_env cpu_env;
1360 static TCGv cpu_gpr[32], cpu_PC;
1361 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
1362 static TCGv cpu_dspctrl, btarget, bcond;
1363 static TCGv_i32 hflags;
1364 static TCGv_i32 fpu_fcr0, fpu_fcr31;
1365 static TCGv_i64 fpu_f64[32];
1366 static TCGv_i64 msa_wr_d[64];
1368 #include "exec/gen-icount.h"
1370 #define gen_helper_0e0i(name, arg) do { \
1371 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
1372 gen_helper_##name(cpu_env, helper_tmp); \
1373 tcg_temp_free_i32(helper_tmp); \
1374 } while(0)
1376 #define gen_helper_0e1i(name, arg1, arg2) do { \
1377 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1378 gen_helper_##name(cpu_env, arg1, helper_tmp); \
1379 tcg_temp_free_i32(helper_tmp); \
1380 } while(0)
1382 #define gen_helper_1e0i(name, ret, arg1) do { \
1383 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1384 gen_helper_##name(ret, cpu_env, helper_tmp); \
1385 tcg_temp_free_i32(helper_tmp); \
1386 } while(0)
1388 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1389 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1390 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1391 tcg_temp_free_i32(helper_tmp); \
1392 } while(0)
1394 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1395 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1396 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
1397 tcg_temp_free_i32(helper_tmp); \
1398 } while(0)
1400 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
1401 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1402 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
1403 tcg_temp_free_i32(helper_tmp); \
1404 } while(0)
1406 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
1407 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
1408 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
1409 tcg_temp_free_i32(helper_tmp); \
1410 } while(0)
1412 typedef struct DisasContext {
1413 struct TranslationBlock *tb;
1414 target_ulong pc, saved_pc;
1415 uint32_t opcode;
1416 int singlestep_enabled;
1417 int insn_flags;
1418 int32_t CP0_Config1;
1419 /* Routine used to access memory */
1420 int mem_idx;
1421 TCGMemOp default_tcg_memop_mask;
1422 uint32_t hflags, saved_hflags;
1423 int bstate;
1424 target_ulong btarget;
1425 bool ulri;
1426 int kscrexist;
1427 bool rxi;
1428 int ie;
1429 bool bi;
1430 bool bp;
1431 uint64_t PAMask;
1432 bool mvh;
1433 int CP0_LLAddr_shift;
1434 bool ps;
1435 bool vp;
1436 bool cmgcr;
1437 bool mrp;
1438 bool nan2008;
1439 bool abs2008;
1440 } DisasContext;
1442 enum {
1443 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
1444 * exception condition */
1445 BS_STOP = 1, /* We want to stop translation for any reason */
1446 BS_BRANCH = 2, /* We reached a branch condition */
1447 BS_EXCP = 3, /* We reached an exception condition */
1450 static const char * const regnames[] = {
1451 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
1452 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
1453 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1454 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
1457 static const char * const regnames_HI[] = {
1458 "HI0", "HI1", "HI2", "HI3",
1461 static const char * const regnames_LO[] = {
1462 "LO0", "LO1", "LO2", "LO3",
1465 static const char * const fregnames[] = {
1466 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
1467 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
1468 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
1469 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
1472 static const char * const msaregnames[] = {
1473 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
1474 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
1475 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
1476 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
1477 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
1478 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
1479 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
1480 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
1481 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
1482 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
1483 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
1484 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
1485 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
1486 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
1487 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
1488 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
1491 #define LOG_DISAS(...) \
1492 do { \
1493 if (MIPS_DEBUG_DISAS) { \
1494 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
1496 } while (0)
1498 #define MIPS_INVAL(op) \
1499 do { \
1500 if (MIPS_DEBUG_DISAS) { \
1501 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
1502 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
1503 ctx->pc, ctx->opcode, op, ctx->opcode >> 26, \
1504 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
1506 } while (0)
1508 /* General purpose registers moves. */
1509 static inline void gen_load_gpr (TCGv t, int reg)
1511 if (reg == 0)
1512 tcg_gen_movi_tl(t, 0);
1513 else
1514 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1517 static inline void gen_store_gpr (TCGv t, int reg)
1519 if (reg != 0)
1520 tcg_gen_mov_tl(cpu_gpr[reg], t);
1523 /* Moves to/from shadow registers. */
1524 static inline void gen_load_srsgpr (int from, int to)
1526 TCGv t0 = tcg_temp_new();
1528 if (from == 0)
1529 tcg_gen_movi_tl(t0, 0);
1530 else {
1531 TCGv_i32 t2 = tcg_temp_new_i32();
1532 TCGv_ptr addr = tcg_temp_new_ptr();
1534 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1535 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1536 tcg_gen_andi_i32(t2, t2, 0xf);
1537 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1538 tcg_gen_ext_i32_ptr(addr, t2);
1539 tcg_gen_add_ptr(addr, cpu_env, addr);
1541 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
1542 tcg_temp_free_ptr(addr);
1543 tcg_temp_free_i32(t2);
1545 gen_store_gpr(t0, to);
1546 tcg_temp_free(t0);
1549 static inline void gen_store_srsgpr (int from, int to)
1551 if (to != 0) {
1552 TCGv t0 = tcg_temp_new();
1553 TCGv_i32 t2 = tcg_temp_new_i32();
1554 TCGv_ptr addr = tcg_temp_new_ptr();
1556 gen_load_gpr(t0, from);
1557 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1558 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1559 tcg_gen_andi_i32(t2, t2, 0xf);
1560 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1561 tcg_gen_ext_i32_ptr(addr, t2);
1562 tcg_gen_add_ptr(addr, cpu_env, addr);
1564 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
1565 tcg_temp_free_ptr(addr);
1566 tcg_temp_free_i32(t2);
1567 tcg_temp_free(t0);
1571 /* Tests */
1572 static inline void gen_save_pc(target_ulong pc)
1574 tcg_gen_movi_tl(cpu_PC, pc);
1577 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
1579 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1580 if (do_save_pc && ctx->pc != ctx->saved_pc) {
1581 gen_save_pc(ctx->pc);
1582 ctx->saved_pc = ctx->pc;
1584 if (ctx->hflags != ctx->saved_hflags) {
1585 tcg_gen_movi_i32(hflags, ctx->hflags);
1586 ctx->saved_hflags = ctx->hflags;
1587 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1588 case MIPS_HFLAG_BR:
1589 break;
1590 case MIPS_HFLAG_BC:
1591 case MIPS_HFLAG_BL:
1592 case MIPS_HFLAG_B:
1593 tcg_gen_movi_tl(btarget, ctx->btarget);
1594 break;
1599 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
1601 ctx->saved_hflags = ctx->hflags;
1602 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1603 case MIPS_HFLAG_BR:
1604 break;
1605 case MIPS_HFLAG_BC:
1606 case MIPS_HFLAG_BL:
1607 case MIPS_HFLAG_B:
1608 ctx->btarget = env->btarget;
1609 break;
1613 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
1615 TCGv_i32 texcp = tcg_const_i32(excp);
1616 TCGv_i32 terr = tcg_const_i32(err);
1617 save_cpu_state(ctx, 1);
1618 gen_helper_raise_exception_err(cpu_env, texcp, terr);
1619 tcg_temp_free_i32(terr);
1620 tcg_temp_free_i32(texcp);
1621 ctx->bstate = BS_EXCP;
1624 static inline void generate_exception(DisasContext *ctx, int excp)
1626 gen_helper_0e0i(raise_exception, excp);
1629 static inline void generate_exception_end(DisasContext *ctx, int excp)
1631 generate_exception_err(ctx, excp, 0);
1634 /* Floating point register moves. */
1635 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1637 if (ctx->hflags & MIPS_HFLAG_FRE) {
1638 generate_exception(ctx, EXCP_RI);
1640 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
1643 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1645 TCGv_i64 t64;
1646 if (ctx->hflags & MIPS_HFLAG_FRE) {
1647 generate_exception(ctx, EXCP_RI);
1649 t64 = tcg_temp_new_i64();
1650 tcg_gen_extu_i32_i64(t64, t);
1651 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1652 tcg_temp_free_i64(t64);
1655 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1657 if (ctx->hflags & MIPS_HFLAG_F64) {
1658 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
1659 } else {
1660 gen_load_fpr32(ctx, t, reg | 1);
1664 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1666 if (ctx->hflags & MIPS_HFLAG_F64) {
1667 TCGv_i64 t64 = tcg_temp_new_i64();
1668 tcg_gen_extu_i32_i64(t64, t);
1669 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1670 tcg_temp_free_i64(t64);
1671 } else {
1672 gen_store_fpr32(ctx, t, reg | 1);
1676 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1678 if (ctx->hflags & MIPS_HFLAG_F64) {
1679 tcg_gen_mov_i64(t, fpu_f64[reg]);
1680 } else {
1681 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
1685 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1687 if (ctx->hflags & MIPS_HFLAG_F64) {
1688 tcg_gen_mov_i64(fpu_f64[reg], t);
1689 } else {
1690 TCGv_i64 t0;
1691 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1692 t0 = tcg_temp_new_i64();
1693 tcg_gen_shri_i64(t0, t, 32);
1694 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
1695 tcg_temp_free_i64(t0);
1699 static inline int get_fp_bit (int cc)
1701 if (cc)
1702 return 24 + cc;
1703 else
1704 return 23;
1707 /* Addresses computation */
1708 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
1710 tcg_gen_add_tl(ret, arg0, arg1);
1712 #if defined(TARGET_MIPS64)
1713 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1714 tcg_gen_ext32s_i64(ret, ret);
1716 #endif
1719 /* Addresses computation (translation time) */
1720 static target_long addr_add(DisasContext *ctx, target_long base,
1721 target_long offset)
1723 target_long sum = base + offset;
1725 #if defined(TARGET_MIPS64)
1726 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1727 sum = (int32_t)sum;
1729 #endif
1730 return sum;
1733 /* Sign-extract the low 32-bits to a target_long. */
1734 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
1736 #if defined(TARGET_MIPS64)
1737 tcg_gen_ext32s_i64(ret, arg);
1738 #else
1739 tcg_gen_extrl_i64_i32(ret, arg);
1740 #endif
1743 /* Sign-extract the high 32-bits to a target_long. */
1744 static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
1746 #if defined(TARGET_MIPS64)
1747 tcg_gen_sari_i64(ret, arg, 32);
1748 #else
1749 tcg_gen_extrh_i64_i32(ret, arg);
1750 #endif
1753 static inline void check_cp0_enabled(DisasContext *ctx)
1755 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
1756 generate_exception_err(ctx, EXCP_CpU, 0);
1759 static inline void check_cp1_enabled(DisasContext *ctx)
1761 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
1762 generate_exception_err(ctx, EXCP_CpU, 1);
1765 /* Verify that the processor is running with COP1X instructions enabled.
1766 This is associated with the nabla symbol in the MIPS32 and MIPS64
1767 opcode tables. */
1769 static inline void check_cop1x(DisasContext *ctx)
1771 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
1772 generate_exception_end(ctx, EXCP_RI);
1775 /* Verify that the processor is running with 64-bit floating-point
1776 operations enabled. */
1778 static inline void check_cp1_64bitmode(DisasContext *ctx)
1780 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
1781 generate_exception_end(ctx, EXCP_RI);
1785 * Verify if floating point register is valid; an operation is not defined
1786 * if bit 0 of any register specification is set and the FR bit in the
1787 * Status register equals zero, since the register numbers specify an
1788 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1789 * in the Status register equals one, both even and odd register numbers
1790 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1792 * Multiple 64 bit wide registers can be checked by calling
1793 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1795 static inline void check_cp1_registers(DisasContext *ctx, int regs)
1797 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
1798 generate_exception_end(ctx, EXCP_RI);
1801 /* Verify that the processor is running with DSP instructions enabled.
1802 This is enabled by CP0 Status register MX(24) bit.
1805 static inline void check_dsp(DisasContext *ctx)
1807 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
1808 if (ctx->insn_flags & ASE_DSP) {
1809 generate_exception_end(ctx, EXCP_DSPDIS);
1810 } else {
1811 generate_exception_end(ctx, EXCP_RI);
1816 static inline void check_dspr2(DisasContext *ctx)
1818 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSPR2))) {
1819 if (ctx->insn_flags & ASE_DSP) {
1820 generate_exception_end(ctx, EXCP_DSPDIS);
1821 } else {
1822 generate_exception_end(ctx, EXCP_RI);
1827 /* This code generates a "reserved instruction" exception if the
1828 CPU does not support the instruction set corresponding to flags. */
1829 static inline void check_insn(DisasContext *ctx, int flags)
1831 if (unlikely(!(ctx->insn_flags & flags))) {
1832 generate_exception_end(ctx, EXCP_RI);
1836 /* This code generates a "reserved instruction" exception if the
1837 CPU has corresponding flag set which indicates that the instruction
1838 has been removed. */
1839 static inline void check_insn_opc_removed(DisasContext *ctx, int flags)
1841 if (unlikely(ctx->insn_flags & flags)) {
1842 generate_exception_end(ctx, EXCP_RI);
1846 /* This code generates a "reserved instruction" exception if the
1847 CPU does not support 64-bit paired-single (PS) floating point data type */
1848 static inline void check_ps(DisasContext *ctx)
1850 if (unlikely(!ctx->ps)) {
1851 generate_exception(ctx, EXCP_RI);
1853 check_cp1_64bitmode(ctx);
1856 #ifdef TARGET_MIPS64
1857 /* This code generates a "reserved instruction" exception if 64-bit
1858 instructions are not enabled. */
1859 static inline void check_mips_64(DisasContext *ctx)
1861 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
1862 generate_exception_end(ctx, EXCP_RI);
1864 #endif
1866 #ifndef CONFIG_USER_ONLY
1867 static inline void check_mvh(DisasContext *ctx)
1869 if (unlikely(!ctx->mvh)) {
1870 generate_exception(ctx, EXCP_RI);
1873 #endif
1875 /* Define small wrappers for gen_load_fpr* so that we have a uniform
1876 calling interface for 32 and 64-bit FPRs. No sense in changing
1877 all callers for gen_load_fpr32 when we need the CTX parameter for
1878 this one use. */
1879 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
1880 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1881 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1882 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1883 int ft, int fs, int cc) \
1885 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
1886 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
1887 switch (ifmt) { \
1888 case FMT_PS: \
1889 check_ps(ctx); \
1890 break; \
1891 case FMT_D: \
1892 if (abs) { \
1893 check_cop1x(ctx); \
1895 check_cp1_registers(ctx, fs | ft); \
1896 break; \
1897 case FMT_S: \
1898 if (abs) { \
1899 check_cop1x(ctx); \
1901 break; \
1903 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
1904 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
1905 switch (n) { \
1906 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
1907 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
1908 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
1909 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
1910 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
1911 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
1912 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
1913 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
1914 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
1915 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
1916 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
1917 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
1918 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
1919 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
1920 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
1921 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
1922 default: abort(); \
1924 tcg_temp_free_i##bits (fp0); \
1925 tcg_temp_free_i##bits (fp1); \
1928 FOP_CONDS(, 0, d, FMT_D, 64)
1929 FOP_CONDS(abs, 1, d, FMT_D, 64)
1930 FOP_CONDS(, 0, s, FMT_S, 32)
1931 FOP_CONDS(abs, 1, s, FMT_S, 32)
1932 FOP_CONDS(, 0, ps, FMT_PS, 64)
1933 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1934 #undef FOP_CONDS
1936 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
1937 static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
1938 int ft, int fs, int fd) \
1940 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
1941 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
1942 if (ifmt == FMT_D) { \
1943 check_cp1_registers(ctx, fs | ft | fd); \
1945 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
1946 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
1947 switch (n) { \
1948 case 0: \
1949 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
1950 break; \
1951 case 1: \
1952 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
1953 break; \
1954 case 2: \
1955 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
1956 break; \
1957 case 3: \
1958 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
1959 break; \
1960 case 4: \
1961 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
1962 break; \
1963 case 5: \
1964 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
1965 break; \
1966 case 6: \
1967 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
1968 break; \
1969 case 7: \
1970 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
1971 break; \
1972 case 8: \
1973 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
1974 break; \
1975 case 9: \
1976 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
1977 break; \
1978 case 10: \
1979 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
1980 break; \
1981 case 11: \
1982 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
1983 break; \
1984 case 12: \
1985 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
1986 break; \
1987 case 13: \
1988 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
1989 break; \
1990 case 14: \
1991 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
1992 break; \
1993 case 15: \
1994 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
1995 break; \
1996 case 17: \
1997 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
1998 break; \
1999 case 18: \
2000 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
2001 break; \
2002 case 19: \
2003 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
2004 break; \
2005 case 25: \
2006 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
2007 break; \
2008 case 26: \
2009 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
2010 break; \
2011 case 27: \
2012 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
2013 break; \
2014 default: \
2015 abort(); \
2017 STORE; \
2018 tcg_temp_free_i ## bits (fp0); \
2019 tcg_temp_free_i ## bits (fp1); \
2022 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
2023 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
2024 #undef FOP_CONDNS
2025 #undef gen_ldcmp_fpr32
2026 #undef gen_ldcmp_fpr64
2028 /* load/store instructions. */
2029 #ifdef CONFIG_USER_ONLY
2030 #define OP_LD_ATOMIC(insn,fname) \
2031 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
2033 TCGv t0 = tcg_temp_new(); \
2034 tcg_gen_mov_tl(t0, arg1); \
2035 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
2036 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2037 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
2038 tcg_temp_free(t0); \
2040 #else
2041 #define OP_LD_ATOMIC(insn,fname) \
2042 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
2044 gen_helper_1e1i(insn, ret, arg1, ctx->mem_idx); \
2046 #endif
2047 OP_LD_ATOMIC(ll,ld32s);
2048 #if defined(TARGET_MIPS64)
2049 OP_LD_ATOMIC(lld,ld64);
2050 #endif
2051 #undef OP_LD_ATOMIC
2053 #ifdef CONFIG_USER_ONLY
2054 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2055 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
2057 TCGv t0 = tcg_temp_new(); \
2058 TCGLabel *l1 = gen_new_label(); \
2059 TCGLabel *l2 = gen_new_label(); \
2061 tcg_gen_andi_tl(t0, arg2, almask); \
2062 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
2063 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
2064 generate_exception(ctx, EXCP_AdES); \
2065 gen_set_label(l1); \
2066 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2067 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
2068 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
2069 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
2070 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
2071 generate_exception_end(ctx, EXCP_SC); \
2072 gen_set_label(l2); \
2073 tcg_gen_movi_tl(t0, 0); \
2074 gen_store_gpr(t0, rt); \
2075 tcg_temp_free(t0); \
2077 #else
2078 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2079 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
2081 TCGv t0 = tcg_temp_new(); \
2082 gen_helper_1e2i(insn, t0, arg1, arg2, ctx->mem_idx); \
2083 gen_store_gpr(t0, rt); \
2084 tcg_temp_free(t0); \
2086 #endif
2087 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
2088 #if defined(TARGET_MIPS64)
2089 OP_ST_ATOMIC(scd,st64,ld64,0x7);
2090 #endif
2091 #undef OP_ST_ATOMIC
2093 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
2094 int base, int16_t offset)
2096 if (base == 0) {
2097 tcg_gen_movi_tl(addr, offset);
2098 } else if (offset == 0) {
2099 gen_load_gpr(addr, base);
2100 } else {
2101 tcg_gen_movi_tl(addr, offset);
2102 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
2106 static target_ulong pc_relative_pc (DisasContext *ctx)
2108 target_ulong pc = ctx->pc;
2110 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2111 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
2113 pc -= branch_bytes;
2116 pc &= ~(target_ulong)3;
2117 return pc;
2120 /* Load */
2121 static void gen_ld(DisasContext *ctx, uint32_t opc,
2122 int rt, int base, int16_t offset)
2124 TCGv t0, t1, t2;
2126 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
2127 /* Loongson CPU uses a load to zero register for prefetch.
2128 We emulate it as a NOP. On other CPU we must perform the
2129 actual memory access. */
2130 return;
2133 t0 = tcg_temp_new();
2134 gen_base_offset_addr(ctx, t0, base, offset);
2136 switch (opc) {
2137 #if defined(TARGET_MIPS64)
2138 case OPC_LWU:
2139 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL |
2140 ctx->default_tcg_memop_mask);
2141 gen_store_gpr(t0, rt);
2142 break;
2143 case OPC_LD:
2144 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
2145 ctx->default_tcg_memop_mask);
2146 gen_store_gpr(t0, rt);
2147 break;
2148 case OPC_LLD:
2149 case R6_OPC_LLD:
2150 op_ld_lld(t0, t0, ctx);
2151 gen_store_gpr(t0, rt);
2152 break;
2153 case OPC_LDL:
2154 t1 = tcg_temp_new();
2155 /* Do a byte access to possibly trigger a page
2156 fault with the unaligned address. */
2157 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2158 tcg_gen_andi_tl(t1, t0, 7);
2159 #ifndef TARGET_WORDS_BIGENDIAN
2160 tcg_gen_xori_tl(t1, t1, 7);
2161 #endif
2162 tcg_gen_shli_tl(t1, t1, 3);
2163 tcg_gen_andi_tl(t0, t0, ~7);
2164 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2165 tcg_gen_shl_tl(t0, t0, t1);
2166 t2 = tcg_const_tl(-1);
2167 tcg_gen_shl_tl(t2, t2, t1);
2168 gen_load_gpr(t1, rt);
2169 tcg_gen_andc_tl(t1, t1, t2);
2170 tcg_temp_free(t2);
2171 tcg_gen_or_tl(t0, t0, t1);
2172 tcg_temp_free(t1);
2173 gen_store_gpr(t0, rt);
2174 break;
2175 case OPC_LDR:
2176 t1 = tcg_temp_new();
2177 /* Do a byte access to possibly trigger a page
2178 fault with the unaligned address. */
2179 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2180 tcg_gen_andi_tl(t1, t0, 7);
2181 #ifdef TARGET_WORDS_BIGENDIAN
2182 tcg_gen_xori_tl(t1, t1, 7);
2183 #endif
2184 tcg_gen_shli_tl(t1, t1, 3);
2185 tcg_gen_andi_tl(t0, t0, ~7);
2186 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2187 tcg_gen_shr_tl(t0, t0, t1);
2188 tcg_gen_xori_tl(t1, t1, 63);
2189 t2 = tcg_const_tl(0xfffffffffffffffeull);
2190 tcg_gen_shl_tl(t2, t2, t1);
2191 gen_load_gpr(t1, rt);
2192 tcg_gen_and_tl(t1, t1, t2);
2193 tcg_temp_free(t2);
2194 tcg_gen_or_tl(t0, t0, t1);
2195 tcg_temp_free(t1);
2196 gen_store_gpr(t0, rt);
2197 break;
2198 case OPC_LDPC:
2199 t1 = tcg_const_tl(pc_relative_pc(ctx));
2200 gen_op_addr_add(ctx, t0, t0, t1);
2201 tcg_temp_free(t1);
2202 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
2203 gen_store_gpr(t0, rt);
2204 break;
2205 #endif
2206 case OPC_LWPC:
2207 t1 = tcg_const_tl(pc_relative_pc(ctx));
2208 gen_op_addr_add(ctx, t0, t0, t1);
2209 tcg_temp_free(t1);
2210 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
2211 gen_store_gpr(t0, rt);
2212 break;
2213 case OPC_LW:
2214 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
2215 ctx->default_tcg_memop_mask);
2216 gen_store_gpr(t0, rt);
2217 break;
2218 case OPC_LH:
2219 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
2220 ctx->default_tcg_memop_mask);
2221 gen_store_gpr(t0, rt);
2222 break;
2223 case OPC_LHU:
2224 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUW |
2225 ctx->default_tcg_memop_mask);
2226 gen_store_gpr(t0, rt);
2227 break;
2228 case OPC_LB:
2229 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
2230 gen_store_gpr(t0, rt);
2231 break;
2232 case OPC_LBU:
2233 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
2234 gen_store_gpr(t0, rt);
2235 break;
2236 case OPC_LWL:
2237 t1 = tcg_temp_new();
2238 /* Do a byte access to possibly trigger a page
2239 fault with the unaligned address. */
2240 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2241 tcg_gen_andi_tl(t1, t0, 3);
2242 #ifndef TARGET_WORDS_BIGENDIAN
2243 tcg_gen_xori_tl(t1, t1, 3);
2244 #endif
2245 tcg_gen_shli_tl(t1, t1, 3);
2246 tcg_gen_andi_tl(t0, t0, ~3);
2247 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
2248 tcg_gen_shl_tl(t0, t0, t1);
2249 t2 = tcg_const_tl(-1);
2250 tcg_gen_shl_tl(t2, t2, t1);
2251 gen_load_gpr(t1, rt);
2252 tcg_gen_andc_tl(t1, t1, t2);
2253 tcg_temp_free(t2);
2254 tcg_gen_or_tl(t0, t0, t1);
2255 tcg_temp_free(t1);
2256 tcg_gen_ext32s_tl(t0, t0);
2257 gen_store_gpr(t0, rt);
2258 break;
2259 case OPC_LWR:
2260 t1 = tcg_temp_new();
2261 /* Do a byte access to possibly trigger a page
2262 fault with the unaligned address. */
2263 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
2264 tcg_gen_andi_tl(t1, t0, 3);
2265 #ifdef TARGET_WORDS_BIGENDIAN
2266 tcg_gen_xori_tl(t1, t1, 3);
2267 #endif
2268 tcg_gen_shli_tl(t1, t1, 3);
2269 tcg_gen_andi_tl(t0, t0, ~3);
2270 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
2271 tcg_gen_shr_tl(t0, t0, t1);
2272 tcg_gen_xori_tl(t1, t1, 31);
2273 t2 = tcg_const_tl(0xfffffffeull);
2274 tcg_gen_shl_tl(t2, t2, t1);
2275 gen_load_gpr(t1, rt);
2276 tcg_gen_and_tl(t1, t1, t2);
2277 tcg_temp_free(t2);
2278 tcg_gen_or_tl(t0, t0, t1);
2279 tcg_temp_free(t1);
2280 tcg_gen_ext32s_tl(t0, t0);
2281 gen_store_gpr(t0, rt);
2282 break;
2283 case OPC_LL:
2284 case R6_OPC_LL:
2285 op_ld_ll(t0, t0, ctx);
2286 gen_store_gpr(t0, rt);
2287 break;
2289 tcg_temp_free(t0);
2292 /* Store */
2293 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
2294 int base, int16_t offset)
2296 TCGv t0 = tcg_temp_new();
2297 TCGv t1 = tcg_temp_new();
2299 gen_base_offset_addr(ctx, t0, base, offset);
2300 gen_load_gpr(t1, rt);
2301 switch (opc) {
2302 #if defined(TARGET_MIPS64)
2303 case OPC_SD:
2304 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
2305 ctx->default_tcg_memop_mask);
2306 break;
2307 case OPC_SDL:
2308 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
2309 break;
2310 case OPC_SDR:
2311 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
2312 break;
2313 #endif
2314 case OPC_SW:
2315 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
2316 ctx->default_tcg_memop_mask);
2317 break;
2318 case OPC_SH:
2319 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
2320 ctx->default_tcg_memop_mask);
2321 break;
2322 case OPC_SB:
2323 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_8);
2324 break;
2325 case OPC_SWL:
2326 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
2327 break;
2328 case OPC_SWR:
2329 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
2330 break;
2332 tcg_temp_free(t0);
2333 tcg_temp_free(t1);
2337 /* Store conditional */
2338 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
2339 int base, int16_t offset)
2341 TCGv t0, t1;
2343 #ifdef CONFIG_USER_ONLY
2344 t0 = tcg_temp_local_new();
2345 t1 = tcg_temp_local_new();
2346 #else
2347 t0 = tcg_temp_new();
2348 t1 = tcg_temp_new();
2349 #endif
2350 gen_base_offset_addr(ctx, t0, base, offset);
2351 gen_load_gpr(t1, rt);
2352 switch (opc) {
2353 #if defined(TARGET_MIPS64)
2354 case OPC_SCD:
2355 case R6_OPC_SCD:
2356 op_st_scd(t1, t0, rt, ctx);
2357 break;
2358 #endif
2359 case OPC_SC:
2360 case R6_OPC_SC:
2361 op_st_sc(t1, t0, rt, ctx);
2362 break;
2364 tcg_temp_free(t1);
2365 tcg_temp_free(t0);
2368 /* Load and store */
2369 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
2370 int base, int16_t offset)
2372 TCGv t0 = tcg_temp_new();
2374 gen_base_offset_addr(ctx, t0, base, offset);
2375 /* Don't do NOP if destination is zero: we must perform the actual
2376 memory access. */
2377 switch (opc) {
2378 case OPC_LWC1:
2380 TCGv_i32 fp0 = tcg_temp_new_i32();
2381 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
2382 ctx->default_tcg_memop_mask);
2383 gen_store_fpr32(ctx, fp0, ft);
2384 tcg_temp_free_i32(fp0);
2386 break;
2387 case OPC_SWC1:
2389 TCGv_i32 fp0 = tcg_temp_new_i32();
2390 gen_load_fpr32(ctx, fp0, ft);
2391 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
2392 ctx->default_tcg_memop_mask);
2393 tcg_temp_free_i32(fp0);
2395 break;
2396 case OPC_LDC1:
2398 TCGv_i64 fp0 = tcg_temp_new_i64();
2399 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2400 ctx->default_tcg_memop_mask);
2401 gen_store_fpr64(ctx, fp0, ft);
2402 tcg_temp_free_i64(fp0);
2404 break;
2405 case OPC_SDC1:
2407 TCGv_i64 fp0 = tcg_temp_new_i64();
2408 gen_load_fpr64(ctx, fp0, ft);
2409 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2410 ctx->default_tcg_memop_mask);
2411 tcg_temp_free_i64(fp0);
2413 break;
2414 default:
2415 MIPS_INVAL("flt_ldst");
2416 generate_exception_end(ctx, EXCP_RI);
2417 goto out;
2419 out:
2420 tcg_temp_free(t0);
2423 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2424 int rs, int16_t imm)
2426 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
2427 check_cp1_enabled(ctx);
2428 switch (op) {
2429 case OPC_LDC1:
2430 case OPC_SDC1:
2431 check_insn(ctx, ISA_MIPS2);
2432 /* Fallthrough */
2433 default:
2434 gen_flt_ldst(ctx, op, rt, rs, imm);
2436 } else {
2437 generate_exception_err(ctx, EXCP_CpU, 1);
2441 /* Arithmetic with immediate operand */
2442 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
2443 int rt, int rs, int16_t imm)
2445 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2447 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
2448 /* If no destination, treat it as a NOP.
2449 For addi, we must generate the overflow exception when needed. */
2450 return;
2452 switch (opc) {
2453 case OPC_ADDI:
2455 TCGv t0 = tcg_temp_local_new();
2456 TCGv t1 = tcg_temp_new();
2457 TCGv t2 = tcg_temp_new();
2458 TCGLabel *l1 = gen_new_label();
2460 gen_load_gpr(t1, rs);
2461 tcg_gen_addi_tl(t0, t1, uimm);
2462 tcg_gen_ext32s_tl(t0, t0);
2464 tcg_gen_xori_tl(t1, t1, ~uimm);
2465 tcg_gen_xori_tl(t2, t0, uimm);
2466 tcg_gen_and_tl(t1, t1, t2);
2467 tcg_temp_free(t2);
2468 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2469 tcg_temp_free(t1);
2470 /* operands of same sign, result different sign */
2471 generate_exception(ctx, EXCP_OVERFLOW);
2472 gen_set_label(l1);
2473 tcg_gen_ext32s_tl(t0, t0);
2474 gen_store_gpr(t0, rt);
2475 tcg_temp_free(t0);
2477 break;
2478 case OPC_ADDIU:
2479 if (rs != 0) {
2480 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2481 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2482 } else {
2483 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2485 break;
2486 #if defined(TARGET_MIPS64)
2487 case OPC_DADDI:
2489 TCGv t0 = tcg_temp_local_new();
2490 TCGv t1 = tcg_temp_new();
2491 TCGv t2 = tcg_temp_new();
2492 TCGLabel *l1 = gen_new_label();
2494 gen_load_gpr(t1, rs);
2495 tcg_gen_addi_tl(t0, t1, uimm);
2497 tcg_gen_xori_tl(t1, t1, ~uimm);
2498 tcg_gen_xori_tl(t2, t0, uimm);
2499 tcg_gen_and_tl(t1, t1, t2);
2500 tcg_temp_free(t2);
2501 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2502 tcg_temp_free(t1);
2503 /* operands of same sign, result different sign */
2504 generate_exception(ctx, EXCP_OVERFLOW);
2505 gen_set_label(l1);
2506 gen_store_gpr(t0, rt);
2507 tcg_temp_free(t0);
2509 break;
2510 case OPC_DADDIU:
2511 if (rs != 0) {
2512 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2513 } else {
2514 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2516 break;
2517 #endif
2521 /* Logic with immediate operand */
2522 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
2523 int rt, int rs, int16_t imm)
2525 target_ulong uimm;
2527 if (rt == 0) {
2528 /* If no destination, treat it as a NOP. */
2529 return;
2531 uimm = (uint16_t)imm;
2532 switch (opc) {
2533 case OPC_ANDI:
2534 if (likely(rs != 0))
2535 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2536 else
2537 tcg_gen_movi_tl(cpu_gpr[rt], 0);
2538 break;
2539 case OPC_ORI:
2540 if (rs != 0)
2541 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2542 else
2543 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2544 break;
2545 case OPC_XORI:
2546 if (likely(rs != 0))
2547 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2548 else
2549 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2550 break;
2551 case OPC_LUI:
2552 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
2553 /* OPC_AUI */
2554 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
2555 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2556 } else {
2557 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
2559 break;
2561 default:
2562 break;
2566 /* Set on less than with immediate operand */
2567 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
2568 int rt, int rs, int16_t imm)
2570 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2571 TCGv t0;
2573 if (rt == 0) {
2574 /* If no destination, treat it as a NOP. */
2575 return;
2577 t0 = tcg_temp_new();
2578 gen_load_gpr(t0, rs);
2579 switch (opc) {
2580 case OPC_SLTI:
2581 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
2582 break;
2583 case OPC_SLTIU:
2584 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
2585 break;
2587 tcg_temp_free(t0);
2590 /* Shifts with immediate operand */
2591 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
2592 int rt, int rs, int16_t imm)
2594 target_ulong uimm = ((uint16_t)imm) & 0x1f;
2595 TCGv t0;
2597 if (rt == 0) {
2598 /* If no destination, treat it as a NOP. */
2599 return;
2602 t0 = tcg_temp_new();
2603 gen_load_gpr(t0, rs);
2604 switch (opc) {
2605 case OPC_SLL:
2606 tcg_gen_shli_tl(t0, t0, uimm);
2607 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2608 break;
2609 case OPC_SRA:
2610 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2611 break;
2612 case OPC_SRL:
2613 if (uimm != 0) {
2614 tcg_gen_ext32u_tl(t0, t0);
2615 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2616 } else {
2617 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2619 break;
2620 case OPC_ROTR:
2621 if (uimm != 0) {
2622 TCGv_i32 t1 = tcg_temp_new_i32();
2624 tcg_gen_trunc_tl_i32(t1, t0);
2625 tcg_gen_rotri_i32(t1, t1, uimm);
2626 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2627 tcg_temp_free_i32(t1);
2628 } else {
2629 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2631 break;
2632 #if defined(TARGET_MIPS64)
2633 case OPC_DSLL:
2634 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
2635 break;
2636 case OPC_DSRA:
2637 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2638 break;
2639 case OPC_DSRL:
2640 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2641 break;
2642 case OPC_DROTR:
2643 if (uimm != 0) {
2644 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
2645 } else {
2646 tcg_gen_mov_tl(cpu_gpr[rt], t0);
2648 break;
2649 case OPC_DSLL32:
2650 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
2651 break;
2652 case OPC_DSRA32:
2653 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
2654 break;
2655 case OPC_DSRL32:
2656 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
2657 break;
2658 case OPC_DROTR32:
2659 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
2660 break;
2661 #endif
2663 tcg_temp_free(t0);
2666 /* Arithmetic */
2667 static void gen_arith(DisasContext *ctx, uint32_t opc,
2668 int rd, int rs, int rt)
2670 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2671 && opc != OPC_DADD && opc != OPC_DSUB) {
2672 /* If no destination, treat it as a NOP.
2673 For add & sub, we must generate the overflow exception when needed. */
2674 return;
2677 switch (opc) {
2678 case OPC_ADD:
2680 TCGv t0 = tcg_temp_local_new();
2681 TCGv t1 = tcg_temp_new();
2682 TCGv t2 = tcg_temp_new();
2683 TCGLabel *l1 = gen_new_label();
2685 gen_load_gpr(t1, rs);
2686 gen_load_gpr(t2, rt);
2687 tcg_gen_add_tl(t0, t1, t2);
2688 tcg_gen_ext32s_tl(t0, t0);
2689 tcg_gen_xor_tl(t1, t1, t2);
2690 tcg_gen_xor_tl(t2, t0, t2);
2691 tcg_gen_andc_tl(t1, t2, t1);
2692 tcg_temp_free(t2);
2693 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2694 tcg_temp_free(t1);
2695 /* operands of same sign, result different sign */
2696 generate_exception(ctx, EXCP_OVERFLOW);
2697 gen_set_label(l1);
2698 gen_store_gpr(t0, rd);
2699 tcg_temp_free(t0);
2701 break;
2702 case OPC_ADDU:
2703 if (rs != 0 && rt != 0) {
2704 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2705 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2706 } else if (rs == 0 && rt != 0) {
2707 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2708 } else if (rs != 0 && rt == 0) {
2709 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2710 } else {
2711 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2713 break;
2714 case OPC_SUB:
2716 TCGv t0 = tcg_temp_local_new();
2717 TCGv t1 = tcg_temp_new();
2718 TCGv t2 = tcg_temp_new();
2719 TCGLabel *l1 = gen_new_label();
2721 gen_load_gpr(t1, rs);
2722 gen_load_gpr(t2, rt);
2723 tcg_gen_sub_tl(t0, t1, t2);
2724 tcg_gen_ext32s_tl(t0, t0);
2725 tcg_gen_xor_tl(t2, t1, t2);
2726 tcg_gen_xor_tl(t1, t0, t1);
2727 tcg_gen_and_tl(t1, t1, t2);
2728 tcg_temp_free(t2);
2729 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2730 tcg_temp_free(t1);
2731 /* operands of different sign, first operand and result different sign */
2732 generate_exception(ctx, EXCP_OVERFLOW);
2733 gen_set_label(l1);
2734 gen_store_gpr(t0, rd);
2735 tcg_temp_free(t0);
2737 break;
2738 case OPC_SUBU:
2739 if (rs != 0 && rt != 0) {
2740 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2741 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2742 } else if (rs == 0 && rt != 0) {
2743 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2744 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2745 } else if (rs != 0 && rt == 0) {
2746 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2747 } else {
2748 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2750 break;
2751 #if defined(TARGET_MIPS64)
2752 case OPC_DADD:
2754 TCGv t0 = tcg_temp_local_new();
2755 TCGv t1 = tcg_temp_new();
2756 TCGv t2 = tcg_temp_new();
2757 TCGLabel *l1 = gen_new_label();
2759 gen_load_gpr(t1, rs);
2760 gen_load_gpr(t2, rt);
2761 tcg_gen_add_tl(t0, t1, t2);
2762 tcg_gen_xor_tl(t1, t1, t2);
2763 tcg_gen_xor_tl(t2, t0, t2);
2764 tcg_gen_andc_tl(t1, t2, t1);
2765 tcg_temp_free(t2);
2766 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2767 tcg_temp_free(t1);
2768 /* operands of same sign, result different sign */
2769 generate_exception(ctx, EXCP_OVERFLOW);
2770 gen_set_label(l1);
2771 gen_store_gpr(t0, rd);
2772 tcg_temp_free(t0);
2774 break;
2775 case OPC_DADDU:
2776 if (rs != 0 && rt != 0) {
2777 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2778 } else if (rs == 0 && rt != 0) {
2779 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2780 } else if (rs != 0 && rt == 0) {
2781 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2782 } else {
2783 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2785 break;
2786 case OPC_DSUB:
2788 TCGv t0 = tcg_temp_local_new();
2789 TCGv t1 = tcg_temp_new();
2790 TCGv t2 = tcg_temp_new();
2791 TCGLabel *l1 = gen_new_label();
2793 gen_load_gpr(t1, rs);
2794 gen_load_gpr(t2, rt);
2795 tcg_gen_sub_tl(t0, t1, t2);
2796 tcg_gen_xor_tl(t2, t1, t2);
2797 tcg_gen_xor_tl(t1, t0, t1);
2798 tcg_gen_and_tl(t1, t1, t2);
2799 tcg_temp_free(t2);
2800 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2801 tcg_temp_free(t1);
2802 /* operands of different sign, first operand and result different sign */
2803 generate_exception(ctx, EXCP_OVERFLOW);
2804 gen_set_label(l1);
2805 gen_store_gpr(t0, rd);
2806 tcg_temp_free(t0);
2808 break;
2809 case OPC_DSUBU:
2810 if (rs != 0 && rt != 0) {
2811 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2812 } else if (rs == 0 && rt != 0) {
2813 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2814 } else if (rs != 0 && rt == 0) {
2815 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2816 } else {
2817 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2819 break;
2820 #endif
2821 case OPC_MUL:
2822 if (likely(rs != 0 && rt != 0)) {
2823 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2824 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2825 } else {
2826 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2828 break;
2832 /* Conditional move */
2833 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
2834 int rd, int rs, int rt)
2836 TCGv t0, t1, t2;
2838 if (rd == 0) {
2839 /* If no destination, treat it as a NOP. */
2840 return;
2843 t0 = tcg_temp_new();
2844 gen_load_gpr(t0, rt);
2845 t1 = tcg_const_tl(0);
2846 t2 = tcg_temp_new();
2847 gen_load_gpr(t2, rs);
2848 switch (opc) {
2849 case OPC_MOVN:
2850 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2851 break;
2852 case OPC_MOVZ:
2853 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2854 break;
2855 case OPC_SELNEZ:
2856 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
2857 break;
2858 case OPC_SELEQZ:
2859 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
2860 break;
2862 tcg_temp_free(t2);
2863 tcg_temp_free(t1);
2864 tcg_temp_free(t0);
2867 /* Logic */
2868 static void gen_logic(DisasContext *ctx, uint32_t opc,
2869 int rd, int rs, int rt)
2871 if (rd == 0) {
2872 /* If no destination, treat it as a NOP. */
2873 return;
2876 switch (opc) {
2877 case OPC_AND:
2878 if (likely(rs != 0 && rt != 0)) {
2879 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2880 } else {
2881 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2883 break;
2884 case OPC_NOR:
2885 if (rs != 0 && rt != 0) {
2886 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2887 } else if (rs == 0 && rt != 0) {
2888 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2889 } else if (rs != 0 && rt == 0) {
2890 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2891 } else {
2892 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2894 break;
2895 case OPC_OR:
2896 if (likely(rs != 0 && rt != 0)) {
2897 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2898 } else if (rs == 0 && rt != 0) {
2899 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2900 } else if (rs != 0 && rt == 0) {
2901 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2902 } else {
2903 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2905 break;
2906 case OPC_XOR:
2907 if (likely(rs != 0 && rt != 0)) {
2908 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2909 } else if (rs == 0 && rt != 0) {
2910 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2911 } else if (rs != 0 && rt == 0) {
2912 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2913 } else {
2914 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2916 break;
2920 /* Set on lower than */
2921 static void gen_slt(DisasContext *ctx, uint32_t opc,
2922 int rd, int rs, int rt)
2924 TCGv t0, t1;
2926 if (rd == 0) {
2927 /* If no destination, treat it as a NOP. */
2928 return;
2931 t0 = tcg_temp_new();
2932 t1 = tcg_temp_new();
2933 gen_load_gpr(t0, rs);
2934 gen_load_gpr(t1, rt);
2935 switch (opc) {
2936 case OPC_SLT:
2937 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
2938 break;
2939 case OPC_SLTU:
2940 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
2941 break;
2943 tcg_temp_free(t0);
2944 tcg_temp_free(t1);
2947 /* Shifts */
2948 static void gen_shift(DisasContext *ctx, uint32_t opc,
2949 int rd, int rs, int rt)
2951 TCGv t0, t1;
2953 if (rd == 0) {
2954 /* If no destination, treat it as a NOP.
2955 For add & sub, we must generate the overflow exception when needed. */
2956 return;
2959 t0 = tcg_temp_new();
2960 t1 = tcg_temp_new();
2961 gen_load_gpr(t0, rs);
2962 gen_load_gpr(t1, rt);
2963 switch (opc) {
2964 case OPC_SLLV:
2965 tcg_gen_andi_tl(t0, t0, 0x1f);
2966 tcg_gen_shl_tl(t0, t1, t0);
2967 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2968 break;
2969 case OPC_SRAV:
2970 tcg_gen_andi_tl(t0, t0, 0x1f);
2971 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
2972 break;
2973 case OPC_SRLV:
2974 tcg_gen_ext32u_tl(t1, t1);
2975 tcg_gen_andi_tl(t0, t0, 0x1f);
2976 tcg_gen_shr_tl(t0, t1, t0);
2977 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2978 break;
2979 case OPC_ROTRV:
2981 TCGv_i32 t2 = tcg_temp_new_i32();
2982 TCGv_i32 t3 = tcg_temp_new_i32();
2984 tcg_gen_trunc_tl_i32(t2, t0);
2985 tcg_gen_trunc_tl_i32(t3, t1);
2986 tcg_gen_andi_i32(t2, t2, 0x1f);
2987 tcg_gen_rotr_i32(t2, t3, t2);
2988 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
2989 tcg_temp_free_i32(t2);
2990 tcg_temp_free_i32(t3);
2992 break;
2993 #if defined(TARGET_MIPS64)
2994 case OPC_DSLLV:
2995 tcg_gen_andi_tl(t0, t0, 0x3f);
2996 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
2997 break;
2998 case OPC_DSRAV:
2999 tcg_gen_andi_tl(t0, t0, 0x3f);
3000 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3001 break;
3002 case OPC_DSRLV:
3003 tcg_gen_andi_tl(t0, t0, 0x3f);
3004 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
3005 break;
3006 case OPC_DROTRV:
3007 tcg_gen_andi_tl(t0, t0, 0x3f);
3008 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
3009 break;
3010 #endif
3012 tcg_temp_free(t0);
3013 tcg_temp_free(t1);
3016 /* Arithmetic on HI/LO registers */
3017 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
3019 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
3020 /* Treat as NOP. */
3021 return;
3024 if (acc != 0) {
3025 check_dsp(ctx);
3028 switch (opc) {
3029 case OPC_MFHI:
3030 #if defined(TARGET_MIPS64)
3031 if (acc != 0) {
3032 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
3033 } else
3034 #endif
3036 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
3038 break;
3039 case OPC_MFLO:
3040 #if defined(TARGET_MIPS64)
3041 if (acc != 0) {
3042 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
3043 } else
3044 #endif
3046 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
3048 break;
3049 case OPC_MTHI:
3050 if (reg != 0) {
3051 #if defined(TARGET_MIPS64)
3052 if (acc != 0) {
3053 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
3054 } else
3055 #endif
3057 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
3059 } else {
3060 tcg_gen_movi_tl(cpu_HI[acc], 0);
3062 break;
3063 case OPC_MTLO:
3064 if (reg != 0) {
3065 #if defined(TARGET_MIPS64)
3066 if (acc != 0) {
3067 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
3068 } else
3069 #endif
3071 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
3073 } else {
3074 tcg_gen_movi_tl(cpu_LO[acc], 0);
3076 break;
3080 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
3081 TCGMemOp memop)
3083 TCGv t0 = tcg_const_tl(addr);
3084 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
3085 gen_store_gpr(t0, reg);
3086 tcg_temp_free(t0);
3089 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
3090 int rs)
3092 target_long offset;
3093 target_long addr;
3095 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
3096 case OPC_ADDIUPC:
3097 if (rs != 0) {
3098 offset = sextract32(ctx->opcode << 2, 0, 21);
3099 addr = addr_add(ctx, pc, offset);
3100 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3102 break;
3103 case R6_OPC_LWPC:
3104 offset = sextract32(ctx->opcode << 2, 0, 21);
3105 addr = addr_add(ctx, pc, offset);
3106 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
3107 break;
3108 #if defined(TARGET_MIPS64)
3109 case OPC_LWUPC:
3110 check_mips_64(ctx);
3111 offset = sextract32(ctx->opcode << 2, 0, 21);
3112 addr = addr_add(ctx, pc, offset);
3113 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
3114 break;
3115 #endif
3116 default:
3117 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
3118 case OPC_AUIPC:
3119 if (rs != 0) {
3120 offset = sextract32(ctx->opcode, 0, 16) << 16;
3121 addr = addr_add(ctx, pc, offset);
3122 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3124 break;
3125 case OPC_ALUIPC:
3126 if (rs != 0) {
3127 offset = sextract32(ctx->opcode, 0, 16) << 16;
3128 addr = ~0xFFFF & addr_add(ctx, pc, offset);
3129 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3131 break;
3132 #if defined(TARGET_MIPS64)
3133 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
3134 case R6_OPC_LDPC + (1 << 16):
3135 case R6_OPC_LDPC + (2 << 16):
3136 case R6_OPC_LDPC + (3 << 16):
3137 check_mips_64(ctx);
3138 offset = sextract32(ctx->opcode << 3, 0, 21);
3139 addr = addr_add(ctx, (pc & ~0x7), offset);
3140 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
3141 break;
3142 #endif
3143 default:
3144 MIPS_INVAL("OPC_PCREL");
3145 generate_exception_end(ctx, EXCP_RI);
3146 break;
3148 break;
3152 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
3154 TCGv t0, t1;
3156 if (rd == 0) {
3157 /* Treat as NOP. */
3158 return;
3161 t0 = tcg_temp_new();
3162 t1 = tcg_temp_new();
3164 gen_load_gpr(t0, rs);
3165 gen_load_gpr(t1, rt);
3167 switch (opc) {
3168 case R6_OPC_DIV:
3170 TCGv t2 = tcg_temp_new();
3171 TCGv t3 = tcg_temp_new();
3172 tcg_gen_ext32s_tl(t0, t0);
3173 tcg_gen_ext32s_tl(t1, t1);
3174 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3175 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3176 tcg_gen_and_tl(t2, t2, t3);
3177 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3178 tcg_gen_or_tl(t2, t2, t3);
3179 tcg_gen_movi_tl(t3, 0);
3180 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3181 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3182 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3183 tcg_temp_free(t3);
3184 tcg_temp_free(t2);
3186 break;
3187 case R6_OPC_MOD:
3189 TCGv t2 = tcg_temp_new();
3190 TCGv t3 = tcg_temp_new();
3191 tcg_gen_ext32s_tl(t0, t0);
3192 tcg_gen_ext32s_tl(t1, t1);
3193 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3194 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3195 tcg_gen_and_tl(t2, t2, t3);
3196 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3197 tcg_gen_or_tl(t2, t2, t3);
3198 tcg_gen_movi_tl(t3, 0);
3199 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3200 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3201 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3202 tcg_temp_free(t3);
3203 tcg_temp_free(t2);
3205 break;
3206 case R6_OPC_DIVU:
3208 TCGv t2 = tcg_const_tl(0);
3209 TCGv t3 = tcg_const_tl(1);
3210 tcg_gen_ext32u_tl(t0, t0);
3211 tcg_gen_ext32u_tl(t1, t1);
3212 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3213 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3214 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3215 tcg_temp_free(t3);
3216 tcg_temp_free(t2);
3218 break;
3219 case R6_OPC_MODU:
3221 TCGv t2 = tcg_const_tl(0);
3222 TCGv t3 = tcg_const_tl(1);
3223 tcg_gen_ext32u_tl(t0, t0);
3224 tcg_gen_ext32u_tl(t1, t1);
3225 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3226 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3227 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3228 tcg_temp_free(t3);
3229 tcg_temp_free(t2);
3231 break;
3232 case R6_OPC_MUL:
3234 TCGv_i32 t2 = tcg_temp_new_i32();
3235 TCGv_i32 t3 = tcg_temp_new_i32();
3236 tcg_gen_trunc_tl_i32(t2, t0);
3237 tcg_gen_trunc_tl_i32(t3, t1);
3238 tcg_gen_mul_i32(t2, t2, t3);
3239 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3240 tcg_temp_free_i32(t2);
3241 tcg_temp_free_i32(t3);
3243 break;
3244 case R6_OPC_MUH:
3246 TCGv_i32 t2 = tcg_temp_new_i32();
3247 TCGv_i32 t3 = tcg_temp_new_i32();
3248 tcg_gen_trunc_tl_i32(t2, t0);
3249 tcg_gen_trunc_tl_i32(t3, t1);
3250 tcg_gen_muls2_i32(t2, t3, t2, t3);
3251 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3252 tcg_temp_free_i32(t2);
3253 tcg_temp_free_i32(t3);
3255 break;
3256 case R6_OPC_MULU:
3258 TCGv_i32 t2 = tcg_temp_new_i32();
3259 TCGv_i32 t3 = tcg_temp_new_i32();
3260 tcg_gen_trunc_tl_i32(t2, t0);
3261 tcg_gen_trunc_tl_i32(t3, t1);
3262 tcg_gen_mul_i32(t2, t2, t3);
3263 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3264 tcg_temp_free_i32(t2);
3265 tcg_temp_free_i32(t3);
3267 break;
3268 case R6_OPC_MUHU:
3270 TCGv_i32 t2 = tcg_temp_new_i32();
3271 TCGv_i32 t3 = tcg_temp_new_i32();
3272 tcg_gen_trunc_tl_i32(t2, t0);
3273 tcg_gen_trunc_tl_i32(t3, t1);
3274 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3275 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3276 tcg_temp_free_i32(t2);
3277 tcg_temp_free_i32(t3);
3279 break;
3280 #if defined(TARGET_MIPS64)
3281 case R6_OPC_DDIV:
3283 TCGv t2 = tcg_temp_new();
3284 TCGv t3 = tcg_temp_new();
3285 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3286 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3287 tcg_gen_and_tl(t2, t2, t3);
3288 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3289 tcg_gen_or_tl(t2, t2, t3);
3290 tcg_gen_movi_tl(t3, 0);
3291 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3292 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3293 tcg_temp_free(t3);
3294 tcg_temp_free(t2);
3296 break;
3297 case R6_OPC_DMOD:
3299 TCGv t2 = tcg_temp_new();
3300 TCGv t3 = tcg_temp_new();
3301 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3302 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3303 tcg_gen_and_tl(t2, t2, t3);
3304 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3305 tcg_gen_or_tl(t2, t2, t3);
3306 tcg_gen_movi_tl(t3, 0);
3307 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3308 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3309 tcg_temp_free(t3);
3310 tcg_temp_free(t2);
3312 break;
3313 case R6_OPC_DDIVU:
3315 TCGv t2 = tcg_const_tl(0);
3316 TCGv t3 = tcg_const_tl(1);
3317 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3318 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
3319 tcg_temp_free(t3);
3320 tcg_temp_free(t2);
3322 break;
3323 case R6_OPC_DMODU:
3325 TCGv t2 = tcg_const_tl(0);
3326 TCGv t3 = tcg_const_tl(1);
3327 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3328 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
3329 tcg_temp_free(t3);
3330 tcg_temp_free(t2);
3332 break;
3333 case R6_OPC_DMUL:
3334 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3335 break;
3336 case R6_OPC_DMUH:
3338 TCGv t2 = tcg_temp_new();
3339 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
3340 tcg_temp_free(t2);
3342 break;
3343 case R6_OPC_DMULU:
3344 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3345 break;
3346 case R6_OPC_DMUHU:
3348 TCGv t2 = tcg_temp_new();
3349 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
3350 tcg_temp_free(t2);
3352 break;
3353 #endif
3354 default:
3355 MIPS_INVAL("r6 mul/div");
3356 generate_exception_end(ctx, EXCP_RI);
3357 goto out;
3359 out:
3360 tcg_temp_free(t0);
3361 tcg_temp_free(t1);
3364 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3365 int acc, int rs, int rt)
3367 TCGv t0, t1;
3369 t0 = tcg_temp_new();
3370 t1 = tcg_temp_new();
3372 gen_load_gpr(t0, rs);
3373 gen_load_gpr(t1, rt);
3375 if (acc != 0) {
3376 check_dsp(ctx);
3379 switch (opc) {
3380 case OPC_DIV:
3382 TCGv t2 = tcg_temp_new();
3383 TCGv t3 = tcg_temp_new();
3384 tcg_gen_ext32s_tl(t0, t0);
3385 tcg_gen_ext32s_tl(t1, t1);
3386 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3387 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3388 tcg_gen_and_tl(t2, t2, t3);
3389 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3390 tcg_gen_or_tl(t2, t2, t3);
3391 tcg_gen_movi_tl(t3, 0);
3392 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3393 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3394 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3395 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3396 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3397 tcg_temp_free(t3);
3398 tcg_temp_free(t2);
3400 break;
3401 case OPC_DIVU:
3403 TCGv t2 = tcg_const_tl(0);
3404 TCGv t3 = tcg_const_tl(1);
3405 tcg_gen_ext32u_tl(t0, t0);
3406 tcg_gen_ext32u_tl(t1, t1);
3407 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3408 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3409 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3410 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3411 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3412 tcg_temp_free(t3);
3413 tcg_temp_free(t2);
3415 break;
3416 case OPC_MULT:
3418 TCGv_i32 t2 = tcg_temp_new_i32();
3419 TCGv_i32 t3 = tcg_temp_new_i32();
3420 tcg_gen_trunc_tl_i32(t2, t0);
3421 tcg_gen_trunc_tl_i32(t3, t1);
3422 tcg_gen_muls2_i32(t2, t3, t2, t3);
3423 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3424 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3425 tcg_temp_free_i32(t2);
3426 tcg_temp_free_i32(t3);
3428 break;
3429 case OPC_MULTU:
3431 TCGv_i32 t2 = tcg_temp_new_i32();
3432 TCGv_i32 t3 = tcg_temp_new_i32();
3433 tcg_gen_trunc_tl_i32(t2, t0);
3434 tcg_gen_trunc_tl_i32(t3, t1);
3435 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3436 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3437 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3438 tcg_temp_free_i32(t2);
3439 tcg_temp_free_i32(t3);
3441 break;
3442 #if defined(TARGET_MIPS64)
3443 case OPC_DDIV:
3445 TCGv t2 = tcg_temp_new();
3446 TCGv t3 = tcg_temp_new();
3447 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3448 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3449 tcg_gen_and_tl(t2, t2, t3);
3450 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3451 tcg_gen_or_tl(t2, t2, t3);
3452 tcg_gen_movi_tl(t3, 0);
3453 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3454 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3455 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3456 tcg_temp_free(t3);
3457 tcg_temp_free(t2);
3459 break;
3460 case OPC_DDIVU:
3462 TCGv t2 = tcg_const_tl(0);
3463 TCGv t3 = tcg_const_tl(1);
3464 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3465 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3466 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
3467 tcg_temp_free(t3);
3468 tcg_temp_free(t2);
3470 break;
3471 case OPC_DMULT:
3472 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3473 break;
3474 case OPC_DMULTU:
3475 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3476 break;
3477 #endif
3478 case OPC_MADD:
3480 TCGv_i64 t2 = tcg_temp_new_i64();
3481 TCGv_i64 t3 = tcg_temp_new_i64();
3483 tcg_gen_ext_tl_i64(t2, t0);
3484 tcg_gen_ext_tl_i64(t3, t1);
3485 tcg_gen_mul_i64(t2, t2, t3);
3486 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3487 tcg_gen_add_i64(t2, t2, t3);
3488 tcg_temp_free_i64(t3);
3489 gen_move_low32(cpu_LO[acc], t2);
3490 gen_move_high32(cpu_HI[acc], t2);
3491 tcg_temp_free_i64(t2);
3493 break;
3494 case OPC_MADDU:
3496 TCGv_i64 t2 = tcg_temp_new_i64();
3497 TCGv_i64 t3 = tcg_temp_new_i64();
3499 tcg_gen_ext32u_tl(t0, t0);
3500 tcg_gen_ext32u_tl(t1, t1);
3501 tcg_gen_extu_tl_i64(t2, t0);
3502 tcg_gen_extu_tl_i64(t3, t1);
3503 tcg_gen_mul_i64(t2, t2, t3);
3504 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3505 tcg_gen_add_i64(t2, t2, t3);
3506 tcg_temp_free_i64(t3);
3507 gen_move_low32(cpu_LO[acc], t2);
3508 gen_move_high32(cpu_HI[acc], t2);
3509 tcg_temp_free_i64(t2);
3511 break;
3512 case OPC_MSUB:
3514 TCGv_i64 t2 = tcg_temp_new_i64();
3515 TCGv_i64 t3 = tcg_temp_new_i64();
3517 tcg_gen_ext_tl_i64(t2, t0);
3518 tcg_gen_ext_tl_i64(t3, t1);
3519 tcg_gen_mul_i64(t2, t2, t3);
3520 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3521 tcg_gen_sub_i64(t2, t3, t2);
3522 tcg_temp_free_i64(t3);
3523 gen_move_low32(cpu_LO[acc], t2);
3524 gen_move_high32(cpu_HI[acc], t2);
3525 tcg_temp_free_i64(t2);
3527 break;
3528 case OPC_MSUBU:
3530 TCGv_i64 t2 = tcg_temp_new_i64();
3531 TCGv_i64 t3 = tcg_temp_new_i64();
3533 tcg_gen_ext32u_tl(t0, t0);
3534 tcg_gen_ext32u_tl(t1, t1);
3535 tcg_gen_extu_tl_i64(t2, t0);
3536 tcg_gen_extu_tl_i64(t3, t1);
3537 tcg_gen_mul_i64(t2, t2, t3);
3538 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3539 tcg_gen_sub_i64(t2, t3, t2);
3540 tcg_temp_free_i64(t3);
3541 gen_move_low32(cpu_LO[acc], t2);
3542 gen_move_high32(cpu_HI[acc], t2);
3543 tcg_temp_free_i64(t2);
3545 break;
3546 default:
3547 MIPS_INVAL("mul/div");
3548 generate_exception_end(ctx, EXCP_RI);
3549 goto out;
3551 out:
3552 tcg_temp_free(t0);
3553 tcg_temp_free(t1);
3556 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
3557 int rd, int rs, int rt)
3559 TCGv t0 = tcg_temp_new();
3560 TCGv t1 = tcg_temp_new();
3562 gen_load_gpr(t0, rs);
3563 gen_load_gpr(t1, rt);
3565 switch (opc) {
3566 case OPC_VR54XX_MULS:
3567 gen_helper_muls(t0, cpu_env, t0, t1);
3568 break;
3569 case OPC_VR54XX_MULSU:
3570 gen_helper_mulsu(t0, cpu_env, t0, t1);
3571 break;
3572 case OPC_VR54XX_MACC:
3573 gen_helper_macc(t0, cpu_env, t0, t1);
3574 break;
3575 case OPC_VR54XX_MACCU:
3576 gen_helper_maccu(t0, cpu_env, t0, t1);
3577 break;
3578 case OPC_VR54XX_MSAC:
3579 gen_helper_msac(t0, cpu_env, t0, t1);
3580 break;
3581 case OPC_VR54XX_MSACU:
3582 gen_helper_msacu(t0, cpu_env, t0, t1);
3583 break;
3584 case OPC_VR54XX_MULHI:
3585 gen_helper_mulhi(t0, cpu_env, t0, t1);
3586 break;
3587 case OPC_VR54XX_MULHIU:
3588 gen_helper_mulhiu(t0, cpu_env, t0, t1);
3589 break;
3590 case OPC_VR54XX_MULSHI:
3591 gen_helper_mulshi(t0, cpu_env, t0, t1);
3592 break;
3593 case OPC_VR54XX_MULSHIU:
3594 gen_helper_mulshiu(t0, cpu_env, t0, t1);
3595 break;
3596 case OPC_VR54XX_MACCHI:
3597 gen_helper_macchi(t0, cpu_env, t0, t1);
3598 break;
3599 case OPC_VR54XX_MACCHIU:
3600 gen_helper_macchiu(t0, cpu_env, t0, t1);
3601 break;
3602 case OPC_VR54XX_MSACHI:
3603 gen_helper_msachi(t0, cpu_env, t0, t1);
3604 break;
3605 case OPC_VR54XX_MSACHIU:
3606 gen_helper_msachiu(t0, cpu_env, t0, t1);
3607 break;
3608 default:
3609 MIPS_INVAL("mul vr54xx");
3610 generate_exception_end(ctx, EXCP_RI);
3611 goto out;
3613 gen_store_gpr(t0, rd);
3615 out:
3616 tcg_temp_free(t0);
3617 tcg_temp_free(t1);
3620 static void gen_cl (DisasContext *ctx, uint32_t opc,
3621 int rd, int rs)
3623 TCGv t0;
3625 if (rd == 0) {
3626 /* Treat as NOP. */
3627 return;
3629 t0 = cpu_gpr[rd];
3630 gen_load_gpr(t0, rs);
3632 switch (opc) {
3633 case OPC_CLO:
3634 case R6_OPC_CLO:
3635 #if defined(TARGET_MIPS64)
3636 case OPC_DCLO:
3637 case R6_OPC_DCLO:
3638 #endif
3639 tcg_gen_not_tl(t0, t0);
3640 break;
3643 switch (opc) {
3644 case OPC_CLO:
3645 case R6_OPC_CLO:
3646 case OPC_CLZ:
3647 case R6_OPC_CLZ:
3648 tcg_gen_ext32u_tl(t0, t0);
3649 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
3650 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
3651 break;
3652 #if defined(TARGET_MIPS64)
3653 case OPC_DCLO:
3654 case R6_OPC_DCLO:
3655 case OPC_DCLZ:
3656 case R6_OPC_DCLZ:
3657 tcg_gen_clzi_i64(t0, t0, 64);
3658 break;
3659 #endif
3663 /* Godson integer instructions */
3664 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
3665 int rd, int rs, int rt)
3667 TCGv t0, t1;
3669 if (rd == 0) {
3670 /* Treat as NOP. */
3671 return;
3674 switch (opc) {
3675 case OPC_MULT_G_2E:
3676 case OPC_MULT_G_2F:
3677 case OPC_MULTU_G_2E:
3678 case OPC_MULTU_G_2F:
3679 #if defined(TARGET_MIPS64)
3680 case OPC_DMULT_G_2E:
3681 case OPC_DMULT_G_2F:
3682 case OPC_DMULTU_G_2E:
3683 case OPC_DMULTU_G_2F:
3684 #endif
3685 t0 = tcg_temp_new();
3686 t1 = tcg_temp_new();
3687 break;
3688 default:
3689 t0 = tcg_temp_local_new();
3690 t1 = tcg_temp_local_new();
3691 break;
3694 gen_load_gpr(t0, rs);
3695 gen_load_gpr(t1, rt);
3697 switch (opc) {
3698 case OPC_MULT_G_2E:
3699 case OPC_MULT_G_2F:
3700 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3701 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3702 break;
3703 case OPC_MULTU_G_2E:
3704 case OPC_MULTU_G_2F:
3705 tcg_gen_ext32u_tl(t0, t0);
3706 tcg_gen_ext32u_tl(t1, t1);
3707 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3708 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3709 break;
3710 case OPC_DIV_G_2E:
3711 case OPC_DIV_G_2F:
3713 TCGLabel *l1 = gen_new_label();
3714 TCGLabel *l2 = gen_new_label();
3715 TCGLabel *l3 = gen_new_label();
3716 tcg_gen_ext32s_tl(t0, t0);
3717 tcg_gen_ext32s_tl(t1, t1);
3718 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3719 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3720 tcg_gen_br(l3);
3721 gen_set_label(l1);
3722 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3723 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3724 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3725 tcg_gen_br(l3);
3726 gen_set_label(l2);
3727 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3728 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3729 gen_set_label(l3);
3731 break;
3732 case OPC_DIVU_G_2E:
3733 case OPC_DIVU_G_2F:
3735 TCGLabel *l1 = gen_new_label();
3736 TCGLabel *l2 = gen_new_label();
3737 tcg_gen_ext32u_tl(t0, t0);
3738 tcg_gen_ext32u_tl(t1, t1);
3739 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3740 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3741 tcg_gen_br(l2);
3742 gen_set_label(l1);
3743 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3744 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3745 gen_set_label(l2);
3747 break;
3748 case OPC_MOD_G_2E:
3749 case OPC_MOD_G_2F:
3751 TCGLabel *l1 = gen_new_label();
3752 TCGLabel *l2 = gen_new_label();
3753 TCGLabel *l3 = gen_new_label();
3754 tcg_gen_ext32u_tl(t0, t0);
3755 tcg_gen_ext32u_tl(t1, t1);
3756 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3757 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3758 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3759 gen_set_label(l1);
3760 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3761 tcg_gen_br(l3);
3762 gen_set_label(l2);
3763 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3764 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3765 gen_set_label(l3);
3767 break;
3768 case OPC_MODU_G_2E:
3769 case OPC_MODU_G_2F:
3771 TCGLabel *l1 = gen_new_label();
3772 TCGLabel *l2 = gen_new_label();
3773 tcg_gen_ext32u_tl(t0, t0);
3774 tcg_gen_ext32u_tl(t1, t1);
3775 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3776 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3777 tcg_gen_br(l2);
3778 gen_set_label(l1);
3779 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3780 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3781 gen_set_label(l2);
3783 break;
3784 #if defined(TARGET_MIPS64)
3785 case OPC_DMULT_G_2E:
3786 case OPC_DMULT_G_2F:
3787 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3788 break;
3789 case OPC_DMULTU_G_2E:
3790 case OPC_DMULTU_G_2F:
3791 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3792 break;
3793 case OPC_DDIV_G_2E:
3794 case OPC_DDIV_G_2F:
3796 TCGLabel *l1 = gen_new_label();
3797 TCGLabel *l2 = gen_new_label();
3798 TCGLabel *l3 = gen_new_label();
3799 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3800 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3801 tcg_gen_br(l3);
3802 gen_set_label(l1);
3803 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3804 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3805 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3806 tcg_gen_br(l3);
3807 gen_set_label(l2);
3808 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3809 gen_set_label(l3);
3811 break;
3812 case OPC_DDIVU_G_2E:
3813 case OPC_DDIVU_G_2F:
3815 TCGLabel *l1 = gen_new_label();
3816 TCGLabel *l2 = gen_new_label();
3817 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3818 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3819 tcg_gen_br(l2);
3820 gen_set_label(l1);
3821 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3822 gen_set_label(l2);
3824 break;
3825 case OPC_DMOD_G_2E:
3826 case OPC_DMOD_G_2F:
3828 TCGLabel *l1 = gen_new_label();
3829 TCGLabel *l2 = gen_new_label();
3830 TCGLabel *l3 = gen_new_label();
3831 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3832 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3833 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3834 gen_set_label(l1);
3835 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3836 tcg_gen_br(l3);
3837 gen_set_label(l2);
3838 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3839 gen_set_label(l3);
3841 break;
3842 case OPC_DMODU_G_2E:
3843 case OPC_DMODU_G_2F:
3845 TCGLabel *l1 = gen_new_label();
3846 TCGLabel *l2 = gen_new_label();
3847 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3848 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3849 tcg_gen_br(l2);
3850 gen_set_label(l1);
3851 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3852 gen_set_label(l2);
3854 break;
3855 #endif
3858 tcg_temp_free(t0);
3859 tcg_temp_free(t1);
3862 /* Loongson multimedia instructions */
3863 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
3865 uint32_t opc, shift_max;
3866 TCGv_i64 t0, t1;
3868 opc = MASK_LMI(ctx->opcode);
3869 switch (opc) {
3870 case OPC_ADD_CP2:
3871 case OPC_SUB_CP2:
3872 case OPC_DADD_CP2:
3873 case OPC_DSUB_CP2:
3874 t0 = tcg_temp_local_new_i64();
3875 t1 = tcg_temp_local_new_i64();
3876 break;
3877 default:
3878 t0 = tcg_temp_new_i64();
3879 t1 = tcg_temp_new_i64();
3880 break;
3883 check_cp1_enabled(ctx);
3884 gen_load_fpr64(ctx, t0, rs);
3885 gen_load_fpr64(ctx, t1, rt);
3887 #define LMI_HELPER(UP, LO) \
3888 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
3889 #define LMI_HELPER_1(UP, LO) \
3890 case OPC_##UP: gen_helper_##LO(t0, t0); break
3891 #define LMI_DIRECT(UP, LO, OP) \
3892 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
3894 switch (opc) {
3895 LMI_HELPER(PADDSH, paddsh);
3896 LMI_HELPER(PADDUSH, paddush);
3897 LMI_HELPER(PADDH, paddh);
3898 LMI_HELPER(PADDW, paddw);
3899 LMI_HELPER(PADDSB, paddsb);
3900 LMI_HELPER(PADDUSB, paddusb);
3901 LMI_HELPER(PADDB, paddb);
3903 LMI_HELPER(PSUBSH, psubsh);
3904 LMI_HELPER(PSUBUSH, psubush);
3905 LMI_HELPER(PSUBH, psubh);
3906 LMI_HELPER(PSUBW, psubw);
3907 LMI_HELPER(PSUBSB, psubsb);
3908 LMI_HELPER(PSUBUSB, psubusb);
3909 LMI_HELPER(PSUBB, psubb);
3911 LMI_HELPER(PSHUFH, pshufh);
3912 LMI_HELPER(PACKSSWH, packsswh);
3913 LMI_HELPER(PACKSSHB, packsshb);
3914 LMI_HELPER(PACKUSHB, packushb);
3916 LMI_HELPER(PUNPCKLHW, punpcklhw);
3917 LMI_HELPER(PUNPCKHHW, punpckhhw);
3918 LMI_HELPER(PUNPCKLBH, punpcklbh);
3919 LMI_HELPER(PUNPCKHBH, punpckhbh);
3920 LMI_HELPER(PUNPCKLWD, punpcklwd);
3921 LMI_HELPER(PUNPCKHWD, punpckhwd);
3923 LMI_HELPER(PAVGH, pavgh);
3924 LMI_HELPER(PAVGB, pavgb);
3925 LMI_HELPER(PMAXSH, pmaxsh);
3926 LMI_HELPER(PMINSH, pminsh);
3927 LMI_HELPER(PMAXUB, pmaxub);
3928 LMI_HELPER(PMINUB, pminub);
3930 LMI_HELPER(PCMPEQW, pcmpeqw);
3931 LMI_HELPER(PCMPGTW, pcmpgtw);
3932 LMI_HELPER(PCMPEQH, pcmpeqh);
3933 LMI_HELPER(PCMPGTH, pcmpgth);
3934 LMI_HELPER(PCMPEQB, pcmpeqb);
3935 LMI_HELPER(PCMPGTB, pcmpgtb);
3937 LMI_HELPER(PSLLW, psllw);
3938 LMI_HELPER(PSLLH, psllh);
3939 LMI_HELPER(PSRLW, psrlw);
3940 LMI_HELPER(PSRLH, psrlh);
3941 LMI_HELPER(PSRAW, psraw);
3942 LMI_HELPER(PSRAH, psrah);
3944 LMI_HELPER(PMULLH, pmullh);
3945 LMI_HELPER(PMULHH, pmulhh);
3946 LMI_HELPER(PMULHUH, pmulhuh);
3947 LMI_HELPER(PMADDHW, pmaddhw);
3949 LMI_HELPER(PASUBUB, pasubub);
3950 LMI_HELPER_1(BIADD, biadd);
3951 LMI_HELPER_1(PMOVMSKB, pmovmskb);
3953 LMI_DIRECT(PADDD, paddd, add);
3954 LMI_DIRECT(PSUBD, psubd, sub);
3955 LMI_DIRECT(XOR_CP2, xor, xor);
3956 LMI_DIRECT(NOR_CP2, nor, nor);
3957 LMI_DIRECT(AND_CP2, and, and);
3958 LMI_DIRECT(OR_CP2, or, or);
3960 case OPC_PANDN:
3961 tcg_gen_andc_i64(t0, t1, t0);
3962 break;
3964 case OPC_PINSRH_0:
3965 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
3966 break;
3967 case OPC_PINSRH_1:
3968 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
3969 break;
3970 case OPC_PINSRH_2:
3971 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
3972 break;
3973 case OPC_PINSRH_3:
3974 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
3975 break;
3977 case OPC_PEXTRH:
3978 tcg_gen_andi_i64(t1, t1, 3);
3979 tcg_gen_shli_i64(t1, t1, 4);
3980 tcg_gen_shr_i64(t0, t0, t1);
3981 tcg_gen_ext16u_i64(t0, t0);
3982 break;
3984 case OPC_ADDU_CP2:
3985 tcg_gen_add_i64(t0, t0, t1);
3986 tcg_gen_ext32s_i64(t0, t0);
3987 break;
3988 case OPC_SUBU_CP2:
3989 tcg_gen_sub_i64(t0, t0, t1);
3990 tcg_gen_ext32s_i64(t0, t0);
3991 break;
3993 case OPC_SLL_CP2:
3994 shift_max = 32;
3995 goto do_shift;
3996 case OPC_SRL_CP2:
3997 shift_max = 32;
3998 goto do_shift;
3999 case OPC_SRA_CP2:
4000 shift_max = 32;
4001 goto do_shift;
4002 case OPC_DSLL_CP2:
4003 shift_max = 64;
4004 goto do_shift;
4005 case OPC_DSRL_CP2:
4006 shift_max = 64;
4007 goto do_shift;
4008 case OPC_DSRA_CP2:
4009 shift_max = 64;
4010 goto do_shift;
4011 do_shift:
4012 /* Make sure shift count isn't TCG undefined behaviour. */
4013 tcg_gen_andi_i64(t1, t1, shift_max - 1);
4015 switch (opc) {
4016 case OPC_SLL_CP2:
4017 case OPC_DSLL_CP2:
4018 tcg_gen_shl_i64(t0, t0, t1);
4019 break;
4020 case OPC_SRA_CP2:
4021 case OPC_DSRA_CP2:
4022 /* Since SRA is UndefinedResult without sign-extended inputs,
4023 we can treat SRA and DSRA the same. */
4024 tcg_gen_sar_i64(t0, t0, t1);
4025 break;
4026 case OPC_SRL_CP2:
4027 /* We want to shift in zeros for SRL; zero-extend first. */
4028 tcg_gen_ext32u_i64(t0, t0);
4029 /* FALLTHRU */
4030 case OPC_DSRL_CP2:
4031 tcg_gen_shr_i64(t0, t0, t1);
4032 break;
4035 if (shift_max == 32) {
4036 tcg_gen_ext32s_i64(t0, t0);
4039 /* Shifts larger than MAX produce zero. */
4040 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
4041 tcg_gen_neg_i64(t1, t1);
4042 tcg_gen_and_i64(t0, t0, t1);
4043 break;
4045 case OPC_ADD_CP2:
4046 case OPC_DADD_CP2:
4048 TCGv_i64 t2 = tcg_temp_new_i64();
4049 TCGLabel *lab = gen_new_label();
4051 tcg_gen_mov_i64(t2, t0);
4052 tcg_gen_add_i64(t0, t1, t2);
4053 if (opc == OPC_ADD_CP2) {
4054 tcg_gen_ext32s_i64(t0, t0);
4056 tcg_gen_xor_i64(t1, t1, t2);
4057 tcg_gen_xor_i64(t2, t2, t0);
4058 tcg_gen_andc_i64(t1, t2, t1);
4059 tcg_temp_free_i64(t2);
4060 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4061 generate_exception(ctx, EXCP_OVERFLOW);
4062 gen_set_label(lab);
4063 break;
4066 case OPC_SUB_CP2:
4067 case OPC_DSUB_CP2:
4069 TCGv_i64 t2 = tcg_temp_new_i64();
4070 TCGLabel *lab = gen_new_label();
4072 tcg_gen_mov_i64(t2, t0);
4073 tcg_gen_sub_i64(t0, t1, t2);
4074 if (opc == OPC_SUB_CP2) {
4075 tcg_gen_ext32s_i64(t0, t0);
4077 tcg_gen_xor_i64(t1, t1, t2);
4078 tcg_gen_xor_i64(t2, t2, t0);
4079 tcg_gen_and_i64(t1, t1, t2);
4080 tcg_temp_free_i64(t2);
4081 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4082 generate_exception(ctx, EXCP_OVERFLOW);
4083 gen_set_label(lab);
4084 break;
4087 case OPC_PMULUW:
4088 tcg_gen_ext32u_i64(t0, t0);
4089 tcg_gen_ext32u_i64(t1, t1);
4090 tcg_gen_mul_i64(t0, t0, t1);
4091 break;
4093 case OPC_SEQU_CP2:
4094 case OPC_SEQ_CP2:
4095 case OPC_SLTU_CP2:
4096 case OPC_SLT_CP2:
4097 case OPC_SLEU_CP2:
4098 case OPC_SLE_CP2:
4099 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
4100 FD field is the CC field? */
4101 default:
4102 MIPS_INVAL("loongson_cp2");
4103 generate_exception_end(ctx, EXCP_RI);
4104 return;
4107 #undef LMI_HELPER
4108 #undef LMI_DIRECT
4110 gen_store_fpr64(ctx, t0, rd);
4112 tcg_temp_free_i64(t0);
4113 tcg_temp_free_i64(t1);
4116 /* Traps */
4117 static void gen_trap (DisasContext *ctx, uint32_t opc,
4118 int rs, int rt, int16_t imm)
4120 int cond;
4121 TCGv t0 = tcg_temp_new();
4122 TCGv t1 = tcg_temp_new();
4124 cond = 0;
4125 /* Load needed operands */
4126 switch (opc) {
4127 case OPC_TEQ:
4128 case OPC_TGE:
4129 case OPC_TGEU:
4130 case OPC_TLT:
4131 case OPC_TLTU:
4132 case OPC_TNE:
4133 /* Compare two registers */
4134 if (rs != rt) {
4135 gen_load_gpr(t0, rs);
4136 gen_load_gpr(t1, rt);
4137 cond = 1;
4139 break;
4140 case OPC_TEQI:
4141 case OPC_TGEI:
4142 case OPC_TGEIU:
4143 case OPC_TLTI:
4144 case OPC_TLTIU:
4145 case OPC_TNEI:
4146 /* Compare register to immediate */
4147 if (rs != 0 || imm != 0) {
4148 gen_load_gpr(t0, rs);
4149 tcg_gen_movi_tl(t1, (int32_t)imm);
4150 cond = 1;
4152 break;
4154 if (cond == 0) {
4155 switch (opc) {
4156 case OPC_TEQ: /* rs == rs */
4157 case OPC_TEQI: /* r0 == 0 */
4158 case OPC_TGE: /* rs >= rs */
4159 case OPC_TGEI: /* r0 >= 0 */
4160 case OPC_TGEU: /* rs >= rs unsigned */
4161 case OPC_TGEIU: /* r0 >= 0 unsigned */
4162 /* Always trap */
4163 generate_exception_end(ctx, EXCP_TRAP);
4164 break;
4165 case OPC_TLT: /* rs < rs */
4166 case OPC_TLTI: /* r0 < 0 */
4167 case OPC_TLTU: /* rs < rs unsigned */
4168 case OPC_TLTIU: /* r0 < 0 unsigned */
4169 case OPC_TNE: /* rs != rs */
4170 case OPC_TNEI: /* r0 != 0 */
4171 /* Never trap: treat as NOP. */
4172 break;
4174 } else {
4175 TCGLabel *l1 = gen_new_label();
4177 switch (opc) {
4178 case OPC_TEQ:
4179 case OPC_TEQI:
4180 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
4181 break;
4182 case OPC_TGE:
4183 case OPC_TGEI:
4184 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
4185 break;
4186 case OPC_TGEU:
4187 case OPC_TGEIU:
4188 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
4189 break;
4190 case OPC_TLT:
4191 case OPC_TLTI:
4192 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4193 break;
4194 case OPC_TLTU:
4195 case OPC_TLTIU:
4196 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
4197 break;
4198 case OPC_TNE:
4199 case OPC_TNEI:
4200 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
4201 break;
4203 generate_exception(ctx, EXCP_TRAP);
4204 gen_set_label(l1);
4206 tcg_temp_free(t0);
4207 tcg_temp_free(t1);
4210 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
4212 if (unlikely(ctx->singlestep_enabled)) {
4213 return false;
4216 #ifndef CONFIG_USER_ONLY
4217 return (ctx->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
4218 #else
4219 return true;
4220 #endif
4223 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
4225 if (use_goto_tb(ctx, dest)) {
4226 tcg_gen_goto_tb(n);
4227 gen_save_pc(dest);
4228 tcg_gen_exit_tb((uintptr_t)ctx->tb + n);
4229 } else {
4230 gen_save_pc(dest);
4231 if (ctx->singlestep_enabled) {
4232 save_cpu_state(ctx, 0);
4233 gen_helper_raise_exception_debug(cpu_env);
4235 tcg_gen_exit_tb(0);
4239 /* Branches (before delay slot) */
4240 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
4241 int insn_bytes,
4242 int rs, int rt, int32_t offset,
4243 int delayslot_size)
4245 target_ulong btgt = -1;
4246 int blink = 0;
4247 int bcond_compute = 0;
4248 TCGv t0 = tcg_temp_new();
4249 TCGv t1 = tcg_temp_new();
4251 if (ctx->hflags & MIPS_HFLAG_BMASK) {
4252 #ifdef MIPS_DEBUG_DISAS
4253 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
4254 TARGET_FMT_lx "\n", ctx->pc);
4255 #endif
4256 generate_exception_end(ctx, EXCP_RI);
4257 goto out;
4260 /* Load needed operands */
4261 switch (opc) {
4262 case OPC_BEQ:
4263 case OPC_BEQL:
4264 case OPC_BNE:
4265 case OPC_BNEL:
4266 /* Compare two registers */
4267 if (rs != rt) {
4268 gen_load_gpr(t0, rs);
4269 gen_load_gpr(t1, rt);
4270 bcond_compute = 1;
4272 btgt = ctx->pc + insn_bytes + offset;
4273 break;
4274 case OPC_BGEZ:
4275 case OPC_BGEZAL:
4276 case OPC_BGEZALL:
4277 case OPC_BGEZL:
4278 case OPC_BGTZ:
4279 case OPC_BGTZL:
4280 case OPC_BLEZ:
4281 case OPC_BLEZL:
4282 case OPC_BLTZ:
4283 case OPC_BLTZAL:
4284 case OPC_BLTZALL:
4285 case OPC_BLTZL:
4286 /* Compare to zero */
4287 if (rs != 0) {
4288 gen_load_gpr(t0, rs);
4289 bcond_compute = 1;
4291 btgt = ctx->pc + insn_bytes + offset;
4292 break;
4293 case OPC_BPOSGE32:
4294 #if defined(TARGET_MIPS64)
4295 case OPC_BPOSGE64:
4296 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
4297 #else
4298 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
4299 #endif
4300 bcond_compute = 1;
4301 btgt = ctx->pc + insn_bytes + offset;
4302 break;
4303 case OPC_J:
4304 case OPC_JAL:
4305 case OPC_JALX:
4306 /* Jump to immediate */
4307 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
4308 break;
4309 case OPC_JR:
4310 case OPC_JALR:
4311 /* Jump to register */
4312 if (offset != 0 && offset != 16) {
4313 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
4314 others are reserved. */
4315 MIPS_INVAL("jump hint");
4316 generate_exception_end(ctx, EXCP_RI);
4317 goto out;
4319 gen_load_gpr(btarget, rs);
4320 break;
4321 default:
4322 MIPS_INVAL("branch/jump");
4323 generate_exception_end(ctx, EXCP_RI);
4324 goto out;
4326 if (bcond_compute == 0) {
4327 /* No condition to be computed */
4328 switch (opc) {
4329 case OPC_BEQ: /* rx == rx */
4330 case OPC_BEQL: /* rx == rx likely */
4331 case OPC_BGEZ: /* 0 >= 0 */
4332 case OPC_BGEZL: /* 0 >= 0 likely */
4333 case OPC_BLEZ: /* 0 <= 0 */
4334 case OPC_BLEZL: /* 0 <= 0 likely */
4335 /* Always take */
4336 ctx->hflags |= MIPS_HFLAG_B;
4337 break;
4338 case OPC_BGEZAL: /* 0 >= 0 */
4339 case OPC_BGEZALL: /* 0 >= 0 likely */
4340 /* Always take and link */
4341 blink = 31;
4342 ctx->hflags |= MIPS_HFLAG_B;
4343 break;
4344 case OPC_BNE: /* rx != rx */
4345 case OPC_BGTZ: /* 0 > 0 */
4346 case OPC_BLTZ: /* 0 < 0 */
4347 /* Treat as NOP. */
4348 goto out;
4349 case OPC_BLTZAL: /* 0 < 0 */
4350 /* Handle as an unconditional branch to get correct delay
4351 slot checking. */
4352 blink = 31;
4353 btgt = ctx->pc + insn_bytes + delayslot_size;
4354 ctx->hflags |= MIPS_HFLAG_B;
4355 break;
4356 case OPC_BLTZALL: /* 0 < 0 likely */
4357 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
4358 /* Skip the instruction in the delay slot */
4359 ctx->pc += 4;
4360 goto out;
4361 case OPC_BNEL: /* rx != rx likely */
4362 case OPC_BGTZL: /* 0 > 0 likely */
4363 case OPC_BLTZL: /* 0 < 0 likely */
4364 /* Skip the instruction in the delay slot */
4365 ctx->pc += 4;
4366 goto out;
4367 case OPC_J:
4368 ctx->hflags |= MIPS_HFLAG_B;
4369 break;
4370 case OPC_JALX:
4371 ctx->hflags |= MIPS_HFLAG_BX;
4372 /* Fallthrough */
4373 case OPC_JAL:
4374 blink = 31;
4375 ctx->hflags |= MIPS_HFLAG_B;
4376 break;
4377 case OPC_JR:
4378 ctx->hflags |= MIPS_HFLAG_BR;
4379 break;
4380 case OPC_JALR:
4381 blink = rt;
4382 ctx->hflags |= MIPS_HFLAG_BR;
4383 break;
4384 default:
4385 MIPS_INVAL("branch/jump");
4386 generate_exception_end(ctx, EXCP_RI);
4387 goto out;
4389 } else {
4390 switch (opc) {
4391 case OPC_BEQ:
4392 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4393 goto not_likely;
4394 case OPC_BEQL:
4395 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4396 goto likely;
4397 case OPC_BNE:
4398 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4399 goto not_likely;
4400 case OPC_BNEL:
4401 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4402 goto likely;
4403 case OPC_BGEZ:
4404 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4405 goto not_likely;
4406 case OPC_BGEZL:
4407 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4408 goto likely;
4409 case OPC_BGEZAL:
4410 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4411 blink = 31;
4412 goto not_likely;
4413 case OPC_BGEZALL:
4414 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4415 blink = 31;
4416 goto likely;
4417 case OPC_BGTZ:
4418 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4419 goto not_likely;
4420 case OPC_BGTZL:
4421 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4422 goto likely;
4423 case OPC_BLEZ:
4424 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4425 goto not_likely;
4426 case OPC_BLEZL:
4427 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4428 goto likely;
4429 case OPC_BLTZ:
4430 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4431 goto not_likely;
4432 case OPC_BLTZL:
4433 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4434 goto likely;
4435 case OPC_BPOSGE32:
4436 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
4437 goto not_likely;
4438 #if defined(TARGET_MIPS64)
4439 case OPC_BPOSGE64:
4440 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
4441 goto not_likely;
4442 #endif
4443 case OPC_BLTZAL:
4444 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4445 blink = 31;
4446 not_likely:
4447 ctx->hflags |= MIPS_HFLAG_BC;
4448 break;
4449 case OPC_BLTZALL:
4450 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4451 blink = 31;
4452 likely:
4453 ctx->hflags |= MIPS_HFLAG_BL;
4454 break;
4455 default:
4456 MIPS_INVAL("conditional branch/jump");
4457 generate_exception_end(ctx, EXCP_RI);
4458 goto out;
4462 ctx->btarget = btgt;
4464 switch (delayslot_size) {
4465 case 2:
4466 ctx->hflags |= MIPS_HFLAG_BDS16;
4467 break;
4468 case 4:
4469 ctx->hflags |= MIPS_HFLAG_BDS32;
4470 break;
4473 if (blink > 0) {
4474 int post_delay = insn_bytes + delayslot_size;
4475 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
4477 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
4480 out:
4481 if (insn_bytes == 2)
4482 ctx->hflags |= MIPS_HFLAG_B16;
4483 tcg_temp_free(t0);
4484 tcg_temp_free(t1);
4487 /* special3 bitfield operations */
4488 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
4489 int rs, int lsb, int msb)
4491 TCGv t0 = tcg_temp_new();
4492 TCGv t1 = tcg_temp_new();
4494 gen_load_gpr(t1, rs);
4495 switch (opc) {
4496 case OPC_EXT:
4497 if (lsb + msb > 31) {
4498 goto fail;
4500 if (msb != 31) {
4501 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
4502 } else {
4503 /* The two checks together imply that lsb == 0,
4504 so this is a simple sign-extension. */
4505 tcg_gen_ext32s_tl(t0, t1);
4507 break;
4508 #if defined(TARGET_MIPS64)
4509 case OPC_DEXTU:
4510 lsb += 32;
4511 goto do_dext;
4512 case OPC_DEXTM:
4513 msb += 32;
4514 goto do_dext;
4515 case OPC_DEXT:
4516 do_dext:
4517 if (lsb + msb > 63) {
4518 goto fail;
4520 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
4521 break;
4522 #endif
4523 case OPC_INS:
4524 if (lsb > msb) {
4525 goto fail;
4527 gen_load_gpr(t0, rt);
4528 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4529 tcg_gen_ext32s_tl(t0, t0);
4530 break;
4531 #if defined(TARGET_MIPS64)
4532 case OPC_DINSU:
4533 lsb += 32;
4534 /* FALLTHRU */
4535 case OPC_DINSM:
4536 msb += 32;
4537 /* FALLTHRU */
4538 case OPC_DINS:
4539 if (lsb > msb) {
4540 goto fail;
4542 gen_load_gpr(t0, rt);
4543 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4544 break;
4545 #endif
4546 default:
4547 fail:
4548 MIPS_INVAL("bitops");
4549 generate_exception_end(ctx, EXCP_RI);
4550 tcg_temp_free(t0);
4551 tcg_temp_free(t1);
4552 return;
4554 gen_store_gpr(t0, rt);
4555 tcg_temp_free(t0);
4556 tcg_temp_free(t1);
4559 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
4561 TCGv t0;
4563 if (rd == 0) {
4564 /* If no destination, treat it as a NOP. */
4565 return;
4568 t0 = tcg_temp_new();
4569 gen_load_gpr(t0, rt);
4570 switch (op2) {
4571 case OPC_WSBH:
4573 TCGv t1 = tcg_temp_new();
4575 tcg_gen_shri_tl(t1, t0, 8);
4576 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
4577 tcg_gen_shli_tl(t0, t0, 8);
4578 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
4579 tcg_gen_or_tl(t0, t0, t1);
4580 tcg_temp_free(t1);
4581 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4583 break;
4584 case OPC_SEB:
4585 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
4586 break;
4587 case OPC_SEH:
4588 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
4589 break;
4590 #if defined(TARGET_MIPS64)
4591 case OPC_DSBH:
4593 TCGv t1 = tcg_temp_new();
4595 tcg_gen_shri_tl(t1, t0, 8);
4596 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
4597 tcg_gen_shli_tl(t0, t0, 8);
4598 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
4599 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4600 tcg_temp_free(t1);
4602 break;
4603 case OPC_DSHD:
4605 TCGv t1 = tcg_temp_new();
4607 tcg_gen_shri_tl(t1, t0, 16);
4608 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
4609 tcg_gen_shli_tl(t0, t0, 16);
4610 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
4611 tcg_gen_or_tl(t0, t0, t1);
4612 tcg_gen_shri_tl(t1, t0, 32);
4613 tcg_gen_shli_tl(t0, t0, 32);
4614 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4615 tcg_temp_free(t1);
4617 break;
4618 #endif
4619 default:
4620 MIPS_INVAL("bsfhl");
4621 generate_exception_end(ctx, EXCP_RI);
4622 tcg_temp_free(t0);
4623 return;
4625 tcg_temp_free(t0);
4628 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
4629 int imm2)
4631 TCGv t0;
4632 TCGv t1;
4633 if (rd == 0) {
4634 /* Treat as NOP. */
4635 return;
4637 t0 = tcg_temp_new();
4638 t1 = tcg_temp_new();
4639 gen_load_gpr(t0, rs);
4640 gen_load_gpr(t1, rt);
4641 tcg_gen_shli_tl(t0, t0, imm2 + 1);
4642 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
4643 if (opc == OPC_LSA) {
4644 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4647 tcg_temp_free(t1);
4648 tcg_temp_free(t0);
4650 return;
4653 static void gen_align(DisasContext *ctx, int opc, int rd, int rs, int rt,
4654 int bp)
4656 TCGv t0;
4657 if (rd == 0) {
4658 /* Treat as NOP. */
4659 return;
4661 t0 = tcg_temp_new();
4662 gen_load_gpr(t0, rt);
4663 if (bp == 0) {
4664 switch (opc) {
4665 case OPC_ALIGN:
4666 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4667 break;
4668 #if defined(TARGET_MIPS64)
4669 case OPC_DALIGN:
4670 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4671 break;
4672 #endif
4674 } else {
4675 TCGv t1 = tcg_temp_new();
4676 gen_load_gpr(t1, rs);
4677 switch (opc) {
4678 case OPC_ALIGN:
4680 TCGv_i64 t2 = tcg_temp_new_i64();
4681 tcg_gen_concat_tl_i64(t2, t1, t0);
4682 tcg_gen_shri_i64(t2, t2, 8 * (4 - bp));
4683 gen_move_low32(cpu_gpr[rd], t2);
4684 tcg_temp_free_i64(t2);
4686 break;
4687 #if defined(TARGET_MIPS64)
4688 case OPC_DALIGN:
4689 tcg_gen_shli_tl(t0, t0, 8 * bp);
4690 tcg_gen_shri_tl(t1, t1, 8 * (8 - bp));
4691 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
4692 break;
4693 #endif
4695 tcg_temp_free(t1);
4698 tcg_temp_free(t0);
4701 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
4703 TCGv t0;
4704 if (rd == 0) {
4705 /* Treat as NOP. */
4706 return;
4708 t0 = tcg_temp_new();
4709 gen_load_gpr(t0, rt);
4710 switch (opc) {
4711 case OPC_BITSWAP:
4712 gen_helper_bitswap(cpu_gpr[rd], t0);
4713 break;
4714 #if defined(TARGET_MIPS64)
4715 case OPC_DBITSWAP:
4716 gen_helper_dbitswap(cpu_gpr[rd], t0);
4717 break;
4718 #endif
4720 tcg_temp_free(t0);
4723 #ifndef CONFIG_USER_ONLY
4724 /* CP0 (MMU and control) */
4725 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
4727 TCGv_i64 t0 = tcg_temp_new_i64();
4728 TCGv_i64 t1 = tcg_temp_new_i64();
4730 tcg_gen_ext_tl_i64(t0, arg);
4731 tcg_gen_ld_i64(t1, cpu_env, off);
4732 #if defined(TARGET_MIPS64)
4733 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
4734 #else
4735 tcg_gen_concat32_i64(t1, t1, t0);
4736 #endif
4737 tcg_gen_st_i64(t1, cpu_env, off);
4738 tcg_temp_free_i64(t1);
4739 tcg_temp_free_i64(t0);
4742 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
4744 TCGv_i64 t0 = tcg_temp_new_i64();
4745 TCGv_i64 t1 = tcg_temp_new_i64();
4747 tcg_gen_ext_tl_i64(t0, arg);
4748 tcg_gen_ld_i64(t1, cpu_env, off);
4749 tcg_gen_concat32_i64(t1, t1, t0);
4750 tcg_gen_st_i64(t1, cpu_env, off);
4751 tcg_temp_free_i64(t1);
4752 tcg_temp_free_i64(t0);
4755 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
4757 TCGv_i64 t0 = tcg_temp_new_i64();
4759 tcg_gen_ld_i64(t0, cpu_env, off);
4760 #if defined(TARGET_MIPS64)
4761 tcg_gen_shri_i64(t0, t0, 30);
4762 #else
4763 tcg_gen_shri_i64(t0, t0, 32);
4764 #endif
4765 gen_move_low32(arg, t0);
4766 tcg_temp_free_i64(t0);
4769 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
4771 TCGv_i64 t0 = tcg_temp_new_i64();
4773 tcg_gen_ld_i64(t0, cpu_env, off);
4774 tcg_gen_shri_i64(t0, t0, 32 + shift);
4775 gen_move_low32(arg, t0);
4776 tcg_temp_free_i64(t0);
4779 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
4781 TCGv_i32 t0 = tcg_temp_new_i32();
4783 tcg_gen_ld_i32(t0, cpu_env, off);
4784 tcg_gen_ext_i32_tl(arg, t0);
4785 tcg_temp_free_i32(t0);
4788 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
4790 tcg_gen_ld_tl(arg, cpu_env, off);
4791 tcg_gen_ext32s_tl(arg, arg);
4794 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
4796 TCGv_i32 t0 = tcg_temp_new_i32();
4798 tcg_gen_trunc_tl_i32(t0, arg);
4799 tcg_gen_st_i32(t0, cpu_env, off);
4800 tcg_temp_free_i32(t0);
4803 #define CP0_CHECK(c) \
4804 do { \
4805 if (!(c)) { \
4806 goto cp0_unimplemented; \
4808 } while (0)
4810 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4812 const char *rn = "invalid";
4814 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
4816 switch (reg) {
4817 case 2:
4818 switch (sel) {
4819 case 0:
4820 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
4821 rn = "EntryLo0";
4822 break;
4823 default:
4824 goto cp0_unimplemented;
4826 break;
4827 case 3:
4828 switch (sel) {
4829 case 0:
4830 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
4831 rn = "EntryLo1";
4832 break;
4833 default:
4834 goto cp0_unimplemented;
4836 break;
4837 case 17:
4838 switch (sel) {
4839 case 0:
4840 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
4841 ctx->CP0_LLAddr_shift);
4842 rn = "LLAddr";
4843 break;
4844 case 1:
4845 CP0_CHECK(ctx->mrp);
4846 gen_helper_mfhc0_maar(arg, cpu_env);
4847 rn = "MAAR";
4848 break;
4849 default:
4850 goto cp0_unimplemented;
4852 break;
4853 case 28:
4854 switch (sel) {
4855 case 0:
4856 case 2:
4857 case 4:
4858 case 6:
4859 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
4860 rn = "TagLo";
4861 break;
4862 default:
4863 goto cp0_unimplemented;
4865 break;
4866 default:
4867 goto cp0_unimplemented;
4870 (void)rn; /* avoid a compiler warning */
4871 LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
4872 return;
4874 cp0_unimplemented:
4875 LOG_DISAS("mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
4876 tcg_gen_movi_tl(arg, 0);
4879 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4881 const char *rn = "invalid";
4882 uint64_t mask = ctx->PAMask >> 36;
4884 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
4886 switch (reg) {
4887 case 2:
4888 switch (sel) {
4889 case 0:
4890 tcg_gen_andi_tl(arg, arg, mask);
4891 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
4892 rn = "EntryLo0";
4893 break;
4894 default:
4895 goto cp0_unimplemented;
4897 break;
4898 case 3:
4899 switch (sel) {
4900 case 0:
4901 tcg_gen_andi_tl(arg, arg, mask);
4902 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
4903 rn = "EntryLo1";
4904 break;
4905 default:
4906 goto cp0_unimplemented;
4908 break;
4909 case 17:
4910 switch (sel) {
4911 case 0:
4912 /* LLAddr is read-only (the only exception is bit 0 if LLB is
4913 supported); the CP0_LLAddr_rw_bitmask does not seem to be
4914 relevant for modern MIPS cores supporting MTHC0, therefore
4915 treating MTHC0 to LLAddr as NOP. */
4916 rn = "LLAddr";
4917 break;
4918 case 1:
4919 CP0_CHECK(ctx->mrp);
4920 gen_helper_mthc0_maar(cpu_env, arg);
4921 rn = "MAAR";
4922 break;
4923 default:
4924 goto cp0_unimplemented;
4926 break;
4927 case 28:
4928 switch (sel) {
4929 case 0:
4930 case 2:
4931 case 4:
4932 case 6:
4933 tcg_gen_andi_tl(arg, arg, mask);
4934 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
4935 rn = "TagLo";
4936 break;
4937 default:
4938 goto cp0_unimplemented;
4940 break;
4941 default:
4942 goto cp0_unimplemented;
4945 (void)rn; /* avoid a compiler warning */
4946 cp0_unimplemented:
4947 LOG_DISAS("mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
4950 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
4952 if (ctx->insn_flags & ISA_MIPS32R6) {
4953 tcg_gen_movi_tl(arg, 0);
4954 } else {
4955 tcg_gen_movi_tl(arg, ~0);
4959 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4961 const char *rn = "invalid";
4963 if (sel != 0)
4964 check_insn(ctx, ISA_MIPS32);
4966 switch (reg) {
4967 case 0:
4968 switch (sel) {
4969 case 0:
4970 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
4971 rn = "Index";
4972 break;
4973 case 1:
4974 CP0_CHECK(ctx->insn_flags & ASE_MT);
4975 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
4976 rn = "MVPControl";
4977 break;
4978 case 2:
4979 CP0_CHECK(ctx->insn_flags & ASE_MT);
4980 gen_helper_mfc0_mvpconf0(arg, cpu_env);
4981 rn = "MVPConf0";
4982 break;
4983 case 3:
4984 CP0_CHECK(ctx->insn_flags & ASE_MT);
4985 gen_helper_mfc0_mvpconf1(arg, cpu_env);
4986 rn = "MVPConf1";
4987 break;
4988 case 4:
4989 CP0_CHECK(ctx->vp);
4990 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
4991 rn = "VPControl";
4992 break;
4993 default:
4994 goto cp0_unimplemented;
4996 break;
4997 case 1:
4998 switch (sel) {
4999 case 0:
5000 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
5001 gen_helper_mfc0_random(arg, cpu_env);
5002 rn = "Random";
5003 break;
5004 case 1:
5005 CP0_CHECK(ctx->insn_flags & ASE_MT);
5006 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
5007 rn = "VPEControl";
5008 break;
5009 case 2:
5010 CP0_CHECK(ctx->insn_flags & ASE_MT);
5011 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
5012 rn = "VPEConf0";
5013 break;
5014 case 3:
5015 CP0_CHECK(ctx->insn_flags & ASE_MT);
5016 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
5017 rn = "VPEConf1";
5018 break;
5019 case 4:
5020 CP0_CHECK(ctx->insn_flags & ASE_MT);
5021 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
5022 rn = "YQMask";
5023 break;
5024 case 5:
5025 CP0_CHECK(ctx->insn_flags & ASE_MT);
5026 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
5027 rn = "VPESchedule";
5028 break;
5029 case 6:
5030 CP0_CHECK(ctx->insn_flags & ASE_MT);
5031 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5032 rn = "VPEScheFBack";
5033 break;
5034 case 7:
5035 CP0_CHECK(ctx->insn_flags & ASE_MT);
5036 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
5037 rn = "VPEOpt";
5038 break;
5039 default:
5040 goto cp0_unimplemented;
5042 break;
5043 case 2:
5044 switch (sel) {
5045 case 0:
5047 TCGv_i64 tmp = tcg_temp_new_i64();
5048 tcg_gen_ld_i64(tmp, cpu_env,
5049 offsetof(CPUMIPSState, CP0_EntryLo0));
5050 #if defined(TARGET_MIPS64)
5051 if (ctx->rxi) {
5052 /* Move RI/XI fields to bits 31:30 */
5053 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5054 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5056 #endif
5057 gen_move_low32(arg, tmp);
5058 tcg_temp_free_i64(tmp);
5060 rn = "EntryLo0";
5061 break;
5062 case 1:
5063 CP0_CHECK(ctx->insn_flags & ASE_MT);
5064 gen_helper_mfc0_tcstatus(arg, cpu_env);
5065 rn = "TCStatus";
5066 break;
5067 case 2:
5068 CP0_CHECK(ctx->insn_flags & ASE_MT);
5069 gen_helper_mfc0_tcbind(arg, cpu_env);
5070 rn = "TCBind";
5071 break;
5072 case 3:
5073 CP0_CHECK(ctx->insn_flags & ASE_MT);
5074 gen_helper_mfc0_tcrestart(arg, cpu_env);
5075 rn = "TCRestart";
5076 break;
5077 case 4:
5078 CP0_CHECK(ctx->insn_flags & ASE_MT);
5079 gen_helper_mfc0_tchalt(arg, cpu_env);
5080 rn = "TCHalt";
5081 break;
5082 case 5:
5083 CP0_CHECK(ctx->insn_flags & ASE_MT);
5084 gen_helper_mfc0_tccontext(arg, cpu_env);
5085 rn = "TCContext";
5086 break;
5087 case 6:
5088 CP0_CHECK(ctx->insn_flags & ASE_MT);
5089 gen_helper_mfc0_tcschedule(arg, cpu_env);
5090 rn = "TCSchedule";
5091 break;
5092 case 7:
5093 CP0_CHECK(ctx->insn_flags & ASE_MT);
5094 gen_helper_mfc0_tcschefback(arg, cpu_env);
5095 rn = "TCScheFBack";
5096 break;
5097 default:
5098 goto cp0_unimplemented;
5100 break;
5101 case 3:
5102 switch (sel) {
5103 case 0:
5105 TCGv_i64 tmp = tcg_temp_new_i64();
5106 tcg_gen_ld_i64(tmp, cpu_env,
5107 offsetof(CPUMIPSState, CP0_EntryLo1));
5108 #if defined(TARGET_MIPS64)
5109 if (ctx->rxi) {
5110 /* Move RI/XI fields to bits 31:30 */
5111 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5112 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5114 #endif
5115 gen_move_low32(arg, tmp);
5116 tcg_temp_free_i64(tmp);
5118 rn = "EntryLo1";
5119 break;
5120 case 1:
5121 CP0_CHECK(ctx->vp);
5122 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
5123 rn = "GlobalNumber";
5124 break;
5125 default:
5126 goto cp0_unimplemented;
5128 break;
5129 case 4:
5130 switch (sel) {
5131 case 0:
5132 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
5133 tcg_gen_ext32s_tl(arg, arg);
5134 rn = "Context";
5135 break;
5136 case 1:
5137 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
5138 rn = "ContextConfig";
5139 goto cp0_unimplemented;
5140 // break;
5141 case 2:
5142 CP0_CHECK(ctx->ulri);
5143 tcg_gen_ld32s_tl(arg, cpu_env,
5144 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5145 rn = "UserLocal";
5146 break;
5147 default:
5148 goto cp0_unimplemented;
5150 break;
5151 case 5:
5152 switch (sel) {
5153 case 0:
5154 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
5155 rn = "PageMask";
5156 break;
5157 case 1:
5158 check_insn(ctx, ISA_MIPS32R2);
5159 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
5160 rn = "PageGrain";
5161 break;
5162 default:
5163 goto cp0_unimplemented;
5165 break;
5166 case 6:
5167 switch (sel) {
5168 case 0:
5169 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
5170 rn = "Wired";
5171 break;
5172 case 1:
5173 check_insn(ctx, ISA_MIPS32R2);
5174 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
5175 rn = "SRSConf0";
5176 break;
5177 case 2:
5178 check_insn(ctx, ISA_MIPS32R2);
5179 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
5180 rn = "SRSConf1";
5181 break;
5182 case 3:
5183 check_insn(ctx, ISA_MIPS32R2);
5184 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
5185 rn = "SRSConf2";
5186 break;
5187 case 4:
5188 check_insn(ctx, ISA_MIPS32R2);
5189 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
5190 rn = "SRSConf3";
5191 break;
5192 case 5:
5193 check_insn(ctx, ISA_MIPS32R2);
5194 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
5195 rn = "SRSConf4";
5196 break;
5197 default:
5198 goto cp0_unimplemented;
5200 break;
5201 case 7:
5202 switch (sel) {
5203 case 0:
5204 check_insn(ctx, ISA_MIPS32R2);
5205 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
5206 rn = "HWREna";
5207 break;
5208 default:
5209 goto cp0_unimplemented;
5211 break;
5212 case 8:
5213 switch (sel) {
5214 case 0:
5215 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
5216 tcg_gen_ext32s_tl(arg, arg);
5217 rn = "BadVAddr";
5218 break;
5219 case 1:
5220 CP0_CHECK(ctx->bi);
5221 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
5222 rn = "BadInstr";
5223 break;
5224 case 2:
5225 CP0_CHECK(ctx->bp);
5226 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
5227 rn = "BadInstrP";
5228 break;
5229 default:
5230 goto cp0_unimplemented;
5232 break;
5233 case 9:
5234 switch (sel) {
5235 case 0:
5236 /* Mark as an IO operation because we read the time. */
5237 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5238 gen_io_start();
5240 gen_helper_mfc0_count(arg, cpu_env);
5241 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5242 gen_io_end();
5244 /* Break the TB to be able to take timer interrupts immediately
5245 after reading count. */
5246 ctx->bstate = BS_STOP;
5247 rn = "Count";
5248 break;
5249 /* 6,7 are implementation dependent */
5250 default:
5251 goto cp0_unimplemented;
5253 break;
5254 case 10:
5255 switch (sel) {
5256 case 0:
5257 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
5258 tcg_gen_ext32s_tl(arg, arg);
5259 rn = "EntryHi";
5260 break;
5261 default:
5262 goto cp0_unimplemented;
5264 break;
5265 case 11:
5266 switch (sel) {
5267 case 0:
5268 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
5269 rn = "Compare";
5270 break;
5271 /* 6,7 are implementation dependent */
5272 default:
5273 goto cp0_unimplemented;
5275 break;
5276 case 12:
5277 switch (sel) {
5278 case 0:
5279 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
5280 rn = "Status";
5281 break;
5282 case 1:
5283 check_insn(ctx, ISA_MIPS32R2);
5284 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
5285 rn = "IntCtl";
5286 break;
5287 case 2:
5288 check_insn(ctx, ISA_MIPS32R2);
5289 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
5290 rn = "SRSCtl";
5291 break;
5292 case 3:
5293 check_insn(ctx, ISA_MIPS32R2);
5294 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5295 rn = "SRSMap";
5296 break;
5297 default:
5298 goto cp0_unimplemented;
5300 break;
5301 case 13:
5302 switch (sel) {
5303 case 0:
5304 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
5305 rn = "Cause";
5306 break;
5307 default:
5308 goto cp0_unimplemented;
5310 break;
5311 case 14:
5312 switch (sel) {
5313 case 0:
5314 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
5315 tcg_gen_ext32s_tl(arg, arg);
5316 rn = "EPC";
5317 break;
5318 default:
5319 goto cp0_unimplemented;
5321 break;
5322 case 15:
5323 switch (sel) {
5324 case 0:
5325 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
5326 rn = "PRid";
5327 break;
5328 case 1:
5329 check_insn(ctx, ISA_MIPS32R2);
5330 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
5331 rn = "EBase";
5332 break;
5333 case 3:
5334 check_insn(ctx, ISA_MIPS32R2);
5335 CP0_CHECK(ctx->cmgcr);
5336 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
5337 tcg_gen_ext32s_tl(arg, arg);
5338 rn = "CMGCRBase";
5339 break;
5340 default:
5341 goto cp0_unimplemented;
5343 break;
5344 case 16:
5345 switch (sel) {
5346 case 0:
5347 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
5348 rn = "Config";
5349 break;
5350 case 1:
5351 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
5352 rn = "Config1";
5353 break;
5354 case 2:
5355 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
5356 rn = "Config2";
5357 break;
5358 case 3:
5359 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
5360 rn = "Config3";
5361 break;
5362 case 4:
5363 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
5364 rn = "Config4";
5365 break;
5366 case 5:
5367 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
5368 rn = "Config5";
5369 break;
5370 /* 6,7 are implementation dependent */
5371 case 6:
5372 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
5373 rn = "Config6";
5374 break;
5375 case 7:
5376 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
5377 rn = "Config7";
5378 break;
5379 default:
5380 goto cp0_unimplemented;
5382 break;
5383 case 17:
5384 switch (sel) {
5385 case 0:
5386 gen_helper_mfc0_lladdr(arg, cpu_env);
5387 rn = "LLAddr";
5388 break;
5389 case 1:
5390 CP0_CHECK(ctx->mrp);
5391 gen_helper_mfc0_maar(arg, cpu_env);
5392 rn = "MAAR";
5393 break;
5394 case 2:
5395 CP0_CHECK(ctx->mrp);
5396 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
5397 rn = "MAARI";
5398 break;
5399 default:
5400 goto cp0_unimplemented;
5402 break;
5403 case 18:
5404 switch (sel) {
5405 case 0 ... 7:
5406 gen_helper_1e0i(mfc0_watchlo, arg, sel);
5407 rn = "WatchLo";
5408 break;
5409 default:
5410 goto cp0_unimplemented;
5412 break;
5413 case 19:
5414 switch (sel) {
5415 case 0 ...7:
5416 gen_helper_1e0i(mfc0_watchhi, arg, sel);
5417 rn = "WatchHi";
5418 break;
5419 default:
5420 goto cp0_unimplemented;
5422 break;
5423 case 20:
5424 switch (sel) {
5425 case 0:
5426 #if defined(TARGET_MIPS64)
5427 check_insn(ctx, ISA_MIPS3);
5428 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
5429 tcg_gen_ext32s_tl(arg, arg);
5430 rn = "XContext";
5431 break;
5432 #endif
5433 default:
5434 goto cp0_unimplemented;
5436 break;
5437 case 21:
5438 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5439 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
5440 switch (sel) {
5441 case 0:
5442 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
5443 rn = "Framemask";
5444 break;
5445 default:
5446 goto cp0_unimplemented;
5448 break;
5449 case 22:
5450 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5451 rn = "'Diagnostic"; /* implementation dependent */
5452 break;
5453 case 23:
5454 switch (sel) {
5455 case 0:
5456 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
5457 rn = "Debug";
5458 break;
5459 case 1:
5460 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
5461 rn = "TraceControl";
5462 // break;
5463 case 2:
5464 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
5465 rn = "TraceControl2";
5466 // break;
5467 case 3:
5468 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
5469 rn = "UserTraceData";
5470 // break;
5471 case 4:
5472 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
5473 rn = "TraceBPC";
5474 // break;
5475 default:
5476 goto cp0_unimplemented;
5478 break;
5479 case 24:
5480 switch (sel) {
5481 case 0:
5482 /* EJTAG support */
5483 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
5484 tcg_gen_ext32s_tl(arg, arg);
5485 rn = "DEPC";
5486 break;
5487 default:
5488 goto cp0_unimplemented;
5490 break;
5491 case 25:
5492 switch (sel) {
5493 case 0:
5494 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
5495 rn = "Performance0";
5496 break;
5497 case 1:
5498 // gen_helper_mfc0_performance1(arg);
5499 rn = "Performance1";
5500 // break;
5501 case 2:
5502 // gen_helper_mfc0_performance2(arg);
5503 rn = "Performance2";
5504 // break;
5505 case 3:
5506 // gen_helper_mfc0_performance3(arg);
5507 rn = "Performance3";
5508 // break;
5509 case 4:
5510 // gen_helper_mfc0_performance4(arg);
5511 rn = "Performance4";
5512 // break;
5513 case 5:
5514 // gen_helper_mfc0_performance5(arg);
5515 rn = "Performance5";
5516 // break;
5517 case 6:
5518 // gen_helper_mfc0_performance6(arg);
5519 rn = "Performance6";
5520 // break;
5521 case 7:
5522 // gen_helper_mfc0_performance7(arg);
5523 rn = "Performance7";
5524 // break;
5525 default:
5526 goto cp0_unimplemented;
5528 break;
5529 case 26:
5530 switch (sel) {
5531 case 0:
5532 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
5533 rn = "ErrCtl";
5534 break;
5535 default:
5536 goto cp0_unimplemented;
5538 break;
5539 case 27:
5540 switch (sel) {
5541 case 0 ... 3:
5542 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5543 rn = "CacheErr";
5544 break;
5545 default:
5546 goto cp0_unimplemented;
5548 break;
5549 case 28:
5550 switch (sel) {
5551 case 0:
5552 case 2:
5553 case 4:
5554 case 6:
5556 TCGv_i64 tmp = tcg_temp_new_i64();
5557 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
5558 gen_move_low32(arg, tmp);
5559 tcg_temp_free_i64(tmp);
5561 rn = "TagLo";
5562 break;
5563 case 1:
5564 case 3:
5565 case 5:
5566 case 7:
5567 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
5568 rn = "DataLo";
5569 break;
5570 default:
5571 goto cp0_unimplemented;
5573 break;
5574 case 29:
5575 switch (sel) {
5576 case 0:
5577 case 2:
5578 case 4:
5579 case 6:
5580 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
5581 rn = "TagHi";
5582 break;
5583 case 1:
5584 case 3:
5585 case 5:
5586 case 7:
5587 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
5588 rn = "DataHi";
5589 break;
5590 default:
5591 goto cp0_unimplemented;
5593 break;
5594 case 30:
5595 switch (sel) {
5596 case 0:
5597 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
5598 tcg_gen_ext32s_tl(arg, arg);
5599 rn = "ErrorEPC";
5600 break;
5601 default:
5602 goto cp0_unimplemented;
5604 break;
5605 case 31:
5606 switch (sel) {
5607 case 0:
5608 /* EJTAG support */
5609 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
5610 rn = "DESAVE";
5611 break;
5612 case 2 ... 7:
5613 CP0_CHECK(ctx->kscrexist & (1 << sel));
5614 tcg_gen_ld_tl(arg, cpu_env,
5615 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
5616 tcg_gen_ext32s_tl(arg, arg);
5617 rn = "KScratch";
5618 break;
5619 default:
5620 goto cp0_unimplemented;
5622 break;
5623 default:
5624 goto cp0_unimplemented;
5626 (void)rn; /* avoid a compiler warning */
5627 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5628 return;
5630 cp0_unimplemented:
5631 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5632 gen_mfc0_unimplemented(ctx, arg);
5635 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5637 const char *rn = "invalid";
5639 if (sel != 0)
5640 check_insn(ctx, ISA_MIPS32);
5642 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5643 gen_io_start();
5646 switch (reg) {
5647 case 0:
5648 switch (sel) {
5649 case 0:
5650 gen_helper_mtc0_index(cpu_env, arg);
5651 rn = "Index";
5652 break;
5653 case 1:
5654 CP0_CHECK(ctx->insn_flags & ASE_MT);
5655 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
5656 rn = "MVPControl";
5657 break;
5658 case 2:
5659 CP0_CHECK(ctx->insn_flags & ASE_MT);
5660 /* ignored */
5661 rn = "MVPConf0";
5662 break;
5663 case 3:
5664 CP0_CHECK(ctx->insn_flags & ASE_MT);
5665 /* ignored */
5666 rn = "MVPConf1";
5667 break;
5668 case 4:
5669 CP0_CHECK(ctx->vp);
5670 /* ignored */
5671 rn = "VPControl";
5672 break;
5673 default:
5674 goto cp0_unimplemented;
5676 break;
5677 case 1:
5678 switch (sel) {
5679 case 0:
5680 /* ignored */
5681 rn = "Random";
5682 break;
5683 case 1:
5684 CP0_CHECK(ctx->insn_flags & ASE_MT);
5685 gen_helper_mtc0_vpecontrol(cpu_env, arg);
5686 rn = "VPEControl";
5687 break;
5688 case 2:
5689 CP0_CHECK(ctx->insn_flags & ASE_MT);
5690 gen_helper_mtc0_vpeconf0(cpu_env, arg);
5691 rn = "VPEConf0";
5692 break;
5693 case 3:
5694 CP0_CHECK(ctx->insn_flags & ASE_MT);
5695 gen_helper_mtc0_vpeconf1(cpu_env, arg);
5696 rn = "VPEConf1";
5697 break;
5698 case 4:
5699 CP0_CHECK(ctx->insn_flags & ASE_MT);
5700 gen_helper_mtc0_yqmask(cpu_env, arg);
5701 rn = "YQMask";
5702 break;
5703 case 5:
5704 CP0_CHECK(ctx->insn_flags & ASE_MT);
5705 tcg_gen_st_tl(arg, cpu_env,
5706 offsetof(CPUMIPSState, CP0_VPESchedule));
5707 rn = "VPESchedule";
5708 break;
5709 case 6:
5710 CP0_CHECK(ctx->insn_flags & ASE_MT);
5711 tcg_gen_st_tl(arg, cpu_env,
5712 offsetof(CPUMIPSState, CP0_VPEScheFBack));
5713 rn = "VPEScheFBack";
5714 break;
5715 case 7:
5716 CP0_CHECK(ctx->insn_flags & ASE_MT);
5717 gen_helper_mtc0_vpeopt(cpu_env, arg);
5718 rn = "VPEOpt";
5719 break;
5720 default:
5721 goto cp0_unimplemented;
5723 break;
5724 case 2:
5725 switch (sel) {
5726 case 0:
5727 gen_helper_mtc0_entrylo0(cpu_env, arg);
5728 rn = "EntryLo0";
5729 break;
5730 case 1:
5731 CP0_CHECK(ctx->insn_flags & ASE_MT);
5732 gen_helper_mtc0_tcstatus(cpu_env, arg);
5733 rn = "TCStatus";
5734 break;
5735 case 2:
5736 CP0_CHECK(ctx->insn_flags & ASE_MT);
5737 gen_helper_mtc0_tcbind(cpu_env, arg);
5738 rn = "TCBind";
5739 break;
5740 case 3:
5741 CP0_CHECK(ctx->insn_flags & ASE_MT);
5742 gen_helper_mtc0_tcrestart(cpu_env, arg);
5743 rn = "TCRestart";
5744 break;
5745 case 4:
5746 CP0_CHECK(ctx->insn_flags & ASE_MT);
5747 gen_helper_mtc0_tchalt(cpu_env, arg);
5748 rn = "TCHalt";
5749 break;
5750 case 5:
5751 CP0_CHECK(ctx->insn_flags & ASE_MT);
5752 gen_helper_mtc0_tccontext(cpu_env, arg);
5753 rn = "TCContext";
5754 break;
5755 case 6:
5756 CP0_CHECK(ctx->insn_flags & ASE_MT);
5757 gen_helper_mtc0_tcschedule(cpu_env, arg);
5758 rn = "TCSchedule";
5759 break;
5760 case 7:
5761 CP0_CHECK(ctx->insn_flags & ASE_MT);
5762 gen_helper_mtc0_tcschefback(cpu_env, arg);
5763 rn = "TCScheFBack";
5764 break;
5765 default:
5766 goto cp0_unimplemented;
5768 break;
5769 case 3:
5770 switch (sel) {
5771 case 0:
5772 gen_helper_mtc0_entrylo1(cpu_env, arg);
5773 rn = "EntryLo1";
5774 break;
5775 case 1:
5776 CP0_CHECK(ctx->vp);
5777 /* ignored */
5778 rn = "GlobalNumber";
5779 break;
5780 default:
5781 goto cp0_unimplemented;
5783 break;
5784 case 4:
5785 switch (sel) {
5786 case 0:
5787 gen_helper_mtc0_context(cpu_env, arg);
5788 rn = "Context";
5789 break;
5790 case 1:
5791 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
5792 rn = "ContextConfig";
5793 goto cp0_unimplemented;
5794 // break;
5795 case 2:
5796 CP0_CHECK(ctx->ulri);
5797 tcg_gen_st_tl(arg, cpu_env,
5798 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5799 rn = "UserLocal";
5800 break;
5801 default:
5802 goto cp0_unimplemented;
5804 break;
5805 case 5:
5806 switch (sel) {
5807 case 0:
5808 gen_helper_mtc0_pagemask(cpu_env, arg);
5809 rn = "PageMask";
5810 break;
5811 case 1:
5812 check_insn(ctx, ISA_MIPS32R2);
5813 gen_helper_mtc0_pagegrain(cpu_env, arg);
5814 rn = "PageGrain";
5815 ctx->bstate = BS_STOP;
5816 break;
5817 default:
5818 goto cp0_unimplemented;
5820 break;
5821 case 6:
5822 switch (sel) {
5823 case 0:
5824 gen_helper_mtc0_wired(cpu_env, arg);
5825 rn = "Wired";
5826 break;
5827 case 1:
5828 check_insn(ctx, ISA_MIPS32R2);
5829 gen_helper_mtc0_srsconf0(cpu_env, arg);
5830 rn = "SRSConf0";
5831 break;
5832 case 2:
5833 check_insn(ctx, ISA_MIPS32R2);
5834 gen_helper_mtc0_srsconf1(cpu_env, arg);
5835 rn = "SRSConf1";
5836 break;
5837 case 3:
5838 check_insn(ctx, ISA_MIPS32R2);
5839 gen_helper_mtc0_srsconf2(cpu_env, arg);
5840 rn = "SRSConf2";
5841 break;
5842 case 4:
5843 check_insn(ctx, ISA_MIPS32R2);
5844 gen_helper_mtc0_srsconf3(cpu_env, arg);
5845 rn = "SRSConf3";
5846 break;
5847 case 5:
5848 check_insn(ctx, ISA_MIPS32R2);
5849 gen_helper_mtc0_srsconf4(cpu_env, arg);
5850 rn = "SRSConf4";
5851 break;
5852 default:
5853 goto cp0_unimplemented;
5855 break;
5856 case 7:
5857 switch (sel) {
5858 case 0:
5859 check_insn(ctx, ISA_MIPS32R2);
5860 gen_helper_mtc0_hwrena(cpu_env, arg);
5861 ctx->bstate = BS_STOP;
5862 rn = "HWREna";
5863 break;
5864 default:
5865 goto cp0_unimplemented;
5867 break;
5868 case 8:
5869 switch (sel) {
5870 case 0:
5871 /* ignored */
5872 rn = "BadVAddr";
5873 break;
5874 case 1:
5875 /* ignored */
5876 rn = "BadInstr";
5877 break;
5878 case 2:
5879 /* ignored */
5880 rn = "BadInstrP";
5881 break;
5882 default:
5883 goto cp0_unimplemented;
5885 break;
5886 case 9:
5887 switch (sel) {
5888 case 0:
5889 gen_helper_mtc0_count(cpu_env, arg);
5890 rn = "Count";
5891 break;
5892 /* 6,7 are implementation dependent */
5893 default:
5894 goto cp0_unimplemented;
5896 break;
5897 case 10:
5898 switch (sel) {
5899 case 0:
5900 gen_helper_mtc0_entryhi(cpu_env, arg);
5901 rn = "EntryHi";
5902 break;
5903 default:
5904 goto cp0_unimplemented;
5906 break;
5907 case 11:
5908 switch (sel) {
5909 case 0:
5910 gen_helper_mtc0_compare(cpu_env, arg);
5911 rn = "Compare";
5912 break;
5913 /* 6,7 are implementation dependent */
5914 default:
5915 goto cp0_unimplemented;
5917 break;
5918 case 12:
5919 switch (sel) {
5920 case 0:
5921 save_cpu_state(ctx, 1);
5922 gen_helper_mtc0_status(cpu_env, arg);
5923 /* BS_STOP isn't good enough here, hflags may have changed. */
5924 gen_save_pc(ctx->pc + 4);
5925 ctx->bstate = BS_EXCP;
5926 rn = "Status";
5927 break;
5928 case 1:
5929 check_insn(ctx, ISA_MIPS32R2);
5930 gen_helper_mtc0_intctl(cpu_env, arg);
5931 /* Stop translation as we may have switched the execution mode */
5932 ctx->bstate = BS_STOP;
5933 rn = "IntCtl";
5934 break;
5935 case 2:
5936 check_insn(ctx, ISA_MIPS32R2);
5937 gen_helper_mtc0_srsctl(cpu_env, arg);
5938 /* Stop translation as we may have switched the execution mode */
5939 ctx->bstate = BS_STOP;
5940 rn = "SRSCtl";
5941 break;
5942 case 3:
5943 check_insn(ctx, ISA_MIPS32R2);
5944 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5945 /* Stop translation as we may have switched the execution mode */
5946 ctx->bstate = BS_STOP;
5947 rn = "SRSMap";
5948 break;
5949 default:
5950 goto cp0_unimplemented;
5952 break;
5953 case 13:
5954 switch (sel) {
5955 case 0:
5956 save_cpu_state(ctx, 1);
5957 gen_helper_mtc0_cause(cpu_env, arg);
5958 rn = "Cause";
5959 break;
5960 default:
5961 goto cp0_unimplemented;
5963 break;
5964 case 14:
5965 switch (sel) {
5966 case 0:
5967 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
5968 rn = "EPC";
5969 break;
5970 default:
5971 goto cp0_unimplemented;
5973 break;
5974 case 15:
5975 switch (sel) {
5976 case 0:
5977 /* ignored */
5978 rn = "PRid";
5979 break;
5980 case 1:
5981 check_insn(ctx, ISA_MIPS32R2);
5982 gen_helper_mtc0_ebase(cpu_env, arg);
5983 rn = "EBase";
5984 break;
5985 default:
5986 goto cp0_unimplemented;
5988 break;
5989 case 16:
5990 switch (sel) {
5991 case 0:
5992 gen_helper_mtc0_config0(cpu_env, arg);
5993 rn = "Config";
5994 /* Stop translation as we may have switched the execution mode */
5995 ctx->bstate = BS_STOP;
5996 break;
5997 case 1:
5998 /* ignored, read only */
5999 rn = "Config1";
6000 break;
6001 case 2:
6002 gen_helper_mtc0_config2(cpu_env, arg);
6003 rn = "Config2";
6004 /* Stop translation as we may have switched the execution mode */
6005 ctx->bstate = BS_STOP;
6006 break;
6007 case 3:
6008 gen_helper_mtc0_config3(cpu_env, arg);
6009 rn = "Config3";
6010 /* Stop translation as we may have switched the execution mode */
6011 ctx->bstate = BS_STOP;
6012 break;
6013 case 4:
6014 gen_helper_mtc0_config4(cpu_env, arg);
6015 rn = "Config4";
6016 ctx->bstate = BS_STOP;
6017 break;
6018 case 5:
6019 gen_helper_mtc0_config5(cpu_env, arg);
6020 rn = "Config5";
6021 /* Stop translation as we may have switched the execution mode */
6022 ctx->bstate = BS_STOP;
6023 break;
6024 /* 6,7 are implementation dependent */
6025 case 6:
6026 /* ignored */
6027 rn = "Config6";
6028 break;
6029 case 7:
6030 /* ignored */
6031 rn = "Config7";
6032 break;
6033 default:
6034 rn = "Invalid config selector";
6035 goto cp0_unimplemented;
6037 break;
6038 case 17:
6039 switch (sel) {
6040 case 0:
6041 gen_helper_mtc0_lladdr(cpu_env, arg);
6042 rn = "LLAddr";
6043 break;
6044 case 1:
6045 CP0_CHECK(ctx->mrp);
6046 gen_helper_mtc0_maar(cpu_env, arg);
6047 rn = "MAAR";
6048 break;
6049 case 2:
6050 CP0_CHECK(ctx->mrp);
6051 gen_helper_mtc0_maari(cpu_env, arg);
6052 rn = "MAARI";
6053 break;
6054 default:
6055 goto cp0_unimplemented;
6057 break;
6058 case 18:
6059 switch (sel) {
6060 case 0 ... 7:
6061 gen_helper_0e1i(mtc0_watchlo, arg, sel);
6062 rn = "WatchLo";
6063 break;
6064 default:
6065 goto cp0_unimplemented;
6067 break;
6068 case 19:
6069 switch (sel) {
6070 case 0 ... 7:
6071 gen_helper_0e1i(mtc0_watchhi, arg, sel);
6072 rn = "WatchHi";
6073 break;
6074 default:
6075 goto cp0_unimplemented;
6077 break;
6078 case 20:
6079 switch (sel) {
6080 case 0:
6081 #if defined(TARGET_MIPS64)
6082 check_insn(ctx, ISA_MIPS3);
6083 gen_helper_mtc0_xcontext(cpu_env, arg);
6084 rn = "XContext";
6085 break;
6086 #endif
6087 default:
6088 goto cp0_unimplemented;
6090 break;
6091 case 21:
6092 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6093 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6094 switch (sel) {
6095 case 0:
6096 gen_helper_mtc0_framemask(cpu_env, arg);
6097 rn = "Framemask";
6098 break;
6099 default:
6100 goto cp0_unimplemented;
6102 break;
6103 case 22:
6104 /* ignored */
6105 rn = "Diagnostic"; /* implementation dependent */
6106 break;
6107 case 23:
6108 switch (sel) {
6109 case 0:
6110 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
6111 /* BS_STOP isn't good enough here, hflags may have changed. */
6112 gen_save_pc(ctx->pc + 4);
6113 ctx->bstate = BS_EXCP;
6114 rn = "Debug";
6115 break;
6116 case 1:
6117 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
6118 rn = "TraceControl";
6119 /* Stop translation as we may have switched the execution mode */
6120 ctx->bstate = BS_STOP;
6121 // break;
6122 case 2:
6123 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
6124 rn = "TraceControl2";
6125 /* Stop translation as we may have switched the execution mode */
6126 ctx->bstate = BS_STOP;
6127 // break;
6128 case 3:
6129 /* Stop translation as we may have switched the execution mode */
6130 ctx->bstate = BS_STOP;
6131 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
6132 rn = "UserTraceData";
6133 /* Stop translation as we may have switched the execution mode */
6134 ctx->bstate = BS_STOP;
6135 // break;
6136 case 4:
6137 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
6138 /* Stop translation as we may have switched the execution mode */
6139 ctx->bstate = BS_STOP;
6140 rn = "TraceBPC";
6141 // break;
6142 default:
6143 goto cp0_unimplemented;
6145 break;
6146 case 24:
6147 switch (sel) {
6148 case 0:
6149 /* EJTAG support */
6150 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6151 rn = "DEPC";
6152 break;
6153 default:
6154 goto cp0_unimplemented;
6156 break;
6157 case 25:
6158 switch (sel) {
6159 case 0:
6160 gen_helper_mtc0_performance0(cpu_env, arg);
6161 rn = "Performance0";
6162 break;
6163 case 1:
6164 // gen_helper_mtc0_performance1(arg);
6165 rn = "Performance1";
6166 // break;
6167 case 2:
6168 // gen_helper_mtc0_performance2(arg);
6169 rn = "Performance2";
6170 // break;
6171 case 3:
6172 // gen_helper_mtc0_performance3(arg);
6173 rn = "Performance3";
6174 // break;
6175 case 4:
6176 // gen_helper_mtc0_performance4(arg);
6177 rn = "Performance4";
6178 // break;
6179 case 5:
6180 // gen_helper_mtc0_performance5(arg);
6181 rn = "Performance5";
6182 // break;
6183 case 6:
6184 // gen_helper_mtc0_performance6(arg);
6185 rn = "Performance6";
6186 // break;
6187 case 7:
6188 // gen_helper_mtc0_performance7(arg);
6189 rn = "Performance7";
6190 // break;
6191 default:
6192 goto cp0_unimplemented;
6194 break;
6195 case 26:
6196 switch (sel) {
6197 case 0:
6198 gen_helper_mtc0_errctl(cpu_env, arg);
6199 ctx->bstate = BS_STOP;
6200 rn = "ErrCtl";
6201 break;
6202 default:
6203 goto cp0_unimplemented;
6205 break;
6206 case 27:
6207 switch (sel) {
6208 case 0 ... 3:
6209 /* ignored */
6210 rn = "CacheErr";
6211 break;
6212 default:
6213 goto cp0_unimplemented;
6215 break;
6216 case 28:
6217 switch (sel) {
6218 case 0:
6219 case 2:
6220 case 4:
6221 case 6:
6222 gen_helper_mtc0_taglo(cpu_env, arg);
6223 rn = "TagLo";
6224 break;
6225 case 1:
6226 case 3:
6227 case 5:
6228 case 7:
6229 gen_helper_mtc0_datalo(cpu_env, arg);
6230 rn = "DataLo";
6231 break;
6232 default:
6233 goto cp0_unimplemented;
6235 break;
6236 case 29:
6237 switch (sel) {
6238 case 0:
6239 case 2:
6240 case 4:
6241 case 6:
6242 gen_helper_mtc0_taghi(cpu_env, arg);
6243 rn = "TagHi";
6244 break;
6245 case 1:
6246 case 3:
6247 case 5:
6248 case 7:
6249 gen_helper_mtc0_datahi(cpu_env, arg);
6250 rn = "DataHi";
6251 break;
6252 default:
6253 rn = "invalid sel";
6254 goto cp0_unimplemented;
6256 break;
6257 case 30:
6258 switch (sel) {
6259 case 0:
6260 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6261 rn = "ErrorEPC";
6262 break;
6263 default:
6264 goto cp0_unimplemented;
6266 break;
6267 case 31:
6268 switch (sel) {
6269 case 0:
6270 /* EJTAG support */
6271 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6272 rn = "DESAVE";
6273 break;
6274 case 2 ... 7:
6275 CP0_CHECK(ctx->kscrexist & (1 << sel));
6276 tcg_gen_st_tl(arg, cpu_env,
6277 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6278 rn = "KScratch";
6279 break;
6280 default:
6281 goto cp0_unimplemented;
6283 /* Stop translation as we may have switched the execution mode */
6284 ctx->bstate = BS_STOP;
6285 break;
6286 default:
6287 goto cp0_unimplemented;
6289 (void)rn; /* avoid a compiler warning */
6290 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6291 /* For simplicity assume that all writes can cause interrupts. */
6292 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6293 gen_io_end();
6294 ctx->bstate = BS_STOP;
6296 return;
6298 cp0_unimplemented:
6299 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6302 #if defined(TARGET_MIPS64)
6303 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6305 const char *rn = "invalid";
6307 if (sel != 0)
6308 check_insn(ctx, ISA_MIPS64);
6310 switch (reg) {
6311 case 0:
6312 switch (sel) {
6313 case 0:
6314 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6315 rn = "Index";
6316 break;
6317 case 1:
6318 CP0_CHECK(ctx->insn_flags & ASE_MT);
6319 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6320 rn = "MVPControl";
6321 break;
6322 case 2:
6323 CP0_CHECK(ctx->insn_flags & ASE_MT);
6324 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6325 rn = "MVPConf0";
6326 break;
6327 case 3:
6328 CP0_CHECK(ctx->insn_flags & ASE_MT);
6329 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6330 rn = "MVPConf1";
6331 break;
6332 case 4:
6333 CP0_CHECK(ctx->vp);
6334 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6335 rn = "VPControl";
6336 break;
6337 default:
6338 goto cp0_unimplemented;
6340 break;
6341 case 1:
6342 switch (sel) {
6343 case 0:
6344 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6345 gen_helper_mfc0_random(arg, cpu_env);
6346 rn = "Random";
6347 break;
6348 case 1:
6349 CP0_CHECK(ctx->insn_flags & ASE_MT);
6350 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6351 rn = "VPEControl";
6352 break;
6353 case 2:
6354 CP0_CHECK(ctx->insn_flags & ASE_MT);
6355 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6356 rn = "VPEConf0";
6357 break;
6358 case 3:
6359 CP0_CHECK(ctx->insn_flags & ASE_MT);
6360 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6361 rn = "VPEConf1";
6362 break;
6363 case 4:
6364 CP0_CHECK(ctx->insn_flags & ASE_MT);
6365 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
6366 rn = "YQMask";
6367 break;
6368 case 5:
6369 CP0_CHECK(ctx->insn_flags & ASE_MT);
6370 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
6371 rn = "VPESchedule";
6372 break;
6373 case 6:
6374 CP0_CHECK(ctx->insn_flags & ASE_MT);
6375 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6376 rn = "VPEScheFBack";
6377 break;
6378 case 7:
6379 CP0_CHECK(ctx->insn_flags & ASE_MT);
6380 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6381 rn = "VPEOpt";
6382 break;
6383 default:
6384 goto cp0_unimplemented;
6386 break;
6387 case 2:
6388 switch (sel) {
6389 case 0:
6390 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
6391 rn = "EntryLo0";
6392 break;
6393 case 1:
6394 CP0_CHECK(ctx->insn_flags & ASE_MT);
6395 gen_helper_mfc0_tcstatus(arg, cpu_env);
6396 rn = "TCStatus";
6397 break;
6398 case 2:
6399 CP0_CHECK(ctx->insn_flags & ASE_MT);
6400 gen_helper_mfc0_tcbind(arg, cpu_env);
6401 rn = "TCBind";
6402 break;
6403 case 3:
6404 CP0_CHECK(ctx->insn_flags & ASE_MT);
6405 gen_helper_dmfc0_tcrestart(arg, cpu_env);
6406 rn = "TCRestart";
6407 break;
6408 case 4:
6409 CP0_CHECK(ctx->insn_flags & ASE_MT);
6410 gen_helper_dmfc0_tchalt(arg, cpu_env);
6411 rn = "TCHalt";
6412 break;
6413 case 5:
6414 CP0_CHECK(ctx->insn_flags & ASE_MT);
6415 gen_helper_dmfc0_tccontext(arg, cpu_env);
6416 rn = "TCContext";
6417 break;
6418 case 6:
6419 CP0_CHECK(ctx->insn_flags & ASE_MT);
6420 gen_helper_dmfc0_tcschedule(arg, cpu_env);
6421 rn = "TCSchedule";
6422 break;
6423 case 7:
6424 CP0_CHECK(ctx->insn_flags & ASE_MT);
6425 gen_helper_dmfc0_tcschefback(arg, cpu_env);
6426 rn = "TCScheFBack";
6427 break;
6428 default:
6429 goto cp0_unimplemented;
6431 break;
6432 case 3:
6433 switch (sel) {
6434 case 0:
6435 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
6436 rn = "EntryLo1";
6437 break;
6438 case 1:
6439 CP0_CHECK(ctx->vp);
6440 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6441 rn = "GlobalNumber";
6442 break;
6443 default:
6444 goto cp0_unimplemented;
6446 break;
6447 case 4:
6448 switch (sel) {
6449 case 0:
6450 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6451 rn = "Context";
6452 break;
6453 case 1:
6454 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
6455 rn = "ContextConfig";
6456 goto cp0_unimplemented;
6457 // break;
6458 case 2:
6459 CP0_CHECK(ctx->ulri);
6460 tcg_gen_ld_tl(arg, cpu_env,
6461 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6462 rn = "UserLocal";
6463 break;
6464 default:
6465 goto cp0_unimplemented;
6467 break;
6468 case 5:
6469 switch (sel) {
6470 case 0:
6471 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6472 rn = "PageMask";
6473 break;
6474 case 1:
6475 check_insn(ctx, ISA_MIPS32R2);
6476 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6477 rn = "PageGrain";
6478 break;
6479 default:
6480 goto cp0_unimplemented;
6482 break;
6483 case 6:
6484 switch (sel) {
6485 case 0:
6486 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6487 rn = "Wired";
6488 break;
6489 case 1:
6490 check_insn(ctx, ISA_MIPS32R2);
6491 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6492 rn = "SRSConf0";
6493 break;
6494 case 2:
6495 check_insn(ctx, ISA_MIPS32R2);
6496 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6497 rn = "SRSConf1";
6498 break;
6499 case 3:
6500 check_insn(ctx, ISA_MIPS32R2);
6501 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6502 rn = "SRSConf2";
6503 break;
6504 case 4:
6505 check_insn(ctx, ISA_MIPS32R2);
6506 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6507 rn = "SRSConf3";
6508 break;
6509 case 5:
6510 check_insn(ctx, ISA_MIPS32R2);
6511 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6512 rn = "SRSConf4";
6513 break;
6514 default:
6515 goto cp0_unimplemented;
6517 break;
6518 case 7:
6519 switch (sel) {
6520 case 0:
6521 check_insn(ctx, ISA_MIPS32R2);
6522 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6523 rn = "HWREna";
6524 break;
6525 default:
6526 goto cp0_unimplemented;
6528 break;
6529 case 8:
6530 switch (sel) {
6531 case 0:
6532 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6533 rn = "BadVAddr";
6534 break;
6535 case 1:
6536 CP0_CHECK(ctx->bi);
6537 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6538 rn = "BadInstr";
6539 break;
6540 case 2:
6541 CP0_CHECK(ctx->bp);
6542 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6543 rn = "BadInstrP";
6544 break;
6545 default:
6546 goto cp0_unimplemented;
6548 break;
6549 case 9:
6550 switch (sel) {
6551 case 0:
6552 /* Mark as an IO operation because we read the time. */
6553 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6554 gen_io_start();
6556 gen_helper_mfc0_count(arg, cpu_env);
6557 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6558 gen_io_end();
6560 /* Break the TB to be able to take timer interrupts immediately
6561 after reading count. */
6562 ctx->bstate = BS_STOP;
6563 rn = "Count";
6564 break;
6565 /* 6,7 are implementation dependent */
6566 default:
6567 goto cp0_unimplemented;
6569 break;
6570 case 10:
6571 switch (sel) {
6572 case 0:
6573 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6574 rn = "EntryHi";
6575 break;
6576 default:
6577 goto cp0_unimplemented;
6579 break;
6580 case 11:
6581 switch (sel) {
6582 case 0:
6583 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6584 rn = "Compare";
6585 break;
6586 /* 6,7 are implementation dependent */
6587 default:
6588 goto cp0_unimplemented;
6590 break;
6591 case 12:
6592 switch (sel) {
6593 case 0:
6594 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6595 rn = "Status";
6596 break;
6597 case 1:
6598 check_insn(ctx, ISA_MIPS32R2);
6599 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6600 rn = "IntCtl";
6601 break;
6602 case 2:
6603 check_insn(ctx, ISA_MIPS32R2);
6604 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6605 rn = "SRSCtl";
6606 break;
6607 case 3:
6608 check_insn(ctx, ISA_MIPS32R2);
6609 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6610 rn = "SRSMap";
6611 break;
6612 default:
6613 goto cp0_unimplemented;
6615 break;
6616 case 13:
6617 switch (sel) {
6618 case 0:
6619 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6620 rn = "Cause";
6621 break;
6622 default:
6623 goto cp0_unimplemented;
6625 break;
6626 case 14:
6627 switch (sel) {
6628 case 0:
6629 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6630 rn = "EPC";
6631 break;
6632 default:
6633 goto cp0_unimplemented;
6635 break;
6636 case 15:
6637 switch (sel) {
6638 case 0:
6639 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6640 rn = "PRid";
6641 break;
6642 case 1:
6643 check_insn(ctx, ISA_MIPS32R2);
6644 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
6645 rn = "EBase";
6646 break;
6647 case 3:
6648 check_insn(ctx, ISA_MIPS32R2);
6649 CP0_CHECK(ctx->cmgcr);
6650 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
6651 rn = "CMGCRBase";
6652 break;
6653 default:
6654 goto cp0_unimplemented;
6656 break;
6657 case 16:
6658 switch (sel) {
6659 case 0:
6660 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6661 rn = "Config";
6662 break;
6663 case 1:
6664 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6665 rn = "Config1";
6666 break;
6667 case 2:
6668 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6669 rn = "Config2";
6670 break;
6671 case 3:
6672 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6673 rn = "Config3";
6674 break;
6675 case 4:
6676 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6677 rn = "Config4";
6678 break;
6679 case 5:
6680 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6681 rn = "Config5";
6682 break;
6683 /* 6,7 are implementation dependent */
6684 case 6:
6685 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6686 rn = "Config6";
6687 break;
6688 case 7:
6689 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6690 rn = "Config7";
6691 break;
6692 default:
6693 goto cp0_unimplemented;
6695 break;
6696 case 17:
6697 switch (sel) {
6698 case 0:
6699 gen_helper_dmfc0_lladdr(arg, cpu_env);
6700 rn = "LLAddr";
6701 break;
6702 case 1:
6703 CP0_CHECK(ctx->mrp);
6704 gen_helper_dmfc0_maar(arg, cpu_env);
6705 rn = "MAAR";
6706 break;
6707 case 2:
6708 CP0_CHECK(ctx->mrp);
6709 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
6710 rn = "MAARI";
6711 break;
6712 default:
6713 goto cp0_unimplemented;
6715 break;
6716 case 18:
6717 switch (sel) {
6718 case 0 ... 7:
6719 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
6720 rn = "WatchLo";
6721 break;
6722 default:
6723 goto cp0_unimplemented;
6725 break;
6726 case 19:
6727 switch (sel) {
6728 case 0 ... 7:
6729 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6730 rn = "WatchHi";
6731 break;
6732 default:
6733 goto cp0_unimplemented;
6735 break;
6736 case 20:
6737 switch (sel) {
6738 case 0:
6739 check_insn(ctx, ISA_MIPS3);
6740 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
6741 rn = "XContext";
6742 break;
6743 default:
6744 goto cp0_unimplemented;
6746 break;
6747 case 21:
6748 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6749 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6750 switch (sel) {
6751 case 0:
6752 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
6753 rn = "Framemask";
6754 break;
6755 default:
6756 goto cp0_unimplemented;
6758 break;
6759 case 22:
6760 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6761 rn = "'Diagnostic"; /* implementation dependent */
6762 break;
6763 case 23:
6764 switch (sel) {
6765 case 0:
6766 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
6767 rn = "Debug";
6768 break;
6769 case 1:
6770 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
6771 rn = "TraceControl";
6772 // break;
6773 case 2:
6774 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
6775 rn = "TraceControl2";
6776 // break;
6777 case 3:
6778 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
6779 rn = "UserTraceData";
6780 // break;
6781 case 4:
6782 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
6783 rn = "TraceBPC";
6784 // break;
6785 default:
6786 goto cp0_unimplemented;
6788 break;
6789 case 24:
6790 switch (sel) {
6791 case 0:
6792 /* EJTAG support */
6793 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6794 rn = "DEPC";
6795 break;
6796 default:
6797 goto cp0_unimplemented;
6799 break;
6800 case 25:
6801 switch (sel) {
6802 case 0:
6803 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
6804 rn = "Performance0";
6805 break;
6806 case 1:
6807 // gen_helper_dmfc0_performance1(arg);
6808 rn = "Performance1";
6809 // break;
6810 case 2:
6811 // gen_helper_dmfc0_performance2(arg);
6812 rn = "Performance2";
6813 // break;
6814 case 3:
6815 // gen_helper_dmfc0_performance3(arg);
6816 rn = "Performance3";
6817 // break;
6818 case 4:
6819 // gen_helper_dmfc0_performance4(arg);
6820 rn = "Performance4";
6821 // break;
6822 case 5:
6823 // gen_helper_dmfc0_performance5(arg);
6824 rn = "Performance5";
6825 // break;
6826 case 6:
6827 // gen_helper_dmfc0_performance6(arg);
6828 rn = "Performance6";
6829 // break;
6830 case 7:
6831 // gen_helper_dmfc0_performance7(arg);
6832 rn = "Performance7";
6833 // break;
6834 default:
6835 goto cp0_unimplemented;
6837 break;
6838 case 26:
6839 switch (sel) {
6840 case 0:
6841 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
6842 rn = "ErrCtl";
6843 break;
6844 default:
6845 goto cp0_unimplemented;
6847 break;
6848 case 27:
6849 switch (sel) {
6850 /* ignored */
6851 case 0 ... 3:
6852 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6853 rn = "CacheErr";
6854 break;
6855 default:
6856 goto cp0_unimplemented;
6858 break;
6859 case 28:
6860 switch (sel) {
6861 case 0:
6862 case 2:
6863 case 4:
6864 case 6:
6865 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
6866 rn = "TagLo";
6867 break;
6868 case 1:
6869 case 3:
6870 case 5:
6871 case 7:
6872 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
6873 rn = "DataLo";
6874 break;
6875 default:
6876 goto cp0_unimplemented;
6878 break;
6879 case 29:
6880 switch (sel) {
6881 case 0:
6882 case 2:
6883 case 4:
6884 case 6:
6885 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
6886 rn = "TagHi";
6887 break;
6888 case 1:
6889 case 3:
6890 case 5:
6891 case 7:
6892 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
6893 rn = "DataHi";
6894 break;
6895 default:
6896 goto cp0_unimplemented;
6898 break;
6899 case 30:
6900 switch (sel) {
6901 case 0:
6902 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6903 rn = "ErrorEPC";
6904 break;
6905 default:
6906 goto cp0_unimplemented;
6908 break;
6909 case 31:
6910 switch (sel) {
6911 case 0:
6912 /* EJTAG support */
6913 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6914 rn = "DESAVE";
6915 break;
6916 case 2 ... 7:
6917 CP0_CHECK(ctx->kscrexist & (1 << sel));
6918 tcg_gen_ld_tl(arg, cpu_env,
6919 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6920 rn = "KScratch";
6921 break;
6922 default:
6923 goto cp0_unimplemented;
6925 break;
6926 default:
6927 goto cp0_unimplemented;
6929 (void)rn; /* avoid a compiler warning */
6930 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
6931 return;
6933 cp0_unimplemented:
6934 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
6935 gen_mfc0_unimplemented(ctx, arg);
6938 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6940 const char *rn = "invalid";
6942 if (sel != 0)
6943 check_insn(ctx, ISA_MIPS64);
6945 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6946 gen_io_start();
6949 switch (reg) {
6950 case 0:
6951 switch (sel) {
6952 case 0:
6953 gen_helper_mtc0_index(cpu_env, arg);
6954 rn = "Index";
6955 break;
6956 case 1:
6957 CP0_CHECK(ctx->insn_flags & ASE_MT);
6958 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
6959 rn = "MVPControl";
6960 break;
6961 case 2:
6962 CP0_CHECK(ctx->insn_flags & ASE_MT);
6963 /* ignored */
6964 rn = "MVPConf0";
6965 break;
6966 case 3:
6967 CP0_CHECK(ctx->insn_flags & ASE_MT);
6968 /* ignored */
6969 rn = "MVPConf1";
6970 break;
6971 case 4:
6972 CP0_CHECK(ctx->vp);
6973 /* ignored */
6974 rn = "VPControl";
6975 break;
6976 default:
6977 goto cp0_unimplemented;
6979 break;
6980 case 1:
6981 switch (sel) {
6982 case 0:
6983 /* ignored */
6984 rn = "Random";
6985 break;
6986 case 1:
6987 CP0_CHECK(ctx->insn_flags & ASE_MT);
6988 gen_helper_mtc0_vpecontrol(cpu_env, arg);
6989 rn = "VPEControl";
6990 break;
6991 case 2:
6992 CP0_CHECK(ctx->insn_flags & ASE_MT);
6993 gen_helper_mtc0_vpeconf0(cpu_env, arg);
6994 rn = "VPEConf0";
6995 break;
6996 case 3:
6997 CP0_CHECK(ctx->insn_flags & ASE_MT);
6998 gen_helper_mtc0_vpeconf1(cpu_env, arg);
6999 rn = "VPEConf1";
7000 break;
7001 case 4:
7002 CP0_CHECK(ctx->insn_flags & ASE_MT);
7003 gen_helper_mtc0_yqmask(cpu_env, arg);
7004 rn = "YQMask";
7005 break;
7006 case 5:
7007 CP0_CHECK(ctx->insn_flags & ASE_MT);
7008 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
7009 rn = "VPESchedule";
7010 break;
7011 case 6:
7012 CP0_CHECK(ctx->insn_flags & ASE_MT);
7013 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7014 rn = "VPEScheFBack";
7015 break;
7016 case 7:
7017 CP0_CHECK(ctx->insn_flags & ASE_MT);
7018 gen_helper_mtc0_vpeopt(cpu_env, arg);
7019 rn = "VPEOpt";
7020 break;
7021 default:
7022 goto cp0_unimplemented;
7024 break;
7025 case 2:
7026 switch (sel) {
7027 case 0:
7028 gen_helper_dmtc0_entrylo0(cpu_env, arg);
7029 rn = "EntryLo0";
7030 break;
7031 case 1:
7032 CP0_CHECK(ctx->insn_flags & ASE_MT);
7033 gen_helper_mtc0_tcstatus(cpu_env, arg);
7034 rn = "TCStatus";
7035 break;
7036 case 2:
7037 CP0_CHECK(ctx->insn_flags & ASE_MT);
7038 gen_helper_mtc0_tcbind(cpu_env, arg);
7039 rn = "TCBind";
7040 break;
7041 case 3:
7042 CP0_CHECK(ctx->insn_flags & ASE_MT);
7043 gen_helper_mtc0_tcrestart(cpu_env, arg);
7044 rn = "TCRestart";
7045 break;
7046 case 4:
7047 CP0_CHECK(ctx->insn_flags & ASE_MT);
7048 gen_helper_mtc0_tchalt(cpu_env, arg);
7049 rn = "TCHalt";
7050 break;
7051 case 5:
7052 CP0_CHECK(ctx->insn_flags & ASE_MT);
7053 gen_helper_mtc0_tccontext(cpu_env, arg);
7054 rn = "TCContext";
7055 break;
7056 case 6:
7057 CP0_CHECK(ctx->insn_flags & ASE_MT);
7058 gen_helper_mtc0_tcschedule(cpu_env, arg);
7059 rn = "TCSchedule";
7060 break;
7061 case 7:
7062 CP0_CHECK(ctx->insn_flags & ASE_MT);
7063 gen_helper_mtc0_tcschefback(cpu_env, arg);
7064 rn = "TCScheFBack";
7065 break;
7066 default:
7067 goto cp0_unimplemented;
7069 break;
7070 case 3:
7071 switch (sel) {
7072 case 0:
7073 gen_helper_dmtc0_entrylo1(cpu_env, arg);
7074 rn = "EntryLo1";
7075 break;
7076 case 1:
7077 CP0_CHECK(ctx->vp);
7078 /* ignored */
7079 rn = "GlobalNumber";
7080 break;
7081 default:
7082 goto cp0_unimplemented;
7084 break;
7085 case 4:
7086 switch (sel) {
7087 case 0:
7088 gen_helper_mtc0_context(cpu_env, arg);
7089 rn = "Context";
7090 break;
7091 case 1:
7092 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
7093 rn = "ContextConfig";
7094 goto cp0_unimplemented;
7095 // break;
7096 case 2:
7097 CP0_CHECK(ctx->ulri);
7098 tcg_gen_st_tl(arg, cpu_env,
7099 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7100 rn = "UserLocal";
7101 break;
7102 default:
7103 goto cp0_unimplemented;
7105 break;
7106 case 5:
7107 switch (sel) {
7108 case 0:
7109 gen_helper_mtc0_pagemask(cpu_env, arg);
7110 rn = "PageMask";
7111 break;
7112 case 1:
7113 check_insn(ctx, ISA_MIPS32R2);
7114 gen_helper_mtc0_pagegrain(cpu_env, arg);
7115 rn = "PageGrain";
7116 break;
7117 default:
7118 goto cp0_unimplemented;
7120 break;
7121 case 6:
7122 switch (sel) {
7123 case 0:
7124 gen_helper_mtc0_wired(cpu_env, arg);
7125 rn = "Wired";
7126 break;
7127 case 1:
7128 check_insn(ctx, ISA_MIPS32R2);
7129 gen_helper_mtc0_srsconf0(cpu_env, arg);
7130 rn = "SRSConf0";
7131 break;
7132 case 2:
7133 check_insn(ctx, ISA_MIPS32R2);
7134 gen_helper_mtc0_srsconf1(cpu_env, arg);
7135 rn = "SRSConf1";
7136 break;
7137 case 3:
7138 check_insn(ctx, ISA_MIPS32R2);
7139 gen_helper_mtc0_srsconf2(cpu_env, arg);
7140 rn = "SRSConf2";
7141 break;
7142 case 4:
7143 check_insn(ctx, ISA_MIPS32R2);
7144 gen_helper_mtc0_srsconf3(cpu_env, arg);
7145 rn = "SRSConf3";
7146 break;
7147 case 5:
7148 check_insn(ctx, ISA_MIPS32R2);
7149 gen_helper_mtc0_srsconf4(cpu_env, arg);
7150 rn = "SRSConf4";
7151 break;
7152 default:
7153 goto cp0_unimplemented;
7155 break;
7156 case 7:
7157 switch (sel) {
7158 case 0:
7159 check_insn(ctx, ISA_MIPS32R2);
7160 gen_helper_mtc0_hwrena(cpu_env, arg);
7161 ctx->bstate = BS_STOP;
7162 rn = "HWREna";
7163 break;
7164 default:
7165 goto cp0_unimplemented;
7167 break;
7168 case 8:
7169 switch (sel) {
7170 case 0:
7171 /* ignored */
7172 rn = "BadVAddr";
7173 break;
7174 case 1:
7175 /* ignored */
7176 rn = "BadInstr";
7177 break;
7178 case 2:
7179 /* ignored */
7180 rn = "BadInstrP";
7181 break;
7182 default:
7183 goto cp0_unimplemented;
7185 break;
7186 case 9:
7187 switch (sel) {
7188 case 0:
7189 gen_helper_mtc0_count(cpu_env, arg);
7190 rn = "Count";
7191 break;
7192 /* 6,7 are implementation dependent */
7193 default:
7194 goto cp0_unimplemented;
7196 /* Stop translation as we may have switched the execution mode */
7197 ctx->bstate = BS_STOP;
7198 break;
7199 case 10:
7200 switch (sel) {
7201 case 0:
7202 gen_helper_mtc0_entryhi(cpu_env, arg);
7203 rn = "EntryHi";
7204 break;
7205 default:
7206 goto cp0_unimplemented;
7208 break;
7209 case 11:
7210 switch (sel) {
7211 case 0:
7212 gen_helper_mtc0_compare(cpu_env, arg);
7213 rn = "Compare";
7214 break;
7215 /* 6,7 are implementation dependent */
7216 default:
7217 goto cp0_unimplemented;
7219 /* Stop translation as we may have switched the execution mode */
7220 ctx->bstate = BS_STOP;
7221 break;
7222 case 12:
7223 switch (sel) {
7224 case 0:
7225 save_cpu_state(ctx, 1);
7226 gen_helper_mtc0_status(cpu_env, arg);
7227 /* BS_STOP isn't good enough here, hflags may have changed. */
7228 gen_save_pc(ctx->pc + 4);
7229 ctx->bstate = BS_EXCP;
7230 rn = "Status";
7231 break;
7232 case 1:
7233 check_insn(ctx, ISA_MIPS32R2);
7234 gen_helper_mtc0_intctl(cpu_env, arg);
7235 /* Stop translation as we may have switched the execution mode */
7236 ctx->bstate = BS_STOP;
7237 rn = "IntCtl";
7238 break;
7239 case 2:
7240 check_insn(ctx, ISA_MIPS32R2);
7241 gen_helper_mtc0_srsctl(cpu_env, arg);
7242 /* Stop translation as we may have switched the execution mode */
7243 ctx->bstate = BS_STOP;
7244 rn = "SRSCtl";
7245 break;
7246 case 3:
7247 check_insn(ctx, ISA_MIPS32R2);
7248 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7249 /* Stop translation as we may have switched the execution mode */
7250 ctx->bstate = BS_STOP;
7251 rn = "SRSMap";
7252 break;
7253 default:
7254 goto cp0_unimplemented;
7256 break;
7257 case 13:
7258 switch (sel) {
7259 case 0:
7260 save_cpu_state(ctx, 1);
7261 /* Mark as an IO operation because we may trigger a software
7262 interrupt. */
7263 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7264 gen_io_start();
7266 gen_helper_mtc0_cause(cpu_env, arg);
7267 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7268 gen_io_end();
7270 /* Stop translation as we may have triggered an intetrupt */
7271 ctx->bstate = BS_STOP;
7272 rn = "Cause";
7273 break;
7274 default:
7275 goto cp0_unimplemented;
7277 break;
7278 case 14:
7279 switch (sel) {
7280 case 0:
7281 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7282 rn = "EPC";
7283 break;
7284 default:
7285 goto cp0_unimplemented;
7287 break;
7288 case 15:
7289 switch (sel) {
7290 case 0:
7291 /* ignored */
7292 rn = "PRid";
7293 break;
7294 case 1:
7295 check_insn(ctx, ISA_MIPS32R2);
7296 gen_helper_mtc0_ebase(cpu_env, arg);
7297 rn = "EBase";
7298 break;
7299 default:
7300 goto cp0_unimplemented;
7302 break;
7303 case 16:
7304 switch (sel) {
7305 case 0:
7306 gen_helper_mtc0_config0(cpu_env, arg);
7307 rn = "Config";
7308 /* Stop translation as we may have switched the execution mode */
7309 ctx->bstate = BS_STOP;
7310 break;
7311 case 1:
7312 /* ignored, read only */
7313 rn = "Config1";
7314 break;
7315 case 2:
7316 gen_helper_mtc0_config2(cpu_env, arg);
7317 rn = "Config2";
7318 /* Stop translation as we may have switched the execution mode */
7319 ctx->bstate = BS_STOP;
7320 break;
7321 case 3:
7322 gen_helper_mtc0_config3(cpu_env, arg);
7323 rn = "Config3";
7324 /* Stop translation as we may have switched the execution mode */
7325 ctx->bstate = BS_STOP;
7326 break;
7327 case 4:
7328 /* currently ignored */
7329 rn = "Config4";
7330 break;
7331 case 5:
7332 gen_helper_mtc0_config5(cpu_env, arg);
7333 rn = "Config5";
7334 /* Stop translation as we may have switched the execution mode */
7335 ctx->bstate = BS_STOP;
7336 break;
7337 /* 6,7 are implementation dependent */
7338 default:
7339 rn = "Invalid config selector";
7340 goto cp0_unimplemented;
7342 break;
7343 case 17:
7344 switch (sel) {
7345 case 0:
7346 gen_helper_mtc0_lladdr(cpu_env, arg);
7347 rn = "LLAddr";
7348 break;
7349 case 1:
7350 CP0_CHECK(ctx->mrp);
7351 gen_helper_mtc0_maar(cpu_env, arg);
7352 rn = "MAAR";
7353 break;
7354 case 2:
7355 CP0_CHECK(ctx->mrp);
7356 gen_helper_mtc0_maari(cpu_env, arg);
7357 rn = "MAARI";
7358 break;
7359 default:
7360 goto cp0_unimplemented;
7362 break;
7363 case 18:
7364 switch (sel) {
7365 case 0 ... 7:
7366 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7367 rn = "WatchLo";
7368 break;
7369 default:
7370 goto cp0_unimplemented;
7372 break;
7373 case 19:
7374 switch (sel) {
7375 case 0 ... 7:
7376 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7377 rn = "WatchHi";
7378 break;
7379 default:
7380 goto cp0_unimplemented;
7382 break;
7383 case 20:
7384 switch (sel) {
7385 case 0:
7386 check_insn(ctx, ISA_MIPS3);
7387 gen_helper_mtc0_xcontext(cpu_env, arg);
7388 rn = "XContext";
7389 break;
7390 default:
7391 goto cp0_unimplemented;
7393 break;
7394 case 21:
7395 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7396 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7397 switch (sel) {
7398 case 0:
7399 gen_helper_mtc0_framemask(cpu_env, arg);
7400 rn = "Framemask";
7401 break;
7402 default:
7403 goto cp0_unimplemented;
7405 break;
7406 case 22:
7407 /* ignored */
7408 rn = "Diagnostic"; /* implementation dependent */
7409 break;
7410 case 23:
7411 switch (sel) {
7412 case 0:
7413 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7414 /* BS_STOP isn't good enough here, hflags may have changed. */
7415 gen_save_pc(ctx->pc + 4);
7416 ctx->bstate = BS_EXCP;
7417 rn = "Debug";
7418 break;
7419 case 1:
7420 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
7421 /* Stop translation as we may have switched the execution mode */
7422 ctx->bstate = BS_STOP;
7423 rn = "TraceControl";
7424 // break;
7425 case 2:
7426 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
7427 /* Stop translation as we may have switched the execution mode */
7428 ctx->bstate = BS_STOP;
7429 rn = "TraceControl2";
7430 // break;
7431 case 3:
7432 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
7433 /* Stop translation as we may have switched the execution mode */
7434 ctx->bstate = BS_STOP;
7435 rn = "UserTraceData";
7436 // break;
7437 case 4:
7438 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
7439 /* Stop translation as we may have switched the execution mode */
7440 ctx->bstate = BS_STOP;
7441 rn = "TraceBPC";
7442 // break;
7443 default:
7444 goto cp0_unimplemented;
7446 break;
7447 case 24:
7448 switch (sel) {
7449 case 0:
7450 /* EJTAG support */
7451 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7452 rn = "DEPC";
7453 break;
7454 default:
7455 goto cp0_unimplemented;
7457 break;
7458 case 25:
7459 switch (sel) {
7460 case 0:
7461 gen_helper_mtc0_performance0(cpu_env, arg);
7462 rn = "Performance0";
7463 break;
7464 case 1:
7465 // gen_helper_mtc0_performance1(cpu_env, arg);
7466 rn = "Performance1";
7467 // break;
7468 case 2:
7469 // gen_helper_mtc0_performance2(cpu_env, arg);
7470 rn = "Performance2";
7471 // break;
7472 case 3:
7473 // gen_helper_mtc0_performance3(cpu_env, arg);
7474 rn = "Performance3";
7475 // break;
7476 case 4:
7477 // gen_helper_mtc0_performance4(cpu_env, arg);
7478 rn = "Performance4";
7479 // break;
7480 case 5:
7481 // gen_helper_mtc0_performance5(cpu_env, arg);
7482 rn = "Performance5";
7483 // break;
7484 case 6:
7485 // gen_helper_mtc0_performance6(cpu_env, arg);
7486 rn = "Performance6";
7487 // break;
7488 case 7:
7489 // gen_helper_mtc0_performance7(cpu_env, arg);
7490 rn = "Performance7";
7491 // break;
7492 default:
7493 goto cp0_unimplemented;
7495 break;
7496 case 26:
7497 switch (sel) {
7498 case 0:
7499 gen_helper_mtc0_errctl(cpu_env, arg);
7500 ctx->bstate = BS_STOP;
7501 rn = "ErrCtl";
7502 break;
7503 default:
7504 goto cp0_unimplemented;
7506 break;
7507 case 27:
7508 switch (sel) {
7509 case 0 ... 3:
7510 /* ignored */
7511 rn = "CacheErr";
7512 break;
7513 default:
7514 goto cp0_unimplemented;
7516 break;
7517 case 28:
7518 switch (sel) {
7519 case 0:
7520 case 2:
7521 case 4:
7522 case 6:
7523 gen_helper_mtc0_taglo(cpu_env, arg);
7524 rn = "TagLo";
7525 break;
7526 case 1:
7527 case 3:
7528 case 5:
7529 case 7:
7530 gen_helper_mtc0_datalo(cpu_env, arg);
7531 rn = "DataLo";
7532 break;
7533 default:
7534 goto cp0_unimplemented;
7536 break;
7537 case 29:
7538 switch (sel) {
7539 case 0:
7540 case 2:
7541 case 4:
7542 case 6:
7543 gen_helper_mtc0_taghi(cpu_env, arg);
7544 rn = "TagHi";
7545 break;
7546 case 1:
7547 case 3:
7548 case 5:
7549 case 7:
7550 gen_helper_mtc0_datahi(cpu_env, arg);
7551 rn = "DataHi";
7552 break;
7553 default:
7554 rn = "invalid sel";
7555 goto cp0_unimplemented;
7557 break;
7558 case 30:
7559 switch (sel) {
7560 case 0:
7561 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7562 rn = "ErrorEPC";
7563 break;
7564 default:
7565 goto cp0_unimplemented;
7567 break;
7568 case 31:
7569 switch (sel) {
7570 case 0:
7571 /* EJTAG support */
7572 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7573 rn = "DESAVE";
7574 break;
7575 case 2 ... 7:
7576 CP0_CHECK(ctx->kscrexist & (1 << sel));
7577 tcg_gen_st_tl(arg, cpu_env,
7578 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7579 rn = "KScratch";
7580 break;
7581 default:
7582 goto cp0_unimplemented;
7584 /* Stop translation as we may have switched the execution mode */
7585 ctx->bstate = BS_STOP;
7586 break;
7587 default:
7588 goto cp0_unimplemented;
7590 (void)rn; /* avoid a compiler warning */
7591 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7592 /* For simplicity assume that all writes can cause interrupts. */
7593 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7594 gen_io_end();
7595 ctx->bstate = BS_STOP;
7597 return;
7599 cp0_unimplemented:
7600 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7602 #endif /* TARGET_MIPS64 */
7604 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
7605 int u, int sel, int h)
7607 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7608 TCGv t0 = tcg_temp_local_new();
7610 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7611 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7612 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7613 tcg_gen_movi_tl(t0, -1);
7614 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7615 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7616 tcg_gen_movi_tl(t0, -1);
7617 else if (u == 0) {
7618 switch (rt) {
7619 case 1:
7620 switch (sel) {
7621 case 1:
7622 gen_helper_mftc0_vpecontrol(t0, cpu_env);
7623 break;
7624 case 2:
7625 gen_helper_mftc0_vpeconf0(t0, cpu_env);
7626 break;
7627 default:
7628 goto die;
7629 break;
7631 break;
7632 case 2:
7633 switch (sel) {
7634 case 1:
7635 gen_helper_mftc0_tcstatus(t0, cpu_env);
7636 break;
7637 case 2:
7638 gen_helper_mftc0_tcbind(t0, cpu_env);
7639 break;
7640 case 3:
7641 gen_helper_mftc0_tcrestart(t0, cpu_env);
7642 break;
7643 case 4:
7644 gen_helper_mftc0_tchalt(t0, cpu_env);
7645 break;
7646 case 5:
7647 gen_helper_mftc0_tccontext(t0, cpu_env);
7648 break;
7649 case 6:
7650 gen_helper_mftc0_tcschedule(t0, cpu_env);
7651 break;
7652 case 7:
7653 gen_helper_mftc0_tcschefback(t0, cpu_env);
7654 break;
7655 default:
7656 gen_mfc0(ctx, t0, rt, sel);
7657 break;
7659 break;
7660 case 10:
7661 switch (sel) {
7662 case 0:
7663 gen_helper_mftc0_entryhi(t0, cpu_env);
7664 break;
7665 default:
7666 gen_mfc0(ctx, t0, rt, sel);
7667 break;
7669 case 12:
7670 switch (sel) {
7671 case 0:
7672 gen_helper_mftc0_status(t0, cpu_env);
7673 break;
7674 default:
7675 gen_mfc0(ctx, t0, rt, sel);
7676 break;
7678 case 13:
7679 switch (sel) {
7680 case 0:
7681 gen_helper_mftc0_cause(t0, cpu_env);
7682 break;
7683 default:
7684 goto die;
7685 break;
7687 break;
7688 case 14:
7689 switch (sel) {
7690 case 0:
7691 gen_helper_mftc0_epc(t0, cpu_env);
7692 break;
7693 default:
7694 goto die;
7695 break;
7697 break;
7698 case 15:
7699 switch (sel) {
7700 case 1:
7701 gen_helper_mftc0_ebase(t0, cpu_env);
7702 break;
7703 default:
7704 goto die;
7705 break;
7707 break;
7708 case 16:
7709 switch (sel) {
7710 case 0 ... 7:
7711 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
7712 break;
7713 default:
7714 goto die;
7715 break;
7717 break;
7718 case 23:
7719 switch (sel) {
7720 case 0:
7721 gen_helper_mftc0_debug(t0, cpu_env);
7722 break;
7723 default:
7724 gen_mfc0(ctx, t0, rt, sel);
7725 break;
7727 break;
7728 default:
7729 gen_mfc0(ctx, t0, rt, sel);
7731 } else switch (sel) {
7732 /* GPR registers. */
7733 case 0:
7734 gen_helper_1e0i(mftgpr, t0, rt);
7735 break;
7736 /* Auxiliary CPU registers */
7737 case 1:
7738 switch (rt) {
7739 case 0:
7740 gen_helper_1e0i(mftlo, t0, 0);
7741 break;
7742 case 1:
7743 gen_helper_1e0i(mfthi, t0, 0);
7744 break;
7745 case 2:
7746 gen_helper_1e0i(mftacx, t0, 0);
7747 break;
7748 case 4:
7749 gen_helper_1e0i(mftlo, t0, 1);
7750 break;
7751 case 5:
7752 gen_helper_1e0i(mfthi, t0, 1);
7753 break;
7754 case 6:
7755 gen_helper_1e0i(mftacx, t0, 1);
7756 break;
7757 case 8:
7758 gen_helper_1e0i(mftlo, t0, 2);
7759 break;
7760 case 9:
7761 gen_helper_1e0i(mfthi, t0, 2);
7762 break;
7763 case 10:
7764 gen_helper_1e0i(mftacx, t0, 2);
7765 break;
7766 case 12:
7767 gen_helper_1e0i(mftlo, t0, 3);
7768 break;
7769 case 13:
7770 gen_helper_1e0i(mfthi, t0, 3);
7771 break;
7772 case 14:
7773 gen_helper_1e0i(mftacx, t0, 3);
7774 break;
7775 case 16:
7776 gen_helper_mftdsp(t0, cpu_env);
7777 break;
7778 default:
7779 goto die;
7781 break;
7782 /* Floating point (COP1). */
7783 case 2:
7784 /* XXX: For now we support only a single FPU context. */
7785 if (h == 0) {
7786 TCGv_i32 fp0 = tcg_temp_new_i32();
7788 gen_load_fpr32(ctx, fp0, rt);
7789 tcg_gen_ext_i32_tl(t0, fp0);
7790 tcg_temp_free_i32(fp0);
7791 } else {
7792 TCGv_i32 fp0 = tcg_temp_new_i32();
7794 gen_load_fpr32h(ctx, fp0, rt);
7795 tcg_gen_ext_i32_tl(t0, fp0);
7796 tcg_temp_free_i32(fp0);
7798 break;
7799 case 3:
7800 /* XXX: For now we support only a single FPU context. */
7801 gen_helper_1e0i(cfc1, t0, rt);
7802 break;
7803 /* COP2: Not implemented. */
7804 case 4:
7805 case 5:
7806 /* fall through */
7807 default:
7808 goto die;
7810 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
7811 gen_store_gpr(t0, rd);
7812 tcg_temp_free(t0);
7813 return;
7815 die:
7816 tcg_temp_free(t0);
7817 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
7818 generate_exception_end(ctx, EXCP_RI);
7821 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
7822 int u, int sel, int h)
7824 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7825 TCGv t0 = tcg_temp_local_new();
7827 gen_load_gpr(t0, rt);
7828 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7829 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7830 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7831 /* NOP */ ;
7832 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7833 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7834 /* NOP */ ;
7835 else if (u == 0) {
7836 switch (rd) {
7837 case 1:
7838 switch (sel) {
7839 case 1:
7840 gen_helper_mttc0_vpecontrol(cpu_env, t0);
7841 break;
7842 case 2:
7843 gen_helper_mttc0_vpeconf0(cpu_env, t0);
7844 break;
7845 default:
7846 goto die;
7847 break;
7849 break;
7850 case 2:
7851 switch (sel) {
7852 case 1:
7853 gen_helper_mttc0_tcstatus(cpu_env, t0);
7854 break;
7855 case 2:
7856 gen_helper_mttc0_tcbind(cpu_env, t0);
7857 break;
7858 case 3:
7859 gen_helper_mttc0_tcrestart(cpu_env, t0);
7860 break;
7861 case 4:
7862 gen_helper_mttc0_tchalt(cpu_env, t0);
7863 break;
7864 case 5:
7865 gen_helper_mttc0_tccontext(cpu_env, t0);
7866 break;
7867 case 6:
7868 gen_helper_mttc0_tcschedule(cpu_env, t0);
7869 break;
7870 case 7:
7871 gen_helper_mttc0_tcschefback(cpu_env, t0);
7872 break;
7873 default:
7874 gen_mtc0(ctx, t0, rd, sel);
7875 break;
7877 break;
7878 case 10:
7879 switch (sel) {
7880 case 0:
7881 gen_helper_mttc0_entryhi(cpu_env, t0);
7882 break;
7883 default:
7884 gen_mtc0(ctx, t0, rd, sel);
7885 break;
7887 case 12:
7888 switch (sel) {
7889 case 0:
7890 gen_helper_mttc0_status(cpu_env, t0);
7891 break;
7892 default:
7893 gen_mtc0(ctx, t0, rd, sel);
7894 break;
7896 case 13:
7897 switch (sel) {
7898 case 0:
7899 gen_helper_mttc0_cause(cpu_env, t0);
7900 break;
7901 default:
7902 goto die;
7903 break;
7905 break;
7906 case 15:
7907 switch (sel) {
7908 case 1:
7909 gen_helper_mttc0_ebase(cpu_env, t0);
7910 break;
7911 default:
7912 goto die;
7913 break;
7915 break;
7916 case 23:
7917 switch (sel) {
7918 case 0:
7919 gen_helper_mttc0_debug(cpu_env, t0);
7920 break;
7921 default:
7922 gen_mtc0(ctx, t0, rd, sel);
7923 break;
7925 break;
7926 default:
7927 gen_mtc0(ctx, t0, rd, sel);
7929 } else switch (sel) {
7930 /* GPR registers. */
7931 case 0:
7932 gen_helper_0e1i(mttgpr, t0, rd);
7933 break;
7934 /* Auxiliary CPU registers */
7935 case 1:
7936 switch (rd) {
7937 case 0:
7938 gen_helper_0e1i(mttlo, t0, 0);
7939 break;
7940 case 1:
7941 gen_helper_0e1i(mtthi, t0, 0);
7942 break;
7943 case 2:
7944 gen_helper_0e1i(mttacx, t0, 0);
7945 break;
7946 case 4:
7947 gen_helper_0e1i(mttlo, t0, 1);
7948 break;
7949 case 5:
7950 gen_helper_0e1i(mtthi, t0, 1);
7951 break;
7952 case 6:
7953 gen_helper_0e1i(mttacx, t0, 1);
7954 break;
7955 case 8:
7956 gen_helper_0e1i(mttlo, t0, 2);
7957 break;
7958 case 9:
7959 gen_helper_0e1i(mtthi, t0, 2);
7960 break;
7961 case 10:
7962 gen_helper_0e1i(mttacx, t0, 2);
7963 break;
7964 case 12:
7965 gen_helper_0e1i(mttlo, t0, 3);
7966 break;
7967 case 13:
7968 gen_helper_0e1i(mtthi, t0, 3);
7969 break;
7970 case 14:
7971 gen_helper_0e1i(mttacx, t0, 3);
7972 break;
7973 case 16:
7974 gen_helper_mttdsp(cpu_env, t0);
7975 break;
7976 default:
7977 goto die;
7979 break;
7980 /* Floating point (COP1). */
7981 case 2:
7982 /* XXX: For now we support only a single FPU context. */
7983 if (h == 0) {
7984 TCGv_i32 fp0 = tcg_temp_new_i32();
7986 tcg_gen_trunc_tl_i32(fp0, t0);
7987 gen_store_fpr32(ctx, fp0, rd);
7988 tcg_temp_free_i32(fp0);
7989 } else {
7990 TCGv_i32 fp0 = tcg_temp_new_i32();
7992 tcg_gen_trunc_tl_i32(fp0, t0);
7993 gen_store_fpr32h(ctx, fp0, rd);
7994 tcg_temp_free_i32(fp0);
7996 break;
7997 case 3:
7998 /* XXX: For now we support only a single FPU context. */
8000 TCGv_i32 fs_tmp = tcg_const_i32(rd);
8002 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
8003 tcg_temp_free_i32(fs_tmp);
8005 /* Stop translation as we may have changed hflags */
8006 ctx->bstate = BS_STOP;
8007 break;
8008 /* COP2: Not implemented. */
8009 case 4:
8010 case 5:
8011 /* fall through */
8012 default:
8013 goto die;
8015 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
8016 tcg_temp_free(t0);
8017 return;
8019 die:
8020 tcg_temp_free(t0);
8021 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
8022 generate_exception_end(ctx, EXCP_RI);
8025 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
8027 const char *opn = "ldst";
8029 check_cp0_enabled(ctx);
8030 switch (opc) {
8031 case OPC_MFC0:
8032 if (rt == 0) {
8033 /* Treat as NOP. */
8034 return;
8036 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8037 opn = "mfc0";
8038 break;
8039 case OPC_MTC0:
8041 TCGv t0 = tcg_temp_new();
8043 gen_load_gpr(t0, rt);
8044 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
8045 tcg_temp_free(t0);
8047 opn = "mtc0";
8048 break;
8049 #if defined(TARGET_MIPS64)
8050 case OPC_DMFC0:
8051 check_insn(ctx, ISA_MIPS3);
8052 if (rt == 0) {
8053 /* Treat as NOP. */
8054 return;
8056 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8057 opn = "dmfc0";
8058 break;
8059 case OPC_DMTC0:
8060 check_insn(ctx, ISA_MIPS3);
8062 TCGv t0 = tcg_temp_new();
8064 gen_load_gpr(t0, rt);
8065 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
8066 tcg_temp_free(t0);
8068 opn = "dmtc0";
8069 break;
8070 #endif
8071 case OPC_MFHC0:
8072 check_mvh(ctx);
8073 if (rt == 0) {
8074 /* Treat as NOP. */
8075 return;
8077 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8078 opn = "mfhc0";
8079 break;
8080 case OPC_MTHC0:
8081 check_mvh(ctx);
8083 TCGv t0 = tcg_temp_new();
8084 gen_load_gpr(t0, rt);
8085 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
8086 tcg_temp_free(t0);
8088 opn = "mthc0";
8089 break;
8090 case OPC_MFTR:
8091 check_insn(ctx, ASE_MT);
8092 if (rd == 0) {
8093 /* Treat as NOP. */
8094 return;
8096 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
8097 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8098 opn = "mftr";
8099 break;
8100 case OPC_MTTR:
8101 check_insn(ctx, ASE_MT);
8102 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
8103 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8104 opn = "mttr";
8105 break;
8106 case OPC_TLBWI:
8107 opn = "tlbwi";
8108 if (!env->tlb->helper_tlbwi)
8109 goto die;
8110 gen_helper_tlbwi(cpu_env);
8111 break;
8112 case OPC_TLBINV:
8113 opn = "tlbinv";
8114 if (ctx->ie >= 2) {
8115 if (!env->tlb->helper_tlbinv) {
8116 goto die;
8118 gen_helper_tlbinv(cpu_env);
8119 } /* treat as nop if TLBINV not supported */
8120 break;
8121 case OPC_TLBINVF:
8122 opn = "tlbinvf";
8123 if (ctx->ie >= 2) {
8124 if (!env->tlb->helper_tlbinvf) {
8125 goto die;
8127 gen_helper_tlbinvf(cpu_env);
8128 } /* treat as nop if TLBINV not supported */
8129 break;
8130 case OPC_TLBWR:
8131 opn = "tlbwr";
8132 if (!env->tlb->helper_tlbwr)
8133 goto die;
8134 gen_helper_tlbwr(cpu_env);
8135 break;
8136 case OPC_TLBP:
8137 opn = "tlbp";
8138 if (!env->tlb->helper_tlbp)
8139 goto die;
8140 gen_helper_tlbp(cpu_env);
8141 break;
8142 case OPC_TLBR:
8143 opn = "tlbr";
8144 if (!env->tlb->helper_tlbr)
8145 goto die;
8146 gen_helper_tlbr(cpu_env);
8147 break;
8148 case OPC_ERET: /* OPC_ERETNC */
8149 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8150 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8151 goto die;
8152 } else {
8153 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
8154 if (ctx->opcode & (1 << bit_shift)) {
8155 /* OPC_ERETNC */
8156 opn = "eretnc";
8157 check_insn(ctx, ISA_MIPS32R5);
8158 gen_helper_eretnc(cpu_env);
8159 } else {
8160 /* OPC_ERET */
8161 opn = "eret";
8162 check_insn(ctx, ISA_MIPS2);
8163 gen_helper_eret(cpu_env);
8165 ctx->bstate = BS_EXCP;
8167 break;
8168 case OPC_DERET:
8169 opn = "deret";
8170 check_insn(ctx, ISA_MIPS32);
8171 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8172 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8173 goto die;
8175 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
8176 MIPS_INVAL(opn);
8177 generate_exception_end(ctx, EXCP_RI);
8178 } else {
8179 gen_helper_deret(cpu_env);
8180 ctx->bstate = BS_EXCP;
8182 break;
8183 case OPC_WAIT:
8184 opn = "wait";
8185 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
8186 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8187 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8188 goto die;
8190 /* If we get an exception, we want to restart at next instruction */
8191 ctx->pc += 4;
8192 save_cpu_state(ctx, 1);
8193 ctx->pc -= 4;
8194 gen_helper_wait(cpu_env);
8195 ctx->bstate = BS_EXCP;
8196 break;
8197 default:
8198 die:
8199 MIPS_INVAL(opn);
8200 generate_exception_end(ctx, EXCP_RI);
8201 return;
8203 (void)opn; /* avoid a compiler warning */
8205 #endif /* !CONFIG_USER_ONLY */
8207 /* CP1 Branches (before delay slot) */
8208 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
8209 int32_t cc, int32_t offset)
8211 target_ulong btarget;
8212 TCGv_i32 t0 = tcg_temp_new_i32();
8214 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8215 generate_exception_end(ctx, EXCP_RI);
8216 goto out;
8219 if (cc != 0)
8220 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
8222 btarget = ctx->pc + 4 + offset;
8224 switch (op) {
8225 case OPC_BC1F:
8226 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8227 tcg_gen_not_i32(t0, t0);
8228 tcg_gen_andi_i32(t0, t0, 1);
8229 tcg_gen_extu_i32_tl(bcond, t0);
8230 goto not_likely;
8231 case OPC_BC1FL:
8232 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8233 tcg_gen_not_i32(t0, t0);
8234 tcg_gen_andi_i32(t0, t0, 1);
8235 tcg_gen_extu_i32_tl(bcond, t0);
8236 goto likely;
8237 case OPC_BC1T:
8238 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8239 tcg_gen_andi_i32(t0, t0, 1);
8240 tcg_gen_extu_i32_tl(bcond, t0);
8241 goto not_likely;
8242 case OPC_BC1TL:
8243 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8244 tcg_gen_andi_i32(t0, t0, 1);
8245 tcg_gen_extu_i32_tl(bcond, t0);
8246 likely:
8247 ctx->hflags |= MIPS_HFLAG_BL;
8248 break;
8249 case OPC_BC1FANY2:
8251 TCGv_i32 t1 = tcg_temp_new_i32();
8252 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8253 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8254 tcg_gen_nand_i32(t0, t0, t1);
8255 tcg_temp_free_i32(t1);
8256 tcg_gen_andi_i32(t0, t0, 1);
8257 tcg_gen_extu_i32_tl(bcond, t0);
8259 goto not_likely;
8260 case OPC_BC1TANY2:
8262 TCGv_i32 t1 = tcg_temp_new_i32();
8263 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8264 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8265 tcg_gen_or_i32(t0, t0, t1);
8266 tcg_temp_free_i32(t1);
8267 tcg_gen_andi_i32(t0, t0, 1);
8268 tcg_gen_extu_i32_tl(bcond, t0);
8270 goto not_likely;
8271 case OPC_BC1FANY4:
8273 TCGv_i32 t1 = tcg_temp_new_i32();
8274 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8275 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8276 tcg_gen_and_i32(t0, t0, t1);
8277 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8278 tcg_gen_and_i32(t0, t0, t1);
8279 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8280 tcg_gen_nand_i32(t0, t0, t1);
8281 tcg_temp_free_i32(t1);
8282 tcg_gen_andi_i32(t0, t0, 1);
8283 tcg_gen_extu_i32_tl(bcond, t0);
8285 goto not_likely;
8286 case OPC_BC1TANY4:
8288 TCGv_i32 t1 = tcg_temp_new_i32();
8289 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8290 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8291 tcg_gen_or_i32(t0, t0, t1);
8292 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8293 tcg_gen_or_i32(t0, t0, t1);
8294 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8295 tcg_gen_or_i32(t0, t0, t1);
8296 tcg_temp_free_i32(t1);
8297 tcg_gen_andi_i32(t0, t0, 1);
8298 tcg_gen_extu_i32_tl(bcond, t0);
8300 not_likely:
8301 ctx->hflags |= MIPS_HFLAG_BC;
8302 break;
8303 default:
8304 MIPS_INVAL("cp1 cond branch");
8305 generate_exception_end(ctx, EXCP_RI);
8306 goto out;
8308 ctx->btarget = btarget;
8309 ctx->hflags |= MIPS_HFLAG_BDS32;
8310 out:
8311 tcg_temp_free_i32(t0);
8314 /* R6 CP1 Branches */
8315 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
8316 int32_t ft, int32_t offset,
8317 int delayslot_size)
8319 target_ulong btarget;
8320 TCGv_i64 t0 = tcg_temp_new_i64();
8322 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8323 #ifdef MIPS_DEBUG_DISAS
8324 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
8325 "\n", ctx->pc);
8326 #endif
8327 generate_exception_end(ctx, EXCP_RI);
8328 goto out;
8331 gen_load_fpr64(ctx, t0, ft);
8332 tcg_gen_andi_i64(t0, t0, 1);
8334 btarget = addr_add(ctx, ctx->pc + 4, offset);
8336 switch (op) {
8337 case OPC_BC1EQZ:
8338 tcg_gen_xori_i64(t0, t0, 1);
8339 ctx->hflags |= MIPS_HFLAG_BC;
8340 break;
8341 case OPC_BC1NEZ:
8342 /* t0 already set */
8343 ctx->hflags |= MIPS_HFLAG_BC;
8344 break;
8345 default:
8346 MIPS_INVAL("cp1 cond branch");
8347 generate_exception_end(ctx, EXCP_RI);
8348 goto out;
8351 tcg_gen_trunc_i64_tl(bcond, t0);
8353 ctx->btarget = btarget;
8355 switch (delayslot_size) {
8356 case 2:
8357 ctx->hflags |= MIPS_HFLAG_BDS16;
8358 break;
8359 case 4:
8360 ctx->hflags |= MIPS_HFLAG_BDS32;
8361 break;
8364 out:
8365 tcg_temp_free_i64(t0);
8368 /* Coprocessor 1 (FPU) */
8370 #define FOP(func, fmt) (((fmt) << 21) | (func))
8372 enum fopcode {
8373 OPC_ADD_S = FOP(0, FMT_S),
8374 OPC_SUB_S = FOP(1, FMT_S),
8375 OPC_MUL_S = FOP(2, FMT_S),
8376 OPC_DIV_S = FOP(3, FMT_S),
8377 OPC_SQRT_S = FOP(4, FMT_S),
8378 OPC_ABS_S = FOP(5, FMT_S),
8379 OPC_MOV_S = FOP(6, FMT_S),
8380 OPC_NEG_S = FOP(7, FMT_S),
8381 OPC_ROUND_L_S = FOP(8, FMT_S),
8382 OPC_TRUNC_L_S = FOP(9, FMT_S),
8383 OPC_CEIL_L_S = FOP(10, FMT_S),
8384 OPC_FLOOR_L_S = FOP(11, FMT_S),
8385 OPC_ROUND_W_S = FOP(12, FMT_S),
8386 OPC_TRUNC_W_S = FOP(13, FMT_S),
8387 OPC_CEIL_W_S = FOP(14, FMT_S),
8388 OPC_FLOOR_W_S = FOP(15, FMT_S),
8389 OPC_SEL_S = FOP(16, FMT_S),
8390 OPC_MOVCF_S = FOP(17, FMT_S),
8391 OPC_MOVZ_S = FOP(18, FMT_S),
8392 OPC_MOVN_S = FOP(19, FMT_S),
8393 OPC_SELEQZ_S = FOP(20, FMT_S),
8394 OPC_RECIP_S = FOP(21, FMT_S),
8395 OPC_RSQRT_S = FOP(22, FMT_S),
8396 OPC_SELNEZ_S = FOP(23, FMT_S),
8397 OPC_MADDF_S = FOP(24, FMT_S),
8398 OPC_MSUBF_S = FOP(25, FMT_S),
8399 OPC_RINT_S = FOP(26, FMT_S),
8400 OPC_CLASS_S = FOP(27, FMT_S),
8401 OPC_MIN_S = FOP(28, FMT_S),
8402 OPC_RECIP2_S = FOP(28, FMT_S),
8403 OPC_MINA_S = FOP(29, FMT_S),
8404 OPC_RECIP1_S = FOP(29, FMT_S),
8405 OPC_MAX_S = FOP(30, FMT_S),
8406 OPC_RSQRT1_S = FOP(30, FMT_S),
8407 OPC_MAXA_S = FOP(31, FMT_S),
8408 OPC_RSQRT2_S = FOP(31, FMT_S),
8409 OPC_CVT_D_S = FOP(33, FMT_S),
8410 OPC_CVT_W_S = FOP(36, FMT_S),
8411 OPC_CVT_L_S = FOP(37, FMT_S),
8412 OPC_CVT_PS_S = FOP(38, FMT_S),
8413 OPC_CMP_F_S = FOP (48, FMT_S),
8414 OPC_CMP_UN_S = FOP (49, FMT_S),
8415 OPC_CMP_EQ_S = FOP (50, FMT_S),
8416 OPC_CMP_UEQ_S = FOP (51, FMT_S),
8417 OPC_CMP_OLT_S = FOP (52, FMT_S),
8418 OPC_CMP_ULT_S = FOP (53, FMT_S),
8419 OPC_CMP_OLE_S = FOP (54, FMT_S),
8420 OPC_CMP_ULE_S = FOP (55, FMT_S),
8421 OPC_CMP_SF_S = FOP (56, FMT_S),
8422 OPC_CMP_NGLE_S = FOP (57, FMT_S),
8423 OPC_CMP_SEQ_S = FOP (58, FMT_S),
8424 OPC_CMP_NGL_S = FOP (59, FMT_S),
8425 OPC_CMP_LT_S = FOP (60, FMT_S),
8426 OPC_CMP_NGE_S = FOP (61, FMT_S),
8427 OPC_CMP_LE_S = FOP (62, FMT_S),
8428 OPC_CMP_NGT_S = FOP (63, FMT_S),
8430 OPC_ADD_D = FOP(0, FMT_D),
8431 OPC_SUB_D = FOP(1, FMT_D),
8432 OPC_MUL_D = FOP(2, FMT_D),
8433 OPC_DIV_D = FOP(3, FMT_D),
8434 OPC_SQRT_D = FOP(4, FMT_D),
8435 OPC_ABS_D = FOP(5, FMT_D),
8436 OPC_MOV_D = FOP(6, FMT_D),
8437 OPC_NEG_D = FOP(7, FMT_D),
8438 OPC_ROUND_L_D = FOP(8, FMT_D),
8439 OPC_TRUNC_L_D = FOP(9, FMT_D),
8440 OPC_CEIL_L_D = FOP(10, FMT_D),
8441 OPC_FLOOR_L_D = FOP(11, FMT_D),
8442 OPC_ROUND_W_D = FOP(12, FMT_D),
8443 OPC_TRUNC_W_D = FOP(13, FMT_D),
8444 OPC_CEIL_W_D = FOP(14, FMT_D),
8445 OPC_FLOOR_W_D = FOP(15, FMT_D),
8446 OPC_SEL_D = FOP(16, FMT_D),
8447 OPC_MOVCF_D = FOP(17, FMT_D),
8448 OPC_MOVZ_D = FOP(18, FMT_D),
8449 OPC_MOVN_D = FOP(19, FMT_D),
8450 OPC_SELEQZ_D = FOP(20, FMT_D),
8451 OPC_RECIP_D = FOP(21, FMT_D),
8452 OPC_RSQRT_D = FOP(22, FMT_D),
8453 OPC_SELNEZ_D = FOP(23, FMT_D),
8454 OPC_MADDF_D = FOP(24, FMT_D),
8455 OPC_MSUBF_D = FOP(25, FMT_D),
8456 OPC_RINT_D = FOP(26, FMT_D),
8457 OPC_CLASS_D = FOP(27, FMT_D),
8458 OPC_MIN_D = FOP(28, FMT_D),
8459 OPC_RECIP2_D = FOP(28, FMT_D),
8460 OPC_MINA_D = FOP(29, FMT_D),
8461 OPC_RECIP1_D = FOP(29, FMT_D),
8462 OPC_MAX_D = FOP(30, FMT_D),
8463 OPC_RSQRT1_D = FOP(30, FMT_D),
8464 OPC_MAXA_D = FOP(31, FMT_D),
8465 OPC_RSQRT2_D = FOP(31, FMT_D),
8466 OPC_CVT_S_D = FOP(32, FMT_D),
8467 OPC_CVT_W_D = FOP(36, FMT_D),
8468 OPC_CVT_L_D = FOP(37, FMT_D),
8469 OPC_CMP_F_D = FOP (48, FMT_D),
8470 OPC_CMP_UN_D = FOP (49, FMT_D),
8471 OPC_CMP_EQ_D = FOP (50, FMT_D),
8472 OPC_CMP_UEQ_D = FOP (51, FMT_D),
8473 OPC_CMP_OLT_D = FOP (52, FMT_D),
8474 OPC_CMP_ULT_D = FOP (53, FMT_D),
8475 OPC_CMP_OLE_D = FOP (54, FMT_D),
8476 OPC_CMP_ULE_D = FOP (55, FMT_D),
8477 OPC_CMP_SF_D = FOP (56, FMT_D),
8478 OPC_CMP_NGLE_D = FOP (57, FMT_D),
8479 OPC_CMP_SEQ_D = FOP (58, FMT_D),
8480 OPC_CMP_NGL_D = FOP (59, FMT_D),
8481 OPC_CMP_LT_D = FOP (60, FMT_D),
8482 OPC_CMP_NGE_D = FOP (61, FMT_D),
8483 OPC_CMP_LE_D = FOP (62, FMT_D),
8484 OPC_CMP_NGT_D = FOP (63, FMT_D),
8486 OPC_CVT_S_W = FOP(32, FMT_W),
8487 OPC_CVT_D_W = FOP(33, FMT_W),
8488 OPC_CVT_S_L = FOP(32, FMT_L),
8489 OPC_CVT_D_L = FOP(33, FMT_L),
8490 OPC_CVT_PS_PW = FOP(38, FMT_W),
8492 OPC_ADD_PS = FOP(0, FMT_PS),
8493 OPC_SUB_PS = FOP(1, FMT_PS),
8494 OPC_MUL_PS = FOP(2, FMT_PS),
8495 OPC_DIV_PS = FOP(3, FMT_PS),
8496 OPC_ABS_PS = FOP(5, FMT_PS),
8497 OPC_MOV_PS = FOP(6, FMT_PS),
8498 OPC_NEG_PS = FOP(7, FMT_PS),
8499 OPC_MOVCF_PS = FOP(17, FMT_PS),
8500 OPC_MOVZ_PS = FOP(18, FMT_PS),
8501 OPC_MOVN_PS = FOP(19, FMT_PS),
8502 OPC_ADDR_PS = FOP(24, FMT_PS),
8503 OPC_MULR_PS = FOP(26, FMT_PS),
8504 OPC_RECIP2_PS = FOP(28, FMT_PS),
8505 OPC_RECIP1_PS = FOP(29, FMT_PS),
8506 OPC_RSQRT1_PS = FOP(30, FMT_PS),
8507 OPC_RSQRT2_PS = FOP(31, FMT_PS),
8509 OPC_CVT_S_PU = FOP(32, FMT_PS),
8510 OPC_CVT_PW_PS = FOP(36, FMT_PS),
8511 OPC_CVT_S_PL = FOP(40, FMT_PS),
8512 OPC_PLL_PS = FOP(44, FMT_PS),
8513 OPC_PLU_PS = FOP(45, FMT_PS),
8514 OPC_PUL_PS = FOP(46, FMT_PS),
8515 OPC_PUU_PS = FOP(47, FMT_PS),
8516 OPC_CMP_F_PS = FOP (48, FMT_PS),
8517 OPC_CMP_UN_PS = FOP (49, FMT_PS),
8518 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
8519 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
8520 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
8521 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
8522 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
8523 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
8524 OPC_CMP_SF_PS = FOP (56, FMT_PS),
8525 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
8526 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
8527 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
8528 OPC_CMP_LT_PS = FOP (60, FMT_PS),
8529 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
8530 OPC_CMP_LE_PS = FOP (62, FMT_PS),
8531 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
8534 enum r6_f_cmp_op {
8535 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
8536 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
8537 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
8538 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
8539 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
8540 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
8541 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
8542 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
8543 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
8544 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
8545 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
8546 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
8547 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
8548 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
8549 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
8550 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
8551 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
8552 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
8553 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
8554 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
8555 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
8556 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
8558 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
8559 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
8560 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
8561 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
8562 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
8563 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
8564 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
8565 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
8566 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
8567 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
8568 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
8569 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
8570 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
8571 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
8572 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
8573 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
8574 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
8575 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
8576 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
8577 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
8578 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
8579 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
8581 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
8583 TCGv t0 = tcg_temp_new();
8585 switch (opc) {
8586 case OPC_MFC1:
8588 TCGv_i32 fp0 = tcg_temp_new_i32();
8590 gen_load_fpr32(ctx, fp0, fs);
8591 tcg_gen_ext_i32_tl(t0, fp0);
8592 tcg_temp_free_i32(fp0);
8594 gen_store_gpr(t0, rt);
8595 break;
8596 case OPC_MTC1:
8597 gen_load_gpr(t0, rt);
8599 TCGv_i32 fp0 = tcg_temp_new_i32();
8601 tcg_gen_trunc_tl_i32(fp0, t0);
8602 gen_store_fpr32(ctx, fp0, fs);
8603 tcg_temp_free_i32(fp0);
8605 break;
8606 case OPC_CFC1:
8607 gen_helper_1e0i(cfc1, t0, fs);
8608 gen_store_gpr(t0, rt);
8609 break;
8610 case OPC_CTC1:
8611 gen_load_gpr(t0, rt);
8612 save_cpu_state(ctx, 0);
8614 TCGv_i32 fs_tmp = tcg_const_i32(fs);
8616 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
8617 tcg_temp_free_i32(fs_tmp);
8619 /* Stop translation as we may have changed hflags */
8620 ctx->bstate = BS_STOP;
8621 break;
8622 #if defined(TARGET_MIPS64)
8623 case OPC_DMFC1:
8624 gen_load_fpr64(ctx, t0, fs);
8625 gen_store_gpr(t0, rt);
8626 break;
8627 case OPC_DMTC1:
8628 gen_load_gpr(t0, rt);
8629 gen_store_fpr64(ctx, t0, fs);
8630 break;
8631 #endif
8632 case OPC_MFHC1:
8634 TCGv_i32 fp0 = tcg_temp_new_i32();
8636 gen_load_fpr32h(ctx, fp0, fs);
8637 tcg_gen_ext_i32_tl(t0, fp0);
8638 tcg_temp_free_i32(fp0);
8640 gen_store_gpr(t0, rt);
8641 break;
8642 case OPC_MTHC1:
8643 gen_load_gpr(t0, rt);
8645 TCGv_i32 fp0 = tcg_temp_new_i32();
8647 tcg_gen_trunc_tl_i32(fp0, t0);
8648 gen_store_fpr32h(ctx, fp0, fs);
8649 tcg_temp_free_i32(fp0);
8651 break;
8652 default:
8653 MIPS_INVAL("cp1 move");
8654 generate_exception_end(ctx, EXCP_RI);
8655 goto out;
8658 out:
8659 tcg_temp_free(t0);
8662 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
8664 TCGLabel *l1;
8665 TCGCond cond;
8666 TCGv_i32 t0;
8668 if (rd == 0) {
8669 /* Treat as NOP. */
8670 return;
8673 if (tf)
8674 cond = TCG_COND_EQ;
8675 else
8676 cond = TCG_COND_NE;
8678 l1 = gen_new_label();
8679 t0 = tcg_temp_new_i32();
8680 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8681 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8682 tcg_temp_free_i32(t0);
8683 if (rs == 0) {
8684 tcg_gen_movi_tl(cpu_gpr[rd], 0);
8685 } else {
8686 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
8688 gen_set_label(l1);
8691 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
8692 int tf)
8694 int cond;
8695 TCGv_i32 t0 = tcg_temp_new_i32();
8696 TCGLabel *l1 = gen_new_label();
8698 if (tf)
8699 cond = TCG_COND_EQ;
8700 else
8701 cond = TCG_COND_NE;
8703 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8704 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8705 gen_load_fpr32(ctx, t0, fs);
8706 gen_store_fpr32(ctx, t0, fd);
8707 gen_set_label(l1);
8708 tcg_temp_free_i32(t0);
8711 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
8713 int cond;
8714 TCGv_i32 t0 = tcg_temp_new_i32();
8715 TCGv_i64 fp0;
8716 TCGLabel *l1 = gen_new_label();
8718 if (tf)
8719 cond = TCG_COND_EQ;
8720 else
8721 cond = TCG_COND_NE;
8723 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8724 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8725 tcg_temp_free_i32(t0);
8726 fp0 = tcg_temp_new_i64();
8727 gen_load_fpr64(ctx, fp0, fs);
8728 gen_store_fpr64(ctx, fp0, fd);
8729 tcg_temp_free_i64(fp0);
8730 gen_set_label(l1);
8733 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
8734 int cc, int tf)
8736 int cond;
8737 TCGv_i32 t0 = tcg_temp_new_i32();
8738 TCGLabel *l1 = gen_new_label();
8739 TCGLabel *l2 = gen_new_label();
8741 if (tf)
8742 cond = TCG_COND_EQ;
8743 else
8744 cond = TCG_COND_NE;
8746 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8747 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8748 gen_load_fpr32(ctx, t0, fs);
8749 gen_store_fpr32(ctx, t0, fd);
8750 gen_set_label(l1);
8752 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
8753 tcg_gen_brcondi_i32(cond, t0, 0, l2);
8754 gen_load_fpr32h(ctx, t0, fs);
8755 gen_store_fpr32h(ctx, t0, fd);
8756 tcg_temp_free_i32(t0);
8757 gen_set_label(l2);
8760 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8761 int fs)
8763 TCGv_i32 t1 = tcg_const_i32(0);
8764 TCGv_i32 fp0 = tcg_temp_new_i32();
8765 TCGv_i32 fp1 = tcg_temp_new_i32();
8766 TCGv_i32 fp2 = tcg_temp_new_i32();
8767 gen_load_fpr32(ctx, fp0, fd);
8768 gen_load_fpr32(ctx, fp1, ft);
8769 gen_load_fpr32(ctx, fp2, fs);
8771 switch (op1) {
8772 case OPC_SEL_S:
8773 tcg_gen_andi_i32(fp0, fp0, 1);
8774 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8775 break;
8776 case OPC_SELEQZ_S:
8777 tcg_gen_andi_i32(fp1, fp1, 1);
8778 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8779 break;
8780 case OPC_SELNEZ_S:
8781 tcg_gen_andi_i32(fp1, fp1, 1);
8782 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8783 break;
8784 default:
8785 MIPS_INVAL("gen_sel_s");
8786 generate_exception_end(ctx, EXCP_RI);
8787 break;
8790 gen_store_fpr32(ctx, fp0, fd);
8791 tcg_temp_free_i32(fp2);
8792 tcg_temp_free_i32(fp1);
8793 tcg_temp_free_i32(fp0);
8794 tcg_temp_free_i32(t1);
8797 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8798 int fs)
8800 TCGv_i64 t1 = tcg_const_i64(0);
8801 TCGv_i64 fp0 = tcg_temp_new_i64();
8802 TCGv_i64 fp1 = tcg_temp_new_i64();
8803 TCGv_i64 fp2 = tcg_temp_new_i64();
8804 gen_load_fpr64(ctx, fp0, fd);
8805 gen_load_fpr64(ctx, fp1, ft);
8806 gen_load_fpr64(ctx, fp2, fs);
8808 switch (op1) {
8809 case OPC_SEL_D:
8810 tcg_gen_andi_i64(fp0, fp0, 1);
8811 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8812 break;
8813 case OPC_SELEQZ_D:
8814 tcg_gen_andi_i64(fp1, fp1, 1);
8815 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8816 break;
8817 case OPC_SELNEZ_D:
8818 tcg_gen_andi_i64(fp1, fp1, 1);
8819 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8820 break;
8821 default:
8822 MIPS_INVAL("gen_sel_d");
8823 generate_exception_end(ctx, EXCP_RI);
8824 break;
8827 gen_store_fpr64(ctx, fp0, fd);
8828 tcg_temp_free_i64(fp2);
8829 tcg_temp_free_i64(fp1);
8830 tcg_temp_free_i64(fp0);
8831 tcg_temp_free_i64(t1);
8834 static void gen_farith (DisasContext *ctx, enum fopcode op1,
8835 int ft, int fs, int fd, int cc)
8837 uint32_t func = ctx->opcode & 0x3f;
8838 switch (op1) {
8839 case OPC_ADD_S:
8841 TCGv_i32 fp0 = tcg_temp_new_i32();
8842 TCGv_i32 fp1 = tcg_temp_new_i32();
8844 gen_load_fpr32(ctx, fp0, fs);
8845 gen_load_fpr32(ctx, fp1, ft);
8846 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
8847 tcg_temp_free_i32(fp1);
8848 gen_store_fpr32(ctx, fp0, fd);
8849 tcg_temp_free_i32(fp0);
8851 break;
8852 case OPC_SUB_S:
8854 TCGv_i32 fp0 = tcg_temp_new_i32();
8855 TCGv_i32 fp1 = tcg_temp_new_i32();
8857 gen_load_fpr32(ctx, fp0, fs);
8858 gen_load_fpr32(ctx, fp1, ft);
8859 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
8860 tcg_temp_free_i32(fp1);
8861 gen_store_fpr32(ctx, fp0, fd);
8862 tcg_temp_free_i32(fp0);
8864 break;
8865 case OPC_MUL_S:
8867 TCGv_i32 fp0 = tcg_temp_new_i32();
8868 TCGv_i32 fp1 = tcg_temp_new_i32();
8870 gen_load_fpr32(ctx, fp0, fs);
8871 gen_load_fpr32(ctx, fp1, ft);
8872 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
8873 tcg_temp_free_i32(fp1);
8874 gen_store_fpr32(ctx, fp0, fd);
8875 tcg_temp_free_i32(fp0);
8877 break;
8878 case OPC_DIV_S:
8880 TCGv_i32 fp0 = tcg_temp_new_i32();
8881 TCGv_i32 fp1 = tcg_temp_new_i32();
8883 gen_load_fpr32(ctx, fp0, fs);
8884 gen_load_fpr32(ctx, fp1, ft);
8885 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
8886 tcg_temp_free_i32(fp1);
8887 gen_store_fpr32(ctx, fp0, fd);
8888 tcg_temp_free_i32(fp0);
8890 break;
8891 case OPC_SQRT_S:
8893 TCGv_i32 fp0 = tcg_temp_new_i32();
8895 gen_load_fpr32(ctx, fp0, fs);
8896 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
8897 gen_store_fpr32(ctx, fp0, fd);
8898 tcg_temp_free_i32(fp0);
8900 break;
8901 case OPC_ABS_S:
8903 TCGv_i32 fp0 = tcg_temp_new_i32();
8905 gen_load_fpr32(ctx, fp0, fs);
8906 if (ctx->abs2008) {
8907 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
8908 } else {
8909 gen_helper_float_abs_s(fp0, fp0);
8911 gen_store_fpr32(ctx, fp0, fd);
8912 tcg_temp_free_i32(fp0);
8914 break;
8915 case OPC_MOV_S:
8917 TCGv_i32 fp0 = tcg_temp_new_i32();
8919 gen_load_fpr32(ctx, fp0, fs);
8920 gen_store_fpr32(ctx, fp0, fd);
8921 tcg_temp_free_i32(fp0);
8923 break;
8924 case OPC_NEG_S:
8926 TCGv_i32 fp0 = tcg_temp_new_i32();
8928 gen_load_fpr32(ctx, fp0, fs);
8929 if (ctx->abs2008) {
8930 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
8931 } else {
8932 gen_helper_float_chs_s(fp0, fp0);
8934 gen_store_fpr32(ctx, fp0, fd);
8935 tcg_temp_free_i32(fp0);
8937 break;
8938 case OPC_ROUND_L_S:
8939 check_cp1_64bitmode(ctx);
8941 TCGv_i32 fp32 = tcg_temp_new_i32();
8942 TCGv_i64 fp64 = tcg_temp_new_i64();
8944 gen_load_fpr32(ctx, fp32, fs);
8945 if (ctx->nan2008) {
8946 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
8947 } else {
8948 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
8950 tcg_temp_free_i32(fp32);
8951 gen_store_fpr64(ctx, fp64, fd);
8952 tcg_temp_free_i64(fp64);
8954 break;
8955 case OPC_TRUNC_L_S:
8956 check_cp1_64bitmode(ctx);
8958 TCGv_i32 fp32 = tcg_temp_new_i32();
8959 TCGv_i64 fp64 = tcg_temp_new_i64();
8961 gen_load_fpr32(ctx, fp32, fs);
8962 if (ctx->nan2008) {
8963 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
8964 } else {
8965 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
8967 tcg_temp_free_i32(fp32);
8968 gen_store_fpr64(ctx, fp64, fd);
8969 tcg_temp_free_i64(fp64);
8971 break;
8972 case OPC_CEIL_L_S:
8973 check_cp1_64bitmode(ctx);
8975 TCGv_i32 fp32 = tcg_temp_new_i32();
8976 TCGv_i64 fp64 = tcg_temp_new_i64();
8978 gen_load_fpr32(ctx, fp32, fs);
8979 if (ctx->nan2008) {
8980 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
8981 } else {
8982 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
8984 tcg_temp_free_i32(fp32);
8985 gen_store_fpr64(ctx, fp64, fd);
8986 tcg_temp_free_i64(fp64);
8988 break;
8989 case OPC_FLOOR_L_S:
8990 check_cp1_64bitmode(ctx);
8992 TCGv_i32 fp32 = tcg_temp_new_i32();
8993 TCGv_i64 fp64 = tcg_temp_new_i64();
8995 gen_load_fpr32(ctx, fp32, fs);
8996 if (ctx->nan2008) {
8997 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
8998 } else {
8999 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
9001 tcg_temp_free_i32(fp32);
9002 gen_store_fpr64(ctx, fp64, fd);
9003 tcg_temp_free_i64(fp64);
9005 break;
9006 case OPC_ROUND_W_S:
9008 TCGv_i32 fp0 = tcg_temp_new_i32();
9010 gen_load_fpr32(ctx, fp0, fs);
9011 if (ctx->nan2008) {
9012 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
9013 } else {
9014 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
9016 gen_store_fpr32(ctx, fp0, fd);
9017 tcg_temp_free_i32(fp0);
9019 break;
9020 case OPC_TRUNC_W_S:
9022 TCGv_i32 fp0 = tcg_temp_new_i32();
9024 gen_load_fpr32(ctx, fp0, fs);
9025 if (ctx->nan2008) {
9026 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
9027 } else {
9028 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
9030 gen_store_fpr32(ctx, fp0, fd);
9031 tcg_temp_free_i32(fp0);
9033 break;
9034 case OPC_CEIL_W_S:
9036 TCGv_i32 fp0 = tcg_temp_new_i32();
9038 gen_load_fpr32(ctx, fp0, fs);
9039 if (ctx->nan2008) {
9040 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
9041 } else {
9042 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
9044 gen_store_fpr32(ctx, fp0, fd);
9045 tcg_temp_free_i32(fp0);
9047 break;
9048 case OPC_FLOOR_W_S:
9050 TCGv_i32 fp0 = tcg_temp_new_i32();
9052 gen_load_fpr32(ctx, fp0, fs);
9053 if (ctx->nan2008) {
9054 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
9055 } else {
9056 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
9058 gen_store_fpr32(ctx, fp0, fd);
9059 tcg_temp_free_i32(fp0);
9061 break;
9062 case OPC_SEL_S:
9063 check_insn(ctx, ISA_MIPS32R6);
9064 gen_sel_s(ctx, op1, fd, ft, fs);
9065 break;
9066 case OPC_SELEQZ_S:
9067 check_insn(ctx, ISA_MIPS32R6);
9068 gen_sel_s(ctx, op1, fd, ft, fs);
9069 break;
9070 case OPC_SELNEZ_S:
9071 check_insn(ctx, ISA_MIPS32R6);
9072 gen_sel_s(ctx, op1, fd, ft, fs);
9073 break;
9074 case OPC_MOVCF_S:
9075 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9076 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9077 break;
9078 case OPC_MOVZ_S:
9079 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9081 TCGLabel *l1 = gen_new_label();
9082 TCGv_i32 fp0;
9084 if (ft != 0) {
9085 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9087 fp0 = tcg_temp_new_i32();
9088 gen_load_fpr32(ctx, fp0, fs);
9089 gen_store_fpr32(ctx, fp0, fd);
9090 tcg_temp_free_i32(fp0);
9091 gen_set_label(l1);
9093 break;
9094 case OPC_MOVN_S:
9095 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9097 TCGLabel *l1 = gen_new_label();
9098 TCGv_i32 fp0;
9100 if (ft != 0) {
9101 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9102 fp0 = tcg_temp_new_i32();
9103 gen_load_fpr32(ctx, fp0, fs);
9104 gen_store_fpr32(ctx, fp0, fd);
9105 tcg_temp_free_i32(fp0);
9106 gen_set_label(l1);
9109 break;
9110 case OPC_RECIP_S:
9112 TCGv_i32 fp0 = tcg_temp_new_i32();
9114 gen_load_fpr32(ctx, fp0, fs);
9115 gen_helper_float_recip_s(fp0, cpu_env, fp0);
9116 gen_store_fpr32(ctx, fp0, fd);
9117 tcg_temp_free_i32(fp0);
9119 break;
9120 case OPC_RSQRT_S:
9122 TCGv_i32 fp0 = tcg_temp_new_i32();
9124 gen_load_fpr32(ctx, fp0, fs);
9125 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
9126 gen_store_fpr32(ctx, fp0, fd);
9127 tcg_temp_free_i32(fp0);
9129 break;
9130 case OPC_MADDF_S:
9131 check_insn(ctx, ISA_MIPS32R6);
9133 TCGv_i32 fp0 = tcg_temp_new_i32();
9134 TCGv_i32 fp1 = tcg_temp_new_i32();
9135 TCGv_i32 fp2 = tcg_temp_new_i32();
9136 gen_load_fpr32(ctx, fp0, fs);
9137 gen_load_fpr32(ctx, fp1, ft);
9138 gen_load_fpr32(ctx, fp2, fd);
9139 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
9140 gen_store_fpr32(ctx, fp2, fd);
9141 tcg_temp_free_i32(fp2);
9142 tcg_temp_free_i32(fp1);
9143 tcg_temp_free_i32(fp0);
9145 break;
9146 case OPC_MSUBF_S:
9147 check_insn(ctx, ISA_MIPS32R6);
9149 TCGv_i32 fp0 = tcg_temp_new_i32();
9150 TCGv_i32 fp1 = tcg_temp_new_i32();
9151 TCGv_i32 fp2 = tcg_temp_new_i32();
9152 gen_load_fpr32(ctx, fp0, fs);
9153 gen_load_fpr32(ctx, fp1, ft);
9154 gen_load_fpr32(ctx, fp2, fd);
9155 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
9156 gen_store_fpr32(ctx, fp2, fd);
9157 tcg_temp_free_i32(fp2);
9158 tcg_temp_free_i32(fp1);
9159 tcg_temp_free_i32(fp0);
9161 break;
9162 case OPC_RINT_S:
9163 check_insn(ctx, ISA_MIPS32R6);
9165 TCGv_i32 fp0 = tcg_temp_new_i32();
9166 gen_load_fpr32(ctx, fp0, fs);
9167 gen_helper_float_rint_s(fp0, cpu_env, fp0);
9168 gen_store_fpr32(ctx, fp0, fd);
9169 tcg_temp_free_i32(fp0);
9171 break;
9172 case OPC_CLASS_S:
9173 check_insn(ctx, ISA_MIPS32R6);
9175 TCGv_i32 fp0 = tcg_temp_new_i32();
9176 gen_load_fpr32(ctx, fp0, fs);
9177 gen_helper_float_class_s(fp0, cpu_env, fp0);
9178 gen_store_fpr32(ctx, fp0, fd);
9179 tcg_temp_free_i32(fp0);
9181 break;
9182 case OPC_MIN_S: /* OPC_RECIP2_S */
9183 if (ctx->insn_flags & ISA_MIPS32R6) {
9184 /* OPC_MIN_S */
9185 TCGv_i32 fp0 = tcg_temp_new_i32();
9186 TCGv_i32 fp1 = tcg_temp_new_i32();
9187 TCGv_i32 fp2 = tcg_temp_new_i32();
9188 gen_load_fpr32(ctx, fp0, fs);
9189 gen_load_fpr32(ctx, fp1, ft);
9190 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
9191 gen_store_fpr32(ctx, fp2, fd);
9192 tcg_temp_free_i32(fp2);
9193 tcg_temp_free_i32(fp1);
9194 tcg_temp_free_i32(fp0);
9195 } else {
9196 /* OPC_RECIP2_S */
9197 check_cp1_64bitmode(ctx);
9199 TCGv_i32 fp0 = tcg_temp_new_i32();
9200 TCGv_i32 fp1 = tcg_temp_new_i32();
9202 gen_load_fpr32(ctx, fp0, fs);
9203 gen_load_fpr32(ctx, fp1, ft);
9204 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
9205 tcg_temp_free_i32(fp1);
9206 gen_store_fpr32(ctx, fp0, fd);
9207 tcg_temp_free_i32(fp0);
9210 break;
9211 case OPC_MINA_S: /* OPC_RECIP1_S */
9212 if (ctx->insn_flags & ISA_MIPS32R6) {
9213 /* OPC_MINA_S */
9214 TCGv_i32 fp0 = tcg_temp_new_i32();
9215 TCGv_i32 fp1 = tcg_temp_new_i32();
9216 TCGv_i32 fp2 = tcg_temp_new_i32();
9217 gen_load_fpr32(ctx, fp0, fs);
9218 gen_load_fpr32(ctx, fp1, ft);
9219 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
9220 gen_store_fpr32(ctx, fp2, fd);
9221 tcg_temp_free_i32(fp2);
9222 tcg_temp_free_i32(fp1);
9223 tcg_temp_free_i32(fp0);
9224 } else {
9225 /* OPC_RECIP1_S */
9226 check_cp1_64bitmode(ctx);
9228 TCGv_i32 fp0 = tcg_temp_new_i32();
9230 gen_load_fpr32(ctx, fp0, fs);
9231 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
9232 gen_store_fpr32(ctx, fp0, fd);
9233 tcg_temp_free_i32(fp0);
9236 break;
9237 case OPC_MAX_S: /* OPC_RSQRT1_S */
9238 if (ctx->insn_flags & ISA_MIPS32R6) {
9239 /* OPC_MAX_S */
9240 TCGv_i32 fp0 = tcg_temp_new_i32();
9241 TCGv_i32 fp1 = tcg_temp_new_i32();
9242 gen_load_fpr32(ctx, fp0, fs);
9243 gen_load_fpr32(ctx, fp1, ft);
9244 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
9245 gen_store_fpr32(ctx, fp1, fd);
9246 tcg_temp_free_i32(fp1);
9247 tcg_temp_free_i32(fp0);
9248 } else {
9249 /* OPC_RSQRT1_S */
9250 check_cp1_64bitmode(ctx);
9252 TCGv_i32 fp0 = tcg_temp_new_i32();
9254 gen_load_fpr32(ctx, fp0, fs);
9255 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
9256 gen_store_fpr32(ctx, fp0, fd);
9257 tcg_temp_free_i32(fp0);
9260 break;
9261 case OPC_MAXA_S: /* OPC_RSQRT2_S */
9262 if (ctx->insn_flags & ISA_MIPS32R6) {
9263 /* OPC_MAXA_S */
9264 TCGv_i32 fp0 = tcg_temp_new_i32();
9265 TCGv_i32 fp1 = tcg_temp_new_i32();
9266 gen_load_fpr32(ctx, fp0, fs);
9267 gen_load_fpr32(ctx, fp1, ft);
9268 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
9269 gen_store_fpr32(ctx, fp1, fd);
9270 tcg_temp_free_i32(fp1);
9271 tcg_temp_free_i32(fp0);
9272 } else {
9273 /* OPC_RSQRT2_S */
9274 check_cp1_64bitmode(ctx);
9276 TCGv_i32 fp0 = tcg_temp_new_i32();
9277 TCGv_i32 fp1 = tcg_temp_new_i32();
9279 gen_load_fpr32(ctx, fp0, fs);
9280 gen_load_fpr32(ctx, fp1, ft);
9281 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
9282 tcg_temp_free_i32(fp1);
9283 gen_store_fpr32(ctx, fp0, fd);
9284 tcg_temp_free_i32(fp0);
9287 break;
9288 case OPC_CVT_D_S:
9289 check_cp1_registers(ctx, fd);
9291 TCGv_i32 fp32 = tcg_temp_new_i32();
9292 TCGv_i64 fp64 = tcg_temp_new_i64();
9294 gen_load_fpr32(ctx, fp32, fs);
9295 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
9296 tcg_temp_free_i32(fp32);
9297 gen_store_fpr64(ctx, fp64, fd);
9298 tcg_temp_free_i64(fp64);
9300 break;
9301 case OPC_CVT_W_S:
9303 TCGv_i32 fp0 = tcg_temp_new_i32();
9305 gen_load_fpr32(ctx, fp0, fs);
9306 if (ctx->nan2008) {
9307 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
9308 } else {
9309 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
9311 gen_store_fpr32(ctx, fp0, fd);
9312 tcg_temp_free_i32(fp0);
9314 break;
9315 case OPC_CVT_L_S:
9316 check_cp1_64bitmode(ctx);
9318 TCGv_i32 fp32 = tcg_temp_new_i32();
9319 TCGv_i64 fp64 = tcg_temp_new_i64();
9321 gen_load_fpr32(ctx, fp32, fs);
9322 if (ctx->nan2008) {
9323 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
9324 } else {
9325 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
9327 tcg_temp_free_i32(fp32);
9328 gen_store_fpr64(ctx, fp64, fd);
9329 tcg_temp_free_i64(fp64);
9331 break;
9332 case OPC_CVT_PS_S:
9333 check_ps(ctx);
9335 TCGv_i64 fp64 = tcg_temp_new_i64();
9336 TCGv_i32 fp32_0 = tcg_temp_new_i32();
9337 TCGv_i32 fp32_1 = tcg_temp_new_i32();
9339 gen_load_fpr32(ctx, fp32_0, fs);
9340 gen_load_fpr32(ctx, fp32_1, ft);
9341 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
9342 tcg_temp_free_i32(fp32_1);
9343 tcg_temp_free_i32(fp32_0);
9344 gen_store_fpr64(ctx, fp64, fd);
9345 tcg_temp_free_i64(fp64);
9347 break;
9348 case OPC_CMP_F_S:
9349 case OPC_CMP_UN_S:
9350 case OPC_CMP_EQ_S:
9351 case OPC_CMP_UEQ_S:
9352 case OPC_CMP_OLT_S:
9353 case OPC_CMP_ULT_S:
9354 case OPC_CMP_OLE_S:
9355 case OPC_CMP_ULE_S:
9356 case OPC_CMP_SF_S:
9357 case OPC_CMP_NGLE_S:
9358 case OPC_CMP_SEQ_S:
9359 case OPC_CMP_NGL_S:
9360 case OPC_CMP_LT_S:
9361 case OPC_CMP_NGE_S:
9362 case OPC_CMP_LE_S:
9363 case OPC_CMP_NGT_S:
9364 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9365 if (ctx->opcode & (1 << 6)) {
9366 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
9367 } else {
9368 gen_cmp_s(ctx, func-48, ft, fs, cc);
9370 break;
9371 case OPC_ADD_D:
9372 check_cp1_registers(ctx, fs | ft | fd);
9374 TCGv_i64 fp0 = tcg_temp_new_i64();
9375 TCGv_i64 fp1 = tcg_temp_new_i64();
9377 gen_load_fpr64(ctx, fp0, fs);
9378 gen_load_fpr64(ctx, fp1, ft);
9379 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
9380 tcg_temp_free_i64(fp1);
9381 gen_store_fpr64(ctx, fp0, fd);
9382 tcg_temp_free_i64(fp0);
9384 break;
9385 case OPC_SUB_D:
9386 check_cp1_registers(ctx, fs | ft | fd);
9388 TCGv_i64 fp0 = tcg_temp_new_i64();
9389 TCGv_i64 fp1 = tcg_temp_new_i64();
9391 gen_load_fpr64(ctx, fp0, fs);
9392 gen_load_fpr64(ctx, fp1, ft);
9393 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
9394 tcg_temp_free_i64(fp1);
9395 gen_store_fpr64(ctx, fp0, fd);
9396 tcg_temp_free_i64(fp0);
9398 break;
9399 case OPC_MUL_D:
9400 check_cp1_registers(ctx, fs | ft | fd);
9402 TCGv_i64 fp0 = tcg_temp_new_i64();
9403 TCGv_i64 fp1 = tcg_temp_new_i64();
9405 gen_load_fpr64(ctx, fp0, fs);
9406 gen_load_fpr64(ctx, fp1, ft);
9407 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
9408 tcg_temp_free_i64(fp1);
9409 gen_store_fpr64(ctx, fp0, fd);
9410 tcg_temp_free_i64(fp0);
9412 break;
9413 case OPC_DIV_D:
9414 check_cp1_registers(ctx, fs | ft | fd);
9416 TCGv_i64 fp0 = tcg_temp_new_i64();
9417 TCGv_i64 fp1 = tcg_temp_new_i64();
9419 gen_load_fpr64(ctx, fp0, fs);
9420 gen_load_fpr64(ctx, fp1, ft);
9421 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
9422 tcg_temp_free_i64(fp1);
9423 gen_store_fpr64(ctx, fp0, fd);
9424 tcg_temp_free_i64(fp0);
9426 break;
9427 case OPC_SQRT_D:
9428 check_cp1_registers(ctx, fs | fd);
9430 TCGv_i64 fp0 = tcg_temp_new_i64();
9432 gen_load_fpr64(ctx, fp0, fs);
9433 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
9434 gen_store_fpr64(ctx, fp0, fd);
9435 tcg_temp_free_i64(fp0);
9437 break;
9438 case OPC_ABS_D:
9439 check_cp1_registers(ctx, fs | fd);
9441 TCGv_i64 fp0 = tcg_temp_new_i64();
9443 gen_load_fpr64(ctx, fp0, fs);
9444 if (ctx->abs2008) {
9445 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
9446 } else {
9447 gen_helper_float_abs_d(fp0, fp0);
9449 gen_store_fpr64(ctx, fp0, fd);
9450 tcg_temp_free_i64(fp0);
9452 break;
9453 case OPC_MOV_D:
9454 check_cp1_registers(ctx, fs | fd);
9456 TCGv_i64 fp0 = tcg_temp_new_i64();
9458 gen_load_fpr64(ctx, fp0, fs);
9459 gen_store_fpr64(ctx, fp0, fd);
9460 tcg_temp_free_i64(fp0);
9462 break;
9463 case OPC_NEG_D:
9464 check_cp1_registers(ctx, fs | fd);
9466 TCGv_i64 fp0 = tcg_temp_new_i64();
9468 gen_load_fpr64(ctx, fp0, fs);
9469 if (ctx->abs2008) {
9470 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
9471 } else {
9472 gen_helper_float_chs_d(fp0, fp0);
9474 gen_store_fpr64(ctx, fp0, fd);
9475 tcg_temp_free_i64(fp0);
9477 break;
9478 case OPC_ROUND_L_D:
9479 check_cp1_64bitmode(ctx);
9481 TCGv_i64 fp0 = tcg_temp_new_i64();
9483 gen_load_fpr64(ctx, fp0, fs);
9484 if (ctx->nan2008) {
9485 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
9486 } else {
9487 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
9489 gen_store_fpr64(ctx, fp0, fd);
9490 tcg_temp_free_i64(fp0);
9492 break;
9493 case OPC_TRUNC_L_D:
9494 check_cp1_64bitmode(ctx);
9496 TCGv_i64 fp0 = tcg_temp_new_i64();
9498 gen_load_fpr64(ctx, fp0, fs);
9499 if (ctx->nan2008) {
9500 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
9501 } else {
9502 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
9504 gen_store_fpr64(ctx, fp0, fd);
9505 tcg_temp_free_i64(fp0);
9507 break;
9508 case OPC_CEIL_L_D:
9509 check_cp1_64bitmode(ctx);
9511 TCGv_i64 fp0 = tcg_temp_new_i64();
9513 gen_load_fpr64(ctx, fp0, fs);
9514 if (ctx->nan2008) {
9515 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
9516 } else {
9517 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
9519 gen_store_fpr64(ctx, fp0, fd);
9520 tcg_temp_free_i64(fp0);
9522 break;
9523 case OPC_FLOOR_L_D:
9524 check_cp1_64bitmode(ctx);
9526 TCGv_i64 fp0 = tcg_temp_new_i64();
9528 gen_load_fpr64(ctx, fp0, fs);
9529 if (ctx->nan2008) {
9530 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
9531 } else {
9532 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
9534 gen_store_fpr64(ctx, fp0, fd);
9535 tcg_temp_free_i64(fp0);
9537 break;
9538 case OPC_ROUND_W_D:
9539 check_cp1_registers(ctx, fs);
9541 TCGv_i32 fp32 = tcg_temp_new_i32();
9542 TCGv_i64 fp64 = tcg_temp_new_i64();
9544 gen_load_fpr64(ctx, fp64, fs);
9545 if (ctx->nan2008) {
9546 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
9547 } else {
9548 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
9550 tcg_temp_free_i64(fp64);
9551 gen_store_fpr32(ctx, fp32, fd);
9552 tcg_temp_free_i32(fp32);
9554 break;
9555 case OPC_TRUNC_W_D:
9556 check_cp1_registers(ctx, fs);
9558 TCGv_i32 fp32 = tcg_temp_new_i32();
9559 TCGv_i64 fp64 = tcg_temp_new_i64();
9561 gen_load_fpr64(ctx, fp64, fs);
9562 if (ctx->nan2008) {
9563 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
9564 } else {
9565 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
9567 tcg_temp_free_i64(fp64);
9568 gen_store_fpr32(ctx, fp32, fd);
9569 tcg_temp_free_i32(fp32);
9571 break;
9572 case OPC_CEIL_W_D:
9573 check_cp1_registers(ctx, fs);
9575 TCGv_i32 fp32 = tcg_temp_new_i32();
9576 TCGv_i64 fp64 = tcg_temp_new_i64();
9578 gen_load_fpr64(ctx, fp64, fs);
9579 if (ctx->nan2008) {
9580 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
9581 } else {
9582 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
9584 tcg_temp_free_i64(fp64);
9585 gen_store_fpr32(ctx, fp32, fd);
9586 tcg_temp_free_i32(fp32);
9588 break;
9589 case OPC_FLOOR_W_D:
9590 check_cp1_registers(ctx, fs);
9592 TCGv_i32 fp32 = tcg_temp_new_i32();
9593 TCGv_i64 fp64 = tcg_temp_new_i64();
9595 gen_load_fpr64(ctx, fp64, fs);
9596 if (ctx->nan2008) {
9597 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
9598 } else {
9599 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
9601 tcg_temp_free_i64(fp64);
9602 gen_store_fpr32(ctx, fp32, fd);
9603 tcg_temp_free_i32(fp32);
9605 break;
9606 case OPC_SEL_D:
9607 check_insn(ctx, ISA_MIPS32R6);
9608 gen_sel_d(ctx, op1, fd, ft, fs);
9609 break;
9610 case OPC_SELEQZ_D:
9611 check_insn(ctx, ISA_MIPS32R6);
9612 gen_sel_d(ctx, op1, fd, ft, fs);
9613 break;
9614 case OPC_SELNEZ_D:
9615 check_insn(ctx, ISA_MIPS32R6);
9616 gen_sel_d(ctx, op1, fd, ft, fs);
9617 break;
9618 case OPC_MOVCF_D:
9619 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9620 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9621 break;
9622 case OPC_MOVZ_D:
9623 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9625 TCGLabel *l1 = gen_new_label();
9626 TCGv_i64 fp0;
9628 if (ft != 0) {
9629 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9631 fp0 = tcg_temp_new_i64();
9632 gen_load_fpr64(ctx, fp0, fs);
9633 gen_store_fpr64(ctx, fp0, fd);
9634 tcg_temp_free_i64(fp0);
9635 gen_set_label(l1);
9637 break;
9638 case OPC_MOVN_D:
9639 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9641 TCGLabel *l1 = gen_new_label();
9642 TCGv_i64 fp0;
9644 if (ft != 0) {
9645 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9646 fp0 = tcg_temp_new_i64();
9647 gen_load_fpr64(ctx, fp0, fs);
9648 gen_store_fpr64(ctx, fp0, fd);
9649 tcg_temp_free_i64(fp0);
9650 gen_set_label(l1);
9653 break;
9654 case OPC_RECIP_D:
9655 check_cp1_registers(ctx, fs | fd);
9657 TCGv_i64 fp0 = tcg_temp_new_i64();
9659 gen_load_fpr64(ctx, fp0, fs);
9660 gen_helper_float_recip_d(fp0, cpu_env, fp0);
9661 gen_store_fpr64(ctx, fp0, fd);
9662 tcg_temp_free_i64(fp0);
9664 break;
9665 case OPC_RSQRT_D:
9666 check_cp1_registers(ctx, fs | fd);
9668 TCGv_i64 fp0 = tcg_temp_new_i64();
9670 gen_load_fpr64(ctx, fp0, fs);
9671 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
9672 gen_store_fpr64(ctx, fp0, fd);
9673 tcg_temp_free_i64(fp0);
9675 break;
9676 case OPC_MADDF_D:
9677 check_insn(ctx, ISA_MIPS32R6);
9679 TCGv_i64 fp0 = tcg_temp_new_i64();
9680 TCGv_i64 fp1 = tcg_temp_new_i64();
9681 TCGv_i64 fp2 = tcg_temp_new_i64();
9682 gen_load_fpr64(ctx, fp0, fs);
9683 gen_load_fpr64(ctx, fp1, ft);
9684 gen_load_fpr64(ctx, fp2, fd);
9685 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
9686 gen_store_fpr64(ctx, fp2, fd);
9687 tcg_temp_free_i64(fp2);
9688 tcg_temp_free_i64(fp1);
9689 tcg_temp_free_i64(fp0);
9691 break;
9692 case OPC_MSUBF_D:
9693 check_insn(ctx, ISA_MIPS32R6);
9695 TCGv_i64 fp0 = tcg_temp_new_i64();
9696 TCGv_i64 fp1 = tcg_temp_new_i64();
9697 TCGv_i64 fp2 = tcg_temp_new_i64();
9698 gen_load_fpr64(ctx, fp0, fs);
9699 gen_load_fpr64(ctx, fp1, ft);
9700 gen_load_fpr64(ctx, fp2, fd);
9701 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
9702 gen_store_fpr64(ctx, fp2, fd);
9703 tcg_temp_free_i64(fp2);
9704 tcg_temp_free_i64(fp1);
9705 tcg_temp_free_i64(fp0);
9707 break;
9708 case OPC_RINT_D:
9709 check_insn(ctx, ISA_MIPS32R6);
9711 TCGv_i64 fp0 = tcg_temp_new_i64();
9712 gen_load_fpr64(ctx, fp0, fs);
9713 gen_helper_float_rint_d(fp0, cpu_env, fp0);
9714 gen_store_fpr64(ctx, fp0, fd);
9715 tcg_temp_free_i64(fp0);
9717 break;
9718 case OPC_CLASS_D:
9719 check_insn(ctx, ISA_MIPS32R6);
9721 TCGv_i64 fp0 = tcg_temp_new_i64();
9722 gen_load_fpr64(ctx, fp0, fs);
9723 gen_helper_float_class_d(fp0, cpu_env, fp0);
9724 gen_store_fpr64(ctx, fp0, fd);
9725 tcg_temp_free_i64(fp0);
9727 break;
9728 case OPC_MIN_D: /* OPC_RECIP2_D */
9729 if (ctx->insn_flags & ISA_MIPS32R6) {
9730 /* OPC_MIN_D */
9731 TCGv_i64 fp0 = tcg_temp_new_i64();
9732 TCGv_i64 fp1 = tcg_temp_new_i64();
9733 gen_load_fpr64(ctx, fp0, fs);
9734 gen_load_fpr64(ctx, fp1, ft);
9735 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
9736 gen_store_fpr64(ctx, fp1, fd);
9737 tcg_temp_free_i64(fp1);
9738 tcg_temp_free_i64(fp0);
9739 } else {
9740 /* OPC_RECIP2_D */
9741 check_cp1_64bitmode(ctx);
9743 TCGv_i64 fp0 = tcg_temp_new_i64();
9744 TCGv_i64 fp1 = tcg_temp_new_i64();
9746 gen_load_fpr64(ctx, fp0, fs);
9747 gen_load_fpr64(ctx, fp1, ft);
9748 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
9749 tcg_temp_free_i64(fp1);
9750 gen_store_fpr64(ctx, fp0, fd);
9751 tcg_temp_free_i64(fp0);
9754 break;
9755 case OPC_MINA_D: /* OPC_RECIP1_D */
9756 if (ctx->insn_flags & ISA_MIPS32R6) {
9757 /* OPC_MINA_D */
9758 TCGv_i64 fp0 = tcg_temp_new_i64();
9759 TCGv_i64 fp1 = tcg_temp_new_i64();
9760 gen_load_fpr64(ctx, fp0, fs);
9761 gen_load_fpr64(ctx, fp1, ft);
9762 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
9763 gen_store_fpr64(ctx, fp1, fd);
9764 tcg_temp_free_i64(fp1);
9765 tcg_temp_free_i64(fp0);
9766 } else {
9767 /* OPC_RECIP1_D */
9768 check_cp1_64bitmode(ctx);
9770 TCGv_i64 fp0 = tcg_temp_new_i64();
9772 gen_load_fpr64(ctx, fp0, fs);
9773 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
9774 gen_store_fpr64(ctx, fp0, fd);
9775 tcg_temp_free_i64(fp0);
9778 break;
9779 case OPC_MAX_D: /* OPC_RSQRT1_D */
9780 if (ctx->insn_flags & ISA_MIPS32R6) {
9781 /* OPC_MAX_D */
9782 TCGv_i64 fp0 = tcg_temp_new_i64();
9783 TCGv_i64 fp1 = tcg_temp_new_i64();
9784 gen_load_fpr64(ctx, fp0, fs);
9785 gen_load_fpr64(ctx, fp1, ft);
9786 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
9787 gen_store_fpr64(ctx, fp1, fd);
9788 tcg_temp_free_i64(fp1);
9789 tcg_temp_free_i64(fp0);
9790 } else {
9791 /* OPC_RSQRT1_D */
9792 check_cp1_64bitmode(ctx);
9794 TCGv_i64 fp0 = tcg_temp_new_i64();
9796 gen_load_fpr64(ctx, fp0, fs);
9797 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
9798 gen_store_fpr64(ctx, fp0, fd);
9799 tcg_temp_free_i64(fp0);
9802 break;
9803 case OPC_MAXA_D: /* OPC_RSQRT2_D */
9804 if (ctx->insn_flags & ISA_MIPS32R6) {
9805 /* OPC_MAXA_D */
9806 TCGv_i64 fp0 = tcg_temp_new_i64();
9807 TCGv_i64 fp1 = tcg_temp_new_i64();
9808 gen_load_fpr64(ctx, fp0, fs);
9809 gen_load_fpr64(ctx, fp1, ft);
9810 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
9811 gen_store_fpr64(ctx, fp1, fd);
9812 tcg_temp_free_i64(fp1);
9813 tcg_temp_free_i64(fp0);
9814 } else {
9815 /* OPC_RSQRT2_D */
9816 check_cp1_64bitmode(ctx);
9818 TCGv_i64 fp0 = tcg_temp_new_i64();
9819 TCGv_i64 fp1 = tcg_temp_new_i64();
9821 gen_load_fpr64(ctx, fp0, fs);
9822 gen_load_fpr64(ctx, fp1, ft);
9823 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
9824 tcg_temp_free_i64(fp1);
9825 gen_store_fpr64(ctx, fp0, fd);
9826 tcg_temp_free_i64(fp0);
9829 break;
9830 case OPC_CMP_F_D:
9831 case OPC_CMP_UN_D:
9832 case OPC_CMP_EQ_D:
9833 case OPC_CMP_UEQ_D:
9834 case OPC_CMP_OLT_D:
9835 case OPC_CMP_ULT_D:
9836 case OPC_CMP_OLE_D:
9837 case OPC_CMP_ULE_D:
9838 case OPC_CMP_SF_D:
9839 case OPC_CMP_NGLE_D:
9840 case OPC_CMP_SEQ_D:
9841 case OPC_CMP_NGL_D:
9842 case OPC_CMP_LT_D:
9843 case OPC_CMP_NGE_D:
9844 case OPC_CMP_LE_D:
9845 case OPC_CMP_NGT_D:
9846 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9847 if (ctx->opcode & (1 << 6)) {
9848 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
9849 } else {
9850 gen_cmp_d(ctx, func-48, ft, fs, cc);
9852 break;
9853 case OPC_CVT_S_D:
9854 check_cp1_registers(ctx, fs);
9856 TCGv_i32 fp32 = tcg_temp_new_i32();
9857 TCGv_i64 fp64 = tcg_temp_new_i64();
9859 gen_load_fpr64(ctx, fp64, fs);
9860 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
9861 tcg_temp_free_i64(fp64);
9862 gen_store_fpr32(ctx, fp32, fd);
9863 tcg_temp_free_i32(fp32);
9865 break;
9866 case OPC_CVT_W_D:
9867 check_cp1_registers(ctx, fs);
9869 TCGv_i32 fp32 = tcg_temp_new_i32();
9870 TCGv_i64 fp64 = tcg_temp_new_i64();
9872 gen_load_fpr64(ctx, fp64, fs);
9873 if (ctx->nan2008) {
9874 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
9875 } else {
9876 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
9878 tcg_temp_free_i64(fp64);
9879 gen_store_fpr32(ctx, fp32, fd);
9880 tcg_temp_free_i32(fp32);
9882 break;
9883 case OPC_CVT_L_D:
9884 check_cp1_64bitmode(ctx);
9886 TCGv_i64 fp0 = tcg_temp_new_i64();
9888 gen_load_fpr64(ctx, fp0, fs);
9889 if (ctx->nan2008) {
9890 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
9891 } else {
9892 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
9894 gen_store_fpr64(ctx, fp0, fd);
9895 tcg_temp_free_i64(fp0);
9897 break;
9898 case OPC_CVT_S_W:
9900 TCGv_i32 fp0 = tcg_temp_new_i32();
9902 gen_load_fpr32(ctx, fp0, fs);
9903 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
9904 gen_store_fpr32(ctx, fp0, fd);
9905 tcg_temp_free_i32(fp0);
9907 break;
9908 case OPC_CVT_D_W:
9909 check_cp1_registers(ctx, fd);
9911 TCGv_i32 fp32 = tcg_temp_new_i32();
9912 TCGv_i64 fp64 = tcg_temp_new_i64();
9914 gen_load_fpr32(ctx, fp32, fs);
9915 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
9916 tcg_temp_free_i32(fp32);
9917 gen_store_fpr64(ctx, fp64, fd);
9918 tcg_temp_free_i64(fp64);
9920 break;
9921 case OPC_CVT_S_L:
9922 check_cp1_64bitmode(ctx);
9924 TCGv_i32 fp32 = tcg_temp_new_i32();
9925 TCGv_i64 fp64 = tcg_temp_new_i64();
9927 gen_load_fpr64(ctx, fp64, fs);
9928 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
9929 tcg_temp_free_i64(fp64);
9930 gen_store_fpr32(ctx, fp32, fd);
9931 tcg_temp_free_i32(fp32);
9933 break;
9934 case OPC_CVT_D_L:
9935 check_cp1_64bitmode(ctx);
9937 TCGv_i64 fp0 = tcg_temp_new_i64();
9939 gen_load_fpr64(ctx, fp0, fs);
9940 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
9941 gen_store_fpr64(ctx, fp0, fd);
9942 tcg_temp_free_i64(fp0);
9944 break;
9945 case OPC_CVT_PS_PW:
9946 check_ps(ctx);
9948 TCGv_i64 fp0 = tcg_temp_new_i64();
9950 gen_load_fpr64(ctx, fp0, fs);
9951 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
9952 gen_store_fpr64(ctx, fp0, fd);
9953 tcg_temp_free_i64(fp0);
9955 break;
9956 case OPC_ADD_PS:
9957 check_ps(ctx);
9959 TCGv_i64 fp0 = tcg_temp_new_i64();
9960 TCGv_i64 fp1 = tcg_temp_new_i64();
9962 gen_load_fpr64(ctx, fp0, fs);
9963 gen_load_fpr64(ctx, fp1, ft);
9964 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
9965 tcg_temp_free_i64(fp1);
9966 gen_store_fpr64(ctx, fp0, fd);
9967 tcg_temp_free_i64(fp0);
9969 break;
9970 case OPC_SUB_PS:
9971 check_ps(ctx);
9973 TCGv_i64 fp0 = tcg_temp_new_i64();
9974 TCGv_i64 fp1 = tcg_temp_new_i64();
9976 gen_load_fpr64(ctx, fp0, fs);
9977 gen_load_fpr64(ctx, fp1, ft);
9978 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
9979 tcg_temp_free_i64(fp1);
9980 gen_store_fpr64(ctx, fp0, fd);
9981 tcg_temp_free_i64(fp0);
9983 break;
9984 case OPC_MUL_PS:
9985 check_ps(ctx);
9987 TCGv_i64 fp0 = tcg_temp_new_i64();
9988 TCGv_i64 fp1 = tcg_temp_new_i64();
9990 gen_load_fpr64(ctx, fp0, fs);
9991 gen_load_fpr64(ctx, fp1, ft);
9992 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
9993 tcg_temp_free_i64(fp1);
9994 gen_store_fpr64(ctx, fp0, fd);
9995 tcg_temp_free_i64(fp0);
9997 break;
9998 case OPC_ABS_PS:
9999 check_ps(ctx);
10001 TCGv_i64 fp0 = tcg_temp_new_i64();
10003 gen_load_fpr64(ctx, fp0, fs);
10004 gen_helper_float_abs_ps(fp0, fp0);
10005 gen_store_fpr64(ctx, fp0, fd);
10006 tcg_temp_free_i64(fp0);
10008 break;
10009 case OPC_MOV_PS:
10010 check_ps(ctx);
10012 TCGv_i64 fp0 = tcg_temp_new_i64();
10014 gen_load_fpr64(ctx, fp0, fs);
10015 gen_store_fpr64(ctx, fp0, fd);
10016 tcg_temp_free_i64(fp0);
10018 break;
10019 case OPC_NEG_PS:
10020 check_ps(ctx);
10022 TCGv_i64 fp0 = tcg_temp_new_i64();
10024 gen_load_fpr64(ctx, fp0, fs);
10025 gen_helper_float_chs_ps(fp0, fp0);
10026 gen_store_fpr64(ctx, fp0, fd);
10027 tcg_temp_free_i64(fp0);
10029 break;
10030 case OPC_MOVCF_PS:
10031 check_ps(ctx);
10032 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10033 break;
10034 case OPC_MOVZ_PS:
10035 check_ps(ctx);
10037 TCGLabel *l1 = gen_new_label();
10038 TCGv_i64 fp0;
10040 if (ft != 0)
10041 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10042 fp0 = tcg_temp_new_i64();
10043 gen_load_fpr64(ctx, fp0, fs);
10044 gen_store_fpr64(ctx, fp0, fd);
10045 tcg_temp_free_i64(fp0);
10046 gen_set_label(l1);
10048 break;
10049 case OPC_MOVN_PS:
10050 check_ps(ctx);
10052 TCGLabel *l1 = gen_new_label();
10053 TCGv_i64 fp0;
10055 if (ft != 0) {
10056 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10057 fp0 = tcg_temp_new_i64();
10058 gen_load_fpr64(ctx, fp0, fs);
10059 gen_store_fpr64(ctx, fp0, fd);
10060 tcg_temp_free_i64(fp0);
10061 gen_set_label(l1);
10064 break;
10065 case OPC_ADDR_PS:
10066 check_ps(ctx);
10068 TCGv_i64 fp0 = tcg_temp_new_i64();
10069 TCGv_i64 fp1 = tcg_temp_new_i64();
10071 gen_load_fpr64(ctx, fp0, ft);
10072 gen_load_fpr64(ctx, fp1, fs);
10073 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
10074 tcg_temp_free_i64(fp1);
10075 gen_store_fpr64(ctx, fp0, fd);
10076 tcg_temp_free_i64(fp0);
10078 break;
10079 case OPC_MULR_PS:
10080 check_ps(ctx);
10082 TCGv_i64 fp0 = tcg_temp_new_i64();
10083 TCGv_i64 fp1 = tcg_temp_new_i64();
10085 gen_load_fpr64(ctx, fp0, ft);
10086 gen_load_fpr64(ctx, fp1, fs);
10087 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
10088 tcg_temp_free_i64(fp1);
10089 gen_store_fpr64(ctx, fp0, fd);
10090 tcg_temp_free_i64(fp0);
10092 break;
10093 case OPC_RECIP2_PS:
10094 check_ps(ctx);
10096 TCGv_i64 fp0 = tcg_temp_new_i64();
10097 TCGv_i64 fp1 = tcg_temp_new_i64();
10099 gen_load_fpr64(ctx, fp0, fs);
10100 gen_load_fpr64(ctx, fp1, ft);
10101 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
10102 tcg_temp_free_i64(fp1);
10103 gen_store_fpr64(ctx, fp0, fd);
10104 tcg_temp_free_i64(fp0);
10106 break;
10107 case OPC_RECIP1_PS:
10108 check_ps(ctx);
10110 TCGv_i64 fp0 = tcg_temp_new_i64();
10112 gen_load_fpr64(ctx, fp0, fs);
10113 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
10114 gen_store_fpr64(ctx, fp0, fd);
10115 tcg_temp_free_i64(fp0);
10117 break;
10118 case OPC_RSQRT1_PS:
10119 check_ps(ctx);
10121 TCGv_i64 fp0 = tcg_temp_new_i64();
10123 gen_load_fpr64(ctx, fp0, fs);
10124 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
10125 gen_store_fpr64(ctx, fp0, fd);
10126 tcg_temp_free_i64(fp0);
10128 break;
10129 case OPC_RSQRT2_PS:
10130 check_ps(ctx);
10132 TCGv_i64 fp0 = tcg_temp_new_i64();
10133 TCGv_i64 fp1 = tcg_temp_new_i64();
10135 gen_load_fpr64(ctx, fp0, fs);
10136 gen_load_fpr64(ctx, fp1, ft);
10137 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
10138 tcg_temp_free_i64(fp1);
10139 gen_store_fpr64(ctx, fp0, fd);
10140 tcg_temp_free_i64(fp0);
10142 break;
10143 case OPC_CVT_S_PU:
10144 check_cp1_64bitmode(ctx);
10146 TCGv_i32 fp0 = tcg_temp_new_i32();
10148 gen_load_fpr32h(ctx, fp0, fs);
10149 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
10150 gen_store_fpr32(ctx, fp0, fd);
10151 tcg_temp_free_i32(fp0);
10153 break;
10154 case OPC_CVT_PW_PS:
10155 check_ps(ctx);
10157 TCGv_i64 fp0 = tcg_temp_new_i64();
10159 gen_load_fpr64(ctx, fp0, fs);
10160 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
10161 gen_store_fpr64(ctx, fp0, fd);
10162 tcg_temp_free_i64(fp0);
10164 break;
10165 case OPC_CVT_S_PL:
10166 check_cp1_64bitmode(ctx);
10168 TCGv_i32 fp0 = tcg_temp_new_i32();
10170 gen_load_fpr32(ctx, fp0, fs);
10171 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
10172 gen_store_fpr32(ctx, fp0, fd);
10173 tcg_temp_free_i32(fp0);
10175 break;
10176 case OPC_PLL_PS:
10177 check_ps(ctx);
10179 TCGv_i32 fp0 = tcg_temp_new_i32();
10180 TCGv_i32 fp1 = tcg_temp_new_i32();
10182 gen_load_fpr32(ctx, fp0, fs);
10183 gen_load_fpr32(ctx, fp1, ft);
10184 gen_store_fpr32h(ctx, fp0, fd);
10185 gen_store_fpr32(ctx, fp1, fd);
10186 tcg_temp_free_i32(fp0);
10187 tcg_temp_free_i32(fp1);
10189 break;
10190 case OPC_PLU_PS:
10191 check_ps(ctx);
10193 TCGv_i32 fp0 = tcg_temp_new_i32();
10194 TCGv_i32 fp1 = tcg_temp_new_i32();
10196 gen_load_fpr32(ctx, fp0, fs);
10197 gen_load_fpr32h(ctx, fp1, ft);
10198 gen_store_fpr32(ctx, fp1, fd);
10199 gen_store_fpr32h(ctx, fp0, fd);
10200 tcg_temp_free_i32(fp0);
10201 tcg_temp_free_i32(fp1);
10203 break;
10204 case OPC_PUL_PS:
10205 check_ps(ctx);
10207 TCGv_i32 fp0 = tcg_temp_new_i32();
10208 TCGv_i32 fp1 = tcg_temp_new_i32();
10210 gen_load_fpr32h(ctx, fp0, fs);
10211 gen_load_fpr32(ctx, fp1, ft);
10212 gen_store_fpr32(ctx, fp1, fd);
10213 gen_store_fpr32h(ctx, fp0, fd);
10214 tcg_temp_free_i32(fp0);
10215 tcg_temp_free_i32(fp1);
10217 break;
10218 case OPC_PUU_PS:
10219 check_ps(ctx);
10221 TCGv_i32 fp0 = tcg_temp_new_i32();
10222 TCGv_i32 fp1 = tcg_temp_new_i32();
10224 gen_load_fpr32h(ctx, fp0, fs);
10225 gen_load_fpr32h(ctx, fp1, ft);
10226 gen_store_fpr32(ctx, fp1, fd);
10227 gen_store_fpr32h(ctx, fp0, fd);
10228 tcg_temp_free_i32(fp0);
10229 tcg_temp_free_i32(fp1);
10231 break;
10232 case OPC_CMP_F_PS:
10233 case OPC_CMP_UN_PS:
10234 case OPC_CMP_EQ_PS:
10235 case OPC_CMP_UEQ_PS:
10236 case OPC_CMP_OLT_PS:
10237 case OPC_CMP_ULT_PS:
10238 case OPC_CMP_OLE_PS:
10239 case OPC_CMP_ULE_PS:
10240 case OPC_CMP_SF_PS:
10241 case OPC_CMP_NGLE_PS:
10242 case OPC_CMP_SEQ_PS:
10243 case OPC_CMP_NGL_PS:
10244 case OPC_CMP_LT_PS:
10245 case OPC_CMP_NGE_PS:
10246 case OPC_CMP_LE_PS:
10247 case OPC_CMP_NGT_PS:
10248 if (ctx->opcode & (1 << 6)) {
10249 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
10250 } else {
10251 gen_cmp_ps(ctx, func-48, ft, fs, cc);
10253 break;
10254 default:
10255 MIPS_INVAL("farith");
10256 generate_exception_end(ctx, EXCP_RI);
10257 return;
10261 /* Coprocessor 3 (FPU) */
10262 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
10263 int fd, int fs, int base, int index)
10265 TCGv t0 = tcg_temp_new();
10267 if (base == 0) {
10268 gen_load_gpr(t0, index);
10269 } else if (index == 0) {
10270 gen_load_gpr(t0, base);
10271 } else {
10272 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
10274 /* Don't do NOP if destination is zero: we must perform the actual
10275 memory access. */
10276 switch (opc) {
10277 case OPC_LWXC1:
10278 check_cop1x(ctx);
10280 TCGv_i32 fp0 = tcg_temp_new_i32();
10282 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
10283 tcg_gen_trunc_tl_i32(fp0, t0);
10284 gen_store_fpr32(ctx, fp0, fd);
10285 tcg_temp_free_i32(fp0);
10287 break;
10288 case OPC_LDXC1:
10289 check_cop1x(ctx);
10290 check_cp1_registers(ctx, fd);
10292 TCGv_i64 fp0 = tcg_temp_new_i64();
10293 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10294 gen_store_fpr64(ctx, fp0, fd);
10295 tcg_temp_free_i64(fp0);
10297 break;
10298 case OPC_LUXC1:
10299 check_cp1_64bitmode(ctx);
10300 tcg_gen_andi_tl(t0, t0, ~0x7);
10302 TCGv_i64 fp0 = tcg_temp_new_i64();
10304 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10305 gen_store_fpr64(ctx, fp0, fd);
10306 tcg_temp_free_i64(fp0);
10308 break;
10309 case OPC_SWXC1:
10310 check_cop1x(ctx);
10312 TCGv_i32 fp0 = tcg_temp_new_i32();
10313 gen_load_fpr32(ctx, fp0, fs);
10314 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
10315 tcg_temp_free_i32(fp0);
10317 break;
10318 case OPC_SDXC1:
10319 check_cop1x(ctx);
10320 check_cp1_registers(ctx, fs);
10322 TCGv_i64 fp0 = tcg_temp_new_i64();
10323 gen_load_fpr64(ctx, fp0, fs);
10324 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10325 tcg_temp_free_i64(fp0);
10327 break;
10328 case OPC_SUXC1:
10329 check_cp1_64bitmode(ctx);
10330 tcg_gen_andi_tl(t0, t0, ~0x7);
10332 TCGv_i64 fp0 = tcg_temp_new_i64();
10333 gen_load_fpr64(ctx, fp0, fs);
10334 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10335 tcg_temp_free_i64(fp0);
10337 break;
10339 tcg_temp_free(t0);
10342 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
10343 int fd, int fr, int fs, int ft)
10345 switch (opc) {
10346 case OPC_ALNV_PS:
10347 check_ps(ctx);
10349 TCGv t0 = tcg_temp_local_new();
10350 TCGv_i32 fp = tcg_temp_new_i32();
10351 TCGv_i32 fph = tcg_temp_new_i32();
10352 TCGLabel *l1 = gen_new_label();
10353 TCGLabel *l2 = gen_new_label();
10355 gen_load_gpr(t0, fr);
10356 tcg_gen_andi_tl(t0, t0, 0x7);
10358 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
10359 gen_load_fpr32(ctx, fp, fs);
10360 gen_load_fpr32h(ctx, fph, fs);
10361 gen_store_fpr32(ctx, fp, fd);
10362 gen_store_fpr32h(ctx, fph, fd);
10363 tcg_gen_br(l2);
10364 gen_set_label(l1);
10365 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
10366 tcg_temp_free(t0);
10367 #ifdef TARGET_WORDS_BIGENDIAN
10368 gen_load_fpr32(ctx, fp, fs);
10369 gen_load_fpr32h(ctx, fph, ft);
10370 gen_store_fpr32h(ctx, fp, fd);
10371 gen_store_fpr32(ctx, fph, fd);
10372 #else
10373 gen_load_fpr32h(ctx, fph, fs);
10374 gen_load_fpr32(ctx, fp, ft);
10375 gen_store_fpr32(ctx, fph, fd);
10376 gen_store_fpr32h(ctx, fp, fd);
10377 #endif
10378 gen_set_label(l2);
10379 tcg_temp_free_i32(fp);
10380 tcg_temp_free_i32(fph);
10382 break;
10383 case OPC_MADD_S:
10384 check_cop1x(ctx);
10386 TCGv_i32 fp0 = tcg_temp_new_i32();
10387 TCGv_i32 fp1 = tcg_temp_new_i32();
10388 TCGv_i32 fp2 = tcg_temp_new_i32();
10390 gen_load_fpr32(ctx, fp0, fs);
10391 gen_load_fpr32(ctx, fp1, ft);
10392 gen_load_fpr32(ctx, fp2, fr);
10393 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
10394 tcg_temp_free_i32(fp0);
10395 tcg_temp_free_i32(fp1);
10396 gen_store_fpr32(ctx, fp2, fd);
10397 tcg_temp_free_i32(fp2);
10399 break;
10400 case OPC_MADD_D:
10401 check_cop1x(ctx);
10402 check_cp1_registers(ctx, fd | fs | ft | fr);
10404 TCGv_i64 fp0 = tcg_temp_new_i64();
10405 TCGv_i64 fp1 = tcg_temp_new_i64();
10406 TCGv_i64 fp2 = tcg_temp_new_i64();
10408 gen_load_fpr64(ctx, fp0, fs);
10409 gen_load_fpr64(ctx, fp1, ft);
10410 gen_load_fpr64(ctx, fp2, fr);
10411 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
10412 tcg_temp_free_i64(fp0);
10413 tcg_temp_free_i64(fp1);
10414 gen_store_fpr64(ctx, fp2, fd);
10415 tcg_temp_free_i64(fp2);
10417 break;
10418 case OPC_MADD_PS:
10419 check_ps(ctx);
10421 TCGv_i64 fp0 = tcg_temp_new_i64();
10422 TCGv_i64 fp1 = tcg_temp_new_i64();
10423 TCGv_i64 fp2 = tcg_temp_new_i64();
10425 gen_load_fpr64(ctx, fp0, fs);
10426 gen_load_fpr64(ctx, fp1, ft);
10427 gen_load_fpr64(ctx, fp2, fr);
10428 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
10429 tcg_temp_free_i64(fp0);
10430 tcg_temp_free_i64(fp1);
10431 gen_store_fpr64(ctx, fp2, fd);
10432 tcg_temp_free_i64(fp2);
10434 break;
10435 case OPC_MSUB_S:
10436 check_cop1x(ctx);
10438 TCGv_i32 fp0 = tcg_temp_new_i32();
10439 TCGv_i32 fp1 = tcg_temp_new_i32();
10440 TCGv_i32 fp2 = tcg_temp_new_i32();
10442 gen_load_fpr32(ctx, fp0, fs);
10443 gen_load_fpr32(ctx, fp1, ft);
10444 gen_load_fpr32(ctx, fp2, fr);
10445 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
10446 tcg_temp_free_i32(fp0);
10447 tcg_temp_free_i32(fp1);
10448 gen_store_fpr32(ctx, fp2, fd);
10449 tcg_temp_free_i32(fp2);
10451 break;
10452 case OPC_MSUB_D:
10453 check_cop1x(ctx);
10454 check_cp1_registers(ctx, fd | fs | ft | fr);
10456 TCGv_i64 fp0 = tcg_temp_new_i64();
10457 TCGv_i64 fp1 = tcg_temp_new_i64();
10458 TCGv_i64 fp2 = tcg_temp_new_i64();
10460 gen_load_fpr64(ctx, fp0, fs);
10461 gen_load_fpr64(ctx, fp1, ft);
10462 gen_load_fpr64(ctx, fp2, fr);
10463 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
10464 tcg_temp_free_i64(fp0);
10465 tcg_temp_free_i64(fp1);
10466 gen_store_fpr64(ctx, fp2, fd);
10467 tcg_temp_free_i64(fp2);
10469 break;
10470 case OPC_MSUB_PS:
10471 check_ps(ctx);
10473 TCGv_i64 fp0 = tcg_temp_new_i64();
10474 TCGv_i64 fp1 = tcg_temp_new_i64();
10475 TCGv_i64 fp2 = tcg_temp_new_i64();
10477 gen_load_fpr64(ctx, fp0, fs);
10478 gen_load_fpr64(ctx, fp1, ft);
10479 gen_load_fpr64(ctx, fp2, fr);
10480 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
10481 tcg_temp_free_i64(fp0);
10482 tcg_temp_free_i64(fp1);
10483 gen_store_fpr64(ctx, fp2, fd);
10484 tcg_temp_free_i64(fp2);
10486 break;
10487 case OPC_NMADD_S:
10488 check_cop1x(ctx);
10490 TCGv_i32 fp0 = tcg_temp_new_i32();
10491 TCGv_i32 fp1 = tcg_temp_new_i32();
10492 TCGv_i32 fp2 = tcg_temp_new_i32();
10494 gen_load_fpr32(ctx, fp0, fs);
10495 gen_load_fpr32(ctx, fp1, ft);
10496 gen_load_fpr32(ctx, fp2, fr);
10497 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
10498 tcg_temp_free_i32(fp0);
10499 tcg_temp_free_i32(fp1);
10500 gen_store_fpr32(ctx, fp2, fd);
10501 tcg_temp_free_i32(fp2);
10503 break;
10504 case OPC_NMADD_D:
10505 check_cop1x(ctx);
10506 check_cp1_registers(ctx, fd | fs | ft | fr);
10508 TCGv_i64 fp0 = tcg_temp_new_i64();
10509 TCGv_i64 fp1 = tcg_temp_new_i64();
10510 TCGv_i64 fp2 = tcg_temp_new_i64();
10512 gen_load_fpr64(ctx, fp0, fs);
10513 gen_load_fpr64(ctx, fp1, ft);
10514 gen_load_fpr64(ctx, fp2, fr);
10515 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
10516 tcg_temp_free_i64(fp0);
10517 tcg_temp_free_i64(fp1);
10518 gen_store_fpr64(ctx, fp2, fd);
10519 tcg_temp_free_i64(fp2);
10521 break;
10522 case OPC_NMADD_PS:
10523 check_ps(ctx);
10525 TCGv_i64 fp0 = tcg_temp_new_i64();
10526 TCGv_i64 fp1 = tcg_temp_new_i64();
10527 TCGv_i64 fp2 = tcg_temp_new_i64();
10529 gen_load_fpr64(ctx, fp0, fs);
10530 gen_load_fpr64(ctx, fp1, ft);
10531 gen_load_fpr64(ctx, fp2, fr);
10532 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
10533 tcg_temp_free_i64(fp0);
10534 tcg_temp_free_i64(fp1);
10535 gen_store_fpr64(ctx, fp2, fd);
10536 tcg_temp_free_i64(fp2);
10538 break;
10539 case OPC_NMSUB_S:
10540 check_cop1x(ctx);
10542 TCGv_i32 fp0 = tcg_temp_new_i32();
10543 TCGv_i32 fp1 = tcg_temp_new_i32();
10544 TCGv_i32 fp2 = tcg_temp_new_i32();
10546 gen_load_fpr32(ctx, fp0, fs);
10547 gen_load_fpr32(ctx, fp1, ft);
10548 gen_load_fpr32(ctx, fp2, fr);
10549 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
10550 tcg_temp_free_i32(fp0);
10551 tcg_temp_free_i32(fp1);
10552 gen_store_fpr32(ctx, fp2, fd);
10553 tcg_temp_free_i32(fp2);
10555 break;
10556 case OPC_NMSUB_D:
10557 check_cop1x(ctx);
10558 check_cp1_registers(ctx, fd | fs | ft | fr);
10560 TCGv_i64 fp0 = tcg_temp_new_i64();
10561 TCGv_i64 fp1 = tcg_temp_new_i64();
10562 TCGv_i64 fp2 = tcg_temp_new_i64();
10564 gen_load_fpr64(ctx, fp0, fs);
10565 gen_load_fpr64(ctx, fp1, ft);
10566 gen_load_fpr64(ctx, fp2, fr);
10567 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
10568 tcg_temp_free_i64(fp0);
10569 tcg_temp_free_i64(fp1);
10570 gen_store_fpr64(ctx, fp2, fd);
10571 tcg_temp_free_i64(fp2);
10573 break;
10574 case OPC_NMSUB_PS:
10575 check_ps(ctx);
10577 TCGv_i64 fp0 = tcg_temp_new_i64();
10578 TCGv_i64 fp1 = tcg_temp_new_i64();
10579 TCGv_i64 fp2 = tcg_temp_new_i64();
10581 gen_load_fpr64(ctx, fp0, fs);
10582 gen_load_fpr64(ctx, fp1, ft);
10583 gen_load_fpr64(ctx, fp2, fr);
10584 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
10585 tcg_temp_free_i64(fp0);
10586 tcg_temp_free_i64(fp1);
10587 gen_store_fpr64(ctx, fp2, fd);
10588 tcg_temp_free_i64(fp2);
10590 break;
10591 default:
10592 MIPS_INVAL("flt3_arith");
10593 generate_exception_end(ctx, EXCP_RI);
10594 return;
10598 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
10600 TCGv t0;
10602 #if !defined(CONFIG_USER_ONLY)
10603 /* The Linux kernel will emulate rdhwr if it's not supported natively.
10604 Therefore only check the ISA in system mode. */
10605 check_insn(ctx, ISA_MIPS32R2);
10606 #endif
10607 t0 = tcg_temp_new();
10609 switch (rd) {
10610 case 0:
10611 gen_helper_rdhwr_cpunum(t0, cpu_env);
10612 gen_store_gpr(t0, rt);
10613 break;
10614 case 1:
10615 gen_helper_rdhwr_synci_step(t0, cpu_env);
10616 gen_store_gpr(t0, rt);
10617 break;
10618 case 2:
10619 gen_helper_rdhwr_cc(t0, cpu_env);
10620 gen_store_gpr(t0, rt);
10621 break;
10622 case 3:
10623 gen_helper_rdhwr_ccres(t0, cpu_env);
10624 gen_store_gpr(t0, rt);
10625 break;
10626 case 4:
10627 check_insn(ctx, ISA_MIPS32R6);
10628 if (sel != 0) {
10629 /* Performance counter registers are not implemented other than
10630 * control register 0.
10632 generate_exception(ctx, EXCP_RI);
10634 gen_helper_rdhwr_performance(t0, cpu_env);
10635 gen_store_gpr(t0, rt);
10636 break;
10637 case 5:
10638 check_insn(ctx, ISA_MIPS32R6);
10639 gen_helper_rdhwr_xnp(t0, cpu_env);
10640 gen_store_gpr(t0, rt);
10641 break;
10642 case 29:
10643 #if defined(CONFIG_USER_ONLY)
10644 tcg_gen_ld_tl(t0, cpu_env,
10645 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10646 gen_store_gpr(t0, rt);
10647 break;
10648 #else
10649 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
10650 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
10651 tcg_gen_ld_tl(t0, cpu_env,
10652 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10653 gen_store_gpr(t0, rt);
10654 } else {
10655 generate_exception_end(ctx, EXCP_RI);
10657 break;
10658 #endif
10659 default: /* Invalid */
10660 MIPS_INVAL("rdhwr");
10661 generate_exception_end(ctx, EXCP_RI);
10662 break;
10664 tcg_temp_free(t0);
10667 static inline void clear_branch_hflags(DisasContext *ctx)
10669 ctx->hflags &= ~MIPS_HFLAG_BMASK;
10670 if (ctx->bstate == BS_NONE) {
10671 save_cpu_state(ctx, 0);
10672 } else {
10673 /* it is not safe to save ctx->hflags as hflags may be changed
10674 in execution time by the instruction in delay / forbidden slot. */
10675 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
10679 static void gen_branch(DisasContext *ctx, int insn_bytes)
10681 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10682 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
10683 /* Branches completion */
10684 clear_branch_hflags(ctx);
10685 ctx->bstate = BS_BRANCH;
10686 /* FIXME: Need to clear can_do_io. */
10687 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
10688 case MIPS_HFLAG_FBNSLOT:
10689 gen_goto_tb(ctx, 0, ctx->pc + insn_bytes);
10690 break;
10691 case MIPS_HFLAG_B:
10692 /* unconditional branch */
10693 if (proc_hflags & MIPS_HFLAG_BX) {
10694 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
10696 gen_goto_tb(ctx, 0, ctx->btarget);
10697 break;
10698 case MIPS_HFLAG_BL:
10699 /* blikely taken case */
10700 gen_goto_tb(ctx, 0, ctx->btarget);
10701 break;
10702 case MIPS_HFLAG_BC:
10703 /* Conditional branch */
10705 TCGLabel *l1 = gen_new_label();
10707 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
10708 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
10709 gen_set_label(l1);
10710 gen_goto_tb(ctx, 0, ctx->btarget);
10712 break;
10713 case MIPS_HFLAG_BR:
10714 /* unconditional branch to register */
10715 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
10716 TCGv t0 = tcg_temp_new();
10717 TCGv_i32 t1 = tcg_temp_new_i32();
10719 tcg_gen_andi_tl(t0, btarget, 0x1);
10720 tcg_gen_trunc_tl_i32(t1, t0);
10721 tcg_temp_free(t0);
10722 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
10723 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
10724 tcg_gen_or_i32(hflags, hflags, t1);
10725 tcg_temp_free_i32(t1);
10727 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
10728 } else {
10729 tcg_gen_mov_tl(cpu_PC, btarget);
10731 if (ctx->singlestep_enabled) {
10732 save_cpu_state(ctx, 0);
10733 gen_helper_raise_exception_debug(cpu_env);
10735 tcg_gen_exit_tb(0);
10736 break;
10737 default:
10738 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
10739 abort();
10744 /* Compact Branches */
10745 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
10746 int rs, int rt, int32_t offset)
10748 int bcond_compute = 0;
10749 TCGv t0 = tcg_temp_new();
10750 TCGv t1 = tcg_temp_new();
10751 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
10753 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10754 #ifdef MIPS_DEBUG_DISAS
10755 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
10756 "\n", ctx->pc);
10757 #endif
10758 generate_exception_end(ctx, EXCP_RI);
10759 goto out;
10762 /* Load needed operands and calculate btarget */
10763 switch (opc) {
10764 /* compact branch */
10765 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
10766 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
10767 gen_load_gpr(t0, rs);
10768 gen_load_gpr(t1, rt);
10769 bcond_compute = 1;
10770 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10771 if (rs <= rt && rs == 0) {
10772 /* OPC_BEQZALC, OPC_BNEZALC */
10773 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
10775 break;
10776 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
10777 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
10778 gen_load_gpr(t0, rs);
10779 gen_load_gpr(t1, rt);
10780 bcond_compute = 1;
10781 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10782 break;
10783 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
10784 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
10785 if (rs == 0 || rs == rt) {
10786 /* OPC_BLEZALC, OPC_BGEZALC */
10787 /* OPC_BGTZALC, OPC_BLTZALC */
10788 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
10790 gen_load_gpr(t0, rs);
10791 gen_load_gpr(t1, rt);
10792 bcond_compute = 1;
10793 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10794 break;
10795 case OPC_BC:
10796 case OPC_BALC:
10797 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10798 break;
10799 case OPC_BEQZC:
10800 case OPC_BNEZC:
10801 if (rs != 0) {
10802 /* OPC_BEQZC, OPC_BNEZC */
10803 gen_load_gpr(t0, rs);
10804 bcond_compute = 1;
10805 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10806 } else {
10807 /* OPC_JIC, OPC_JIALC */
10808 TCGv tbase = tcg_temp_new();
10809 TCGv toffset = tcg_temp_new();
10811 gen_load_gpr(tbase, rt);
10812 tcg_gen_movi_tl(toffset, offset);
10813 gen_op_addr_add(ctx, btarget, tbase, toffset);
10814 tcg_temp_free(tbase);
10815 tcg_temp_free(toffset);
10817 break;
10818 default:
10819 MIPS_INVAL("Compact branch/jump");
10820 generate_exception_end(ctx, EXCP_RI);
10821 goto out;
10824 if (bcond_compute == 0) {
10825 /* Uncoditional compact branch */
10826 switch (opc) {
10827 case OPC_JIALC:
10828 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
10829 /* Fallthrough */
10830 case OPC_JIC:
10831 ctx->hflags |= MIPS_HFLAG_BR;
10832 break;
10833 case OPC_BALC:
10834 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
10835 /* Fallthrough */
10836 case OPC_BC:
10837 ctx->hflags |= MIPS_HFLAG_B;
10838 break;
10839 default:
10840 MIPS_INVAL("Compact branch/jump");
10841 generate_exception_end(ctx, EXCP_RI);
10842 goto out;
10845 /* Generating branch here as compact branches don't have delay slot */
10846 gen_branch(ctx, 4);
10847 } else {
10848 /* Conditional compact branch */
10849 TCGLabel *fs = gen_new_label();
10850 save_cpu_state(ctx, 0);
10852 switch (opc) {
10853 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
10854 if (rs == 0 && rt != 0) {
10855 /* OPC_BLEZALC */
10856 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
10857 } else if (rs != 0 && rt != 0 && rs == rt) {
10858 /* OPC_BGEZALC */
10859 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
10860 } else {
10861 /* OPC_BGEUC */
10862 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
10864 break;
10865 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
10866 if (rs == 0 && rt != 0) {
10867 /* OPC_BGTZALC */
10868 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
10869 } else if (rs != 0 && rt != 0 && rs == rt) {
10870 /* OPC_BLTZALC */
10871 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
10872 } else {
10873 /* OPC_BLTUC */
10874 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
10876 break;
10877 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
10878 if (rs == 0 && rt != 0) {
10879 /* OPC_BLEZC */
10880 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
10881 } else if (rs != 0 && rt != 0 && rs == rt) {
10882 /* OPC_BGEZC */
10883 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
10884 } else {
10885 /* OPC_BGEC */
10886 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
10888 break;
10889 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
10890 if (rs == 0 && rt != 0) {
10891 /* OPC_BGTZC */
10892 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
10893 } else if (rs != 0 && rt != 0 && rs == rt) {
10894 /* OPC_BLTZC */
10895 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
10896 } else {
10897 /* OPC_BLTC */
10898 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
10900 break;
10901 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
10902 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
10903 if (rs >= rt) {
10904 /* OPC_BOVC, OPC_BNVC */
10905 TCGv t2 = tcg_temp_new();
10906 TCGv t3 = tcg_temp_new();
10907 TCGv t4 = tcg_temp_new();
10908 TCGv input_overflow = tcg_temp_new();
10910 gen_load_gpr(t0, rs);
10911 gen_load_gpr(t1, rt);
10912 tcg_gen_ext32s_tl(t2, t0);
10913 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
10914 tcg_gen_ext32s_tl(t3, t1);
10915 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
10916 tcg_gen_or_tl(input_overflow, input_overflow, t4);
10918 tcg_gen_add_tl(t4, t2, t3);
10919 tcg_gen_ext32s_tl(t4, t4);
10920 tcg_gen_xor_tl(t2, t2, t3);
10921 tcg_gen_xor_tl(t3, t4, t3);
10922 tcg_gen_andc_tl(t2, t3, t2);
10923 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
10924 tcg_gen_or_tl(t4, t4, input_overflow);
10925 if (opc == OPC_BOVC) {
10926 /* OPC_BOVC */
10927 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
10928 } else {
10929 /* OPC_BNVC */
10930 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
10932 tcg_temp_free(input_overflow);
10933 tcg_temp_free(t4);
10934 tcg_temp_free(t3);
10935 tcg_temp_free(t2);
10936 } else if (rs < rt && rs == 0) {
10937 /* OPC_BEQZALC, OPC_BNEZALC */
10938 if (opc == OPC_BEQZALC) {
10939 /* OPC_BEQZALC */
10940 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
10941 } else {
10942 /* OPC_BNEZALC */
10943 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
10945 } else {
10946 /* OPC_BEQC, OPC_BNEC */
10947 if (opc == OPC_BEQC) {
10948 /* OPC_BEQC */
10949 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
10950 } else {
10951 /* OPC_BNEC */
10952 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
10955 break;
10956 case OPC_BEQZC:
10957 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
10958 break;
10959 case OPC_BNEZC:
10960 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
10961 break;
10962 default:
10963 MIPS_INVAL("Compact conditional branch/jump");
10964 generate_exception_end(ctx, EXCP_RI);
10965 goto out;
10968 /* Generating branch here as compact branches don't have delay slot */
10969 gen_goto_tb(ctx, 1, ctx->btarget);
10970 gen_set_label(fs);
10972 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
10975 out:
10976 tcg_temp_free(t0);
10977 tcg_temp_free(t1);
10980 /* ISA extensions (ASEs) */
10981 /* MIPS16 extension to MIPS32 */
10983 /* MIPS16 major opcodes */
10984 enum {
10985 M16_OPC_ADDIUSP = 0x00,
10986 M16_OPC_ADDIUPC = 0x01,
10987 M16_OPC_B = 0x02,
10988 M16_OPC_JAL = 0x03,
10989 M16_OPC_BEQZ = 0x04,
10990 M16_OPC_BNEQZ = 0x05,
10991 M16_OPC_SHIFT = 0x06,
10992 M16_OPC_LD = 0x07,
10993 M16_OPC_RRIA = 0x08,
10994 M16_OPC_ADDIU8 = 0x09,
10995 M16_OPC_SLTI = 0x0a,
10996 M16_OPC_SLTIU = 0x0b,
10997 M16_OPC_I8 = 0x0c,
10998 M16_OPC_LI = 0x0d,
10999 M16_OPC_CMPI = 0x0e,
11000 M16_OPC_SD = 0x0f,
11001 M16_OPC_LB = 0x10,
11002 M16_OPC_LH = 0x11,
11003 M16_OPC_LWSP = 0x12,
11004 M16_OPC_LW = 0x13,
11005 M16_OPC_LBU = 0x14,
11006 M16_OPC_LHU = 0x15,
11007 M16_OPC_LWPC = 0x16,
11008 M16_OPC_LWU = 0x17,
11009 M16_OPC_SB = 0x18,
11010 M16_OPC_SH = 0x19,
11011 M16_OPC_SWSP = 0x1a,
11012 M16_OPC_SW = 0x1b,
11013 M16_OPC_RRR = 0x1c,
11014 M16_OPC_RR = 0x1d,
11015 M16_OPC_EXTEND = 0x1e,
11016 M16_OPC_I64 = 0x1f
11019 /* I8 funct field */
11020 enum {
11021 I8_BTEQZ = 0x0,
11022 I8_BTNEZ = 0x1,
11023 I8_SWRASP = 0x2,
11024 I8_ADJSP = 0x3,
11025 I8_SVRS = 0x4,
11026 I8_MOV32R = 0x5,
11027 I8_MOVR32 = 0x7
11030 /* RRR f field */
11031 enum {
11032 RRR_DADDU = 0x0,
11033 RRR_ADDU = 0x1,
11034 RRR_DSUBU = 0x2,
11035 RRR_SUBU = 0x3
11038 /* RR funct field */
11039 enum {
11040 RR_JR = 0x00,
11041 RR_SDBBP = 0x01,
11042 RR_SLT = 0x02,
11043 RR_SLTU = 0x03,
11044 RR_SLLV = 0x04,
11045 RR_BREAK = 0x05,
11046 RR_SRLV = 0x06,
11047 RR_SRAV = 0x07,
11048 RR_DSRL = 0x08,
11049 RR_CMP = 0x0a,
11050 RR_NEG = 0x0b,
11051 RR_AND = 0x0c,
11052 RR_OR = 0x0d,
11053 RR_XOR = 0x0e,
11054 RR_NOT = 0x0f,
11055 RR_MFHI = 0x10,
11056 RR_CNVT = 0x11,
11057 RR_MFLO = 0x12,
11058 RR_DSRA = 0x13,
11059 RR_DSLLV = 0x14,
11060 RR_DSRLV = 0x16,
11061 RR_DSRAV = 0x17,
11062 RR_MULT = 0x18,
11063 RR_MULTU = 0x19,
11064 RR_DIV = 0x1a,
11065 RR_DIVU = 0x1b,
11066 RR_DMULT = 0x1c,
11067 RR_DMULTU = 0x1d,
11068 RR_DDIV = 0x1e,
11069 RR_DDIVU = 0x1f
11072 /* I64 funct field */
11073 enum {
11074 I64_LDSP = 0x0,
11075 I64_SDSP = 0x1,
11076 I64_SDRASP = 0x2,
11077 I64_DADJSP = 0x3,
11078 I64_LDPC = 0x4,
11079 I64_DADDIU5 = 0x5,
11080 I64_DADDIUPC = 0x6,
11081 I64_DADDIUSP = 0x7
11084 /* RR ry field for CNVT */
11085 enum {
11086 RR_RY_CNVT_ZEB = 0x0,
11087 RR_RY_CNVT_ZEH = 0x1,
11088 RR_RY_CNVT_ZEW = 0x2,
11089 RR_RY_CNVT_SEB = 0x4,
11090 RR_RY_CNVT_SEH = 0x5,
11091 RR_RY_CNVT_SEW = 0x6,
11094 static int xlat (int r)
11096 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
11098 return map[r];
11101 static void gen_mips16_save (DisasContext *ctx,
11102 int xsregs, int aregs,
11103 int do_ra, int do_s0, int do_s1,
11104 int framesize)
11106 TCGv t0 = tcg_temp_new();
11107 TCGv t1 = tcg_temp_new();
11108 TCGv t2 = tcg_temp_new();
11109 int args, astatic;
11111 switch (aregs) {
11112 case 0:
11113 case 1:
11114 case 2:
11115 case 3:
11116 case 11:
11117 args = 0;
11118 break;
11119 case 4:
11120 case 5:
11121 case 6:
11122 case 7:
11123 args = 1;
11124 break;
11125 case 8:
11126 case 9:
11127 case 10:
11128 args = 2;
11129 break;
11130 case 12:
11131 case 13:
11132 args = 3;
11133 break;
11134 case 14:
11135 args = 4;
11136 break;
11137 default:
11138 generate_exception_end(ctx, EXCP_RI);
11139 return;
11142 switch (args) {
11143 case 4:
11144 gen_base_offset_addr(ctx, t0, 29, 12);
11145 gen_load_gpr(t1, 7);
11146 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11147 /* Fall through */
11148 case 3:
11149 gen_base_offset_addr(ctx, t0, 29, 8);
11150 gen_load_gpr(t1, 6);
11151 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11152 /* Fall through */
11153 case 2:
11154 gen_base_offset_addr(ctx, t0, 29, 4);
11155 gen_load_gpr(t1, 5);
11156 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11157 /* Fall through */
11158 case 1:
11159 gen_base_offset_addr(ctx, t0, 29, 0);
11160 gen_load_gpr(t1, 4);
11161 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11164 gen_load_gpr(t0, 29);
11166 #define DECR_AND_STORE(reg) do { \
11167 tcg_gen_movi_tl(t2, -4); \
11168 gen_op_addr_add(ctx, t0, t0, t2); \
11169 gen_load_gpr(t1, reg); \
11170 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
11171 } while (0)
11173 if (do_ra) {
11174 DECR_AND_STORE(31);
11177 switch (xsregs) {
11178 case 7:
11179 DECR_AND_STORE(30);
11180 /* Fall through */
11181 case 6:
11182 DECR_AND_STORE(23);
11183 /* Fall through */
11184 case 5:
11185 DECR_AND_STORE(22);
11186 /* Fall through */
11187 case 4:
11188 DECR_AND_STORE(21);
11189 /* Fall through */
11190 case 3:
11191 DECR_AND_STORE(20);
11192 /* Fall through */
11193 case 2:
11194 DECR_AND_STORE(19);
11195 /* Fall through */
11196 case 1:
11197 DECR_AND_STORE(18);
11200 if (do_s1) {
11201 DECR_AND_STORE(17);
11203 if (do_s0) {
11204 DECR_AND_STORE(16);
11207 switch (aregs) {
11208 case 0:
11209 case 4:
11210 case 8:
11211 case 12:
11212 case 14:
11213 astatic = 0;
11214 break;
11215 case 1:
11216 case 5:
11217 case 9:
11218 case 13:
11219 astatic = 1;
11220 break;
11221 case 2:
11222 case 6:
11223 case 10:
11224 astatic = 2;
11225 break;
11226 case 3:
11227 case 7:
11228 astatic = 3;
11229 break;
11230 case 11:
11231 astatic = 4;
11232 break;
11233 default:
11234 generate_exception_end(ctx, EXCP_RI);
11235 return;
11238 if (astatic > 0) {
11239 DECR_AND_STORE(7);
11240 if (astatic > 1) {
11241 DECR_AND_STORE(6);
11242 if (astatic > 2) {
11243 DECR_AND_STORE(5);
11244 if (astatic > 3) {
11245 DECR_AND_STORE(4);
11250 #undef DECR_AND_STORE
11252 tcg_gen_movi_tl(t2, -framesize);
11253 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
11254 tcg_temp_free(t0);
11255 tcg_temp_free(t1);
11256 tcg_temp_free(t2);
11259 static void gen_mips16_restore (DisasContext *ctx,
11260 int xsregs, int aregs,
11261 int do_ra, int do_s0, int do_s1,
11262 int framesize)
11264 int astatic;
11265 TCGv t0 = tcg_temp_new();
11266 TCGv t1 = tcg_temp_new();
11267 TCGv t2 = tcg_temp_new();
11269 tcg_gen_movi_tl(t2, framesize);
11270 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
11272 #define DECR_AND_LOAD(reg) do { \
11273 tcg_gen_movi_tl(t2, -4); \
11274 gen_op_addr_add(ctx, t0, t0, t2); \
11275 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
11276 gen_store_gpr(t1, reg); \
11277 } while (0)
11279 if (do_ra) {
11280 DECR_AND_LOAD(31);
11283 switch (xsregs) {
11284 case 7:
11285 DECR_AND_LOAD(30);
11286 /* Fall through */
11287 case 6:
11288 DECR_AND_LOAD(23);
11289 /* Fall through */
11290 case 5:
11291 DECR_AND_LOAD(22);
11292 /* Fall through */
11293 case 4:
11294 DECR_AND_LOAD(21);
11295 /* Fall through */
11296 case 3:
11297 DECR_AND_LOAD(20);
11298 /* Fall through */
11299 case 2:
11300 DECR_AND_LOAD(19);
11301 /* Fall through */
11302 case 1:
11303 DECR_AND_LOAD(18);
11306 if (do_s1) {
11307 DECR_AND_LOAD(17);
11309 if (do_s0) {
11310 DECR_AND_LOAD(16);
11313 switch (aregs) {
11314 case 0:
11315 case 4:
11316 case 8:
11317 case 12:
11318 case 14:
11319 astatic = 0;
11320 break;
11321 case 1:
11322 case 5:
11323 case 9:
11324 case 13:
11325 astatic = 1;
11326 break;
11327 case 2:
11328 case 6:
11329 case 10:
11330 astatic = 2;
11331 break;
11332 case 3:
11333 case 7:
11334 astatic = 3;
11335 break;
11336 case 11:
11337 astatic = 4;
11338 break;
11339 default:
11340 generate_exception_end(ctx, EXCP_RI);
11341 return;
11344 if (astatic > 0) {
11345 DECR_AND_LOAD(7);
11346 if (astatic > 1) {
11347 DECR_AND_LOAD(6);
11348 if (astatic > 2) {
11349 DECR_AND_LOAD(5);
11350 if (astatic > 3) {
11351 DECR_AND_LOAD(4);
11356 #undef DECR_AND_LOAD
11358 tcg_gen_movi_tl(t2, framesize);
11359 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
11360 tcg_temp_free(t0);
11361 tcg_temp_free(t1);
11362 tcg_temp_free(t2);
11365 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
11366 int is_64_bit, int extended)
11368 TCGv t0;
11370 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11371 generate_exception_end(ctx, EXCP_RI);
11372 return;
11375 t0 = tcg_temp_new();
11377 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
11378 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
11379 if (!is_64_bit) {
11380 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11383 tcg_temp_free(t0);
11386 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
11387 int16_t offset)
11389 TCGv_i32 t0 = tcg_const_i32(op);
11390 TCGv t1 = tcg_temp_new();
11391 gen_base_offset_addr(ctx, t1, base, offset);
11392 gen_helper_cache(cpu_env, t1, t0);
11395 #if defined(TARGET_MIPS64)
11396 static void decode_i64_mips16 (DisasContext *ctx,
11397 int ry, int funct, int16_t offset,
11398 int extended)
11400 switch (funct) {
11401 case I64_LDSP:
11402 check_insn(ctx, ISA_MIPS3);
11403 check_mips_64(ctx);
11404 offset = extended ? offset : offset << 3;
11405 gen_ld(ctx, OPC_LD, ry, 29, offset);
11406 break;
11407 case I64_SDSP:
11408 check_insn(ctx, ISA_MIPS3);
11409 check_mips_64(ctx);
11410 offset = extended ? offset : offset << 3;
11411 gen_st(ctx, OPC_SD, ry, 29, offset);
11412 break;
11413 case I64_SDRASP:
11414 check_insn(ctx, ISA_MIPS3);
11415 check_mips_64(ctx);
11416 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
11417 gen_st(ctx, OPC_SD, 31, 29, offset);
11418 break;
11419 case I64_DADJSP:
11420 check_insn(ctx, ISA_MIPS3);
11421 check_mips_64(ctx);
11422 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
11423 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
11424 break;
11425 case I64_LDPC:
11426 check_insn(ctx, ISA_MIPS3);
11427 check_mips_64(ctx);
11428 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11429 generate_exception_end(ctx, EXCP_RI);
11430 } else {
11431 offset = extended ? offset : offset << 3;
11432 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
11434 break;
11435 case I64_DADDIU5:
11436 check_insn(ctx, ISA_MIPS3);
11437 check_mips_64(ctx);
11438 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
11439 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
11440 break;
11441 case I64_DADDIUPC:
11442 check_insn(ctx, ISA_MIPS3);
11443 check_mips_64(ctx);
11444 offset = extended ? offset : offset << 2;
11445 gen_addiupc(ctx, ry, offset, 1, extended);
11446 break;
11447 case I64_DADDIUSP:
11448 check_insn(ctx, ISA_MIPS3);
11449 check_mips_64(ctx);
11450 offset = extended ? offset : offset << 2;
11451 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
11452 break;
11455 #endif
11457 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
11459 int extend = cpu_lduw_code(env, ctx->pc + 2);
11460 int op, rx, ry, funct, sa;
11461 int16_t imm, offset;
11463 ctx->opcode = (ctx->opcode << 16) | extend;
11464 op = (ctx->opcode >> 11) & 0x1f;
11465 sa = (ctx->opcode >> 22) & 0x1f;
11466 funct = (ctx->opcode >> 8) & 0x7;
11467 rx = xlat((ctx->opcode >> 8) & 0x7);
11468 ry = xlat((ctx->opcode >> 5) & 0x7);
11469 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
11470 | ((ctx->opcode >> 21) & 0x3f) << 5
11471 | (ctx->opcode & 0x1f));
11473 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
11474 counterparts. */
11475 switch (op) {
11476 case M16_OPC_ADDIUSP:
11477 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
11478 break;
11479 case M16_OPC_ADDIUPC:
11480 gen_addiupc(ctx, rx, imm, 0, 1);
11481 break;
11482 case M16_OPC_B:
11483 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
11484 /* No delay slot, so just process as a normal instruction */
11485 break;
11486 case M16_OPC_BEQZ:
11487 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
11488 /* No delay slot, so just process as a normal instruction */
11489 break;
11490 case M16_OPC_BNEQZ:
11491 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
11492 /* No delay slot, so just process as a normal instruction */
11493 break;
11494 case M16_OPC_SHIFT:
11495 switch (ctx->opcode & 0x3) {
11496 case 0x0:
11497 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
11498 break;
11499 case 0x1:
11500 #if defined(TARGET_MIPS64)
11501 check_mips_64(ctx);
11502 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
11503 #else
11504 generate_exception_end(ctx, EXCP_RI);
11505 #endif
11506 break;
11507 case 0x2:
11508 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
11509 break;
11510 case 0x3:
11511 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
11512 break;
11514 break;
11515 #if defined(TARGET_MIPS64)
11516 case M16_OPC_LD:
11517 check_insn(ctx, ISA_MIPS3);
11518 check_mips_64(ctx);
11519 gen_ld(ctx, OPC_LD, ry, rx, offset);
11520 break;
11521 #endif
11522 case M16_OPC_RRIA:
11523 imm = ctx->opcode & 0xf;
11524 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
11525 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
11526 imm = (int16_t) (imm << 1) >> 1;
11527 if ((ctx->opcode >> 4) & 0x1) {
11528 #if defined(TARGET_MIPS64)
11529 check_mips_64(ctx);
11530 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
11531 #else
11532 generate_exception_end(ctx, EXCP_RI);
11533 #endif
11534 } else {
11535 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
11537 break;
11538 case M16_OPC_ADDIU8:
11539 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
11540 break;
11541 case M16_OPC_SLTI:
11542 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
11543 break;
11544 case M16_OPC_SLTIU:
11545 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
11546 break;
11547 case M16_OPC_I8:
11548 switch (funct) {
11549 case I8_BTEQZ:
11550 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
11551 break;
11552 case I8_BTNEZ:
11553 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
11554 break;
11555 case I8_SWRASP:
11556 gen_st(ctx, OPC_SW, 31, 29, imm);
11557 break;
11558 case I8_ADJSP:
11559 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
11560 break;
11561 case I8_SVRS:
11562 check_insn(ctx, ISA_MIPS32);
11564 int xsregs = (ctx->opcode >> 24) & 0x7;
11565 int aregs = (ctx->opcode >> 16) & 0xf;
11566 int do_ra = (ctx->opcode >> 6) & 0x1;
11567 int do_s0 = (ctx->opcode >> 5) & 0x1;
11568 int do_s1 = (ctx->opcode >> 4) & 0x1;
11569 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
11570 | (ctx->opcode & 0xf)) << 3;
11572 if (ctx->opcode & (1 << 7)) {
11573 gen_mips16_save(ctx, xsregs, aregs,
11574 do_ra, do_s0, do_s1,
11575 framesize);
11576 } else {
11577 gen_mips16_restore(ctx, xsregs, aregs,
11578 do_ra, do_s0, do_s1,
11579 framesize);
11582 break;
11583 default:
11584 generate_exception_end(ctx, EXCP_RI);
11585 break;
11587 break;
11588 case M16_OPC_LI:
11589 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
11590 break;
11591 case M16_OPC_CMPI:
11592 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
11593 break;
11594 #if defined(TARGET_MIPS64)
11595 case M16_OPC_SD:
11596 check_insn(ctx, ISA_MIPS3);
11597 check_mips_64(ctx);
11598 gen_st(ctx, OPC_SD, ry, rx, offset);
11599 break;
11600 #endif
11601 case M16_OPC_LB:
11602 gen_ld(ctx, OPC_LB, ry, rx, offset);
11603 break;
11604 case M16_OPC_LH:
11605 gen_ld(ctx, OPC_LH, ry, rx, offset);
11606 break;
11607 case M16_OPC_LWSP:
11608 gen_ld(ctx, OPC_LW, rx, 29, offset);
11609 break;
11610 case M16_OPC_LW:
11611 gen_ld(ctx, OPC_LW, ry, rx, offset);
11612 break;
11613 case M16_OPC_LBU:
11614 gen_ld(ctx, OPC_LBU, ry, rx, offset);
11615 break;
11616 case M16_OPC_LHU:
11617 gen_ld(ctx, OPC_LHU, ry, rx, offset);
11618 break;
11619 case M16_OPC_LWPC:
11620 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
11621 break;
11622 #if defined(TARGET_MIPS64)
11623 case M16_OPC_LWU:
11624 check_insn(ctx, ISA_MIPS3);
11625 check_mips_64(ctx);
11626 gen_ld(ctx, OPC_LWU, ry, rx, offset);
11627 break;
11628 #endif
11629 case M16_OPC_SB:
11630 gen_st(ctx, OPC_SB, ry, rx, offset);
11631 break;
11632 case M16_OPC_SH:
11633 gen_st(ctx, OPC_SH, ry, rx, offset);
11634 break;
11635 case M16_OPC_SWSP:
11636 gen_st(ctx, OPC_SW, rx, 29, offset);
11637 break;
11638 case M16_OPC_SW:
11639 gen_st(ctx, OPC_SW, ry, rx, offset);
11640 break;
11641 #if defined(TARGET_MIPS64)
11642 case M16_OPC_I64:
11643 decode_i64_mips16(ctx, ry, funct, offset, 1);
11644 break;
11645 #endif
11646 default:
11647 generate_exception_end(ctx, EXCP_RI);
11648 break;
11651 return 4;
11654 static inline bool is_uhi(int sdbbp_code)
11656 #ifdef CONFIG_USER_ONLY
11657 return false;
11658 #else
11659 return semihosting_enabled() && sdbbp_code == 1;
11660 #endif
11663 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
11665 int rx, ry;
11666 int sa;
11667 int op, cnvt_op, op1, offset;
11668 int funct;
11669 int n_bytes;
11671 op = (ctx->opcode >> 11) & 0x1f;
11672 sa = (ctx->opcode >> 2) & 0x7;
11673 sa = sa == 0 ? 8 : sa;
11674 rx = xlat((ctx->opcode >> 8) & 0x7);
11675 cnvt_op = (ctx->opcode >> 5) & 0x7;
11676 ry = xlat((ctx->opcode >> 5) & 0x7);
11677 op1 = offset = ctx->opcode & 0x1f;
11679 n_bytes = 2;
11681 switch (op) {
11682 case M16_OPC_ADDIUSP:
11684 int16_t imm = ((uint8_t) ctx->opcode) << 2;
11686 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
11688 break;
11689 case M16_OPC_ADDIUPC:
11690 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
11691 break;
11692 case M16_OPC_B:
11693 offset = (ctx->opcode & 0x7ff) << 1;
11694 offset = (int16_t)(offset << 4) >> 4;
11695 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
11696 /* No delay slot, so just process as a normal instruction */
11697 break;
11698 case M16_OPC_JAL:
11699 offset = cpu_lduw_code(env, ctx->pc + 2);
11700 offset = (((ctx->opcode & 0x1f) << 21)
11701 | ((ctx->opcode >> 5) & 0x1f) << 16
11702 | offset) << 2;
11703 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
11704 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
11705 n_bytes = 4;
11706 break;
11707 case M16_OPC_BEQZ:
11708 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
11709 ((int8_t)ctx->opcode) << 1, 0);
11710 /* No delay slot, so just process as a normal instruction */
11711 break;
11712 case M16_OPC_BNEQZ:
11713 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
11714 ((int8_t)ctx->opcode) << 1, 0);
11715 /* No delay slot, so just process as a normal instruction */
11716 break;
11717 case M16_OPC_SHIFT:
11718 switch (ctx->opcode & 0x3) {
11719 case 0x0:
11720 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
11721 break;
11722 case 0x1:
11723 #if defined(TARGET_MIPS64)
11724 check_insn(ctx, ISA_MIPS3);
11725 check_mips_64(ctx);
11726 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
11727 #else
11728 generate_exception_end(ctx, EXCP_RI);
11729 #endif
11730 break;
11731 case 0x2:
11732 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
11733 break;
11734 case 0x3:
11735 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
11736 break;
11738 break;
11739 #if defined(TARGET_MIPS64)
11740 case M16_OPC_LD:
11741 check_insn(ctx, ISA_MIPS3);
11742 check_mips_64(ctx);
11743 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
11744 break;
11745 #endif
11746 case M16_OPC_RRIA:
11748 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
11750 if ((ctx->opcode >> 4) & 1) {
11751 #if defined(TARGET_MIPS64)
11752 check_insn(ctx, ISA_MIPS3);
11753 check_mips_64(ctx);
11754 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
11755 #else
11756 generate_exception_end(ctx, EXCP_RI);
11757 #endif
11758 } else {
11759 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
11762 break;
11763 case M16_OPC_ADDIU8:
11765 int16_t imm = (int8_t) ctx->opcode;
11767 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
11769 break;
11770 case M16_OPC_SLTI:
11772 int16_t imm = (uint8_t) ctx->opcode;
11773 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
11775 break;
11776 case M16_OPC_SLTIU:
11778 int16_t imm = (uint8_t) ctx->opcode;
11779 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
11781 break;
11782 case M16_OPC_I8:
11784 int reg32;
11786 funct = (ctx->opcode >> 8) & 0x7;
11787 switch (funct) {
11788 case I8_BTEQZ:
11789 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
11790 ((int8_t)ctx->opcode) << 1, 0);
11791 break;
11792 case I8_BTNEZ:
11793 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
11794 ((int8_t)ctx->opcode) << 1, 0);
11795 break;
11796 case I8_SWRASP:
11797 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
11798 break;
11799 case I8_ADJSP:
11800 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
11801 ((int8_t)ctx->opcode) << 3);
11802 break;
11803 case I8_SVRS:
11804 check_insn(ctx, ISA_MIPS32);
11806 int do_ra = ctx->opcode & (1 << 6);
11807 int do_s0 = ctx->opcode & (1 << 5);
11808 int do_s1 = ctx->opcode & (1 << 4);
11809 int framesize = ctx->opcode & 0xf;
11811 if (framesize == 0) {
11812 framesize = 128;
11813 } else {
11814 framesize = framesize << 3;
11817 if (ctx->opcode & (1 << 7)) {
11818 gen_mips16_save(ctx, 0, 0,
11819 do_ra, do_s0, do_s1, framesize);
11820 } else {
11821 gen_mips16_restore(ctx, 0, 0,
11822 do_ra, do_s0, do_s1, framesize);
11825 break;
11826 case I8_MOV32R:
11828 int rz = xlat(ctx->opcode & 0x7);
11830 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
11831 ((ctx->opcode >> 5) & 0x7);
11832 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
11834 break;
11835 case I8_MOVR32:
11836 reg32 = ctx->opcode & 0x1f;
11837 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
11838 break;
11839 default:
11840 generate_exception_end(ctx, EXCP_RI);
11841 break;
11844 break;
11845 case M16_OPC_LI:
11847 int16_t imm = (uint8_t) ctx->opcode;
11849 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
11851 break;
11852 case M16_OPC_CMPI:
11854 int16_t imm = (uint8_t) ctx->opcode;
11855 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
11857 break;
11858 #if defined(TARGET_MIPS64)
11859 case M16_OPC_SD:
11860 check_insn(ctx, ISA_MIPS3);
11861 check_mips_64(ctx);
11862 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
11863 break;
11864 #endif
11865 case M16_OPC_LB:
11866 gen_ld(ctx, OPC_LB, ry, rx, offset);
11867 break;
11868 case M16_OPC_LH:
11869 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
11870 break;
11871 case M16_OPC_LWSP:
11872 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
11873 break;
11874 case M16_OPC_LW:
11875 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
11876 break;
11877 case M16_OPC_LBU:
11878 gen_ld(ctx, OPC_LBU, ry, rx, offset);
11879 break;
11880 case M16_OPC_LHU:
11881 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
11882 break;
11883 case M16_OPC_LWPC:
11884 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
11885 break;
11886 #if defined (TARGET_MIPS64)
11887 case M16_OPC_LWU:
11888 check_insn(ctx, ISA_MIPS3);
11889 check_mips_64(ctx);
11890 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
11891 break;
11892 #endif
11893 case M16_OPC_SB:
11894 gen_st(ctx, OPC_SB, ry, rx, offset);
11895 break;
11896 case M16_OPC_SH:
11897 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
11898 break;
11899 case M16_OPC_SWSP:
11900 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
11901 break;
11902 case M16_OPC_SW:
11903 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
11904 break;
11905 case M16_OPC_RRR:
11907 int rz = xlat((ctx->opcode >> 2) & 0x7);
11908 int mips32_op;
11910 switch (ctx->opcode & 0x3) {
11911 case RRR_ADDU:
11912 mips32_op = OPC_ADDU;
11913 break;
11914 case RRR_SUBU:
11915 mips32_op = OPC_SUBU;
11916 break;
11917 #if defined(TARGET_MIPS64)
11918 case RRR_DADDU:
11919 mips32_op = OPC_DADDU;
11920 check_insn(ctx, ISA_MIPS3);
11921 check_mips_64(ctx);
11922 break;
11923 case RRR_DSUBU:
11924 mips32_op = OPC_DSUBU;
11925 check_insn(ctx, ISA_MIPS3);
11926 check_mips_64(ctx);
11927 break;
11928 #endif
11929 default:
11930 generate_exception_end(ctx, EXCP_RI);
11931 goto done;
11934 gen_arith(ctx, mips32_op, rz, rx, ry);
11935 done:
11938 break;
11939 case M16_OPC_RR:
11940 switch (op1) {
11941 case RR_JR:
11943 int nd = (ctx->opcode >> 7) & 0x1;
11944 int link = (ctx->opcode >> 6) & 0x1;
11945 int ra = (ctx->opcode >> 5) & 0x1;
11947 if (nd) {
11948 check_insn(ctx, ISA_MIPS32);
11951 if (link) {
11952 op = OPC_JALR;
11953 } else {
11954 op = OPC_JR;
11957 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
11958 (nd ? 0 : 2));
11960 break;
11961 case RR_SDBBP:
11962 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
11963 gen_helper_do_semihosting(cpu_env);
11964 } else {
11965 /* XXX: not clear which exception should be raised
11966 * when in debug mode...
11968 check_insn(ctx, ISA_MIPS32);
11969 generate_exception_end(ctx, EXCP_DBp);
11971 break;
11972 case RR_SLT:
11973 gen_slt(ctx, OPC_SLT, 24, rx, ry);
11974 break;
11975 case RR_SLTU:
11976 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
11977 break;
11978 case RR_BREAK:
11979 generate_exception_end(ctx, EXCP_BREAK);
11980 break;
11981 case RR_SLLV:
11982 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
11983 break;
11984 case RR_SRLV:
11985 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
11986 break;
11987 case RR_SRAV:
11988 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
11989 break;
11990 #if defined (TARGET_MIPS64)
11991 case RR_DSRL:
11992 check_insn(ctx, ISA_MIPS3);
11993 check_mips_64(ctx);
11994 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
11995 break;
11996 #endif
11997 case RR_CMP:
11998 gen_logic(ctx, OPC_XOR, 24, rx, ry);
11999 break;
12000 case RR_NEG:
12001 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
12002 break;
12003 case RR_AND:
12004 gen_logic(ctx, OPC_AND, rx, rx, ry);
12005 break;
12006 case RR_OR:
12007 gen_logic(ctx, OPC_OR, rx, rx, ry);
12008 break;
12009 case RR_XOR:
12010 gen_logic(ctx, OPC_XOR, rx, rx, ry);
12011 break;
12012 case RR_NOT:
12013 gen_logic(ctx, OPC_NOR, rx, ry, 0);
12014 break;
12015 case RR_MFHI:
12016 gen_HILO(ctx, OPC_MFHI, 0, rx);
12017 break;
12018 case RR_CNVT:
12019 check_insn(ctx, ISA_MIPS32);
12020 switch (cnvt_op) {
12021 case RR_RY_CNVT_ZEB:
12022 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12023 break;
12024 case RR_RY_CNVT_ZEH:
12025 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12026 break;
12027 case RR_RY_CNVT_SEB:
12028 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12029 break;
12030 case RR_RY_CNVT_SEH:
12031 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12032 break;
12033 #if defined (TARGET_MIPS64)
12034 case RR_RY_CNVT_ZEW:
12035 check_insn(ctx, ISA_MIPS64);
12036 check_mips_64(ctx);
12037 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12038 break;
12039 case RR_RY_CNVT_SEW:
12040 check_insn(ctx, ISA_MIPS64);
12041 check_mips_64(ctx);
12042 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12043 break;
12044 #endif
12045 default:
12046 generate_exception_end(ctx, EXCP_RI);
12047 break;
12049 break;
12050 case RR_MFLO:
12051 gen_HILO(ctx, OPC_MFLO, 0, rx);
12052 break;
12053 #if defined (TARGET_MIPS64)
12054 case RR_DSRA:
12055 check_insn(ctx, ISA_MIPS3);
12056 check_mips_64(ctx);
12057 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
12058 break;
12059 case RR_DSLLV:
12060 check_insn(ctx, ISA_MIPS3);
12061 check_mips_64(ctx);
12062 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
12063 break;
12064 case RR_DSRLV:
12065 check_insn(ctx, ISA_MIPS3);
12066 check_mips_64(ctx);
12067 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
12068 break;
12069 case RR_DSRAV:
12070 check_insn(ctx, ISA_MIPS3);
12071 check_mips_64(ctx);
12072 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
12073 break;
12074 #endif
12075 case RR_MULT:
12076 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
12077 break;
12078 case RR_MULTU:
12079 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
12080 break;
12081 case RR_DIV:
12082 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
12083 break;
12084 case RR_DIVU:
12085 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
12086 break;
12087 #if defined (TARGET_MIPS64)
12088 case RR_DMULT:
12089 check_insn(ctx, ISA_MIPS3);
12090 check_mips_64(ctx);
12091 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
12092 break;
12093 case RR_DMULTU:
12094 check_insn(ctx, ISA_MIPS3);
12095 check_mips_64(ctx);
12096 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
12097 break;
12098 case RR_DDIV:
12099 check_insn(ctx, ISA_MIPS3);
12100 check_mips_64(ctx);
12101 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
12102 break;
12103 case RR_DDIVU:
12104 check_insn(ctx, ISA_MIPS3);
12105 check_mips_64(ctx);
12106 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
12107 break;
12108 #endif
12109 default:
12110 generate_exception_end(ctx, EXCP_RI);
12111 break;
12113 break;
12114 case M16_OPC_EXTEND:
12115 decode_extended_mips16_opc(env, ctx);
12116 n_bytes = 4;
12117 break;
12118 #if defined(TARGET_MIPS64)
12119 case M16_OPC_I64:
12120 funct = (ctx->opcode >> 8) & 0x7;
12121 decode_i64_mips16(ctx, ry, funct, offset, 0);
12122 break;
12123 #endif
12124 default:
12125 generate_exception_end(ctx, EXCP_RI);
12126 break;
12129 return n_bytes;
12132 /* microMIPS extension to MIPS32/MIPS64 */
12135 * microMIPS32/microMIPS64 major opcodes
12137 * 1. MIPS Architecture for Programmers Volume II-B:
12138 * The microMIPS32 Instruction Set (Revision 3.05)
12140 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
12142 * 2. MIPS Architecture For Programmers Volume II-A:
12143 * The MIPS64 Instruction Set (Revision 3.51)
12146 enum {
12147 POOL32A = 0x00,
12148 POOL16A = 0x01,
12149 LBU16 = 0x02,
12150 MOVE16 = 0x03,
12151 ADDI32 = 0x04,
12152 R6_LUI = 0x04,
12153 AUI = 0x04,
12154 LBU32 = 0x05,
12155 SB32 = 0x06,
12156 LB32 = 0x07,
12158 POOL32B = 0x08,
12159 POOL16B = 0x09,
12160 LHU16 = 0x0a,
12161 ANDI16 = 0x0b,
12162 ADDIU32 = 0x0c,
12163 LHU32 = 0x0d,
12164 SH32 = 0x0e,
12165 LH32 = 0x0f,
12167 POOL32I = 0x10,
12168 POOL16C = 0x11,
12169 LWSP16 = 0x12,
12170 POOL16D = 0x13,
12171 ORI32 = 0x14,
12172 POOL32F = 0x15,
12173 POOL32S = 0x16, /* MIPS64 */
12174 DADDIU32 = 0x17, /* MIPS64 */
12176 POOL32C = 0x18,
12177 LWGP16 = 0x19,
12178 LW16 = 0x1a,
12179 POOL16E = 0x1b,
12180 XORI32 = 0x1c,
12181 JALS32 = 0x1d,
12182 BOVC = 0x1d,
12183 BEQC = 0x1d,
12184 BEQZALC = 0x1d,
12185 ADDIUPC = 0x1e,
12186 PCREL = 0x1e,
12187 BNVC = 0x1f,
12188 BNEC = 0x1f,
12189 BNEZALC = 0x1f,
12191 R6_BEQZC = 0x20,
12192 JIC = 0x20,
12193 POOL16F = 0x21,
12194 SB16 = 0x22,
12195 BEQZ16 = 0x23,
12196 BEQZC16 = 0x23,
12197 SLTI32 = 0x24,
12198 BEQ32 = 0x25,
12199 BC = 0x25,
12200 SWC132 = 0x26,
12201 LWC132 = 0x27,
12203 /* 0x29 is reserved */
12204 RES_29 = 0x29,
12205 R6_BNEZC = 0x28,
12206 JIALC = 0x28,
12207 SH16 = 0x2a,
12208 BNEZ16 = 0x2b,
12209 BNEZC16 = 0x2b,
12210 SLTIU32 = 0x2c,
12211 BNE32 = 0x2d,
12212 BALC = 0x2d,
12213 SDC132 = 0x2e,
12214 LDC132 = 0x2f,
12216 /* 0x31 is reserved */
12217 RES_31 = 0x31,
12218 BLEZALC = 0x30,
12219 BGEZALC = 0x30,
12220 BGEUC = 0x30,
12221 SWSP16 = 0x32,
12222 B16 = 0x33,
12223 BC16 = 0x33,
12224 ANDI32 = 0x34,
12225 J32 = 0x35,
12226 BGTZC = 0x35,
12227 BLTZC = 0x35,
12228 BLTC = 0x35,
12229 SD32 = 0x36, /* MIPS64 */
12230 LD32 = 0x37, /* MIPS64 */
12232 /* 0x39 is reserved */
12233 RES_39 = 0x39,
12234 BGTZALC = 0x38,
12235 BLTZALC = 0x38,
12236 BLTUC = 0x38,
12237 SW16 = 0x3a,
12238 LI16 = 0x3b,
12239 JALX32 = 0x3c,
12240 JAL32 = 0x3d,
12241 BLEZC = 0x3d,
12242 BGEZC = 0x3d,
12243 BGEC = 0x3d,
12244 SW32 = 0x3e,
12245 LW32 = 0x3f
12248 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
12249 enum {
12250 ADDIUPC_00 = 0x00,
12251 ADDIUPC_07 = 0x07,
12252 AUIPC = 0x1e,
12253 ALUIPC = 0x1f,
12254 LWPC_08 = 0x08,
12255 LWPC_0F = 0x0F,
12258 /* POOL32A encoding of minor opcode field */
12260 enum {
12261 /* These opcodes are distinguished only by bits 9..6; those bits are
12262 * what are recorded below. */
12263 SLL32 = 0x0,
12264 SRL32 = 0x1,
12265 SRA = 0x2,
12266 ROTR = 0x3,
12267 SELEQZ = 0x5,
12268 SELNEZ = 0x6,
12269 R6_RDHWR = 0x7,
12271 SLLV = 0x0,
12272 SRLV = 0x1,
12273 SRAV = 0x2,
12274 ROTRV = 0x3,
12275 ADD = 0x4,
12276 ADDU32 = 0x5,
12277 SUB = 0x6,
12278 SUBU32 = 0x7,
12279 MUL = 0x8,
12280 AND = 0x9,
12281 OR32 = 0xa,
12282 NOR = 0xb,
12283 XOR32 = 0xc,
12284 SLT = 0xd,
12285 SLTU = 0xe,
12287 MOVN = 0x0,
12288 R6_MUL = 0x0,
12289 MOVZ = 0x1,
12290 MUH = 0x1,
12291 MULU = 0x2,
12292 MUHU = 0x3,
12293 LWXS = 0x4,
12294 R6_DIV = 0x4,
12295 MOD = 0x5,
12296 R6_DIVU = 0x6,
12297 MODU = 0x7,
12299 /* The following can be distinguished by their lower 6 bits. */
12300 BREAK32 = 0x07,
12301 INS = 0x0c,
12302 LSA = 0x0f,
12303 ALIGN = 0x1f,
12304 EXT = 0x2c,
12305 POOL32AXF = 0x3c,
12306 SIGRIE = 0x3f
12309 /* POOL32AXF encoding of minor opcode field extension */
12312 * 1. MIPS Architecture for Programmers Volume II-B:
12313 * The microMIPS32 Instruction Set (Revision 3.05)
12315 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
12317 * 2. MIPS Architecture for Programmers VolumeIV-e:
12318 * The MIPS DSP Application-Specific Extension
12319 * to the microMIPS32 Architecture (Revision 2.34)
12321 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
12324 enum {
12325 /* bits 11..6 */
12326 TEQ = 0x00,
12327 TGE = 0x08,
12328 TGEU = 0x10,
12329 TLT = 0x20,
12330 TLTU = 0x28,
12331 TNE = 0x30,
12333 MFC0 = 0x03,
12334 MTC0 = 0x0b,
12336 /* begin of microMIPS32 DSP */
12338 /* bits 13..12 for 0x01 */
12339 MFHI_ACC = 0x0,
12340 MFLO_ACC = 0x1,
12341 MTHI_ACC = 0x2,
12342 MTLO_ACC = 0x3,
12344 /* bits 13..12 for 0x2a */
12345 MADD_ACC = 0x0,
12346 MADDU_ACC = 0x1,
12347 MSUB_ACC = 0x2,
12348 MSUBU_ACC = 0x3,
12350 /* bits 13..12 for 0x32 */
12351 MULT_ACC = 0x0,
12352 MULTU_ACC = 0x1,
12354 /* end of microMIPS32 DSP */
12356 /* bits 15..12 for 0x2c */
12357 BITSWAP = 0x0,
12358 SEB = 0x2,
12359 SEH = 0x3,
12360 CLO = 0x4,
12361 CLZ = 0x5,
12362 RDHWR = 0x6,
12363 WSBH = 0x7,
12364 MULT = 0x8,
12365 MULTU = 0x9,
12366 DIV = 0xa,
12367 DIVU = 0xb,
12368 MADD = 0xc,
12369 MADDU = 0xd,
12370 MSUB = 0xe,
12371 MSUBU = 0xf,
12373 /* bits 15..12 for 0x34 */
12374 MFC2 = 0x4,
12375 MTC2 = 0x5,
12376 MFHC2 = 0x8,
12377 MTHC2 = 0x9,
12378 CFC2 = 0xc,
12379 CTC2 = 0xd,
12381 /* bits 15..12 for 0x3c */
12382 JALR = 0x0,
12383 JR = 0x0, /* alias */
12384 JALRC = 0x0,
12385 JRC = 0x0,
12386 JALR_HB = 0x1,
12387 JALRC_HB = 0x1,
12388 JALRS = 0x4,
12389 JALRS_HB = 0x5,
12391 /* bits 15..12 for 0x05 */
12392 RDPGPR = 0xe,
12393 WRPGPR = 0xf,
12395 /* bits 15..12 for 0x0d */
12396 TLBP = 0x0,
12397 TLBR = 0x1,
12398 TLBWI = 0x2,
12399 TLBWR = 0x3,
12400 TLBINV = 0x4,
12401 TLBINVF = 0x5,
12402 WAIT = 0x9,
12403 IRET = 0xd,
12404 DERET = 0xe,
12405 ERET = 0xf,
12407 /* bits 15..12 for 0x15 */
12408 DMT = 0x0,
12409 DVPE = 0x1,
12410 EMT = 0x2,
12411 EVPE = 0x3,
12413 /* bits 15..12 for 0x1d */
12414 DI = 0x4,
12415 EI = 0x5,
12417 /* bits 15..12 for 0x2d */
12418 SYNC = 0x6,
12419 SYSCALL = 0x8,
12420 SDBBP = 0xd,
12422 /* bits 15..12 for 0x35 */
12423 MFHI32 = 0x0,
12424 MFLO32 = 0x1,
12425 MTHI32 = 0x2,
12426 MTLO32 = 0x3,
12429 /* POOL32B encoding of minor opcode field (bits 15..12) */
12431 enum {
12432 LWC2 = 0x0,
12433 LWP = 0x1,
12434 LDP = 0x4,
12435 LWM32 = 0x5,
12436 CACHE = 0x6,
12437 LDM = 0x7,
12438 SWC2 = 0x8,
12439 SWP = 0x9,
12440 SDP = 0xc,
12441 SWM32 = 0xd,
12442 SDM = 0xf
12445 /* POOL32C encoding of minor opcode field (bits 15..12) */
12447 enum {
12448 LWL = 0x0,
12449 SWL = 0x8,
12450 LWR = 0x1,
12451 SWR = 0x9,
12452 PREF = 0x2,
12453 /* 0xa is reserved */
12454 LL = 0x3,
12455 SC = 0xb,
12456 LDL = 0x4,
12457 SDL = 0xc,
12458 LDR = 0x5,
12459 SDR = 0xd,
12460 /* 0x6 is reserved */
12461 LWU = 0xe,
12462 LLD = 0x7,
12463 SCD = 0xf
12466 /* POOL32F encoding of minor opcode field (bits 5..0) */
12468 enum {
12469 /* These are the bit 7..6 values */
12470 ADD_FMT = 0x0,
12472 SUB_FMT = 0x1,
12474 MUL_FMT = 0x2,
12476 DIV_FMT = 0x3,
12478 /* These are the bit 8..6 values */
12479 MOVN_FMT = 0x0,
12480 RSQRT2_FMT = 0x0,
12481 MOVF_FMT = 0x0,
12482 RINT_FMT = 0x0,
12483 SELNEZ_FMT = 0x0,
12485 MOVZ_FMT = 0x1,
12486 LWXC1 = 0x1,
12487 MOVT_FMT = 0x1,
12488 CLASS_FMT = 0x1,
12489 SELEQZ_FMT = 0x1,
12491 PLL_PS = 0x2,
12492 SWXC1 = 0x2,
12493 SEL_FMT = 0x2,
12495 PLU_PS = 0x3,
12496 LDXC1 = 0x3,
12498 MOVN_FMT_04 = 0x4,
12499 PUL_PS = 0x4,
12500 SDXC1 = 0x4,
12501 RECIP2_FMT = 0x4,
12503 MOVZ_FMT_05 = 0x05,
12504 PUU_PS = 0x5,
12505 LUXC1 = 0x5,
12507 CVT_PS_S = 0x6,
12508 SUXC1 = 0x6,
12509 ADDR_PS = 0x6,
12510 PREFX = 0x6,
12511 MADDF_FMT = 0x6,
12513 MULR_PS = 0x7,
12514 MSUBF_FMT = 0x7,
12516 MADD_S = 0x01,
12517 MADD_D = 0x09,
12518 MADD_PS = 0x11,
12519 ALNV_PS = 0x19,
12520 MSUB_S = 0x21,
12521 MSUB_D = 0x29,
12522 MSUB_PS = 0x31,
12524 NMADD_S = 0x02,
12525 NMADD_D = 0x0a,
12526 NMADD_PS = 0x12,
12527 NMSUB_S = 0x22,
12528 NMSUB_D = 0x2a,
12529 NMSUB_PS = 0x32,
12531 MIN_FMT = 0x3,
12532 MAX_FMT = 0xb,
12533 MINA_FMT = 0x23,
12534 MAXA_FMT = 0x2b,
12535 POOL32FXF = 0x3b,
12537 CABS_COND_FMT = 0x1c, /* MIPS3D */
12538 C_COND_FMT = 0x3c,
12540 CMP_CONDN_S = 0x5,
12541 CMP_CONDN_D = 0x15
12544 /* POOL32Fxf encoding of minor opcode extension field */
12546 enum {
12547 CVT_L = 0x04,
12548 RSQRT_FMT = 0x08,
12549 FLOOR_L = 0x0c,
12550 CVT_PW_PS = 0x1c,
12551 CVT_W = 0x24,
12552 SQRT_FMT = 0x28,
12553 FLOOR_W = 0x2c,
12554 CVT_PS_PW = 0x3c,
12555 CFC1 = 0x40,
12556 RECIP_FMT = 0x48,
12557 CEIL_L = 0x4c,
12558 CTC1 = 0x60,
12559 CEIL_W = 0x6c,
12560 MFC1 = 0x80,
12561 CVT_S_PL = 0x84,
12562 TRUNC_L = 0x8c,
12563 MTC1 = 0xa0,
12564 CVT_S_PU = 0xa4,
12565 TRUNC_W = 0xac,
12566 MFHC1 = 0xc0,
12567 ROUND_L = 0xcc,
12568 MTHC1 = 0xe0,
12569 ROUND_W = 0xec,
12571 MOV_FMT = 0x01,
12572 MOVF = 0x05,
12573 ABS_FMT = 0x0d,
12574 RSQRT1_FMT = 0x1d,
12575 MOVT = 0x25,
12576 NEG_FMT = 0x2d,
12577 CVT_D = 0x4d,
12578 RECIP1_FMT = 0x5d,
12579 CVT_S = 0x6d
12582 /* POOL32I encoding of minor opcode field (bits 25..21) */
12584 enum {
12585 BLTZ = 0x00,
12586 BLTZAL = 0x01,
12587 BGEZ = 0x02,
12588 BGEZAL = 0x03,
12589 BLEZ = 0x04,
12590 BNEZC = 0x05,
12591 BGTZ = 0x06,
12592 BEQZC = 0x07,
12593 TLTI = 0x08,
12594 BC1EQZC = 0x08,
12595 TGEI = 0x09,
12596 BC1NEZC = 0x09,
12597 TLTIU = 0x0a,
12598 BC2EQZC = 0x0a,
12599 TGEIU = 0x0b,
12600 BC2NEZC = 0x0a,
12601 TNEI = 0x0c,
12602 R6_SYNCI = 0x0c,
12603 LUI = 0x0d,
12604 TEQI = 0x0e,
12605 SYNCI = 0x10,
12606 BLTZALS = 0x11,
12607 BGEZALS = 0x13,
12608 BC2F = 0x14,
12609 BC2T = 0x15,
12610 BPOSGE64 = 0x1a,
12611 BPOSGE32 = 0x1b,
12612 /* These overlap and are distinguished by bit16 of the instruction */
12613 BC1F = 0x1c,
12614 BC1T = 0x1d,
12615 BC1ANY2F = 0x1c,
12616 BC1ANY2T = 0x1d,
12617 BC1ANY4F = 0x1e,
12618 BC1ANY4T = 0x1f
12621 /* POOL16A encoding of minor opcode field */
12623 enum {
12624 ADDU16 = 0x0,
12625 SUBU16 = 0x1
12628 /* POOL16B encoding of minor opcode field */
12630 enum {
12631 SLL16 = 0x0,
12632 SRL16 = 0x1
12635 /* POOL16C encoding of minor opcode field */
12637 enum {
12638 NOT16 = 0x00,
12639 XOR16 = 0x04,
12640 AND16 = 0x08,
12641 OR16 = 0x0c,
12642 LWM16 = 0x10,
12643 SWM16 = 0x14,
12644 JR16 = 0x18,
12645 JRC16 = 0x1a,
12646 JALR16 = 0x1c,
12647 JALR16S = 0x1e,
12648 MFHI16 = 0x20,
12649 MFLO16 = 0x24,
12650 BREAK16 = 0x28,
12651 SDBBP16 = 0x2c,
12652 JRADDIUSP = 0x30
12655 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
12657 enum {
12658 R6_NOT16 = 0x00,
12659 R6_AND16 = 0x01,
12660 R6_LWM16 = 0x02,
12661 R6_JRC16 = 0x03,
12662 MOVEP = 0x04,
12663 MOVEP_07 = 0x07,
12664 R6_XOR16 = 0x08,
12665 R6_OR16 = 0x09,
12666 R6_SWM16 = 0x0a,
12667 JALRC16 = 0x0b,
12668 MOVEP_0C = 0x0c,
12669 MOVEP_0F = 0x0f,
12670 JRCADDIUSP = 0x13,
12671 R6_BREAK16 = 0x1b,
12672 R6_SDBBP16 = 0x3b
12675 /* POOL16D encoding of minor opcode field */
12677 enum {
12678 ADDIUS5 = 0x0,
12679 ADDIUSP = 0x1
12682 /* POOL16E encoding of minor opcode field */
12684 enum {
12685 ADDIUR2 = 0x0,
12686 ADDIUR1SP = 0x1
12689 static int mmreg (int r)
12691 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12693 return map[r];
12696 /* Used for 16-bit store instructions. */
12697 static int mmreg2 (int r)
12699 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
12701 return map[r];
12704 #define uMIPS_RD(op) ((op >> 7) & 0x7)
12705 #define uMIPS_RS(op) ((op >> 4) & 0x7)
12706 #define uMIPS_RS2(op) uMIPS_RS(op)
12707 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
12708 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
12709 #define uMIPS_RS5(op) (op & 0x1f)
12711 /* Signed immediate */
12712 #define SIMM(op, start, width) \
12713 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
12714 << (32-width)) \
12715 >> (32-width))
12716 /* Zero-extended immediate */
12717 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
12719 static void gen_addiur1sp(DisasContext *ctx)
12721 int rd = mmreg(uMIPS_RD(ctx->opcode));
12723 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
12726 static void gen_addiur2(DisasContext *ctx)
12728 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
12729 int rd = mmreg(uMIPS_RD(ctx->opcode));
12730 int rs = mmreg(uMIPS_RS(ctx->opcode));
12732 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
12735 static void gen_addiusp(DisasContext *ctx)
12737 int encoded = ZIMM(ctx->opcode, 1, 9);
12738 int decoded;
12740 if (encoded <= 1) {
12741 decoded = 256 + encoded;
12742 } else if (encoded <= 255) {
12743 decoded = encoded;
12744 } else if (encoded <= 509) {
12745 decoded = encoded - 512;
12746 } else {
12747 decoded = encoded - 768;
12750 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
12753 static void gen_addius5(DisasContext *ctx)
12755 int imm = SIMM(ctx->opcode, 1, 4);
12756 int rd = (ctx->opcode >> 5) & 0x1f;
12758 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
12761 static void gen_andi16(DisasContext *ctx)
12763 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
12764 31, 32, 63, 64, 255, 32768, 65535 };
12765 int rd = mmreg(uMIPS_RD(ctx->opcode));
12766 int rs = mmreg(uMIPS_RS(ctx->opcode));
12767 int encoded = ZIMM(ctx->opcode, 0, 4);
12769 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
12772 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
12773 int base, int16_t offset)
12775 TCGv t0, t1;
12776 TCGv_i32 t2;
12778 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12779 generate_exception_end(ctx, EXCP_RI);
12780 return;
12783 t0 = tcg_temp_new();
12785 gen_base_offset_addr(ctx, t0, base, offset);
12787 t1 = tcg_const_tl(reglist);
12788 t2 = tcg_const_i32(ctx->mem_idx);
12790 save_cpu_state(ctx, 1);
12791 switch (opc) {
12792 case LWM32:
12793 gen_helper_lwm(cpu_env, t0, t1, t2);
12794 break;
12795 case SWM32:
12796 gen_helper_swm(cpu_env, t0, t1, t2);
12797 break;
12798 #ifdef TARGET_MIPS64
12799 case LDM:
12800 gen_helper_ldm(cpu_env, t0, t1, t2);
12801 break;
12802 case SDM:
12803 gen_helper_sdm(cpu_env, t0, t1, t2);
12804 break;
12805 #endif
12807 tcg_temp_free(t0);
12808 tcg_temp_free(t1);
12809 tcg_temp_free_i32(t2);
12813 static void gen_pool16c_insn(DisasContext *ctx)
12815 int rd = mmreg((ctx->opcode >> 3) & 0x7);
12816 int rs = mmreg(ctx->opcode & 0x7);
12818 switch (((ctx->opcode) >> 4) & 0x3f) {
12819 case NOT16 + 0:
12820 case NOT16 + 1:
12821 case NOT16 + 2:
12822 case NOT16 + 3:
12823 gen_logic(ctx, OPC_NOR, rd, rs, 0);
12824 break;
12825 case XOR16 + 0:
12826 case XOR16 + 1:
12827 case XOR16 + 2:
12828 case XOR16 + 3:
12829 gen_logic(ctx, OPC_XOR, rd, rd, rs);
12830 break;
12831 case AND16 + 0:
12832 case AND16 + 1:
12833 case AND16 + 2:
12834 case AND16 + 3:
12835 gen_logic(ctx, OPC_AND, rd, rd, rs);
12836 break;
12837 case OR16 + 0:
12838 case OR16 + 1:
12839 case OR16 + 2:
12840 case OR16 + 3:
12841 gen_logic(ctx, OPC_OR, rd, rd, rs);
12842 break;
12843 case LWM16 + 0:
12844 case LWM16 + 1:
12845 case LWM16 + 2:
12846 case LWM16 + 3:
12848 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
12849 int offset = ZIMM(ctx->opcode, 0, 4);
12851 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
12852 29, offset << 2);
12854 break;
12855 case SWM16 + 0:
12856 case SWM16 + 1:
12857 case SWM16 + 2:
12858 case SWM16 + 3:
12860 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
12861 int offset = ZIMM(ctx->opcode, 0, 4);
12863 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
12864 29, offset << 2);
12866 break;
12867 case JR16 + 0:
12868 case JR16 + 1:
12870 int reg = ctx->opcode & 0x1f;
12872 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
12874 break;
12875 case JRC16 + 0:
12876 case JRC16 + 1:
12878 int reg = ctx->opcode & 0x1f;
12879 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
12880 /* Let normal delay slot handling in our caller take us
12881 to the branch target. */
12883 break;
12884 case JALR16 + 0:
12885 case JALR16 + 1:
12886 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
12887 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
12888 break;
12889 case JALR16S + 0:
12890 case JALR16S + 1:
12891 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
12892 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
12893 break;
12894 case MFHI16 + 0:
12895 case MFHI16 + 1:
12896 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
12897 break;
12898 case MFLO16 + 0:
12899 case MFLO16 + 1:
12900 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
12901 break;
12902 case BREAK16:
12903 generate_exception_end(ctx, EXCP_BREAK);
12904 break;
12905 case SDBBP16:
12906 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
12907 gen_helper_do_semihosting(cpu_env);
12908 } else {
12909 /* XXX: not clear which exception should be raised
12910 * when in debug mode...
12912 check_insn(ctx, ISA_MIPS32);
12913 generate_exception_end(ctx, EXCP_DBp);
12915 break;
12916 case JRADDIUSP + 0:
12917 case JRADDIUSP + 1:
12919 int imm = ZIMM(ctx->opcode, 0, 5);
12920 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
12921 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
12922 /* Let normal delay slot handling in our caller take us
12923 to the branch target. */
12925 break;
12926 default:
12927 generate_exception_end(ctx, EXCP_RI);
12928 break;
12932 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
12933 int enc_rs)
12935 int rd, rs, re, rt;
12936 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
12937 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
12938 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
12939 rd = rd_enc[enc_dest];
12940 re = re_enc[enc_dest];
12941 rs = rs_rt_enc[enc_rs];
12942 rt = rs_rt_enc[enc_rt];
12943 if (rs) {
12944 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
12945 } else {
12946 tcg_gen_movi_tl(cpu_gpr[rd], 0);
12948 if (rt) {
12949 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
12950 } else {
12951 tcg_gen_movi_tl(cpu_gpr[re], 0);
12955 static void gen_pool16c_r6_insn(DisasContext *ctx)
12957 int rt = mmreg((ctx->opcode >> 7) & 0x7);
12958 int rs = mmreg((ctx->opcode >> 4) & 0x7);
12960 switch (ctx->opcode & 0xf) {
12961 case R6_NOT16:
12962 gen_logic(ctx, OPC_NOR, rt, rs, 0);
12963 break;
12964 case R6_AND16:
12965 gen_logic(ctx, OPC_AND, rt, rt, rs);
12966 break;
12967 case R6_LWM16:
12969 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
12970 int offset = extract32(ctx->opcode, 4, 4);
12971 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
12973 break;
12974 case R6_JRC16: /* JRCADDIUSP */
12975 if ((ctx->opcode >> 4) & 1) {
12976 /* JRCADDIUSP */
12977 int imm = extract32(ctx->opcode, 5, 5);
12978 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
12979 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
12980 } else {
12981 /* JRC16 */
12982 int rs = extract32(ctx->opcode, 5, 5);
12983 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
12985 break;
12986 case MOVEP ... MOVEP_07:
12987 case MOVEP_0C ... MOVEP_0F:
12989 int enc_dest = uMIPS_RD(ctx->opcode);
12990 int enc_rt = uMIPS_RS2(ctx->opcode);
12991 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
12992 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
12994 break;
12995 case R6_XOR16:
12996 gen_logic(ctx, OPC_XOR, rt, rt, rs);
12997 break;
12998 case R6_OR16:
12999 gen_logic(ctx, OPC_OR, rt, rt, rs);
13000 break;
13001 case R6_SWM16:
13003 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
13004 int offset = extract32(ctx->opcode, 4, 4);
13005 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
13007 break;
13008 case JALRC16: /* BREAK16, SDBBP16 */
13009 switch (ctx->opcode & 0x3f) {
13010 case JALRC16:
13011 case JALRC16 + 0x20:
13012 /* JALRC16 */
13013 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
13014 31, 0, 0);
13015 break;
13016 case R6_BREAK16:
13017 /* BREAK16 */
13018 generate_exception(ctx, EXCP_BREAK);
13019 break;
13020 case R6_SDBBP16:
13021 /* SDBBP16 */
13022 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
13023 gen_helper_do_semihosting(cpu_env);
13024 } else {
13025 if (ctx->hflags & MIPS_HFLAG_SBRI) {
13026 generate_exception(ctx, EXCP_RI);
13027 } else {
13028 generate_exception(ctx, EXCP_DBp);
13031 break;
13033 break;
13034 default:
13035 generate_exception(ctx, EXCP_RI);
13036 break;
13040 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
13042 TCGv t0 = tcg_temp_new();
13043 TCGv t1 = tcg_temp_new();
13045 gen_load_gpr(t0, base);
13047 if (index != 0) {
13048 gen_load_gpr(t1, index);
13049 tcg_gen_shli_tl(t1, t1, 2);
13050 gen_op_addr_add(ctx, t0, t1, t0);
13053 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
13054 gen_store_gpr(t1, rd);
13056 tcg_temp_free(t0);
13057 tcg_temp_free(t1);
13060 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
13061 int base, int16_t offset)
13063 TCGv t0, t1;
13065 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
13066 generate_exception_end(ctx, EXCP_RI);
13067 return;
13070 t0 = tcg_temp_new();
13071 t1 = tcg_temp_new();
13073 gen_base_offset_addr(ctx, t0, base, offset);
13075 switch (opc) {
13076 case LWP:
13077 if (rd == base) {
13078 generate_exception_end(ctx, EXCP_RI);
13079 return;
13081 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
13082 gen_store_gpr(t1, rd);
13083 tcg_gen_movi_tl(t1, 4);
13084 gen_op_addr_add(ctx, t0, t0, t1);
13085 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
13086 gen_store_gpr(t1, rd+1);
13087 break;
13088 case SWP:
13089 gen_load_gpr(t1, rd);
13090 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13091 tcg_gen_movi_tl(t1, 4);
13092 gen_op_addr_add(ctx, t0, t0, t1);
13093 gen_load_gpr(t1, rd+1);
13094 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13095 break;
13096 #ifdef TARGET_MIPS64
13097 case LDP:
13098 if (rd == base) {
13099 generate_exception_end(ctx, EXCP_RI);
13100 return;
13102 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13103 gen_store_gpr(t1, rd);
13104 tcg_gen_movi_tl(t1, 8);
13105 gen_op_addr_add(ctx, t0, t0, t1);
13106 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13107 gen_store_gpr(t1, rd+1);
13108 break;
13109 case SDP:
13110 gen_load_gpr(t1, rd);
13111 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13112 tcg_gen_movi_tl(t1, 8);
13113 gen_op_addr_add(ctx, t0, t0, t1);
13114 gen_load_gpr(t1, rd+1);
13115 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13116 break;
13117 #endif
13119 tcg_temp_free(t0);
13120 tcg_temp_free(t1);
13123 static void gen_sync(int stype)
13125 TCGBar tcg_mo = TCG_BAR_SC;
13127 switch (stype) {
13128 case 0x4: /* SYNC_WMB */
13129 tcg_mo |= TCG_MO_ST_ST;
13130 break;
13131 case 0x10: /* SYNC_MB */
13132 tcg_mo |= TCG_MO_ALL;
13133 break;
13134 case 0x11: /* SYNC_ACQUIRE */
13135 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
13136 break;
13137 case 0x12: /* SYNC_RELEASE */
13138 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
13139 break;
13140 case 0x13: /* SYNC_RMB */
13141 tcg_mo |= TCG_MO_LD_LD;
13142 break;
13143 default:
13144 tcg_mo |= TCG_MO_ALL;
13145 break;
13148 tcg_gen_mb(tcg_mo);
13151 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
13153 int extension = (ctx->opcode >> 6) & 0x3f;
13154 int minor = (ctx->opcode >> 12) & 0xf;
13155 uint32_t mips32_op;
13157 switch (extension) {
13158 case TEQ:
13159 mips32_op = OPC_TEQ;
13160 goto do_trap;
13161 case TGE:
13162 mips32_op = OPC_TGE;
13163 goto do_trap;
13164 case TGEU:
13165 mips32_op = OPC_TGEU;
13166 goto do_trap;
13167 case TLT:
13168 mips32_op = OPC_TLT;
13169 goto do_trap;
13170 case TLTU:
13171 mips32_op = OPC_TLTU;
13172 goto do_trap;
13173 case TNE:
13174 mips32_op = OPC_TNE;
13175 do_trap:
13176 gen_trap(ctx, mips32_op, rs, rt, -1);
13177 break;
13178 #ifndef CONFIG_USER_ONLY
13179 case MFC0:
13180 case MFC0 + 32:
13181 check_cp0_enabled(ctx);
13182 if (rt == 0) {
13183 /* Treat as NOP. */
13184 break;
13186 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
13187 break;
13188 case MTC0:
13189 case MTC0 + 32:
13190 check_cp0_enabled(ctx);
13192 TCGv t0 = tcg_temp_new();
13194 gen_load_gpr(t0, rt);
13195 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
13196 tcg_temp_free(t0);
13198 break;
13199 #endif
13200 case 0x2a:
13201 switch (minor & 3) {
13202 case MADD_ACC:
13203 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
13204 break;
13205 case MADDU_ACC:
13206 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
13207 break;
13208 case MSUB_ACC:
13209 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
13210 break;
13211 case MSUBU_ACC:
13212 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
13213 break;
13214 default:
13215 goto pool32axf_invalid;
13217 break;
13218 case 0x32:
13219 switch (minor & 3) {
13220 case MULT_ACC:
13221 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
13222 break;
13223 case MULTU_ACC:
13224 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
13225 break;
13226 default:
13227 goto pool32axf_invalid;
13229 break;
13230 case 0x2c:
13231 switch (minor) {
13232 case BITSWAP:
13233 check_insn(ctx, ISA_MIPS32R6);
13234 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
13235 break;
13236 case SEB:
13237 gen_bshfl(ctx, OPC_SEB, rs, rt);
13238 break;
13239 case SEH:
13240 gen_bshfl(ctx, OPC_SEH, rs, rt);
13241 break;
13242 case CLO:
13243 mips32_op = OPC_CLO;
13244 goto do_cl;
13245 case CLZ:
13246 mips32_op = OPC_CLZ;
13247 do_cl:
13248 check_insn(ctx, ISA_MIPS32);
13249 gen_cl(ctx, mips32_op, rt, rs);
13250 break;
13251 case RDHWR:
13252 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13253 gen_rdhwr(ctx, rt, rs, 0);
13254 break;
13255 case WSBH:
13256 gen_bshfl(ctx, OPC_WSBH, rs, rt);
13257 break;
13258 case MULT:
13259 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13260 mips32_op = OPC_MULT;
13261 goto do_mul;
13262 case MULTU:
13263 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13264 mips32_op = OPC_MULTU;
13265 goto do_mul;
13266 case DIV:
13267 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13268 mips32_op = OPC_DIV;
13269 goto do_div;
13270 case DIVU:
13271 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13272 mips32_op = OPC_DIVU;
13273 goto do_div;
13274 do_div:
13275 check_insn(ctx, ISA_MIPS32);
13276 gen_muldiv(ctx, mips32_op, 0, rs, rt);
13277 break;
13278 case MADD:
13279 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13280 mips32_op = OPC_MADD;
13281 goto do_mul;
13282 case MADDU:
13283 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13284 mips32_op = OPC_MADDU;
13285 goto do_mul;
13286 case MSUB:
13287 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13288 mips32_op = OPC_MSUB;
13289 goto do_mul;
13290 case MSUBU:
13291 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13292 mips32_op = OPC_MSUBU;
13293 do_mul:
13294 check_insn(ctx, ISA_MIPS32);
13295 gen_muldiv(ctx, mips32_op, 0, rs, rt);
13296 break;
13297 default:
13298 goto pool32axf_invalid;
13300 break;
13301 case 0x34:
13302 switch (minor) {
13303 case MFC2:
13304 case MTC2:
13305 case MFHC2:
13306 case MTHC2:
13307 case CFC2:
13308 case CTC2:
13309 generate_exception_err(ctx, EXCP_CpU, 2);
13310 break;
13311 default:
13312 goto pool32axf_invalid;
13314 break;
13315 case 0x3c:
13316 switch (minor) {
13317 case JALR: /* JALRC */
13318 case JALR_HB: /* JALRC_HB */
13319 if (ctx->insn_flags & ISA_MIPS32R6) {
13320 /* JALRC, JALRC_HB */
13321 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
13322 } else {
13323 /* JALR, JALR_HB */
13324 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
13325 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13327 break;
13328 case JALRS:
13329 case JALRS_HB:
13330 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13331 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
13332 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13333 break;
13334 default:
13335 goto pool32axf_invalid;
13337 break;
13338 case 0x05:
13339 switch (minor) {
13340 case RDPGPR:
13341 check_cp0_enabled(ctx);
13342 check_insn(ctx, ISA_MIPS32R2);
13343 gen_load_srsgpr(rs, rt);
13344 break;
13345 case WRPGPR:
13346 check_cp0_enabled(ctx);
13347 check_insn(ctx, ISA_MIPS32R2);
13348 gen_store_srsgpr(rs, rt);
13349 break;
13350 default:
13351 goto pool32axf_invalid;
13353 break;
13354 #ifndef CONFIG_USER_ONLY
13355 case 0x0d:
13356 switch (minor) {
13357 case TLBP:
13358 mips32_op = OPC_TLBP;
13359 goto do_cp0;
13360 case TLBR:
13361 mips32_op = OPC_TLBR;
13362 goto do_cp0;
13363 case TLBWI:
13364 mips32_op = OPC_TLBWI;
13365 goto do_cp0;
13366 case TLBWR:
13367 mips32_op = OPC_TLBWR;
13368 goto do_cp0;
13369 case TLBINV:
13370 mips32_op = OPC_TLBINV;
13371 goto do_cp0;
13372 case TLBINVF:
13373 mips32_op = OPC_TLBINVF;
13374 goto do_cp0;
13375 case WAIT:
13376 mips32_op = OPC_WAIT;
13377 goto do_cp0;
13378 case DERET:
13379 mips32_op = OPC_DERET;
13380 goto do_cp0;
13381 case ERET:
13382 mips32_op = OPC_ERET;
13383 do_cp0:
13384 gen_cp0(env, ctx, mips32_op, rt, rs);
13385 break;
13386 default:
13387 goto pool32axf_invalid;
13389 break;
13390 case 0x1d:
13391 switch (minor) {
13392 case DI:
13393 check_cp0_enabled(ctx);
13395 TCGv t0 = tcg_temp_new();
13397 save_cpu_state(ctx, 1);
13398 gen_helper_di(t0, cpu_env);
13399 gen_store_gpr(t0, rs);
13400 /* Stop translation as we may have switched the execution mode */
13401 ctx->bstate = BS_STOP;
13402 tcg_temp_free(t0);
13404 break;
13405 case EI:
13406 check_cp0_enabled(ctx);
13408 TCGv t0 = tcg_temp_new();
13410 save_cpu_state(ctx, 1);
13411 gen_helper_ei(t0, cpu_env);
13412 gen_store_gpr(t0, rs);
13413 /* Stop translation as we may have switched the execution mode */
13414 ctx->bstate = BS_STOP;
13415 tcg_temp_free(t0);
13417 break;
13418 default:
13419 goto pool32axf_invalid;
13421 break;
13422 #endif
13423 case 0x2d:
13424 switch (minor) {
13425 case SYNC:
13426 gen_sync(extract32(ctx->opcode, 16, 5));
13427 break;
13428 case SYSCALL:
13429 generate_exception_end(ctx, EXCP_SYSCALL);
13430 break;
13431 case SDBBP:
13432 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
13433 gen_helper_do_semihosting(cpu_env);
13434 } else {
13435 check_insn(ctx, ISA_MIPS32);
13436 if (ctx->hflags & MIPS_HFLAG_SBRI) {
13437 generate_exception_end(ctx, EXCP_RI);
13438 } else {
13439 generate_exception_end(ctx, EXCP_DBp);
13442 break;
13443 default:
13444 goto pool32axf_invalid;
13446 break;
13447 case 0x01:
13448 switch (minor & 3) {
13449 case MFHI_ACC:
13450 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
13451 break;
13452 case MFLO_ACC:
13453 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
13454 break;
13455 case MTHI_ACC:
13456 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
13457 break;
13458 case MTLO_ACC:
13459 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
13460 break;
13461 default:
13462 goto pool32axf_invalid;
13464 break;
13465 case 0x35:
13466 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13467 switch (minor) {
13468 case MFHI32:
13469 gen_HILO(ctx, OPC_MFHI, 0, rs);
13470 break;
13471 case MFLO32:
13472 gen_HILO(ctx, OPC_MFLO, 0, rs);
13473 break;
13474 case MTHI32:
13475 gen_HILO(ctx, OPC_MTHI, 0, rs);
13476 break;
13477 case MTLO32:
13478 gen_HILO(ctx, OPC_MTLO, 0, rs);
13479 break;
13480 default:
13481 goto pool32axf_invalid;
13483 break;
13484 default:
13485 pool32axf_invalid:
13486 MIPS_INVAL("pool32axf");
13487 generate_exception_end(ctx, EXCP_RI);
13488 break;
13492 /* Values for microMIPS fmt field. Variable-width, depending on which
13493 formats the instruction supports. */
13495 enum {
13496 FMT_SD_S = 0,
13497 FMT_SD_D = 1,
13499 FMT_SDPS_S = 0,
13500 FMT_SDPS_D = 1,
13501 FMT_SDPS_PS = 2,
13503 FMT_SWL_S = 0,
13504 FMT_SWL_W = 1,
13505 FMT_SWL_L = 2,
13507 FMT_DWL_D = 0,
13508 FMT_DWL_W = 1,
13509 FMT_DWL_L = 2
13512 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
13514 int extension = (ctx->opcode >> 6) & 0x3ff;
13515 uint32_t mips32_op;
13517 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
13518 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
13519 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
13521 switch (extension) {
13522 case FLOAT_1BIT_FMT(CFC1, 0):
13523 mips32_op = OPC_CFC1;
13524 goto do_cp1;
13525 case FLOAT_1BIT_FMT(CTC1, 0):
13526 mips32_op = OPC_CTC1;
13527 goto do_cp1;
13528 case FLOAT_1BIT_FMT(MFC1, 0):
13529 mips32_op = OPC_MFC1;
13530 goto do_cp1;
13531 case FLOAT_1BIT_FMT(MTC1, 0):
13532 mips32_op = OPC_MTC1;
13533 goto do_cp1;
13534 case FLOAT_1BIT_FMT(MFHC1, 0):
13535 mips32_op = OPC_MFHC1;
13536 goto do_cp1;
13537 case FLOAT_1BIT_FMT(MTHC1, 0):
13538 mips32_op = OPC_MTHC1;
13539 do_cp1:
13540 gen_cp1(ctx, mips32_op, rt, rs);
13541 break;
13543 /* Reciprocal square root */
13544 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
13545 mips32_op = OPC_RSQRT_S;
13546 goto do_unaryfp;
13547 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
13548 mips32_op = OPC_RSQRT_D;
13549 goto do_unaryfp;
13551 /* Square root */
13552 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
13553 mips32_op = OPC_SQRT_S;
13554 goto do_unaryfp;
13555 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
13556 mips32_op = OPC_SQRT_D;
13557 goto do_unaryfp;
13559 /* Reciprocal */
13560 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
13561 mips32_op = OPC_RECIP_S;
13562 goto do_unaryfp;
13563 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
13564 mips32_op = OPC_RECIP_D;
13565 goto do_unaryfp;
13567 /* Floor */
13568 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
13569 mips32_op = OPC_FLOOR_L_S;
13570 goto do_unaryfp;
13571 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
13572 mips32_op = OPC_FLOOR_L_D;
13573 goto do_unaryfp;
13574 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
13575 mips32_op = OPC_FLOOR_W_S;
13576 goto do_unaryfp;
13577 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
13578 mips32_op = OPC_FLOOR_W_D;
13579 goto do_unaryfp;
13581 /* Ceiling */
13582 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
13583 mips32_op = OPC_CEIL_L_S;
13584 goto do_unaryfp;
13585 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
13586 mips32_op = OPC_CEIL_L_D;
13587 goto do_unaryfp;
13588 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
13589 mips32_op = OPC_CEIL_W_S;
13590 goto do_unaryfp;
13591 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
13592 mips32_op = OPC_CEIL_W_D;
13593 goto do_unaryfp;
13595 /* Truncation */
13596 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
13597 mips32_op = OPC_TRUNC_L_S;
13598 goto do_unaryfp;
13599 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
13600 mips32_op = OPC_TRUNC_L_D;
13601 goto do_unaryfp;
13602 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
13603 mips32_op = OPC_TRUNC_W_S;
13604 goto do_unaryfp;
13605 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
13606 mips32_op = OPC_TRUNC_W_D;
13607 goto do_unaryfp;
13609 /* Round */
13610 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
13611 mips32_op = OPC_ROUND_L_S;
13612 goto do_unaryfp;
13613 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
13614 mips32_op = OPC_ROUND_L_D;
13615 goto do_unaryfp;
13616 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
13617 mips32_op = OPC_ROUND_W_S;
13618 goto do_unaryfp;
13619 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
13620 mips32_op = OPC_ROUND_W_D;
13621 goto do_unaryfp;
13623 /* Integer to floating-point conversion */
13624 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
13625 mips32_op = OPC_CVT_L_S;
13626 goto do_unaryfp;
13627 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
13628 mips32_op = OPC_CVT_L_D;
13629 goto do_unaryfp;
13630 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
13631 mips32_op = OPC_CVT_W_S;
13632 goto do_unaryfp;
13633 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
13634 mips32_op = OPC_CVT_W_D;
13635 goto do_unaryfp;
13637 /* Paired-foo conversions */
13638 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
13639 mips32_op = OPC_CVT_S_PL;
13640 goto do_unaryfp;
13641 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
13642 mips32_op = OPC_CVT_S_PU;
13643 goto do_unaryfp;
13644 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
13645 mips32_op = OPC_CVT_PW_PS;
13646 goto do_unaryfp;
13647 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
13648 mips32_op = OPC_CVT_PS_PW;
13649 goto do_unaryfp;
13651 /* Floating-point moves */
13652 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
13653 mips32_op = OPC_MOV_S;
13654 goto do_unaryfp;
13655 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
13656 mips32_op = OPC_MOV_D;
13657 goto do_unaryfp;
13658 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
13659 mips32_op = OPC_MOV_PS;
13660 goto do_unaryfp;
13662 /* Absolute value */
13663 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
13664 mips32_op = OPC_ABS_S;
13665 goto do_unaryfp;
13666 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
13667 mips32_op = OPC_ABS_D;
13668 goto do_unaryfp;
13669 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
13670 mips32_op = OPC_ABS_PS;
13671 goto do_unaryfp;
13673 /* Negation */
13674 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
13675 mips32_op = OPC_NEG_S;
13676 goto do_unaryfp;
13677 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
13678 mips32_op = OPC_NEG_D;
13679 goto do_unaryfp;
13680 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
13681 mips32_op = OPC_NEG_PS;
13682 goto do_unaryfp;
13684 /* Reciprocal square root step */
13685 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
13686 mips32_op = OPC_RSQRT1_S;
13687 goto do_unaryfp;
13688 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
13689 mips32_op = OPC_RSQRT1_D;
13690 goto do_unaryfp;
13691 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
13692 mips32_op = OPC_RSQRT1_PS;
13693 goto do_unaryfp;
13695 /* Reciprocal step */
13696 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
13697 mips32_op = OPC_RECIP1_S;
13698 goto do_unaryfp;
13699 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
13700 mips32_op = OPC_RECIP1_S;
13701 goto do_unaryfp;
13702 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
13703 mips32_op = OPC_RECIP1_PS;
13704 goto do_unaryfp;
13706 /* Conversions from double */
13707 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
13708 mips32_op = OPC_CVT_D_S;
13709 goto do_unaryfp;
13710 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
13711 mips32_op = OPC_CVT_D_W;
13712 goto do_unaryfp;
13713 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
13714 mips32_op = OPC_CVT_D_L;
13715 goto do_unaryfp;
13717 /* Conversions from single */
13718 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
13719 mips32_op = OPC_CVT_S_D;
13720 goto do_unaryfp;
13721 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
13722 mips32_op = OPC_CVT_S_W;
13723 goto do_unaryfp;
13724 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
13725 mips32_op = OPC_CVT_S_L;
13726 do_unaryfp:
13727 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
13728 break;
13730 /* Conditional moves on floating-point codes */
13731 case COND_FLOAT_MOV(MOVT, 0):
13732 case COND_FLOAT_MOV(MOVT, 1):
13733 case COND_FLOAT_MOV(MOVT, 2):
13734 case COND_FLOAT_MOV(MOVT, 3):
13735 case COND_FLOAT_MOV(MOVT, 4):
13736 case COND_FLOAT_MOV(MOVT, 5):
13737 case COND_FLOAT_MOV(MOVT, 6):
13738 case COND_FLOAT_MOV(MOVT, 7):
13739 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13740 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
13741 break;
13742 case COND_FLOAT_MOV(MOVF, 0):
13743 case COND_FLOAT_MOV(MOVF, 1):
13744 case COND_FLOAT_MOV(MOVF, 2):
13745 case COND_FLOAT_MOV(MOVF, 3):
13746 case COND_FLOAT_MOV(MOVF, 4):
13747 case COND_FLOAT_MOV(MOVF, 5):
13748 case COND_FLOAT_MOV(MOVF, 6):
13749 case COND_FLOAT_MOV(MOVF, 7):
13750 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13751 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
13752 break;
13753 default:
13754 MIPS_INVAL("pool32fxf");
13755 generate_exception_end(ctx, EXCP_RI);
13756 break;
13760 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
13762 int32_t offset;
13763 uint16_t insn;
13764 int rt, rs, rd, rr;
13765 int16_t imm;
13766 uint32_t op, minor, mips32_op;
13767 uint32_t cond, fmt, cc;
13769 insn = cpu_lduw_code(env, ctx->pc + 2);
13770 ctx->opcode = (ctx->opcode << 16) | insn;
13772 rt = (ctx->opcode >> 21) & 0x1f;
13773 rs = (ctx->opcode >> 16) & 0x1f;
13774 rd = (ctx->opcode >> 11) & 0x1f;
13775 rr = (ctx->opcode >> 6) & 0x1f;
13776 imm = (int16_t) ctx->opcode;
13778 op = (ctx->opcode >> 26) & 0x3f;
13779 switch (op) {
13780 case POOL32A:
13781 minor = ctx->opcode & 0x3f;
13782 switch (minor) {
13783 case 0x00:
13784 minor = (ctx->opcode >> 6) & 0xf;
13785 switch (minor) {
13786 case SLL32:
13787 mips32_op = OPC_SLL;
13788 goto do_shifti;
13789 case SRA:
13790 mips32_op = OPC_SRA;
13791 goto do_shifti;
13792 case SRL32:
13793 mips32_op = OPC_SRL;
13794 goto do_shifti;
13795 case ROTR:
13796 mips32_op = OPC_ROTR;
13797 do_shifti:
13798 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
13799 break;
13800 case SELEQZ:
13801 check_insn(ctx, ISA_MIPS32R6);
13802 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
13803 break;
13804 case SELNEZ:
13805 check_insn(ctx, ISA_MIPS32R6);
13806 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
13807 break;
13808 case R6_RDHWR:
13809 check_insn(ctx, ISA_MIPS32R6);
13810 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
13811 break;
13812 default:
13813 goto pool32a_invalid;
13815 break;
13816 case 0x10:
13817 minor = (ctx->opcode >> 6) & 0xf;
13818 switch (minor) {
13819 /* Arithmetic */
13820 case ADD:
13821 mips32_op = OPC_ADD;
13822 goto do_arith;
13823 case ADDU32:
13824 mips32_op = OPC_ADDU;
13825 goto do_arith;
13826 case SUB:
13827 mips32_op = OPC_SUB;
13828 goto do_arith;
13829 case SUBU32:
13830 mips32_op = OPC_SUBU;
13831 goto do_arith;
13832 case MUL:
13833 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13834 mips32_op = OPC_MUL;
13835 do_arith:
13836 gen_arith(ctx, mips32_op, rd, rs, rt);
13837 break;
13838 /* Shifts */
13839 case SLLV:
13840 mips32_op = OPC_SLLV;
13841 goto do_shift;
13842 case SRLV:
13843 mips32_op = OPC_SRLV;
13844 goto do_shift;
13845 case SRAV:
13846 mips32_op = OPC_SRAV;
13847 goto do_shift;
13848 case ROTRV:
13849 mips32_op = OPC_ROTRV;
13850 do_shift:
13851 gen_shift(ctx, mips32_op, rd, rs, rt);
13852 break;
13853 /* Logical operations */
13854 case AND:
13855 mips32_op = OPC_AND;
13856 goto do_logic;
13857 case OR32:
13858 mips32_op = OPC_OR;
13859 goto do_logic;
13860 case NOR:
13861 mips32_op = OPC_NOR;
13862 goto do_logic;
13863 case XOR32:
13864 mips32_op = OPC_XOR;
13865 do_logic:
13866 gen_logic(ctx, mips32_op, rd, rs, rt);
13867 break;
13868 /* Set less than */
13869 case SLT:
13870 mips32_op = OPC_SLT;
13871 goto do_slt;
13872 case SLTU:
13873 mips32_op = OPC_SLTU;
13874 do_slt:
13875 gen_slt(ctx, mips32_op, rd, rs, rt);
13876 break;
13877 default:
13878 goto pool32a_invalid;
13880 break;
13881 case 0x18:
13882 minor = (ctx->opcode >> 6) & 0xf;
13883 switch (minor) {
13884 /* Conditional moves */
13885 case MOVN: /* MUL */
13886 if (ctx->insn_flags & ISA_MIPS32R6) {
13887 /* MUL */
13888 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
13889 } else {
13890 /* MOVN */
13891 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
13893 break;
13894 case MOVZ: /* MUH */
13895 if (ctx->insn_flags & ISA_MIPS32R6) {
13896 /* MUH */
13897 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
13898 } else {
13899 /* MOVZ */
13900 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
13902 break;
13903 case MULU:
13904 check_insn(ctx, ISA_MIPS32R6);
13905 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
13906 break;
13907 case MUHU:
13908 check_insn(ctx, ISA_MIPS32R6);
13909 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
13910 break;
13911 case LWXS: /* DIV */
13912 if (ctx->insn_flags & ISA_MIPS32R6) {
13913 /* DIV */
13914 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
13915 } else {
13916 /* LWXS */
13917 gen_ldxs(ctx, rs, rt, rd);
13919 break;
13920 case MOD:
13921 check_insn(ctx, ISA_MIPS32R6);
13922 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
13923 break;
13924 case R6_DIVU:
13925 check_insn(ctx, ISA_MIPS32R6);
13926 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
13927 break;
13928 case MODU:
13929 check_insn(ctx, ISA_MIPS32R6);
13930 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
13931 break;
13932 default:
13933 goto pool32a_invalid;
13935 break;
13936 case INS:
13937 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
13938 return;
13939 case LSA:
13940 check_insn(ctx, ISA_MIPS32R6);
13941 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
13942 extract32(ctx->opcode, 9, 2));
13943 break;
13944 case ALIGN:
13945 check_insn(ctx, ISA_MIPS32R6);
13946 gen_align(ctx, OPC_ALIGN, rd, rs, rt,
13947 extract32(ctx->opcode, 9, 2));
13948 break;
13949 case EXT:
13950 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
13951 return;
13952 case POOL32AXF:
13953 gen_pool32axf(env, ctx, rt, rs);
13954 break;
13955 case BREAK32:
13956 generate_exception_end(ctx, EXCP_BREAK);
13957 break;
13958 case SIGRIE:
13959 check_insn(ctx, ISA_MIPS32R6);
13960 generate_exception_end(ctx, EXCP_RI);
13961 break;
13962 default:
13963 pool32a_invalid:
13964 MIPS_INVAL("pool32a");
13965 generate_exception_end(ctx, EXCP_RI);
13966 break;
13968 break;
13969 case POOL32B:
13970 minor = (ctx->opcode >> 12) & 0xf;
13971 switch (minor) {
13972 case CACHE:
13973 check_cp0_enabled(ctx);
13974 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
13975 gen_cache_operation(ctx, rt, rs, imm);
13977 break;
13978 case LWC2:
13979 case SWC2:
13980 /* COP2: Not implemented. */
13981 generate_exception_err(ctx, EXCP_CpU, 2);
13982 break;
13983 #ifdef TARGET_MIPS64
13984 case LDP:
13985 case SDP:
13986 check_insn(ctx, ISA_MIPS3);
13987 check_mips_64(ctx);
13988 /* Fallthrough */
13989 #endif
13990 case LWP:
13991 case SWP:
13992 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
13993 break;
13994 #ifdef TARGET_MIPS64
13995 case LDM:
13996 case SDM:
13997 check_insn(ctx, ISA_MIPS3);
13998 check_mips_64(ctx);
13999 /* Fallthrough */
14000 #endif
14001 case LWM32:
14002 case SWM32:
14003 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
14004 break;
14005 default:
14006 MIPS_INVAL("pool32b");
14007 generate_exception_end(ctx, EXCP_RI);
14008 break;
14010 break;
14011 case POOL32F:
14012 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
14013 minor = ctx->opcode & 0x3f;
14014 check_cp1_enabled(ctx);
14015 switch (minor) {
14016 case ALNV_PS:
14017 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14018 mips32_op = OPC_ALNV_PS;
14019 goto do_madd;
14020 case MADD_S:
14021 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14022 mips32_op = OPC_MADD_S;
14023 goto do_madd;
14024 case MADD_D:
14025 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14026 mips32_op = OPC_MADD_D;
14027 goto do_madd;
14028 case MADD_PS:
14029 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14030 mips32_op = OPC_MADD_PS;
14031 goto do_madd;
14032 case MSUB_S:
14033 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14034 mips32_op = OPC_MSUB_S;
14035 goto do_madd;
14036 case MSUB_D:
14037 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14038 mips32_op = OPC_MSUB_D;
14039 goto do_madd;
14040 case MSUB_PS:
14041 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14042 mips32_op = OPC_MSUB_PS;
14043 goto do_madd;
14044 case NMADD_S:
14045 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14046 mips32_op = OPC_NMADD_S;
14047 goto do_madd;
14048 case NMADD_D:
14049 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14050 mips32_op = OPC_NMADD_D;
14051 goto do_madd;
14052 case NMADD_PS:
14053 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14054 mips32_op = OPC_NMADD_PS;
14055 goto do_madd;
14056 case NMSUB_S:
14057 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14058 mips32_op = OPC_NMSUB_S;
14059 goto do_madd;
14060 case NMSUB_D:
14061 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14062 mips32_op = OPC_NMSUB_D;
14063 goto do_madd;
14064 case NMSUB_PS:
14065 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14066 mips32_op = OPC_NMSUB_PS;
14067 do_madd:
14068 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
14069 break;
14070 case CABS_COND_FMT:
14071 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14072 cond = (ctx->opcode >> 6) & 0xf;
14073 cc = (ctx->opcode >> 13) & 0x7;
14074 fmt = (ctx->opcode >> 10) & 0x3;
14075 switch (fmt) {
14076 case 0x0:
14077 gen_cmpabs_s(ctx, cond, rt, rs, cc);
14078 break;
14079 case 0x1:
14080 gen_cmpabs_d(ctx, cond, rt, rs, cc);
14081 break;
14082 case 0x2:
14083 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
14084 break;
14085 default:
14086 goto pool32f_invalid;
14088 break;
14089 case C_COND_FMT:
14090 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14091 cond = (ctx->opcode >> 6) & 0xf;
14092 cc = (ctx->opcode >> 13) & 0x7;
14093 fmt = (ctx->opcode >> 10) & 0x3;
14094 switch (fmt) {
14095 case 0x0:
14096 gen_cmp_s(ctx, cond, rt, rs, cc);
14097 break;
14098 case 0x1:
14099 gen_cmp_d(ctx, cond, rt, rs, cc);
14100 break;
14101 case 0x2:
14102 gen_cmp_ps(ctx, cond, rt, rs, cc);
14103 break;
14104 default:
14105 goto pool32f_invalid;
14107 break;
14108 case CMP_CONDN_S:
14109 check_insn(ctx, ISA_MIPS32R6);
14110 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
14111 break;
14112 case CMP_CONDN_D:
14113 check_insn(ctx, ISA_MIPS32R6);
14114 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
14115 break;
14116 case POOL32FXF:
14117 gen_pool32fxf(ctx, rt, rs);
14118 break;
14119 case 0x00:
14120 /* PLL foo */
14121 switch ((ctx->opcode >> 6) & 0x7) {
14122 case PLL_PS:
14123 mips32_op = OPC_PLL_PS;
14124 goto do_ps;
14125 case PLU_PS:
14126 mips32_op = OPC_PLU_PS;
14127 goto do_ps;
14128 case PUL_PS:
14129 mips32_op = OPC_PUL_PS;
14130 goto do_ps;
14131 case PUU_PS:
14132 mips32_op = OPC_PUU_PS;
14133 goto do_ps;
14134 case CVT_PS_S:
14135 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14136 mips32_op = OPC_CVT_PS_S;
14137 do_ps:
14138 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14139 break;
14140 default:
14141 goto pool32f_invalid;
14143 break;
14144 case MIN_FMT:
14145 check_insn(ctx, ISA_MIPS32R6);
14146 switch ((ctx->opcode >> 9) & 0x3) {
14147 case FMT_SDPS_S:
14148 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
14149 break;
14150 case FMT_SDPS_D:
14151 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
14152 break;
14153 default:
14154 goto pool32f_invalid;
14156 break;
14157 case 0x08:
14158 /* [LS][WDU]XC1 */
14159 switch ((ctx->opcode >> 6) & 0x7) {
14160 case LWXC1:
14161 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14162 mips32_op = OPC_LWXC1;
14163 goto do_ldst_cp1;
14164 case SWXC1:
14165 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14166 mips32_op = OPC_SWXC1;
14167 goto do_ldst_cp1;
14168 case LDXC1:
14169 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14170 mips32_op = OPC_LDXC1;
14171 goto do_ldst_cp1;
14172 case SDXC1:
14173 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14174 mips32_op = OPC_SDXC1;
14175 goto do_ldst_cp1;
14176 case LUXC1:
14177 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14178 mips32_op = OPC_LUXC1;
14179 goto do_ldst_cp1;
14180 case SUXC1:
14181 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14182 mips32_op = OPC_SUXC1;
14183 do_ldst_cp1:
14184 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
14185 break;
14186 default:
14187 goto pool32f_invalid;
14189 break;
14190 case MAX_FMT:
14191 check_insn(ctx, ISA_MIPS32R6);
14192 switch ((ctx->opcode >> 9) & 0x3) {
14193 case FMT_SDPS_S:
14194 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
14195 break;
14196 case FMT_SDPS_D:
14197 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
14198 break;
14199 default:
14200 goto pool32f_invalid;
14202 break;
14203 case 0x18:
14204 /* 3D insns */
14205 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14206 fmt = (ctx->opcode >> 9) & 0x3;
14207 switch ((ctx->opcode >> 6) & 0x7) {
14208 case RSQRT2_FMT:
14209 switch (fmt) {
14210 case FMT_SDPS_S:
14211 mips32_op = OPC_RSQRT2_S;
14212 goto do_3d;
14213 case FMT_SDPS_D:
14214 mips32_op = OPC_RSQRT2_D;
14215 goto do_3d;
14216 case FMT_SDPS_PS:
14217 mips32_op = OPC_RSQRT2_PS;
14218 goto do_3d;
14219 default:
14220 goto pool32f_invalid;
14222 break;
14223 case RECIP2_FMT:
14224 switch (fmt) {
14225 case FMT_SDPS_S:
14226 mips32_op = OPC_RECIP2_S;
14227 goto do_3d;
14228 case FMT_SDPS_D:
14229 mips32_op = OPC_RECIP2_D;
14230 goto do_3d;
14231 case FMT_SDPS_PS:
14232 mips32_op = OPC_RECIP2_PS;
14233 goto do_3d;
14234 default:
14235 goto pool32f_invalid;
14237 break;
14238 case ADDR_PS:
14239 mips32_op = OPC_ADDR_PS;
14240 goto do_3d;
14241 case MULR_PS:
14242 mips32_op = OPC_MULR_PS;
14243 do_3d:
14244 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14245 break;
14246 default:
14247 goto pool32f_invalid;
14249 break;
14250 case 0x20:
14251 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
14252 cc = (ctx->opcode >> 13) & 0x7;
14253 fmt = (ctx->opcode >> 9) & 0x3;
14254 switch ((ctx->opcode >> 6) & 0x7) {
14255 case MOVF_FMT: /* RINT_FMT */
14256 if (ctx->insn_flags & ISA_MIPS32R6) {
14257 /* RINT_FMT */
14258 switch (fmt) {
14259 case FMT_SDPS_S:
14260 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
14261 break;
14262 case FMT_SDPS_D:
14263 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
14264 break;
14265 default:
14266 goto pool32f_invalid;
14268 } else {
14269 /* MOVF_FMT */
14270 switch (fmt) {
14271 case FMT_SDPS_S:
14272 gen_movcf_s(ctx, rs, rt, cc, 0);
14273 break;
14274 case FMT_SDPS_D:
14275 gen_movcf_d(ctx, rs, rt, cc, 0);
14276 break;
14277 case FMT_SDPS_PS:
14278 check_ps(ctx);
14279 gen_movcf_ps(ctx, rs, rt, cc, 0);
14280 break;
14281 default:
14282 goto pool32f_invalid;
14285 break;
14286 case MOVT_FMT: /* CLASS_FMT */
14287 if (ctx->insn_flags & ISA_MIPS32R6) {
14288 /* CLASS_FMT */
14289 switch (fmt) {
14290 case FMT_SDPS_S:
14291 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
14292 break;
14293 case FMT_SDPS_D:
14294 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
14295 break;
14296 default:
14297 goto pool32f_invalid;
14299 } else {
14300 /* MOVT_FMT */
14301 switch (fmt) {
14302 case FMT_SDPS_S:
14303 gen_movcf_s(ctx, rs, rt, cc, 1);
14304 break;
14305 case FMT_SDPS_D:
14306 gen_movcf_d(ctx, rs, rt, cc, 1);
14307 break;
14308 case FMT_SDPS_PS:
14309 check_ps(ctx);
14310 gen_movcf_ps(ctx, rs, rt, cc, 1);
14311 break;
14312 default:
14313 goto pool32f_invalid;
14316 break;
14317 case PREFX:
14318 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14319 break;
14320 default:
14321 goto pool32f_invalid;
14323 break;
14324 #define FINSN_3ARG_SDPS(prfx) \
14325 switch ((ctx->opcode >> 8) & 0x3) { \
14326 case FMT_SDPS_S: \
14327 mips32_op = OPC_##prfx##_S; \
14328 goto do_fpop; \
14329 case FMT_SDPS_D: \
14330 mips32_op = OPC_##prfx##_D; \
14331 goto do_fpop; \
14332 case FMT_SDPS_PS: \
14333 check_ps(ctx); \
14334 mips32_op = OPC_##prfx##_PS; \
14335 goto do_fpop; \
14336 default: \
14337 goto pool32f_invalid; \
14339 case MINA_FMT:
14340 check_insn(ctx, ISA_MIPS32R6);
14341 switch ((ctx->opcode >> 9) & 0x3) {
14342 case FMT_SDPS_S:
14343 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
14344 break;
14345 case FMT_SDPS_D:
14346 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
14347 break;
14348 default:
14349 goto pool32f_invalid;
14351 break;
14352 case MAXA_FMT:
14353 check_insn(ctx, ISA_MIPS32R6);
14354 switch ((ctx->opcode >> 9) & 0x3) {
14355 case FMT_SDPS_S:
14356 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
14357 break;
14358 case FMT_SDPS_D:
14359 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
14360 break;
14361 default:
14362 goto pool32f_invalid;
14364 break;
14365 case 0x30:
14366 /* regular FP ops */
14367 switch ((ctx->opcode >> 6) & 0x3) {
14368 case ADD_FMT:
14369 FINSN_3ARG_SDPS(ADD);
14370 break;
14371 case SUB_FMT:
14372 FINSN_3ARG_SDPS(SUB);
14373 break;
14374 case MUL_FMT:
14375 FINSN_3ARG_SDPS(MUL);
14376 break;
14377 case DIV_FMT:
14378 fmt = (ctx->opcode >> 8) & 0x3;
14379 if (fmt == 1) {
14380 mips32_op = OPC_DIV_D;
14381 } else if (fmt == 0) {
14382 mips32_op = OPC_DIV_S;
14383 } else {
14384 goto pool32f_invalid;
14386 goto do_fpop;
14387 default:
14388 goto pool32f_invalid;
14390 break;
14391 case 0x38:
14392 /* cmovs */
14393 switch ((ctx->opcode >> 6) & 0x7) {
14394 case MOVN_FMT: /* SELNEZ_FMT */
14395 if (ctx->insn_flags & ISA_MIPS32R6) {
14396 /* SELNEZ_FMT */
14397 switch ((ctx->opcode >> 9) & 0x3) {
14398 case FMT_SDPS_S:
14399 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
14400 break;
14401 case FMT_SDPS_D:
14402 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
14403 break;
14404 default:
14405 goto pool32f_invalid;
14407 } else {
14408 /* MOVN_FMT */
14409 FINSN_3ARG_SDPS(MOVN);
14411 break;
14412 case MOVN_FMT_04:
14413 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14414 FINSN_3ARG_SDPS(MOVN);
14415 break;
14416 case MOVZ_FMT: /* SELEQZ_FMT */
14417 if (ctx->insn_flags & ISA_MIPS32R6) {
14418 /* SELEQZ_FMT */
14419 switch ((ctx->opcode >> 9) & 0x3) {
14420 case FMT_SDPS_S:
14421 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
14422 break;
14423 case FMT_SDPS_D:
14424 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
14425 break;
14426 default:
14427 goto pool32f_invalid;
14429 } else {
14430 /* MOVZ_FMT */
14431 FINSN_3ARG_SDPS(MOVZ);
14433 break;
14434 case MOVZ_FMT_05:
14435 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14436 FINSN_3ARG_SDPS(MOVZ);
14437 break;
14438 case SEL_FMT:
14439 check_insn(ctx, ISA_MIPS32R6);
14440 switch ((ctx->opcode >> 9) & 0x3) {
14441 case FMT_SDPS_S:
14442 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
14443 break;
14444 case FMT_SDPS_D:
14445 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
14446 break;
14447 default:
14448 goto pool32f_invalid;
14450 break;
14451 case MADDF_FMT:
14452 check_insn(ctx, ISA_MIPS32R6);
14453 switch ((ctx->opcode >> 9) & 0x3) {
14454 case FMT_SDPS_S:
14455 mips32_op = OPC_MADDF_S;
14456 goto do_fpop;
14457 case FMT_SDPS_D:
14458 mips32_op = OPC_MADDF_D;
14459 goto do_fpop;
14460 default:
14461 goto pool32f_invalid;
14463 break;
14464 case MSUBF_FMT:
14465 check_insn(ctx, ISA_MIPS32R6);
14466 switch ((ctx->opcode >> 9) & 0x3) {
14467 case FMT_SDPS_S:
14468 mips32_op = OPC_MSUBF_S;
14469 goto do_fpop;
14470 case FMT_SDPS_D:
14471 mips32_op = OPC_MSUBF_D;
14472 goto do_fpop;
14473 default:
14474 goto pool32f_invalid;
14476 break;
14477 default:
14478 goto pool32f_invalid;
14480 break;
14481 do_fpop:
14482 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14483 break;
14484 default:
14485 pool32f_invalid:
14486 MIPS_INVAL("pool32f");
14487 generate_exception_end(ctx, EXCP_RI);
14488 break;
14490 } else {
14491 generate_exception_err(ctx, EXCP_CpU, 1);
14493 break;
14494 case POOL32I:
14495 minor = (ctx->opcode >> 21) & 0x1f;
14496 switch (minor) {
14497 case BLTZ:
14498 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14499 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
14500 break;
14501 case BLTZAL:
14502 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14503 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
14504 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14505 break;
14506 case BLTZALS:
14507 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14508 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
14509 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14510 break;
14511 case BGEZ:
14512 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14513 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
14514 break;
14515 case BGEZAL:
14516 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14517 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
14518 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14519 break;
14520 case BGEZALS:
14521 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14522 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
14523 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14524 break;
14525 case BLEZ:
14526 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14527 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
14528 break;
14529 case BGTZ:
14530 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14531 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
14532 break;
14534 /* Traps */
14535 case TLTI: /* BC1EQZC */
14536 if (ctx->insn_flags & ISA_MIPS32R6) {
14537 /* BC1EQZC */
14538 check_cp1_enabled(ctx);
14539 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
14540 } else {
14541 /* TLTI */
14542 mips32_op = OPC_TLTI;
14543 goto do_trapi;
14545 break;
14546 case TGEI: /* BC1NEZC */
14547 if (ctx->insn_flags & ISA_MIPS32R6) {
14548 /* BC1NEZC */
14549 check_cp1_enabled(ctx);
14550 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
14551 } else {
14552 /* TGEI */
14553 mips32_op = OPC_TGEI;
14554 goto do_trapi;
14556 break;
14557 case TLTIU:
14558 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14559 mips32_op = OPC_TLTIU;
14560 goto do_trapi;
14561 case TGEIU:
14562 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14563 mips32_op = OPC_TGEIU;
14564 goto do_trapi;
14565 case TNEI: /* SYNCI */
14566 if (ctx->insn_flags & ISA_MIPS32R6) {
14567 /* SYNCI */
14568 /* Break the TB to be able to sync copied instructions
14569 immediately */
14570 ctx->bstate = BS_STOP;
14571 } else {
14572 /* TNEI */
14573 mips32_op = OPC_TNEI;
14574 goto do_trapi;
14576 break;
14577 case TEQI:
14578 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14579 mips32_op = OPC_TEQI;
14580 do_trapi:
14581 gen_trap(ctx, mips32_op, rs, -1, imm);
14582 break;
14584 case BNEZC:
14585 case BEQZC:
14586 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14587 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
14588 4, rs, 0, imm << 1, 0);
14589 /* Compact branches don't have a delay slot, so just let
14590 the normal delay slot handling take us to the branch
14591 target. */
14592 break;
14593 case LUI:
14594 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14595 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
14596 break;
14597 case SYNCI:
14598 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14599 /* Break the TB to be able to sync copied instructions
14600 immediately */
14601 ctx->bstate = BS_STOP;
14602 break;
14603 case BC2F:
14604 case BC2T:
14605 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14606 /* COP2: Not implemented. */
14607 generate_exception_err(ctx, EXCP_CpU, 2);
14608 break;
14609 case BC1F:
14610 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14611 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
14612 goto do_cp1branch;
14613 case BC1T:
14614 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14615 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
14616 goto do_cp1branch;
14617 case BC1ANY4F:
14618 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14619 mips32_op = OPC_BC1FANY4;
14620 goto do_cp1mips3d;
14621 case BC1ANY4T:
14622 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14623 mips32_op = OPC_BC1TANY4;
14624 do_cp1mips3d:
14625 check_cop1x(ctx);
14626 check_insn(ctx, ASE_MIPS3D);
14627 /* Fall through */
14628 do_cp1branch:
14629 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
14630 check_cp1_enabled(ctx);
14631 gen_compute_branch1(ctx, mips32_op,
14632 (ctx->opcode >> 18) & 0x7, imm << 1);
14633 } else {
14634 generate_exception_err(ctx, EXCP_CpU, 1);
14636 break;
14637 case BPOSGE64:
14638 case BPOSGE32:
14639 /* MIPS DSP: not implemented */
14640 /* Fall through */
14641 default:
14642 MIPS_INVAL("pool32i");
14643 generate_exception_end(ctx, EXCP_RI);
14644 break;
14646 break;
14647 case POOL32C:
14648 minor = (ctx->opcode >> 12) & 0xf;
14649 offset = sextract32(ctx->opcode, 0,
14650 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
14651 switch (minor) {
14652 case LWL:
14653 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14654 mips32_op = OPC_LWL;
14655 goto do_ld_lr;
14656 case SWL:
14657 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14658 mips32_op = OPC_SWL;
14659 goto do_st_lr;
14660 case LWR:
14661 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14662 mips32_op = OPC_LWR;
14663 goto do_ld_lr;
14664 case SWR:
14665 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14666 mips32_op = OPC_SWR;
14667 goto do_st_lr;
14668 #if defined(TARGET_MIPS64)
14669 case LDL:
14670 check_insn(ctx, ISA_MIPS3);
14671 check_mips_64(ctx);
14672 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14673 mips32_op = OPC_LDL;
14674 goto do_ld_lr;
14675 case SDL:
14676 check_insn(ctx, ISA_MIPS3);
14677 check_mips_64(ctx);
14678 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14679 mips32_op = OPC_SDL;
14680 goto do_st_lr;
14681 case LDR:
14682 check_insn(ctx, ISA_MIPS3);
14683 check_mips_64(ctx);
14684 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14685 mips32_op = OPC_LDR;
14686 goto do_ld_lr;
14687 case SDR:
14688 check_insn(ctx, ISA_MIPS3);
14689 check_mips_64(ctx);
14690 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14691 mips32_op = OPC_SDR;
14692 goto do_st_lr;
14693 case LWU:
14694 check_insn(ctx, ISA_MIPS3);
14695 check_mips_64(ctx);
14696 mips32_op = OPC_LWU;
14697 goto do_ld_lr;
14698 case LLD:
14699 check_insn(ctx, ISA_MIPS3);
14700 check_mips_64(ctx);
14701 mips32_op = OPC_LLD;
14702 goto do_ld_lr;
14703 #endif
14704 case LL:
14705 mips32_op = OPC_LL;
14706 goto do_ld_lr;
14707 do_ld_lr:
14708 gen_ld(ctx, mips32_op, rt, rs, offset);
14709 break;
14710 do_st_lr:
14711 gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
14712 break;
14713 case SC:
14714 gen_st_cond(ctx, OPC_SC, rt, rs, offset);
14715 break;
14716 #if defined(TARGET_MIPS64)
14717 case SCD:
14718 check_insn(ctx, ISA_MIPS3);
14719 check_mips_64(ctx);
14720 gen_st_cond(ctx, OPC_SCD, rt, rs, offset);
14721 break;
14722 #endif
14723 case PREF:
14724 /* Treat as no-op */
14725 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
14726 /* hint codes 24-31 are reserved and signal RI */
14727 generate_exception(ctx, EXCP_RI);
14729 break;
14730 default:
14731 MIPS_INVAL("pool32c");
14732 generate_exception_end(ctx, EXCP_RI);
14733 break;
14735 break;
14736 case ADDI32: /* AUI, LUI */
14737 if (ctx->insn_flags & ISA_MIPS32R6) {
14738 /* AUI, LUI */
14739 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
14740 } else {
14741 /* ADDI32 */
14742 mips32_op = OPC_ADDI;
14743 goto do_addi;
14745 break;
14746 case ADDIU32:
14747 mips32_op = OPC_ADDIU;
14748 do_addi:
14749 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
14750 break;
14752 /* Logical operations */
14753 case ORI32:
14754 mips32_op = OPC_ORI;
14755 goto do_logici;
14756 case XORI32:
14757 mips32_op = OPC_XORI;
14758 goto do_logici;
14759 case ANDI32:
14760 mips32_op = OPC_ANDI;
14761 do_logici:
14762 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
14763 break;
14765 /* Set less than immediate */
14766 case SLTI32:
14767 mips32_op = OPC_SLTI;
14768 goto do_slti;
14769 case SLTIU32:
14770 mips32_op = OPC_SLTIU;
14771 do_slti:
14772 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
14773 break;
14774 case JALX32:
14775 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14776 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
14777 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
14778 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14779 break;
14780 case JALS32: /* BOVC, BEQC, BEQZALC */
14781 if (ctx->insn_flags & ISA_MIPS32R6) {
14782 if (rs >= rt) {
14783 /* BOVC */
14784 mips32_op = OPC_BOVC;
14785 } else if (rs < rt && rs == 0) {
14786 /* BEQZALC */
14787 mips32_op = OPC_BEQZALC;
14788 } else {
14789 /* BEQC */
14790 mips32_op = OPC_BEQC;
14792 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14793 } else {
14794 /* JALS32 */
14795 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
14796 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
14797 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14799 break;
14800 case BEQ32: /* BC */
14801 if (ctx->insn_flags & ISA_MIPS32R6) {
14802 /* BC */
14803 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
14804 sextract32(ctx->opcode << 1, 0, 27));
14805 } else {
14806 /* BEQ32 */
14807 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
14809 break;
14810 case BNE32: /* BALC */
14811 if (ctx->insn_flags & ISA_MIPS32R6) {
14812 /* BALC */
14813 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
14814 sextract32(ctx->opcode << 1, 0, 27));
14815 } else {
14816 /* BNE32 */
14817 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
14819 break;
14820 case J32: /* BGTZC, BLTZC, BLTC */
14821 if (ctx->insn_flags & ISA_MIPS32R6) {
14822 if (rs == 0 && rt != 0) {
14823 /* BGTZC */
14824 mips32_op = OPC_BGTZC;
14825 } else if (rs != 0 && rt != 0 && rs == rt) {
14826 /* BLTZC */
14827 mips32_op = OPC_BLTZC;
14828 } else {
14829 /* BLTC */
14830 mips32_op = OPC_BLTC;
14832 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14833 } else {
14834 /* J32 */
14835 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
14836 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
14838 break;
14839 case JAL32: /* BLEZC, BGEZC, BGEC */
14840 if (ctx->insn_flags & ISA_MIPS32R6) {
14841 if (rs == 0 && rt != 0) {
14842 /* BLEZC */
14843 mips32_op = OPC_BLEZC;
14844 } else if (rs != 0 && rt != 0 && rs == rt) {
14845 /* BGEZC */
14846 mips32_op = OPC_BGEZC;
14847 } else {
14848 /* BGEC */
14849 mips32_op = OPC_BGEC;
14851 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14852 } else {
14853 /* JAL32 */
14854 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
14855 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
14856 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14858 break;
14859 /* Floating point (COP1) */
14860 case LWC132:
14861 mips32_op = OPC_LWC1;
14862 goto do_cop1;
14863 case LDC132:
14864 mips32_op = OPC_LDC1;
14865 goto do_cop1;
14866 case SWC132:
14867 mips32_op = OPC_SWC1;
14868 goto do_cop1;
14869 case SDC132:
14870 mips32_op = OPC_SDC1;
14871 do_cop1:
14872 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
14873 break;
14874 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
14875 if (ctx->insn_flags & ISA_MIPS32R6) {
14876 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
14877 switch ((ctx->opcode >> 16) & 0x1f) {
14878 case ADDIUPC_00 ... ADDIUPC_07:
14879 gen_pcrel(ctx, OPC_ADDIUPC, ctx->pc & ~0x3, rt);
14880 break;
14881 case AUIPC:
14882 gen_pcrel(ctx, OPC_AUIPC, ctx->pc, rt);
14883 break;
14884 case ALUIPC:
14885 gen_pcrel(ctx, OPC_ALUIPC, ctx->pc, rt);
14886 break;
14887 case LWPC_08 ... LWPC_0F:
14888 gen_pcrel(ctx, R6_OPC_LWPC, ctx->pc & ~0x3, rt);
14889 break;
14890 default:
14891 generate_exception(ctx, EXCP_RI);
14892 break;
14894 } else {
14895 /* ADDIUPC */
14896 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
14897 int offset = SIMM(ctx->opcode, 0, 23) << 2;
14899 gen_addiupc(ctx, reg, offset, 0, 0);
14901 break;
14902 case BNVC: /* BNEC, BNEZALC */
14903 check_insn(ctx, ISA_MIPS32R6);
14904 if (rs >= rt) {
14905 /* BNVC */
14906 mips32_op = OPC_BNVC;
14907 } else if (rs < rt && rs == 0) {
14908 /* BNEZALC */
14909 mips32_op = OPC_BNEZALC;
14910 } else {
14911 /* BNEC */
14912 mips32_op = OPC_BNEC;
14914 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14915 break;
14916 case R6_BNEZC: /* JIALC */
14917 check_insn(ctx, ISA_MIPS32R6);
14918 if (rt != 0) {
14919 /* BNEZC */
14920 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
14921 sextract32(ctx->opcode << 1, 0, 22));
14922 } else {
14923 /* JIALC */
14924 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
14926 break;
14927 case R6_BEQZC: /* JIC */
14928 check_insn(ctx, ISA_MIPS32R6);
14929 if (rt != 0) {
14930 /* BEQZC */
14931 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
14932 sextract32(ctx->opcode << 1, 0, 22));
14933 } else {
14934 /* JIC */
14935 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
14937 break;
14938 case BLEZALC: /* BGEZALC, BGEUC */
14939 check_insn(ctx, ISA_MIPS32R6);
14940 if (rs == 0 && rt != 0) {
14941 /* BLEZALC */
14942 mips32_op = OPC_BLEZALC;
14943 } else if (rs != 0 && rt != 0 && rs == rt) {
14944 /* BGEZALC */
14945 mips32_op = OPC_BGEZALC;
14946 } else {
14947 /* BGEUC */
14948 mips32_op = OPC_BGEUC;
14950 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14951 break;
14952 case BGTZALC: /* BLTZALC, BLTUC */
14953 check_insn(ctx, ISA_MIPS32R6);
14954 if (rs == 0 && rt != 0) {
14955 /* BGTZALC */
14956 mips32_op = OPC_BGTZALC;
14957 } else if (rs != 0 && rt != 0 && rs == rt) {
14958 /* BLTZALC */
14959 mips32_op = OPC_BLTZALC;
14960 } else {
14961 /* BLTUC */
14962 mips32_op = OPC_BLTUC;
14964 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
14965 break;
14966 /* Loads and stores */
14967 case LB32:
14968 mips32_op = OPC_LB;
14969 goto do_ld;
14970 case LBU32:
14971 mips32_op = OPC_LBU;
14972 goto do_ld;
14973 case LH32:
14974 mips32_op = OPC_LH;
14975 goto do_ld;
14976 case LHU32:
14977 mips32_op = OPC_LHU;
14978 goto do_ld;
14979 case LW32:
14980 mips32_op = OPC_LW;
14981 goto do_ld;
14982 #ifdef TARGET_MIPS64
14983 case LD32:
14984 check_insn(ctx, ISA_MIPS3);
14985 check_mips_64(ctx);
14986 mips32_op = OPC_LD;
14987 goto do_ld;
14988 case SD32:
14989 check_insn(ctx, ISA_MIPS3);
14990 check_mips_64(ctx);
14991 mips32_op = OPC_SD;
14992 goto do_st;
14993 #endif
14994 case SB32:
14995 mips32_op = OPC_SB;
14996 goto do_st;
14997 case SH32:
14998 mips32_op = OPC_SH;
14999 goto do_st;
15000 case SW32:
15001 mips32_op = OPC_SW;
15002 goto do_st;
15003 do_ld:
15004 gen_ld(ctx, mips32_op, rt, rs, imm);
15005 break;
15006 do_st:
15007 gen_st(ctx, mips32_op, rt, rs, imm);
15008 break;
15009 default:
15010 generate_exception_end(ctx, EXCP_RI);
15011 break;
15015 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
15017 uint32_t op;
15019 /* make sure instructions are on a halfword boundary */
15020 if (ctx->pc & 0x1) {
15021 env->CP0_BadVAddr = ctx->pc;
15022 generate_exception_end(ctx, EXCP_AdEL);
15023 return 2;
15026 op = (ctx->opcode >> 10) & 0x3f;
15027 /* Enforce properly-sized instructions in a delay slot */
15028 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
15029 switch (op & 0x7) { /* MSB-3..MSB-5 */
15030 case 0:
15031 /* POOL32A, POOL32B, POOL32I, POOL32C */
15032 case 4:
15033 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
15034 case 5:
15035 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
15036 case 6:
15037 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
15038 case 7:
15039 /* LB32, LH32, LWC132, LDC132, LW32 */
15040 if (ctx->hflags & MIPS_HFLAG_BDS16) {
15041 generate_exception_end(ctx, EXCP_RI);
15042 return 2;
15044 break;
15045 case 1:
15046 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
15047 case 2:
15048 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
15049 case 3:
15050 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
15051 if (ctx->hflags & MIPS_HFLAG_BDS32) {
15052 generate_exception_end(ctx, EXCP_RI);
15053 return 2;
15055 break;
15059 switch (op) {
15060 case POOL16A:
15062 int rd = mmreg(uMIPS_RD(ctx->opcode));
15063 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
15064 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
15065 uint32_t opc = 0;
15067 switch (ctx->opcode & 0x1) {
15068 case ADDU16:
15069 opc = OPC_ADDU;
15070 break;
15071 case SUBU16:
15072 opc = OPC_SUBU;
15073 break;
15075 if (ctx->insn_flags & ISA_MIPS32R6) {
15076 /* In the Release 6 the register number location in
15077 * the instruction encoding has changed.
15079 gen_arith(ctx, opc, rs1, rd, rs2);
15080 } else {
15081 gen_arith(ctx, opc, rd, rs1, rs2);
15084 break;
15085 case POOL16B:
15087 int rd = mmreg(uMIPS_RD(ctx->opcode));
15088 int rs = mmreg(uMIPS_RS(ctx->opcode));
15089 int amount = (ctx->opcode >> 1) & 0x7;
15090 uint32_t opc = 0;
15091 amount = amount == 0 ? 8 : amount;
15093 switch (ctx->opcode & 0x1) {
15094 case SLL16:
15095 opc = OPC_SLL;
15096 break;
15097 case SRL16:
15098 opc = OPC_SRL;
15099 break;
15102 gen_shift_imm(ctx, opc, rd, rs, amount);
15104 break;
15105 case POOL16C:
15106 if (ctx->insn_flags & ISA_MIPS32R6) {
15107 gen_pool16c_r6_insn(ctx);
15108 } else {
15109 gen_pool16c_insn(ctx);
15111 break;
15112 case LWGP16:
15114 int rd = mmreg(uMIPS_RD(ctx->opcode));
15115 int rb = 28; /* GP */
15116 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
15118 gen_ld(ctx, OPC_LW, rd, rb, offset);
15120 break;
15121 case POOL16F:
15122 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15123 if (ctx->opcode & 1) {
15124 generate_exception_end(ctx, EXCP_RI);
15125 } else {
15126 /* MOVEP */
15127 int enc_dest = uMIPS_RD(ctx->opcode);
15128 int enc_rt = uMIPS_RS2(ctx->opcode);
15129 int enc_rs = uMIPS_RS1(ctx->opcode);
15130 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15132 break;
15133 case LBU16:
15135 int rd = mmreg(uMIPS_RD(ctx->opcode));
15136 int rb = mmreg(uMIPS_RS(ctx->opcode));
15137 int16_t offset = ZIMM(ctx->opcode, 0, 4);
15138 offset = (offset == 0xf ? -1 : offset);
15140 gen_ld(ctx, OPC_LBU, rd, rb, offset);
15142 break;
15143 case LHU16:
15145 int rd = mmreg(uMIPS_RD(ctx->opcode));
15146 int rb = mmreg(uMIPS_RS(ctx->opcode));
15147 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
15149 gen_ld(ctx, OPC_LHU, rd, rb, offset);
15151 break;
15152 case LWSP16:
15154 int rd = (ctx->opcode >> 5) & 0x1f;
15155 int rb = 29; /* SP */
15156 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
15158 gen_ld(ctx, OPC_LW, rd, rb, offset);
15160 break;
15161 case LW16:
15163 int rd = mmreg(uMIPS_RD(ctx->opcode));
15164 int rb = mmreg(uMIPS_RS(ctx->opcode));
15165 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
15167 gen_ld(ctx, OPC_LW, rd, rb, offset);
15169 break;
15170 case SB16:
15172 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15173 int rb = mmreg(uMIPS_RS(ctx->opcode));
15174 int16_t offset = ZIMM(ctx->opcode, 0, 4);
15176 gen_st(ctx, OPC_SB, rd, rb, offset);
15178 break;
15179 case SH16:
15181 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15182 int rb = mmreg(uMIPS_RS(ctx->opcode));
15183 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
15185 gen_st(ctx, OPC_SH, rd, rb, offset);
15187 break;
15188 case SWSP16:
15190 int rd = (ctx->opcode >> 5) & 0x1f;
15191 int rb = 29; /* SP */
15192 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
15194 gen_st(ctx, OPC_SW, rd, rb, offset);
15196 break;
15197 case SW16:
15199 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15200 int rb = mmreg(uMIPS_RS(ctx->opcode));
15201 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
15203 gen_st(ctx, OPC_SW, rd, rb, offset);
15205 break;
15206 case MOVE16:
15208 int rd = uMIPS_RD5(ctx->opcode);
15209 int rs = uMIPS_RS5(ctx->opcode);
15211 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
15213 break;
15214 case ANDI16:
15215 gen_andi16(ctx);
15216 break;
15217 case POOL16D:
15218 switch (ctx->opcode & 0x1) {
15219 case ADDIUS5:
15220 gen_addius5(ctx);
15221 break;
15222 case ADDIUSP:
15223 gen_addiusp(ctx);
15224 break;
15226 break;
15227 case POOL16E:
15228 switch (ctx->opcode & 0x1) {
15229 case ADDIUR2:
15230 gen_addiur2(ctx);
15231 break;
15232 case ADDIUR1SP:
15233 gen_addiur1sp(ctx);
15234 break;
15236 break;
15237 case B16: /* BC16 */
15238 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
15239 sextract32(ctx->opcode, 0, 10) << 1,
15240 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
15241 break;
15242 case BNEZ16: /* BNEZC16 */
15243 case BEQZ16: /* BEQZC16 */
15244 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
15245 mmreg(uMIPS_RD(ctx->opcode)),
15246 0, sextract32(ctx->opcode, 0, 7) << 1,
15247 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
15249 break;
15250 case LI16:
15252 int reg = mmreg(uMIPS_RD(ctx->opcode));
15253 int imm = ZIMM(ctx->opcode, 0, 7);
15255 imm = (imm == 0x7f ? -1 : imm);
15256 tcg_gen_movi_tl(cpu_gpr[reg], imm);
15258 break;
15259 case RES_29:
15260 case RES_31:
15261 case RES_39:
15262 generate_exception_end(ctx, EXCP_RI);
15263 break;
15264 default:
15265 decode_micromips32_opc(env, ctx);
15266 return 4;
15269 return 2;
15272 /* SmartMIPS extension to MIPS32 */
15274 #if defined(TARGET_MIPS64)
15276 /* MDMX extension to MIPS64 */
15278 #endif
15280 /* MIPSDSP functions. */
15281 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
15282 int rd, int base, int offset)
15284 TCGv t0;
15286 check_dsp(ctx);
15287 t0 = tcg_temp_new();
15289 if (base == 0) {
15290 gen_load_gpr(t0, offset);
15291 } else if (offset == 0) {
15292 gen_load_gpr(t0, base);
15293 } else {
15294 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
15297 switch (opc) {
15298 case OPC_LBUX:
15299 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
15300 gen_store_gpr(t0, rd);
15301 break;
15302 case OPC_LHX:
15303 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
15304 gen_store_gpr(t0, rd);
15305 break;
15306 case OPC_LWX:
15307 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
15308 gen_store_gpr(t0, rd);
15309 break;
15310 #if defined(TARGET_MIPS64)
15311 case OPC_LDX:
15312 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
15313 gen_store_gpr(t0, rd);
15314 break;
15315 #endif
15317 tcg_temp_free(t0);
15320 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
15321 int ret, int v1, int v2)
15323 TCGv v1_t;
15324 TCGv v2_t;
15326 if (ret == 0) {
15327 /* Treat as NOP. */
15328 return;
15331 v1_t = tcg_temp_new();
15332 v2_t = tcg_temp_new();
15334 gen_load_gpr(v1_t, v1);
15335 gen_load_gpr(v2_t, v2);
15337 switch (op1) {
15338 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
15339 case OPC_MULT_G_2E:
15340 check_dspr2(ctx);
15341 switch (op2) {
15342 case OPC_ADDUH_QB:
15343 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
15344 break;
15345 case OPC_ADDUH_R_QB:
15346 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
15347 break;
15348 case OPC_ADDQH_PH:
15349 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
15350 break;
15351 case OPC_ADDQH_R_PH:
15352 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
15353 break;
15354 case OPC_ADDQH_W:
15355 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
15356 break;
15357 case OPC_ADDQH_R_W:
15358 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
15359 break;
15360 case OPC_SUBUH_QB:
15361 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
15362 break;
15363 case OPC_SUBUH_R_QB:
15364 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
15365 break;
15366 case OPC_SUBQH_PH:
15367 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
15368 break;
15369 case OPC_SUBQH_R_PH:
15370 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
15371 break;
15372 case OPC_SUBQH_W:
15373 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
15374 break;
15375 case OPC_SUBQH_R_W:
15376 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
15377 break;
15379 break;
15380 case OPC_ABSQ_S_PH_DSP:
15381 switch (op2) {
15382 case OPC_ABSQ_S_QB:
15383 check_dspr2(ctx);
15384 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
15385 break;
15386 case OPC_ABSQ_S_PH:
15387 check_dsp(ctx);
15388 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
15389 break;
15390 case OPC_ABSQ_S_W:
15391 check_dsp(ctx);
15392 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
15393 break;
15394 case OPC_PRECEQ_W_PHL:
15395 check_dsp(ctx);
15396 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
15397 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
15398 break;
15399 case OPC_PRECEQ_W_PHR:
15400 check_dsp(ctx);
15401 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
15402 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
15403 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
15404 break;
15405 case OPC_PRECEQU_PH_QBL:
15406 check_dsp(ctx);
15407 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
15408 break;
15409 case OPC_PRECEQU_PH_QBR:
15410 check_dsp(ctx);
15411 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
15412 break;
15413 case OPC_PRECEQU_PH_QBLA:
15414 check_dsp(ctx);
15415 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
15416 break;
15417 case OPC_PRECEQU_PH_QBRA:
15418 check_dsp(ctx);
15419 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
15420 break;
15421 case OPC_PRECEU_PH_QBL:
15422 check_dsp(ctx);
15423 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
15424 break;
15425 case OPC_PRECEU_PH_QBR:
15426 check_dsp(ctx);
15427 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
15428 break;
15429 case OPC_PRECEU_PH_QBLA:
15430 check_dsp(ctx);
15431 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
15432 break;
15433 case OPC_PRECEU_PH_QBRA:
15434 check_dsp(ctx);
15435 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
15436 break;
15438 break;
15439 case OPC_ADDU_QB_DSP:
15440 switch (op2) {
15441 case OPC_ADDQ_PH:
15442 check_dsp(ctx);
15443 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15444 break;
15445 case OPC_ADDQ_S_PH:
15446 check_dsp(ctx);
15447 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15448 break;
15449 case OPC_ADDQ_S_W:
15450 check_dsp(ctx);
15451 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15452 break;
15453 case OPC_ADDU_QB:
15454 check_dsp(ctx);
15455 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15456 break;
15457 case OPC_ADDU_S_QB:
15458 check_dsp(ctx);
15459 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15460 break;
15461 case OPC_ADDU_PH:
15462 check_dspr2(ctx);
15463 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15464 break;
15465 case OPC_ADDU_S_PH:
15466 check_dspr2(ctx);
15467 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15468 break;
15469 case OPC_SUBQ_PH:
15470 check_dsp(ctx);
15471 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15472 break;
15473 case OPC_SUBQ_S_PH:
15474 check_dsp(ctx);
15475 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15476 break;
15477 case OPC_SUBQ_S_W:
15478 check_dsp(ctx);
15479 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15480 break;
15481 case OPC_SUBU_QB:
15482 check_dsp(ctx);
15483 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15484 break;
15485 case OPC_SUBU_S_QB:
15486 check_dsp(ctx);
15487 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15488 break;
15489 case OPC_SUBU_PH:
15490 check_dspr2(ctx);
15491 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15492 break;
15493 case OPC_SUBU_S_PH:
15494 check_dspr2(ctx);
15495 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15496 break;
15497 case OPC_ADDSC:
15498 check_dsp(ctx);
15499 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15500 break;
15501 case OPC_ADDWC:
15502 check_dsp(ctx);
15503 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15504 break;
15505 case OPC_MODSUB:
15506 check_dsp(ctx);
15507 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
15508 break;
15509 case OPC_RADDU_W_QB:
15510 check_dsp(ctx);
15511 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
15512 break;
15514 break;
15515 case OPC_CMPU_EQ_QB_DSP:
15516 switch (op2) {
15517 case OPC_PRECR_QB_PH:
15518 check_dspr2(ctx);
15519 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
15520 break;
15521 case OPC_PRECRQ_QB_PH:
15522 check_dsp(ctx);
15523 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
15524 break;
15525 case OPC_PRECR_SRA_PH_W:
15526 check_dspr2(ctx);
15528 TCGv_i32 sa_t = tcg_const_i32(v2);
15529 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
15530 cpu_gpr[ret]);
15531 tcg_temp_free_i32(sa_t);
15532 break;
15534 case OPC_PRECR_SRA_R_PH_W:
15535 check_dspr2(ctx);
15537 TCGv_i32 sa_t = tcg_const_i32(v2);
15538 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
15539 cpu_gpr[ret]);
15540 tcg_temp_free_i32(sa_t);
15541 break;
15543 case OPC_PRECRQ_PH_W:
15544 check_dsp(ctx);
15545 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
15546 break;
15547 case OPC_PRECRQ_RS_PH_W:
15548 check_dsp(ctx);
15549 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15550 break;
15551 case OPC_PRECRQU_S_QB_PH:
15552 check_dsp(ctx);
15553 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15554 break;
15556 break;
15557 #ifdef TARGET_MIPS64
15558 case OPC_ABSQ_S_QH_DSP:
15559 switch (op2) {
15560 case OPC_PRECEQ_L_PWL:
15561 check_dsp(ctx);
15562 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
15563 break;
15564 case OPC_PRECEQ_L_PWR:
15565 check_dsp(ctx);
15566 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
15567 break;
15568 case OPC_PRECEQ_PW_QHL:
15569 check_dsp(ctx);
15570 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
15571 break;
15572 case OPC_PRECEQ_PW_QHR:
15573 check_dsp(ctx);
15574 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
15575 break;
15576 case OPC_PRECEQ_PW_QHLA:
15577 check_dsp(ctx);
15578 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
15579 break;
15580 case OPC_PRECEQ_PW_QHRA:
15581 check_dsp(ctx);
15582 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
15583 break;
15584 case OPC_PRECEQU_QH_OBL:
15585 check_dsp(ctx);
15586 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
15587 break;
15588 case OPC_PRECEQU_QH_OBR:
15589 check_dsp(ctx);
15590 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
15591 break;
15592 case OPC_PRECEQU_QH_OBLA:
15593 check_dsp(ctx);
15594 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
15595 break;
15596 case OPC_PRECEQU_QH_OBRA:
15597 check_dsp(ctx);
15598 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
15599 break;
15600 case OPC_PRECEU_QH_OBL:
15601 check_dsp(ctx);
15602 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
15603 break;
15604 case OPC_PRECEU_QH_OBR:
15605 check_dsp(ctx);
15606 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
15607 break;
15608 case OPC_PRECEU_QH_OBLA:
15609 check_dsp(ctx);
15610 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
15611 break;
15612 case OPC_PRECEU_QH_OBRA:
15613 check_dsp(ctx);
15614 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
15615 break;
15616 case OPC_ABSQ_S_OB:
15617 check_dspr2(ctx);
15618 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
15619 break;
15620 case OPC_ABSQ_S_PW:
15621 check_dsp(ctx);
15622 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
15623 break;
15624 case OPC_ABSQ_S_QH:
15625 check_dsp(ctx);
15626 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
15627 break;
15629 break;
15630 case OPC_ADDU_OB_DSP:
15631 switch (op2) {
15632 case OPC_RADDU_L_OB:
15633 check_dsp(ctx);
15634 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
15635 break;
15636 case OPC_SUBQ_PW:
15637 check_dsp(ctx);
15638 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15639 break;
15640 case OPC_SUBQ_S_PW:
15641 check_dsp(ctx);
15642 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15643 break;
15644 case OPC_SUBQ_QH:
15645 check_dsp(ctx);
15646 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15647 break;
15648 case OPC_SUBQ_S_QH:
15649 check_dsp(ctx);
15650 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15651 break;
15652 case OPC_SUBU_OB:
15653 check_dsp(ctx);
15654 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15655 break;
15656 case OPC_SUBU_S_OB:
15657 check_dsp(ctx);
15658 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15659 break;
15660 case OPC_SUBU_QH:
15661 check_dspr2(ctx);
15662 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15663 break;
15664 case OPC_SUBU_S_QH:
15665 check_dspr2(ctx);
15666 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15667 break;
15668 case OPC_SUBUH_OB:
15669 check_dspr2(ctx);
15670 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
15671 break;
15672 case OPC_SUBUH_R_OB:
15673 check_dspr2(ctx);
15674 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
15675 break;
15676 case OPC_ADDQ_PW:
15677 check_dsp(ctx);
15678 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15679 break;
15680 case OPC_ADDQ_S_PW:
15681 check_dsp(ctx);
15682 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15683 break;
15684 case OPC_ADDQ_QH:
15685 check_dsp(ctx);
15686 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15687 break;
15688 case OPC_ADDQ_S_QH:
15689 check_dsp(ctx);
15690 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15691 break;
15692 case OPC_ADDU_OB:
15693 check_dsp(ctx);
15694 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15695 break;
15696 case OPC_ADDU_S_OB:
15697 check_dsp(ctx);
15698 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15699 break;
15700 case OPC_ADDU_QH:
15701 check_dspr2(ctx);
15702 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15703 break;
15704 case OPC_ADDU_S_QH:
15705 check_dspr2(ctx);
15706 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15707 break;
15708 case OPC_ADDUH_OB:
15709 check_dspr2(ctx);
15710 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
15711 break;
15712 case OPC_ADDUH_R_OB:
15713 check_dspr2(ctx);
15714 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
15715 break;
15717 break;
15718 case OPC_CMPU_EQ_OB_DSP:
15719 switch (op2) {
15720 case OPC_PRECR_OB_QH:
15721 check_dspr2(ctx);
15722 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
15723 break;
15724 case OPC_PRECR_SRA_QH_PW:
15725 check_dspr2(ctx);
15727 TCGv_i32 ret_t = tcg_const_i32(ret);
15728 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
15729 tcg_temp_free_i32(ret_t);
15730 break;
15732 case OPC_PRECR_SRA_R_QH_PW:
15733 check_dspr2(ctx);
15735 TCGv_i32 sa_v = tcg_const_i32(ret);
15736 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
15737 tcg_temp_free_i32(sa_v);
15738 break;
15740 case OPC_PRECRQ_OB_QH:
15741 check_dsp(ctx);
15742 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
15743 break;
15744 case OPC_PRECRQ_PW_L:
15745 check_dsp(ctx);
15746 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
15747 break;
15748 case OPC_PRECRQ_QH_PW:
15749 check_dsp(ctx);
15750 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
15751 break;
15752 case OPC_PRECRQ_RS_QH_PW:
15753 check_dsp(ctx);
15754 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15755 break;
15756 case OPC_PRECRQU_S_OB_QH:
15757 check_dsp(ctx);
15758 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15759 break;
15761 break;
15762 #endif
15765 tcg_temp_free(v1_t);
15766 tcg_temp_free(v2_t);
15769 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
15770 int ret, int v1, int v2)
15772 uint32_t op2;
15773 TCGv t0;
15774 TCGv v1_t;
15775 TCGv v2_t;
15777 if (ret == 0) {
15778 /* Treat as NOP. */
15779 return;
15782 t0 = tcg_temp_new();
15783 v1_t = tcg_temp_new();
15784 v2_t = tcg_temp_new();
15786 tcg_gen_movi_tl(t0, v1);
15787 gen_load_gpr(v1_t, v1);
15788 gen_load_gpr(v2_t, v2);
15790 switch (opc) {
15791 case OPC_SHLL_QB_DSP:
15793 op2 = MASK_SHLL_QB(ctx->opcode);
15794 switch (op2) {
15795 case OPC_SHLL_QB:
15796 check_dsp(ctx);
15797 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
15798 break;
15799 case OPC_SHLLV_QB:
15800 check_dsp(ctx);
15801 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15802 break;
15803 case OPC_SHLL_PH:
15804 check_dsp(ctx);
15805 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
15806 break;
15807 case OPC_SHLLV_PH:
15808 check_dsp(ctx);
15809 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15810 break;
15811 case OPC_SHLL_S_PH:
15812 check_dsp(ctx);
15813 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
15814 break;
15815 case OPC_SHLLV_S_PH:
15816 check_dsp(ctx);
15817 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15818 break;
15819 case OPC_SHLL_S_W:
15820 check_dsp(ctx);
15821 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
15822 break;
15823 case OPC_SHLLV_S_W:
15824 check_dsp(ctx);
15825 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15826 break;
15827 case OPC_SHRL_QB:
15828 check_dsp(ctx);
15829 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
15830 break;
15831 case OPC_SHRLV_QB:
15832 check_dsp(ctx);
15833 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
15834 break;
15835 case OPC_SHRL_PH:
15836 check_dspr2(ctx);
15837 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
15838 break;
15839 case OPC_SHRLV_PH:
15840 check_dspr2(ctx);
15841 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
15842 break;
15843 case OPC_SHRA_QB:
15844 check_dspr2(ctx);
15845 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
15846 break;
15847 case OPC_SHRA_R_QB:
15848 check_dspr2(ctx);
15849 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
15850 break;
15851 case OPC_SHRAV_QB:
15852 check_dspr2(ctx);
15853 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
15854 break;
15855 case OPC_SHRAV_R_QB:
15856 check_dspr2(ctx);
15857 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
15858 break;
15859 case OPC_SHRA_PH:
15860 check_dsp(ctx);
15861 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
15862 break;
15863 case OPC_SHRA_R_PH:
15864 check_dsp(ctx);
15865 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
15866 break;
15867 case OPC_SHRAV_PH:
15868 check_dsp(ctx);
15869 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
15870 break;
15871 case OPC_SHRAV_R_PH:
15872 check_dsp(ctx);
15873 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
15874 break;
15875 case OPC_SHRA_R_W:
15876 check_dsp(ctx);
15877 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
15878 break;
15879 case OPC_SHRAV_R_W:
15880 check_dsp(ctx);
15881 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
15882 break;
15883 default: /* Invalid */
15884 MIPS_INVAL("MASK SHLL.QB");
15885 generate_exception_end(ctx, EXCP_RI);
15886 break;
15888 break;
15890 #ifdef TARGET_MIPS64
15891 case OPC_SHLL_OB_DSP:
15892 op2 = MASK_SHLL_OB(ctx->opcode);
15893 switch (op2) {
15894 case OPC_SHLL_PW:
15895 check_dsp(ctx);
15896 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
15897 break;
15898 case OPC_SHLLV_PW:
15899 check_dsp(ctx);
15900 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15901 break;
15902 case OPC_SHLL_S_PW:
15903 check_dsp(ctx);
15904 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
15905 break;
15906 case OPC_SHLLV_S_PW:
15907 check_dsp(ctx);
15908 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15909 break;
15910 case OPC_SHLL_OB:
15911 check_dsp(ctx);
15912 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
15913 break;
15914 case OPC_SHLLV_OB:
15915 check_dsp(ctx);
15916 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15917 break;
15918 case OPC_SHLL_QH:
15919 check_dsp(ctx);
15920 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
15921 break;
15922 case OPC_SHLLV_QH:
15923 check_dsp(ctx);
15924 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15925 break;
15926 case OPC_SHLL_S_QH:
15927 check_dsp(ctx);
15928 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
15929 break;
15930 case OPC_SHLLV_S_QH:
15931 check_dsp(ctx);
15932 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
15933 break;
15934 case OPC_SHRA_OB:
15935 check_dspr2(ctx);
15936 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
15937 break;
15938 case OPC_SHRAV_OB:
15939 check_dspr2(ctx);
15940 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
15941 break;
15942 case OPC_SHRA_R_OB:
15943 check_dspr2(ctx);
15944 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
15945 break;
15946 case OPC_SHRAV_R_OB:
15947 check_dspr2(ctx);
15948 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
15949 break;
15950 case OPC_SHRA_PW:
15951 check_dsp(ctx);
15952 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
15953 break;
15954 case OPC_SHRAV_PW:
15955 check_dsp(ctx);
15956 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
15957 break;
15958 case OPC_SHRA_R_PW:
15959 check_dsp(ctx);
15960 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
15961 break;
15962 case OPC_SHRAV_R_PW:
15963 check_dsp(ctx);
15964 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
15965 break;
15966 case OPC_SHRA_QH:
15967 check_dsp(ctx);
15968 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
15969 break;
15970 case OPC_SHRAV_QH:
15971 check_dsp(ctx);
15972 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
15973 break;
15974 case OPC_SHRA_R_QH:
15975 check_dsp(ctx);
15976 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
15977 break;
15978 case OPC_SHRAV_R_QH:
15979 check_dsp(ctx);
15980 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
15981 break;
15982 case OPC_SHRL_OB:
15983 check_dsp(ctx);
15984 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
15985 break;
15986 case OPC_SHRLV_OB:
15987 check_dsp(ctx);
15988 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
15989 break;
15990 case OPC_SHRL_QH:
15991 check_dspr2(ctx);
15992 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
15993 break;
15994 case OPC_SHRLV_QH:
15995 check_dspr2(ctx);
15996 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
15997 break;
15998 default: /* Invalid */
15999 MIPS_INVAL("MASK SHLL.OB");
16000 generate_exception_end(ctx, EXCP_RI);
16001 break;
16003 break;
16004 #endif
16007 tcg_temp_free(t0);
16008 tcg_temp_free(v1_t);
16009 tcg_temp_free(v2_t);
16012 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
16013 int ret, int v1, int v2, int check_ret)
16015 TCGv_i32 t0;
16016 TCGv v1_t;
16017 TCGv v2_t;
16019 if ((ret == 0) && (check_ret == 1)) {
16020 /* Treat as NOP. */
16021 return;
16024 t0 = tcg_temp_new_i32();
16025 v1_t = tcg_temp_new();
16026 v2_t = tcg_temp_new();
16028 tcg_gen_movi_i32(t0, ret);
16029 gen_load_gpr(v1_t, v1);
16030 gen_load_gpr(v2_t, v2);
16032 switch (op1) {
16033 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
16034 * the same mask and op1. */
16035 case OPC_MULT_G_2E:
16036 check_dspr2(ctx);
16037 switch (op2) {
16038 case OPC_MUL_PH:
16039 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16040 break;
16041 case OPC_MUL_S_PH:
16042 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16043 break;
16044 case OPC_MULQ_S_W:
16045 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16046 break;
16047 case OPC_MULQ_RS_W:
16048 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16049 break;
16051 break;
16052 case OPC_DPA_W_PH_DSP:
16053 switch (op2) {
16054 case OPC_DPAU_H_QBL:
16055 check_dsp(ctx);
16056 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
16057 break;
16058 case OPC_DPAU_H_QBR:
16059 check_dsp(ctx);
16060 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
16061 break;
16062 case OPC_DPSU_H_QBL:
16063 check_dsp(ctx);
16064 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
16065 break;
16066 case OPC_DPSU_H_QBR:
16067 check_dsp(ctx);
16068 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
16069 break;
16070 case OPC_DPA_W_PH:
16071 check_dspr2(ctx);
16072 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
16073 break;
16074 case OPC_DPAX_W_PH:
16075 check_dspr2(ctx);
16076 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
16077 break;
16078 case OPC_DPAQ_S_W_PH:
16079 check_dsp(ctx);
16080 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
16081 break;
16082 case OPC_DPAQX_S_W_PH:
16083 check_dspr2(ctx);
16084 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
16085 break;
16086 case OPC_DPAQX_SA_W_PH:
16087 check_dspr2(ctx);
16088 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
16089 break;
16090 case OPC_DPS_W_PH:
16091 check_dspr2(ctx);
16092 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
16093 break;
16094 case OPC_DPSX_W_PH:
16095 check_dspr2(ctx);
16096 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
16097 break;
16098 case OPC_DPSQ_S_W_PH:
16099 check_dsp(ctx);
16100 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
16101 break;
16102 case OPC_DPSQX_S_W_PH:
16103 check_dspr2(ctx);
16104 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
16105 break;
16106 case OPC_DPSQX_SA_W_PH:
16107 check_dspr2(ctx);
16108 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
16109 break;
16110 case OPC_MULSAQ_S_W_PH:
16111 check_dsp(ctx);
16112 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
16113 break;
16114 case OPC_DPAQ_SA_L_W:
16115 check_dsp(ctx);
16116 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
16117 break;
16118 case OPC_DPSQ_SA_L_W:
16119 check_dsp(ctx);
16120 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
16121 break;
16122 case OPC_MAQ_S_W_PHL:
16123 check_dsp(ctx);
16124 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
16125 break;
16126 case OPC_MAQ_S_W_PHR:
16127 check_dsp(ctx);
16128 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
16129 break;
16130 case OPC_MAQ_SA_W_PHL:
16131 check_dsp(ctx);
16132 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
16133 break;
16134 case OPC_MAQ_SA_W_PHR:
16135 check_dsp(ctx);
16136 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
16137 break;
16138 case OPC_MULSA_W_PH:
16139 check_dspr2(ctx);
16140 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
16141 break;
16143 break;
16144 #ifdef TARGET_MIPS64
16145 case OPC_DPAQ_W_QH_DSP:
16147 int ac = ret & 0x03;
16148 tcg_gen_movi_i32(t0, ac);
16150 switch (op2) {
16151 case OPC_DMADD:
16152 check_dsp(ctx);
16153 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
16154 break;
16155 case OPC_DMADDU:
16156 check_dsp(ctx);
16157 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
16158 break;
16159 case OPC_DMSUB:
16160 check_dsp(ctx);
16161 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
16162 break;
16163 case OPC_DMSUBU:
16164 check_dsp(ctx);
16165 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
16166 break;
16167 case OPC_DPA_W_QH:
16168 check_dspr2(ctx);
16169 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
16170 break;
16171 case OPC_DPAQ_S_W_QH:
16172 check_dsp(ctx);
16173 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
16174 break;
16175 case OPC_DPAQ_SA_L_PW:
16176 check_dsp(ctx);
16177 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
16178 break;
16179 case OPC_DPAU_H_OBL:
16180 check_dsp(ctx);
16181 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
16182 break;
16183 case OPC_DPAU_H_OBR:
16184 check_dsp(ctx);
16185 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
16186 break;
16187 case OPC_DPS_W_QH:
16188 check_dspr2(ctx);
16189 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
16190 break;
16191 case OPC_DPSQ_S_W_QH:
16192 check_dsp(ctx);
16193 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
16194 break;
16195 case OPC_DPSQ_SA_L_PW:
16196 check_dsp(ctx);
16197 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
16198 break;
16199 case OPC_DPSU_H_OBL:
16200 check_dsp(ctx);
16201 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
16202 break;
16203 case OPC_DPSU_H_OBR:
16204 check_dsp(ctx);
16205 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
16206 break;
16207 case OPC_MAQ_S_L_PWL:
16208 check_dsp(ctx);
16209 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
16210 break;
16211 case OPC_MAQ_S_L_PWR:
16212 check_dsp(ctx);
16213 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
16214 break;
16215 case OPC_MAQ_S_W_QHLL:
16216 check_dsp(ctx);
16217 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
16218 break;
16219 case OPC_MAQ_SA_W_QHLL:
16220 check_dsp(ctx);
16221 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
16222 break;
16223 case OPC_MAQ_S_W_QHLR:
16224 check_dsp(ctx);
16225 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
16226 break;
16227 case OPC_MAQ_SA_W_QHLR:
16228 check_dsp(ctx);
16229 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
16230 break;
16231 case OPC_MAQ_S_W_QHRL:
16232 check_dsp(ctx);
16233 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
16234 break;
16235 case OPC_MAQ_SA_W_QHRL:
16236 check_dsp(ctx);
16237 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
16238 break;
16239 case OPC_MAQ_S_W_QHRR:
16240 check_dsp(ctx);
16241 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
16242 break;
16243 case OPC_MAQ_SA_W_QHRR:
16244 check_dsp(ctx);
16245 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
16246 break;
16247 case OPC_MULSAQ_S_L_PW:
16248 check_dsp(ctx);
16249 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
16250 break;
16251 case OPC_MULSAQ_S_W_QH:
16252 check_dsp(ctx);
16253 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
16254 break;
16257 break;
16258 #endif
16259 case OPC_ADDU_QB_DSP:
16260 switch (op2) {
16261 case OPC_MULEU_S_PH_QBL:
16262 check_dsp(ctx);
16263 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16264 break;
16265 case OPC_MULEU_S_PH_QBR:
16266 check_dsp(ctx);
16267 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16268 break;
16269 case OPC_MULQ_RS_PH:
16270 check_dsp(ctx);
16271 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16272 break;
16273 case OPC_MULEQ_S_W_PHL:
16274 check_dsp(ctx);
16275 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16276 break;
16277 case OPC_MULEQ_S_W_PHR:
16278 check_dsp(ctx);
16279 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16280 break;
16281 case OPC_MULQ_S_PH:
16282 check_dspr2(ctx);
16283 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16284 break;
16286 break;
16287 #ifdef TARGET_MIPS64
16288 case OPC_ADDU_OB_DSP:
16289 switch (op2) {
16290 case OPC_MULEQ_S_PW_QHL:
16291 check_dsp(ctx);
16292 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16293 break;
16294 case OPC_MULEQ_S_PW_QHR:
16295 check_dsp(ctx);
16296 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16297 break;
16298 case OPC_MULEU_S_QH_OBL:
16299 check_dsp(ctx);
16300 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16301 break;
16302 case OPC_MULEU_S_QH_OBR:
16303 check_dsp(ctx);
16304 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16305 break;
16306 case OPC_MULQ_RS_QH:
16307 check_dsp(ctx);
16308 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16309 break;
16311 break;
16312 #endif
16315 tcg_temp_free_i32(t0);
16316 tcg_temp_free(v1_t);
16317 tcg_temp_free(v2_t);
16320 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
16321 int ret, int val)
16323 int16_t imm;
16324 TCGv t0;
16325 TCGv val_t;
16327 if (ret == 0) {
16328 /* Treat as NOP. */
16329 return;
16332 t0 = tcg_temp_new();
16333 val_t = tcg_temp_new();
16334 gen_load_gpr(val_t, val);
16336 switch (op1) {
16337 case OPC_ABSQ_S_PH_DSP:
16338 switch (op2) {
16339 case OPC_BITREV:
16340 check_dsp(ctx);
16341 gen_helper_bitrev(cpu_gpr[ret], val_t);
16342 break;
16343 case OPC_REPL_QB:
16344 check_dsp(ctx);
16346 target_long result;
16347 imm = (ctx->opcode >> 16) & 0xFF;
16348 result = (uint32_t)imm << 24 |
16349 (uint32_t)imm << 16 |
16350 (uint32_t)imm << 8 |
16351 (uint32_t)imm;
16352 result = (int32_t)result;
16353 tcg_gen_movi_tl(cpu_gpr[ret], result);
16355 break;
16356 case OPC_REPLV_QB:
16357 check_dsp(ctx);
16358 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
16359 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
16360 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16361 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16362 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16363 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
16364 break;
16365 case OPC_REPL_PH:
16366 check_dsp(ctx);
16368 imm = (ctx->opcode >> 16) & 0x03FF;
16369 imm = (int16_t)(imm << 6) >> 6;
16370 tcg_gen_movi_tl(cpu_gpr[ret], \
16371 (target_long)((int32_t)imm << 16 | \
16372 (uint16_t)imm));
16374 break;
16375 case OPC_REPLV_PH:
16376 check_dsp(ctx);
16377 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
16378 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16379 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16380 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
16381 break;
16383 break;
16384 #ifdef TARGET_MIPS64
16385 case OPC_ABSQ_S_QH_DSP:
16386 switch (op2) {
16387 case OPC_REPL_OB:
16388 check_dsp(ctx);
16390 target_long temp;
16392 imm = (ctx->opcode >> 16) & 0xFF;
16393 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
16394 temp = (temp << 16) | temp;
16395 temp = (temp << 32) | temp;
16396 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16397 break;
16399 case OPC_REPL_PW:
16400 check_dsp(ctx);
16402 target_long temp;
16404 imm = (ctx->opcode >> 16) & 0x03FF;
16405 imm = (int16_t)(imm << 6) >> 6;
16406 temp = ((target_long)imm << 32) \
16407 | ((target_long)imm & 0xFFFFFFFF);
16408 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16409 break;
16411 case OPC_REPL_QH:
16412 check_dsp(ctx);
16414 target_long temp;
16416 imm = (ctx->opcode >> 16) & 0x03FF;
16417 imm = (int16_t)(imm << 6) >> 6;
16419 temp = ((uint64_t)(uint16_t)imm << 48) |
16420 ((uint64_t)(uint16_t)imm << 32) |
16421 ((uint64_t)(uint16_t)imm << 16) |
16422 (uint64_t)(uint16_t)imm;
16423 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16424 break;
16426 case OPC_REPLV_OB:
16427 check_dsp(ctx);
16428 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
16429 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
16430 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16431 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16432 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16433 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16434 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16435 break;
16436 case OPC_REPLV_PW:
16437 check_dsp(ctx);
16438 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
16439 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16440 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16441 break;
16442 case OPC_REPLV_QH:
16443 check_dsp(ctx);
16444 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
16445 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16446 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16447 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16448 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16449 break;
16451 break;
16452 #endif
16454 tcg_temp_free(t0);
16455 tcg_temp_free(val_t);
16458 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
16459 uint32_t op1, uint32_t op2,
16460 int ret, int v1, int v2, int check_ret)
16462 TCGv t1;
16463 TCGv v1_t;
16464 TCGv v2_t;
16466 if ((ret == 0) && (check_ret == 1)) {
16467 /* Treat as NOP. */
16468 return;
16471 t1 = tcg_temp_new();
16472 v1_t = tcg_temp_new();
16473 v2_t = tcg_temp_new();
16475 gen_load_gpr(v1_t, v1);
16476 gen_load_gpr(v2_t, v2);
16478 switch (op1) {
16479 case OPC_CMPU_EQ_QB_DSP:
16480 switch (op2) {
16481 case OPC_CMPU_EQ_QB:
16482 check_dsp(ctx);
16483 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
16484 break;
16485 case OPC_CMPU_LT_QB:
16486 check_dsp(ctx);
16487 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
16488 break;
16489 case OPC_CMPU_LE_QB:
16490 check_dsp(ctx);
16491 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
16492 break;
16493 case OPC_CMPGU_EQ_QB:
16494 check_dsp(ctx);
16495 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
16496 break;
16497 case OPC_CMPGU_LT_QB:
16498 check_dsp(ctx);
16499 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
16500 break;
16501 case OPC_CMPGU_LE_QB:
16502 check_dsp(ctx);
16503 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
16504 break;
16505 case OPC_CMPGDU_EQ_QB:
16506 check_dspr2(ctx);
16507 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
16508 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16509 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16510 tcg_gen_shli_tl(t1, t1, 24);
16511 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16512 break;
16513 case OPC_CMPGDU_LT_QB:
16514 check_dspr2(ctx);
16515 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
16516 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16517 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16518 tcg_gen_shli_tl(t1, t1, 24);
16519 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16520 break;
16521 case OPC_CMPGDU_LE_QB:
16522 check_dspr2(ctx);
16523 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
16524 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16525 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16526 tcg_gen_shli_tl(t1, t1, 24);
16527 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16528 break;
16529 case OPC_CMP_EQ_PH:
16530 check_dsp(ctx);
16531 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
16532 break;
16533 case OPC_CMP_LT_PH:
16534 check_dsp(ctx);
16535 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
16536 break;
16537 case OPC_CMP_LE_PH:
16538 check_dsp(ctx);
16539 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
16540 break;
16541 case OPC_PICK_QB:
16542 check_dsp(ctx);
16543 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16544 break;
16545 case OPC_PICK_PH:
16546 check_dsp(ctx);
16547 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16548 break;
16549 case OPC_PACKRL_PH:
16550 check_dsp(ctx);
16551 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
16552 break;
16554 break;
16555 #ifdef TARGET_MIPS64
16556 case OPC_CMPU_EQ_OB_DSP:
16557 switch (op2) {
16558 case OPC_CMP_EQ_PW:
16559 check_dsp(ctx);
16560 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
16561 break;
16562 case OPC_CMP_LT_PW:
16563 check_dsp(ctx);
16564 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
16565 break;
16566 case OPC_CMP_LE_PW:
16567 check_dsp(ctx);
16568 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
16569 break;
16570 case OPC_CMP_EQ_QH:
16571 check_dsp(ctx);
16572 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
16573 break;
16574 case OPC_CMP_LT_QH:
16575 check_dsp(ctx);
16576 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
16577 break;
16578 case OPC_CMP_LE_QH:
16579 check_dsp(ctx);
16580 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
16581 break;
16582 case OPC_CMPGDU_EQ_OB:
16583 check_dspr2(ctx);
16584 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16585 break;
16586 case OPC_CMPGDU_LT_OB:
16587 check_dspr2(ctx);
16588 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16589 break;
16590 case OPC_CMPGDU_LE_OB:
16591 check_dspr2(ctx);
16592 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16593 break;
16594 case OPC_CMPGU_EQ_OB:
16595 check_dsp(ctx);
16596 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
16597 break;
16598 case OPC_CMPGU_LT_OB:
16599 check_dsp(ctx);
16600 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
16601 break;
16602 case OPC_CMPGU_LE_OB:
16603 check_dsp(ctx);
16604 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
16605 break;
16606 case OPC_CMPU_EQ_OB:
16607 check_dsp(ctx);
16608 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
16609 break;
16610 case OPC_CMPU_LT_OB:
16611 check_dsp(ctx);
16612 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
16613 break;
16614 case OPC_CMPU_LE_OB:
16615 check_dsp(ctx);
16616 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
16617 break;
16618 case OPC_PACKRL_PW:
16619 check_dsp(ctx);
16620 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
16621 break;
16622 case OPC_PICK_OB:
16623 check_dsp(ctx);
16624 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16625 break;
16626 case OPC_PICK_PW:
16627 check_dsp(ctx);
16628 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16629 break;
16630 case OPC_PICK_QH:
16631 check_dsp(ctx);
16632 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16633 break;
16635 break;
16636 #endif
16639 tcg_temp_free(t1);
16640 tcg_temp_free(v1_t);
16641 tcg_temp_free(v2_t);
16644 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
16645 uint32_t op1, int rt, int rs, int sa)
16647 TCGv t0;
16649 check_dspr2(ctx);
16651 if (rt == 0) {
16652 /* Treat as NOP. */
16653 return;
16656 t0 = tcg_temp_new();
16657 gen_load_gpr(t0, rs);
16659 switch (op1) {
16660 case OPC_APPEND_DSP:
16661 switch (MASK_APPEND(ctx->opcode)) {
16662 case OPC_APPEND:
16663 if (sa != 0) {
16664 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
16666 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16667 break;
16668 case OPC_PREPEND:
16669 if (sa != 0) {
16670 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
16671 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
16672 tcg_gen_shli_tl(t0, t0, 32 - sa);
16673 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16675 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16676 break;
16677 case OPC_BALIGN:
16678 sa &= 3;
16679 if (sa != 0 && sa != 2) {
16680 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
16681 tcg_gen_ext32u_tl(t0, t0);
16682 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
16683 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16685 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16686 break;
16687 default: /* Invalid */
16688 MIPS_INVAL("MASK APPEND");
16689 generate_exception_end(ctx, EXCP_RI);
16690 break;
16692 break;
16693 #ifdef TARGET_MIPS64
16694 case OPC_DAPPEND_DSP:
16695 switch (MASK_DAPPEND(ctx->opcode)) {
16696 case OPC_DAPPEND:
16697 if (sa != 0) {
16698 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
16700 break;
16701 case OPC_PREPENDD:
16702 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
16703 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
16704 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
16705 break;
16706 case OPC_PREPENDW:
16707 if (sa != 0) {
16708 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
16709 tcg_gen_shli_tl(t0, t0, 64 - sa);
16710 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16712 break;
16713 case OPC_DBALIGN:
16714 sa &= 7;
16715 if (sa != 0 && sa != 2 && sa != 4) {
16716 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
16717 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
16718 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16720 break;
16721 default: /* Invalid */
16722 MIPS_INVAL("MASK DAPPEND");
16723 generate_exception_end(ctx, EXCP_RI);
16724 break;
16726 break;
16727 #endif
16729 tcg_temp_free(t0);
16732 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
16733 int ret, int v1, int v2, int check_ret)
16736 TCGv t0;
16737 TCGv t1;
16738 TCGv v1_t;
16739 TCGv v2_t;
16740 int16_t imm;
16742 if ((ret == 0) && (check_ret == 1)) {
16743 /* Treat as NOP. */
16744 return;
16747 t0 = tcg_temp_new();
16748 t1 = tcg_temp_new();
16749 v1_t = tcg_temp_new();
16750 v2_t = tcg_temp_new();
16752 gen_load_gpr(v1_t, v1);
16753 gen_load_gpr(v2_t, v2);
16755 switch (op1) {
16756 case OPC_EXTR_W_DSP:
16757 check_dsp(ctx);
16758 switch (op2) {
16759 case OPC_EXTR_W:
16760 tcg_gen_movi_tl(t0, v2);
16761 tcg_gen_movi_tl(t1, v1);
16762 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
16763 break;
16764 case OPC_EXTR_R_W:
16765 tcg_gen_movi_tl(t0, v2);
16766 tcg_gen_movi_tl(t1, v1);
16767 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
16768 break;
16769 case OPC_EXTR_RS_W:
16770 tcg_gen_movi_tl(t0, v2);
16771 tcg_gen_movi_tl(t1, v1);
16772 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
16773 break;
16774 case OPC_EXTR_S_H:
16775 tcg_gen_movi_tl(t0, v2);
16776 tcg_gen_movi_tl(t1, v1);
16777 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
16778 break;
16779 case OPC_EXTRV_S_H:
16780 tcg_gen_movi_tl(t0, v2);
16781 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
16782 break;
16783 case OPC_EXTRV_W:
16784 tcg_gen_movi_tl(t0, v2);
16785 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16786 break;
16787 case OPC_EXTRV_R_W:
16788 tcg_gen_movi_tl(t0, v2);
16789 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16790 break;
16791 case OPC_EXTRV_RS_W:
16792 tcg_gen_movi_tl(t0, v2);
16793 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16794 break;
16795 case OPC_EXTP:
16796 tcg_gen_movi_tl(t0, v2);
16797 tcg_gen_movi_tl(t1, v1);
16798 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
16799 break;
16800 case OPC_EXTPV:
16801 tcg_gen_movi_tl(t0, v2);
16802 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
16803 break;
16804 case OPC_EXTPDP:
16805 tcg_gen_movi_tl(t0, v2);
16806 tcg_gen_movi_tl(t1, v1);
16807 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
16808 break;
16809 case OPC_EXTPDPV:
16810 tcg_gen_movi_tl(t0, v2);
16811 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
16812 break;
16813 case OPC_SHILO:
16814 imm = (ctx->opcode >> 20) & 0x3F;
16815 tcg_gen_movi_tl(t0, ret);
16816 tcg_gen_movi_tl(t1, imm);
16817 gen_helper_shilo(t0, t1, cpu_env);
16818 break;
16819 case OPC_SHILOV:
16820 tcg_gen_movi_tl(t0, ret);
16821 gen_helper_shilo(t0, v1_t, cpu_env);
16822 break;
16823 case OPC_MTHLIP:
16824 tcg_gen_movi_tl(t0, ret);
16825 gen_helper_mthlip(t0, v1_t, cpu_env);
16826 break;
16827 case OPC_WRDSP:
16828 imm = (ctx->opcode >> 11) & 0x3FF;
16829 tcg_gen_movi_tl(t0, imm);
16830 gen_helper_wrdsp(v1_t, t0, cpu_env);
16831 break;
16832 case OPC_RDDSP:
16833 imm = (ctx->opcode >> 16) & 0x03FF;
16834 tcg_gen_movi_tl(t0, imm);
16835 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
16836 break;
16838 break;
16839 #ifdef TARGET_MIPS64
16840 case OPC_DEXTR_W_DSP:
16841 check_dsp(ctx);
16842 switch (op2) {
16843 case OPC_DMTHLIP:
16844 tcg_gen_movi_tl(t0, ret);
16845 gen_helper_dmthlip(v1_t, t0, cpu_env);
16846 break;
16847 case OPC_DSHILO:
16849 int shift = (ctx->opcode >> 19) & 0x7F;
16850 int ac = (ctx->opcode >> 11) & 0x03;
16851 tcg_gen_movi_tl(t0, shift);
16852 tcg_gen_movi_tl(t1, ac);
16853 gen_helper_dshilo(t0, t1, cpu_env);
16854 break;
16856 case OPC_DSHILOV:
16858 int ac = (ctx->opcode >> 11) & 0x03;
16859 tcg_gen_movi_tl(t0, ac);
16860 gen_helper_dshilo(v1_t, t0, cpu_env);
16861 break;
16863 case OPC_DEXTP:
16864 tcg_gen_movi_tl(t0, v2);
16865 tcg_gen_movi_tl(t1, v1);
16867 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
16868 break;
16869 case OPC_DEXTPV:
16870 tcg_gen_movi_tl(t0, v2);
16871 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
16872 break;
16873 case OPC_DEXTPDP:
16874 tcg_gen_movi_tl(t0, v2);
16875 tcg_gen_movi_tl(t1, v1);
16876 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
16877 break;
16878 case OPC_DEXTPDPV:
16879 tcg_gen_movi_tl(t0, v2);
16880 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
16881 break;
16882 case OPC_DEXTR_L:
16883 tcg_gen_movi_tl(t0, v2);
16884 tcg_gen_movi_tl(t1, v1);
16885 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
16886 break;
16887 case OPC_DEXTR_R_L:
16888 tcg_gen_movi_tl(t0, v2);
16889 tcg_gen_movi_tl(t1, v1);
16890 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
16891 break;
16892 case OPC_DEXTR_RS_L:
16893 tcg_gen_movi_tl(t0, v2);
16894 tcg_gen_movi_tl(t1, v1);
16895 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
16896 break;
16897 case OPC_DEXTR_W:
16898 tcg_gen_movi_tl(t0, v2);
16899 tcg_gen_movi_tl(t1, v1);
16900 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
16901 break;
16902 case OPC_DEXTR_R_W:
16903 tcg_gen_movi_tl(t0, v2);
16904 tcg_gen_movi_tl(t1, v1);
16905 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
16906 break;
16907 case OPC_DEXTR_RS_W:
16908 tcg_gen_movi_tl(t0, v2);
16909 tcg_gen_movi_tl(t1, v1);
16910 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
16911 break;
16912 case OPC_DEXTR_S_H:
16913 tcg_gen_movi_tl(t0, v2);
16914 tcg_gen_movi_tl(t1, v1);
16915 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
16916 break;
16917 case OPC_DEXTRV_S_H:
16918 tcg_gen_movi_tl(t0, v2);
16919 tcg_gen_movi_tl(t1, v1);
16920 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
16921 break;
16922 case OPC_DEXTRV_L:
16923 tcg_gen_movi_tl(t0, v2);
16924 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
16925 break;
16926 case OPC_DEXTRV_R_L:
16927 tcg_gen_movi_tl(t0, v2);
16928 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
16929 break;
16930 case OPC_DEXTRV_RS_L:
16931 tcg_gen_movi_tl(t0, v2);
16932 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
16933 break;
16934 case OPC_DEXTRV_W:
16935 tcg_gen_movi_tl(t0, v2);
16936 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16937 break;
16938 case OPC_DEXTRV_R_W:
16939 tcg_gen_movi_tl(t0, v2);
16940 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16941 break;
16942 case OPC_DEXTRV_RS_W:
16943 tcg_gen_movi_tl(t0, v2);
16944 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
16945 break;
16947 break;
16948 #endif
16951 tcg_temp_free(t0);
16952 tcg_temp_free(t1);
16953 tcg_temp_free(v1_t);
16954 tcg_temp_free(v2_t);
16957 /* End MIPSDSP functions. */
16959 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
16961 int rs, rt, rd, sa;
16962 uint32_t op1, op2;
16964 rs = (ctx->opcode >> 21) & 0x1f;
16965 rt = (ctx->opcode >> 16) & 0x1f;
16966 rd = (ctx->opcode >> 11) & 0x1f;
16967 sa = (ctx->opcode >> 6) & 0x1f;
16969 op1 = MASK_SPECIAL(ctx->opcode);
16970 switch (op1) {
16971 case OPC_LSA:
16972 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
16973 break;
16974 case OPC_MULT ... OPC_DIVU:
16975 op2 = MASK_R6_MULDIV(ctx->opcode);
16976 switch (op2) {
16977 case R6_OPC_MUL:
16978 case R6_OPC_MUH:
16979 case R6_OPC_MULU:
16980 case R6_OPC_MUHU:
16981 case R6_OPC_DIV:
16982 case R6_OPC_MOD:
16983 case R6_OPC_DIVU:
16984 case R6_OPC_MODU:
16985 gen_r6_muldiv(ctx, op2, rd, rs, rt);
16986 break;
16987 default:
16988 MIPS_INVAL("special_r6 muldiv");
16989 generate_exception_end(ctx, EXCP_RI);
16990 break;
16992 break;
16993 case OPC_SELEQZ:
16994 case OPC_SELNEZ:
16995 gen_cond_move(ctx, op1, rd, rs, rt);
16996 break;
16997 case R6_OPC_CLO:
16998 case R6_OPC_CLZ:
16999 if (rt == 0 && sa == 1) {
17000 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
17001 We need additionally to check other fields */
17002 gen_cl(ctx, op1, rd, rs);
17003 } else {
17004 generate_exception_end(ctx, EXCP_RI);
17006 break;
17007 case R6_OPC_SDBBP:
17008 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
17009 gen_helper_do_semihosting(cpu_env);
17010 } else {
17011 if (ctx->hflags & MIPS_HFLAG_SBRI) {
17012 generate_exception_end(ctx, EXCP_RI);
17013 } else {
17014 generate_exception_end(ctx, EXCP_DBp);
17017 break;
17018 #if defined(TARGET_MIPS64)
17019 case OPC_DLSA:
17020 check_mips_64(ctx);
17021 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
17022 break;
17023 case R6_OPC_DCLO:
17024 case R6_OPC_DCLZ:
17025 if (rt == 0 && sa == 1) {
17026 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
17027 We need additionally to check other fields */
17028 check_mips_64(ctx);
17029 gen_cl(ctx, op1, rd, rs);
17030 } else {
17031 generate_exception_end(ctx, EXCP_RI);
17033 break;
17034 case OPC_DMULT ... OPC_DDIVU:
17035 op2 = MASK_R6_MULDIV(ctx->opcode);
17036 switch (op2) {
17037 case R6_OPC_DMUL:
17038 case R6_OPC_DMUH:
17039 case R6_OPC_DMULU:
17040 case R6_OPC_DMUHU:
17041 case R6_OPC_DDIV:
17042 case R6_OPC_DMOD:
17043 case R6_OPC_DDIVU:
17044 case R6_OPC_DMODU:
17045 check_mips_64(ctx);
17046 gen_r6_muldiv(ctx, op2, rd, rs, rt);
17047 break;
17048 default:
17049 MIPS_INVAL("special_r6 muldiv");
17050 generate_exception_end(ctx, EXCP_RI);
17051 break;
17053 break;
17054 #endif
17055 default: /* Invalid */
17056 MIPS_INVAL("special_r6");
17057 generate_exception_end(ctx, EXCP_RI);
17058 break;
17062 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
17064 int rs, rt, rd, sa;
17065 uint32_t op1;
17067 rs = (ctx->opcode >> 21) & 0x1f;
17068 rt = (ctx->opcode >> 16) & 0x1f;
17069 rd = (ctx->opcode >> 11) & 0x1f;
17070 sa = (ctx->opcode >> 6) & 0x1f;
17072 op1 = MASK_SPECIAL(ctx->opcode);
17073 switch (op1) {
17074 case OPC_MOVN: /* Conditional move */
17075 case OPC_MOVZ:
17076 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
17077 INSN_LOONGSON2E | INSN_LOONGSON2F);
17078 gen_cond_move(ctx, op1, rd, rs, rt);
17079 break;
17080 case OPC_MFHI: /* Move from HI/LO */
17081 case OPC_MFLO:
17082 gen_HILO(ctx, op1, rs & 3, rd);
17083 break;
17084 case OPC_MTHI:
17085 case OPC_MTLO: /* Move to HI/LO */
17086 gen_HILO(ctx, op1, rd & 3, rs);
17087 break;
17088 case OPC_MOVCI:
17089 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
17090 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
17091 check_cp1_enabled(ctx);
17092 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
17093 (ctx->opcode >> 16) & 1);
17094 } else {
17095 generate_exception_err(ctx, EXCP_CpU, 1);
17097 break;
17098 case OPC_MULT:
17099 case OPC_MULTU:
17100 if (sa) {
17101 check_insn(ctx, INSN_VR54XX);
17102 op1 = MASK_MUL_VR54XX(ctx->opcode);
17103 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
17104 } else {
17105 gen_muldiv(ctx, op1, rd & 3, rs, rt);
17107 break;
17108 case OPC_DIV:
17109 case OPC_DIVU:
17110 gen_muldiv(ctx, op1, 0, rs, rt);
17111 break;
17112 #if defined(TARGET_MIPS64)
17113 case OPC_DMULT ... OPC_DDIVU:
17114 check_insn(ctx, ISA_MIPS3);
17115 check_mips_64(ctx);
17116 gen_muldiv(ctx, op1, 0, rs, rt);
17117 break;
17118 #endif
17119 case OPC_JR:
17120 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
17121 break;
17122 case OPC_SPIM:
17123 #ifdef MIPS_STRICT_STANDARD
17124 MIPS_INVAL("SPIM");
17125 generate_exception_end(ctx, EXCP_RI);
17126 #else
17127 /* Implemented as RI exception for now. */
17128 MIPS_INVAL("spim (unofficial)");
17129 generate_exception_end(ctx, EXCP_RI);
17130 #endif
17131 break;
17132 default: /* Invalid */
17133 MIPS_INVAL("special_legacy");
17134 generate_exception_end(ctx, EXCP_RI);
17135 break;
17139 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
17141 int rs, rt, rd, sa;
17142 uint32_t op1;
17144 rs = (ctx->opcode >> 21) & 0x1f;
17145 rt = (ctx->opcode >> 16) & 0x1f;
17146 rd = (ctx->opcode >> 11) & 0x1f;
17147 sa = (ctx->opcode >> 6) & 0x1f;
17149 op1 = MASK_SPECIAL(ctx->opcode);
17150 switch (op1) {
17151 case OPC_SLL: /* Shift with immediate */
17152 if (sa == 5 && rd == 0 &&
17153 rs == 0 && rt == 0) { /* PAUSE */
17154 if ((ctx->insn_flags & ISA_MIPS32R6) &&
17155 (ctx->hflags & MIPS_HFLAG_BMASK)) {
17156 generate_exception_end(ctx, EXCP_RI);
17157 break;
17160 /* Fallthrough */
17161 case OPC_SRA:
17162 gen_shift_imm(ctx, op1, rd, rt, sa);
17163 break;
17164 case OPC_SRL:
17165 switch ((ctx->opcode >> 21) & 0x1f) {
17166 case 1:
17167 /* rotr is decoded as srl on non-R2 CPUs */
17168 if (ctx->insn_flags & ISA_MIPS32R2) {
17169 op1 = OPC_ROTR;
17171 /* Fallthrough */
17172 case 0:
17173 gen_shift_imm(ctx, op1, rd, rt, sa);
17174 break;
17175 default:
17176 generate_exception_end(ctx, EXCP_RI);
17177 break;
17179 break;
17180 case OPC_ADD ... OPC_SUBU:
17181 gen_arith(ctx, op1, rd, rs, rt);
17182 break;
17183 case OPC_SLLV: /* Shifts */
17184 case OPC_SRAV:
17185 gen_shift(ctx, op1, rd, rs, rt);
17186 break;
17187 case OPC_SRLV:
17188 switch ((ctx->opcode >> 6) & 0x1f) {
17189 case 1:
17190 /* rotrv is decoded as srlv on non-R2 CPUs */
17191 if (ctx->insn_flags & ISA_MIPS32R2) {
17192 op1 = OPC_ROTRV;
17194 /* Fallthrough */
17195 case 0:
17196 gen_shift(ctx, op1, rd, rs, rt);
17197 break;
17198 default:
17199 generate_exception_end(ctx, EXCP_RI);
17200 break;
17202 break;
17203 case OPC_SLT: /* Set on less than */
17204 case OPC_SLTU:
17205 gen_slt(ctx, op1, rd, rs, rt);
17206 break;
17207 case OPC_AND: /* Logic*/
17208 case OPC_OR:
17209 case OPC_NOR:
17210 case OPC_XOR:
17211 gen_logic(ctx, op1, rd, rs, rt);
17212 break;
17213 case OPC_JALR:
17214 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
17215 break;
17216 case OPC_TGE ... OPC_TEQ: /* Traps */
17217 case OPC_TNE:
17218 check_insn(ctx, ISA_MIPS2);
17219 gen_trap(ctx, op1, rs, rt, -1);
17220 break;
17221 case OPC_LSA: /* OPC_PMON */
17222 if ((ctx->insn_flags & ISA_MIPS32R6) ||
17223 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
17224 decode_opc_special_r6(env, ctx);
17225 } else {
17226 /* Pmon entry point, also R4010 selsl */
17227 #ifdef MIPS_STRICT_STANDARD
17228 MIPS_INVAL("PMON / selsl");
17229 generate_exception_end(ctx, EXCP_RI);
17230 #else
17231 gen_helper_0e0i(pmon, sa);
17232 #endif
17234 break;
17235 case OPC_SYSCALL:
17236 generate_exception_end(ctx, EXCP_SYSCALL);
17237 break;
17238 case OPC_BREAK:
17239 generate_exception_end(ctx, EXCP_BREAK);
17240 break;
17241 case OPC_SYNC:
17242 check_insn(ctx, ISA_MIPS2);
17243 gen_sync(extract32(ctx->opcode, 6, 5));
17244 break;
17246 #if defined(TARGET_MIPS64)
17247 /* MIPS64 specific opcodes */
17248 case OPC_DSLL:
17249 case OPC_DSRA:
17250 case OPC_DSLL32:
17251 case OPC_DSRA32:
17252 check_insn(ctx, ISA_MIPS3);
17253 check_mips_64(ctx);
17254 gen_shift_imm(ctx, op1, rd, rt, sa);
17255 break;
17256 case OPC_DSRL:
17257 switch ((ctx->opcode >> 21) & 0x1f) {
17258 case 1:
17259 /* drotr is decoded as dsrl on non-R2 CPUs */
17260 if (ctx->insn_flags & ISA_MIPS32R2) {
17261 op1 = OPC_DROTR;
17263 /* Fallthrough */
17264 case 0:
17265 check_insn(ctx, ISA_MIPS3);
17266 check_mips_64(ctx);
17267 gen_shift_imm(ctx, op1, rd, rt, sa);
17268 break;
17269 default:
17270 generate_exception_end(ctx, EXCP_RI);
17271 break;
17273 break;
17274 case OPC_DSRL32:
17275 switch ((ctx->opcode >> 21) & 0x1f) {
17276 case 1:
17277 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
17278 if (ctx->insn_flags & ISA_MIPS32R2) {
17279 op1 = OPC_DROTR32;
17281 /* Fallthrough */
17282 case 0:
17283 check_insn(ctx, ISA_MIPS3);
17284 check_mips_64(ctx);
17285 gen_shift_imm(ctx, op1, rd, rt, sa);
17286 break;
17287 default:
17288 generate_exception_end(ctx, EXCP_RI);
17289 break;
17291 break;
17292 case OPC_DADD ... OPC_DSUBU:
17293 check_insn(ctx, ISA_MIPS3);
17294 check_mips_64(ctx);
17295 gen_arith(ctx, op1, rd, rs, rt);
17296 break;
17297 case OPC_DSLLV:
17298 case OPC_DSRAV:
17299 check_insn(ctx, ISA_MIPS3);
17300 check_mips_64(ctx);
17301 gen_shift(ctx, op1, rd, rs, rt);
17302 break;
17303 case OPC_DSRLV:
17304 switch ((ctx->opcode >> 6) & 0x1f) {
17305 case 1:
17306 /* drotrv is decoded as dsrlv on non-R2 CPUs */
17307 if (ctx->insn_flags & ISA_MIPS32R2) {
17308 op1 = OPC_DROTRV;
17310 /* Fallthrough */
17311 case 0:
17312 check_insn(ctx, ISA_MIPS3);
17313 check_mips_64(ctx);
17314 gen_shift(ctx, op1, rd, rs, rt);
17315 break;
17316 default:
17317 generate_exception_end(ctx, EXCP_RI);
17318 break;
17320 break;
17321 case OPC_DLSA:
17322 if ((ctx->insn_flags & ISA_MIPS32R6) ||
17323 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
17324 decode_opc_special_r6(env, ctx);
17326 break;
17327 #endif
17328 default:
17329 if (ctx->insn_flags & ISA_MIPS32R6) {
17330 decode_opc_special_r6(env, ctx);
17331 } else {
17332 decode_opc_special_legacy(env, ctx);
17337 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
17339 int rs, rt, rd;
17340 uint32_t op1;
17342 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17344 rs = (ctx->opcode >> 21) & 0x1f;
17345 rt = (ctx->opcode >> 16) & 0x1f;
17346 rd = (ctx->opcode >> 11) & 0x1f;
17348 op1 = MASK_SPECIAL2(ctx->opcode);
17349 switch (op1) {
17350 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
17351 case OPC_MSUB ... OPC_MSUBU:
17352 check_insn(ctx, ISA_MIPS32);
17353 gen_muldiv(ctx, op1, rd & 3, rs, rt);
17354 break;
17355 case OPC_MUL:
17356 gen_arith(ctx, op1, rd, rs, rt);
17357 break;
17358 case OPC_DIV_G_2F:
17359 case OPC_DIVU_G_2F:
17360 case OPC_MULT_G_2F:
17361 case OPC_MULTU_G_2F:
17362 case OPC_MOD_G_2F:
17363 case OPC_MODU_G_2F:
17364 check_insn(ctx, INSN_LOONGSON2F);
17365 gen_loongson_integer(ctx, op1, rd, rs, rt);
17366 break;
17367 case OPC_CLO:
17368 case OPC_CLZ:
17369 check_insn(ctx, ISA_MIPS32);
17370 gen_cl(ctx, op1, rd, rs);
17371 break;
17372 case OPC_SDBBP:
17373 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
17374 gen_helper_do_semihosting(cpu_env);
17375 } else {
17376 /* XXX: not clear which exception should be raised
17377 * when in debug mode...
17379 check_insn(ctx, ISA_MIPS32);
17380 generate_exception_end(ctx, EXCP_DBp);
17382 break;
17383 #if defined(TARGET_MIPS64)
17384 case OPC_DCLO:
17385 case OPC_DCLZ:
17386 check_insn(ctx, ISA_MIPS64);
17387 check_mips_64(ctx);
17388 gen_cl(ctx, op1, rd, rs);
17389 break;
17390 case OPC_DMULT_G_2F:
17391 case OPC_DMULTU_G_2F:
17392 case OPC_DDIV_G_2F:
17393 case OPC_DDIVU_G_2F:
17394 case OPC_DMOD_G_2F:
17395 case OPC_DMODU_G_2F:
17396 check_insn(ctx, INSN_LOONGSON2F);
17397 gen_loongson_integer(ctx, op1, rd, rs, rt);
17398 break;
17399 #endif
17400 default: /* Invalid */
17401 MIPS_INVAL("special2_legacy");
17402 generate_exception_end(ctx, EXCP_RI);
17403 break;
17407 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
17409 int rs, rt, rd, sa;
17410 uint32_t op1, op2;
17411 int16_t imm;
17413 rs = (ctx->opcode >> 21) & 0x1f;
17414 rt = (ctx->opcode >> 16) & 0x1f;
17415 rd = (ctx->opcode >> 11) & 0x1f;
17416 sa = (ctx->opcode >> 6) & 0x1f;
17417 imm = (int16_t)ctx->opcode >> 7;
17419 op1 = MASK_SPECIAL3(ctx->opcode);
17420 switch (op1) {
17421 case R6_OPC_PREF:
17422 if (rt >= 24) {
17423 /* hint codes 24-31 are reserved and signal RI */
17424 generate_exception_end(ctx, EXCP_RI);
17426 /* Treat as NOP. */
17427 break;
17428 case R6_OPC_CACHE:
17429 check_cp0_enabled(ctx);
17430 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
17431 gen_cache_operation(ctx, rt, rs, imm);
17433 break;
17434 case R6_OPC_SC:
17435 gen_st_cond(ctx, op1, rt, rs, imm);
17436 break;
17437 case R6_OPC_LL:
17438 gen_ld(ctx, op1, rt, rs, imm);
17439 break;
17440 case OPC_BSHFL:
17442 if (rd == 0) {
17443 /* Treat as NOP. */
17444 break;
17446 op2 = MASK_BSHFL(ctx->opcode);
17447 switch (op2) {
17448 case OPC_ALIGN ... OPC_ALIGN_END:
17449 gen_align(ctx, OPC_ALIGN, rd, rs, rt, sa & 3);
17450 break;
17451 case OPC_BITSWAP:
17452 gen_bitswap(ctx, op2, rd, rt);
17453 break;
17456 break;
17457 #if defined(TARGET_MIPS64)
17458 case R6_OPC_SCD:
17459 gen_st_cond(ctx, op1, rt, rs, imm);
17460 break;
17461 case R6_OPC_LLD:
17462 gen_ld(ctx, op1, rt, rs, imm);
17463 break;
17464 case OPC_DBSHFL:
17465 check_mips_64(ctx);
17467 if (rd == 0) {
17468 /* Treat as NOP. */
17469 break;
17471 op2 = MASK_DBSHFL(ctx->opcode);
17472 switch (op2) {
17473 case OPC_DALIGN ... OPC_DALIGN_END:
17474 gen_align(ctx, OPC_DALIGN, rd, rs, rt, sa & 7);
17475 break;
17476 case OPC_DBITSWAP:
17477 gen_bitswap(ctx, op2, rd, rt);
17478 break;
17482 break;
17483 #endif
17484 default: /* Invalid */
17485 MIPS_INVAL("special3_r6");
17486 generate_exception_end(ctx, EXCP_RI);
17487 break;
17491 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
17493 int rs, rt, rd;
17494 uint32_t op1, op2;
17496 rs = (ctx->opcode >> 21) & 0x1f;
17497 rt = (ctx->opcode >> 16) & 0x1f;
17498 rd = (ctx->opcode >> 11) & 0x1f;
17500 op1 = MASK_SPECIAL3(ctx->opcode);
17501 switch (op1) {
17502 case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
17503 case OPC_MOD_G_2E ... OPC_MODU_G_2E:
17504 case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
17505 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
17506 * the same mask and op1. */
17507 if ((ctx->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {
17508 op2 = MASK_ADDUH_QB(ctx->opcode);
17509 switch (op2) {
17510 case OPC_ADDUH_QB:
17511 case OPC_ADDUH_R_QB:
17512 case OPC_ADDQH_PH:
17513 case OPC_ADDQH_R_PH:
17514 case OPC_ADDQH_W:
17515 case OPC_ADDQH_R_W:
17516 case OPC_SUBUH_QB:
17517 case OPC_SUBUH_R_QB:
17518 case OPC_SUBQH_PH:
17519 case OPC_SUBQH_R_PH:
17520 case OPC_SUBQH_W:
17521 case OPC_SUBQH_R_W:
17522 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17523 break;
17524 case OPC_MUL_PH:
17525 case OPC_MUL_S_PH:
17526 case OPC_MULQ_S_W:
17527 case OPC_MULQ_RS_W:
17528 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17529 break;
17530 default:
17531 MIPS_INVAL("MASK ADDUH.QB");
17532 generate_exception_end(ctx, EXCP_RI);
17533 break;
17535 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
17536 gen_loongson_integer(ctx, op1, rd, rs, rt);
17537 } else {
17538 generate_exception_end(ctx, EXCP_RI);
17540 break;
17541 case OPC_LX_DSP:
17542 op2 = MASK_LX(ctx->opcode);
17543 switch (op2) {
17544 #if defined(TARGET_MIPS64)
17545 case OPC_LDX:
17546 #endif
17547 case OPC_LBUX:
17548 case OPC_LHX:
17549 case OPC_LWX:
17550 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
17551 break;
17552 default: /* Invalid */
17553 MIPS_INVAL("MASK LX");
17554 generate_exception_end(ctx, EXCP_RI);
17555 break;
17557 break;
17558 case OPC_ABSQ_S_PH_DSP:
17559 op2 = MASK_ABSQ_S_PH(ctx->opcode);
17560 switch (op2) {
17561 case OPC_ABSQ_S_QB:
17562 case OPC_ABSQ_S_PH:
17563 case OPC_ABSQ_S_W:
17564 case OPC_PRECEQ_W_PHL:
17565 case OPC_PRECEQ_W_PHR:
17566 case OPC_PRECEQU_PH_QBL:
17567 case OPC_PRECEQU_PH_QBR:
17568 case OPC_PRECEQU_PH_QBLA:
17569 case OPC_PRECEQU_PH_QBRA:
17570 case OPC_PRECEU_PH_QBL:
17571 case OPC_PRECEU_PH_QBR:
17572 case OPC_PRECEU_PH_QBLA:
17573 case OPC_PRECEU_PH_QBRA:
17574 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17575 break;
17576 case OPC_BITREV:
17577 case OPC_REPL_QB:
17578 case OPC_REPLV_QB:
17579 case OPC_REPL_PH:
17580 case OPC_REPLV_PH:
17581 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
17582 break;
17583 default:
17584 MIPS_INVAL("MASK ABSQ_S.PH");
17585 generate_exception_end(ctx, EXCP_RI);
17586 break;
17588 break;
17589 case OPC_ADDU_QB_DSP:
17590 op2 = MASK_ADDU_QB(ctx->opcode);
17591 switch (op2) {
17592 case OPC_ADDQ_PH:
17593 case OPC_ADDQ_S_PH:
17594 case OPC_ADDQ_S_W:
17595 case OPC_ADDU_QB:
17596 case OPC_ADDU_S_QB:
17597 case OPC_ADDU_PH:
17598 case OPC_ADDU_S_PH:
17599 case OPC_SUBQ_PH:
17600 case OPC_SUBQ_S_PH:
17601 case OPC_SUBQ_S_W:
17602 case OPC_SUBU_QB:
17603 case OPC_SUBU_S_QB:
17604 case OPC_SUBU_PH:
17605 case OPC_SUBU_S_PH:
17606 case OPC_ADDSC:
17607 case OPC_ADDWC:
17608 case OPC_MODSUB:
17609 case OPC_RADDU_W_QB:
17610 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17611 break;
17612 case OPC_MULEU_S_PH_QBL:
17613 case OPC_MULEU_S_PH_QBR:
17614 case OPC_MULQ_RS_PH:
17615 case OPC_MULEQ_S_W_PHL:
17616 case OPC_MULEQ_S_W_PHR:
17617 case OPC_MULQ_S_PH:
17618 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17619 break;
17620 default: /* Invalid */
17621 MIPS_INVAL("MASK ADDU.QB");
17622 generate_exception_end(ctx, EXCP_RI);
17623 break;
17626 break;
17627 case OPC_CMPU_EQ_QB_DSP:
17628 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
17629 switch (op2) {
17630 case OPC_PRECR_SRA_PH_W:
17631 case OPC_PRECR_SRA_R_PH_W:
17632 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
17633 break;
17634 case OPC_PRECR_QB_PH:
17635 case OPC_PRECRQ_QB_PH:
17636 case OPC_PRECRQ_PH_W:
17637 case OPC_PRECRQ_RS_PH_W:
17638 case OPC_PRECRQU_S_QB_PH:
17639 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17640 break;
17641 case OPC_CMPU_EQ_QB:
17642 case OPC_CMPU_LT_QB:
17643 case OPC_CMPU_LE_QB:
17644 case OPC_CMP_EQ_PH:
17645 case OPC_CMP_LT_PH:
17646 case OPC_CMP_LE_PH:
17647 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
17648 break;
17649 case OPC_CMPGU_EQ_QB:
17650 case OPC_CMPGU_LT_QB:
17651 case OPC_CMPGU_LE_QB:
17652 case OPC_CMPGDU_EQ_QB:
17653 case OPC_CMPGDU_LT_QB:
17654 case OPC_CMPGDU_LE_QB:
17655 case OPC_PICK_QB:
17656 case OPC_PICK_PH:
17657 case OPC_PACKRL_PH:
17658 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
17659 break;
17660 default: /* Invalid */
17661 MIPS_INVAL("MASK CMPU.EQ.QB");
17662 generate_exception_end(ctx, EXCP_RI);
17663 break;
17665 break;
17666 case OPC_SHLL_QB_DSP:
17667 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
17668 break;
17669 case OPC_DPA_W_PH_DSP:
17670 op2 = MASK_DPA_W_PH(ctx->opcode);
17671 switch (op2) {
17672 case OPC_DPAU_H_QBL:
17673 case OPC_DPAU_H_QBR:
17674 case OPC_DPSU_H_QBL:
17675 case OPC_DPSU_H_QBR:
17676 case OPC_DPA_W_PH:
17677 case OPC_DPAX_W_PH:
17678 case OPC_DPAQ_S_W_PH:
17679 case OPC_DPAQX_S_W_PH:
17680 case OPC_DPAQX_SA_W_PH:
17681 case OPC_DPS_W_PH:
17682 case OPC_DPSX_W_PH:
17683 case OPC_DPSQ_S_W_PH:
17684 case OPC_DPSQX_S_W_PH:
17685 case OPC_DPSQX_SA_W_PH:
17686 case OPC_MULSAQ_S_W_PH:
17687 case OPC_DPAQ_SA_L_W:
17688 case OPC_DPSQ_SA_L_W:
17689 case OPC_MAQ_S_W_PHL:
17690 case OPC_MAQ_S_W_PHR:
17691 case OPC_MAQ_SA_W_PHL:
17692 case OPC_MAQ_SA_W_PHR:
17693 case OPC_MULSA_W_PH:
17694 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17695 break;
17696 default: /* Invalid */
17697 MIPS_INVAL("MASK DPAW.PH");
17698 generate_exception_end(ctx, EXCP_RI);
17699 break;
17701 break;
17702 case OPC_INSV_DSP:
17703 op2 = MASK_INSV(ctx->opcode);
17704 switch (op2) {
17705 case OPC_INSV:
17706 check_dsp(ctx);
17708 TCGv t0, t1;
17710 if (rt == 0) {
17711 break;
17714 t0 = tcg_temp_new();
17715 t1 = tcg_temp_new();
17717 gen_load_gpr(t0, rt);
17718 gen_load_gpr(t1, rs);
17720 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
17722 tcg_temp_free(t0);
17723 tcg_temp_free(t1);
17724 break;
17726 default: /* Invalid */
17727 MIPS_INVAL("MASK INSV");
17728 generate_exception_end(ctx, EXCP_RI);
17729 break;
17731 break;
17732 case OPC_APPEND_DSP:
17733 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
17734 break;
17735 case OPC_EXTR_W_DSP:
17736 op2 = MASK_EXTR_W(ctx->opcode);
17737 switch (op2) {
17738 case OPC_EXTR_W:
17739 case OPC_EXTR_R_W:
17740 case OPC_EXTR_RS_W:
17741 case OPC_EXTR_S_H:
17742 case OPC_EXTRV_S_H:
17743 case OPC_EXTRV_W:
17744 case OPC_EXTRV_R_W:
17745 case OPC_EXTRV_RS_W:
17746 case OPC_EXTP:
17747 case OPC_EXTPV:
17748 case OPC_EXTPDP:
17749 case OPC_EXTPDPV:
17750 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
17751 break;
17752 case OPC_RDDSP:
17753 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
17754 break;
17755 case OPC_SHILO:
17756 case OPC_SHILOV:
17757 case OPC_MTHLIP:
17758 case OPC_WRDSP:
17759 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
17760 break;
17761 default: /* Invalid */
17762 MIPS_INVAL("MASK EXTR.W");
17763 generate_exception_end(ctx, EXCP_RI);
17764 break;
17766 break;
17767 #if defined(TARGET_MIPS64)
17768 case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
17769 case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
17770 case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
17771 check_insn(ctx, INSN_LOONGSON2E);
17772 gen_loongson_integer(ctx, op1, rd, rs, rt);
17773 break;
17774 case OPC_ABSQ_S_QH_DSP:
17775 op2 = MASK_ABSQ_S_QH(ctx->opcode);
17776 switch (op2) {
17777 case OPC_PRECEQ_L_PWL:
17778 case OPC_PRECEQ_L_PWR:
17779 case OPC_PRECEQ_PW_QHL:
17780 case OPC_PRECEQ_PW_QHR:
17781 case OPC_PRECEQ_PW_QHLA:
17782 case OPC_PRECEQ_PW_QHRA:
17783 case OPC_PRECEQU_QH_OBL:
17784 case OPC_PRECEQU_QH_OBR:
17785 case OPC_PRECEQU_QH_OBLA:
17786 case OPC_PRECEQU_QH_OBRA:
17787 case OPC_PRECEU_QH_OBL:
17788 case OPC_PRECEU_QH_OBR:
17789 case OPC_PRECEU_QH_OBLA:
17790 case OPC_PRECEU_QH_OBRA:
17791 case OPC_ABSQ_S_OB:
17792 case OPC_ABSQ_S_PW:
17793 case OPC_ABSQ_S_QH:
17794 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17795 break;
17796 case OPC_REPL_OB:
17797 case OPC_REPL_PW:
17798 case OPC_REPL_QH:
17799 case OPC_REPLV_OB:
17800 case OPC_REPLV_PW:
17801 case OPC_REPLV_QH:
17802 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
17803 break;
17804 default: /* Invalid */
17805 MIPS_INVAL("MASK ABSQ_S.QH");
17806 generate_exception_end(ctx, EXCP_RI);
17807 break;
17809 break;
17810 case OPC_ADDU_OB_DSP:
17811 op2 = MASK_ADDU_OB(ctx->opcode);
17812 switch (op2) {
17813 case OPC_RADDU_L_OB:
17814 case OPC_SUBQ_PW:
17815 case OPC_SUBQ_S_PW:
17816 case OPC_SUBQ_QH:
17817 case OPC_SUBQ_S_QH:
17818 case OPC_SUBU_OB:
17819 case OPC_SUBU_S_OB:
17820 case OPC_SUBU_QH:
17821 case OPC_SUBU_S_QH:
17822 case OPC_SUBUH_OB:
17823 case OPC_SUBUH_R_OB:
17824 case OPC_ADDQ_PW:
17825 case OPC_ADDQ_S_PW:
17826 case OPC_ADDQ_QH:
17827 case OPC_ADDQ_S_QH:
17828 case OPC_ADDU_OB:
17829 case OPC_ADDU_S_OB:
17830 case OPC_ADDU_QH:
17831 case OPC_ADDU_S_QH:
17832 case OPC_ADDUH_OB:
17833 case OPC_ADDUH_R_OB:
17834 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17835 break;
17836 case OPC_MULEQ_S_PW_QHL:
17837 case OPC_MULEQ_S_PW_QHR:
17838 case OPC_MULEU_S_QH_OBL:
17839 case OPC_MULEU_S_QH_OBR:
17840 case OPC_MULQ_RS_QH:
17841 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17842 break;
17843 default: /* Invalid */
17844 MIPS_INVAL("MASK ADDU.OB");
17845 generate_exception_end(ctx, EXCP_RI);
17846 break;
17848 break;
17849 case OPC_CMPU_EQ_OB_DSP:
17850 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
17851 switch (op2) {
17852 case OPC_PRECR_SRA_QH_PW:
17853 case OPC_PRECR_SRA_R_QH_PW:
17854 /* Return value is rt. */
17855 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
17856 break;
17857 case OPC_PRECR_OB_QH:
17858 case OPC_PRECRQ_OB_QH:
17859 case OPC_PRECRQ_PW_L:
17860 case OPC_PRECRQ_QH_PW:
17861 case OPC_PRECRQ_RS_QH_PW:
17862 case OPC_PRECRQU_S_OB_QH:
17863 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17864 break;
17865 case OPC_CMPU_EQ_OB:
17866 case OPC_CMPU_LT_OB:
17867 case OPC_CMPU_LE_OB:
17868 case OPC_CMP_EQ_QH:
17869 case OPC_CMP_LT_QH:
17870 case OPC_CMP_LE_QH:
17871 case OPC_CMP_EQ_PW:
17872 case OPC_CMP_LT_PW:
17873 case OPC_CMP_LE_PW:
17874 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
17875 break;
17876 case OPC_CMPGDU_EQ_OB:
17877 case OPC_CMPGDU_LT_OB:
17878 case OPC_CMPGDU_LE_OB:
17879 case OPC_CMPGU_EQ_OB:
17880 case OPC_CMPGU_LT_OB:
17881 case OPC_CMPGU_LE_OB:
17882 case OPC_PACKRL_PW:
17883 case OPC_PICK_OB:
17884 case OPC_PICK_PW:
17885 case OPC_PICK_QH:
17886 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
17887 break;
17888 default: /* Invalid */
17889 MIPS_INVAL("MASK CMPU_EQ.OB");
17890 generate_exception_end(ctx, EXCP_RI);
17891 break;
17893 break;
17894 case OPC_DAPPEND_DSP:
17895 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
17896 break;
17897 case OPC_DEXTR_W_DSP:
17898 op2 = MASK_DEXTR_W(ctx->opcode);
17899 switch (op2) {
17900 case OPC_DEXTP:
17901 case OPC_DEXTPDP:
17902 case OPC_DEXTPDPV:
17903 case OPC_DEXTPV:
17904 case OPC_DEXTR_L:
17905 case OPC_DEXTR_R_L:
17906 case OPC_DEXTR_RS_L:
17907 case OPC_DEXTR_W:
17908 case OPC_DEXTR_R_W:
17909 case OPC_DEXTR_RS_W:
17910 case OPC_DEXTR_S_H:
17911 case OPC_DEXTRV_L:
17912 case OPC_DEXTRV_R_L:
17913 case OPC_DEXTRV_RS_L:
17914 case OPC_DEXTRV_S_H:
17915 case OPC_DEXTRV_W:
17916 case OPC_DEXTRV_R_W:
17917 case OPC_DEXTRV_RS_W:
17918 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
17919 break;
17920 case OPC_DMTHLIP:
17921 case OPC_DSHILO:
17922 case OPC_DSHILOV:
17923 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
17924 break;
17925 default: /* Invalid */
17926 MIPS_INVAL("MASK EXTR.W");
17927 generate_exception_end(ctx, EXCP_RI);
17928 break;
17930 break;
17931 case OPC_DPAQ_W_QH_DSP:
17932 op2 = MASK_DPAQ_W_QH(ctx->opcode);
17933 switch (op2) {
17934 case OPC_DPAU_H_OBL:
17935 case OPC_DPAU_H_OBR:
17936 case OPC_DPSU_H_OBL:
17937 case OPC_DPSU_H_OBR:
17938 case OPC_DPA_W_QH:
17939 case OPC_DPAQ_S_W_QH:
17940 case OPC_DPS_W_QH:
17941 case OPC_DPSQ_S_W_QH:
17942 case OPC_MULSAQ_S_W_QH:
17943 case OPC_DPAQ_SA_L_PW:
17944 case OPC_DPSQ_SA_L_PW:
17945 case OPC_MULSAQ_S_L_PW:
17946 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17947 break;
17948 case OPC_MAQ_S_W_QHLL:
17949 case OPC_MAQ_S_W_QHLR:
17950 case OPC_MAQ_S_W_QHRL:
17951 case OPC_MAQ_S_W_QHRR:
17952 case OPC_MAQ_SA_W_QHLL:
17953 case OPC_MAQ_SA_W_QHLR:
17954 case OPC_MAQ_SA_W_QHRL:
17955 case OPC_MAQ_SA_W_QHRR:
17956 case OPC_MAQ_S_L_PWL:
17957 case OPC_MAQ_S_L_PWR:
17958 case OPC_DMADD:
17959 case OPC_DMADDU:
17960 case OPC_DMSUB:
17961 case OPC_DMSUBU:
17962 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17963 break;
17964 default: /* Invalid */
17965 MIPS_INVAL("MASK DPAQ.W.QH");
17966 generate_exception_end(ctx, EXCP_RI);
17967 break;
17969 break;
17970 case OPC_DINSV_DSP:
17971 op2 = MASK_INSV(ctx->opcode);
17972 switch (op2) {
17973 case OPC_DINSV:
17975 TCGv t0, t1;
17977 if (rt == 0) {
17978 break;
17980 check_dsp(ctx);
17982 t0 = tcg_temp_new();
17983 t1 = tcg_temp_new();
17985 gen_load_gpr(t0, rt);
17986 gen_load_gpr(t1, rs);
17988 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
17990 tcg_temp_free(t0);
17991 tcg_temp_free(t1);
17992 break;
17994 default: /* Invalid */
17995 MIPS_INVAL("MASK DINSV");
17996 generate_exception_end(ctx, EXCP_RI);
17997 break;
17999 break;
18000 case OPC_SHLL_OB_DSP:
18001 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
18002 break;
18003 #endif
18004 default: /* Invalid */
18005 MIPS_INVAL("special3_legacy");
18006 generate_exception_end(ctx, EXCP_RI);
18007 break;
18011 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
18013 int rs, rt, rd, sa;
18014 uint32_t op1, op2;
18016 rs = (ctx->opcode >> 21) & 0x1f;
18017 rt = (ctx->opcode >> 16) & 0x1f;
18018 rd = (ctx->opcode >> 11) & 0x1f;
18019 sa = (ctx->opcode >> 6) & 0x1f;
18021 op1 = MASK_SPECIAL3(ctx->opcode);
18022 switch (op1) {
18023 case OPC_EXT:
18024 case OPC_INS:
18025 check_insn(ctx, ISA_MIPS32R2);
18026 gen_bitops(ctx, op1, rt, rs, sa, rd);
18027 break;
18028 case OPC_BSHFL:
18029 op2 = MASK_BSHFL(ctx->opcode);
18030 switch (op2) {
18031 case OPC_ALIGN ... OPC_ALIGN_END:
18032 case OPC_BITSWAP:
18033 check_insn(ctx, ISA_MIPS32R6);
18034 decode_opc_special3_r6(env, ctx);
18035 break;
18036 default:
18037 check_insn(ctx, ISA_MIPS32R2);
18038 gen_bshfl(ctx, op2, rt, rd);
18039 break;
18041 break;
18042 #if defined(TARGET_MIPS64)
18043 case OPC_DEXTM ... OPC_DEXT:
18044 case OPC_DINSM ... OPC_DINS:
18045 check_insn(ctx, ISA_MIPS64R2);
18046 check_mips_64(ctx);
18047 gen_bitops(ctx, op1, rt, rs, sa, rd);
18048 break;
18049 case OPC_DBSHFL:
18050 op2 = MASK_DBSHFL(ctx->opcode);
18051 switch (op2) {
18052 case OPC_DALIGN ... OPC_DALIGN_END:
18053 case OPC_DBITSWAP:
18054 check_insn(ctx, ISA_MIPS32R6);
18055 decode_opc_special3_r6(env, ctx);
18056 break;
18057 default:
18058 check_insn(ctx, ISA_MIPS64R2);
18059 check_mips_64(ctx);
18060 op2 = MASK_DBSHFL(ctx->opcode);
18061 gen_bshfl(ctx, op2, rt, rd);
18062 break;
18064 break;
18065 #endif
18066 case OPC_RDHWR:
18067 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
18068 break;
18069 case OPC_FORK:
18070 check_insn(ctx, ASE_MT);
18072 TCGv t0 = tcg_temp_new();
18073 TCGv t1 = tcg_temp_new();
18075 gen_load_gpr(t0, rt);
18076 gen_load_gpr(t1, rs);
18077 gen_helper_fork(t0, t1);
18078 tcg_temp_free(t0);
18079 tcg_temp_free(t1);
18081 break;
18082 case OPC_YIELD:
18083 check_insn(ctx, ASE_MT);
18085 TCGv t0 = tcg_temp_new();
18087 gen_load_gpr(t0, rs);
18088 gen_helper_yield(t0, cpu_env, t0);
18089 gen_store_gpr(t0, rd);
18090 tcg_temp_free(t0);
18092 break;
18093 default:
18094 if (ctx->insn_flags & ISA_MIPS32R6) {
18095 decode_opc_special3_r6(env, ctx);
18096 } else {
18097 decode_opc_special3_legacy(env, ctx);
18102 /* MIPS SIMD Architecture (MSA) */
18103 static inline int check_msa_access(DisasContext *ctx)
18105 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
18106 !(ctx->hflags & MIPS_HFLAG_F64))) {
18107 generate_exception_end(ctx, EXCP_RI);
18108 return 0;
18111 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
18112 if (ctx->insn_flags & ASE_MSA) {
18113 generate_exception_end(ctx, EXCP_MSADIS);
18114 return 0;
18115 } else {
18116 generate_exception_end(ctx, EXCP_RI);
18117 return 0;
18120 return 1;
18123 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
18125 /* generates tcg ops to check if any element is 0 */
18126 /* Note this function only works with MSA_WRLEN = 128 */
18127 uint64_t eval_zero_or_big = 0;
18128 uint64_t eval_big = 0;
18129 TCGv_i64 t0 = tcg_temp_new_i64();
18130 TCGv_i64 t1 = tcg_temp_new_i64();
18131 switch (df) {
18132 case DF_BYTE:
18133 eval_zero_or_big = 0x0101010101010101ULL;
18134 eval_big = 0x8080808080808080ULL;
18135 break;
18136 case DF_HALF:
18137 eval_zero_or_big = 0x0001000100010001ULL;
18138 eval_big = 0x8000800080008000ULL;
18139 break;
18140 case DF_WORD:
18141 eval_zero_or_big = 0x0000000100000001ULL;
18142 eval_big = 0x8000000080000000ULL;
18143 break;
18144 case DF_DOUBLE:
18145 eval_zero_or_big = 0x0000000000000001ULL;
18146 eval_big = 0x8000000000000000ULL;
18147 break;
18149 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
18150 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
18151 tcg_gen_andi_i64(t0, t0, eval_big);
18152 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
18153 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
18154 tcg_gen_andi_i64(t1, t1, eval_big);
18155 tcg_gen_or_i64(t0, t0, t1);
18156 /* if all bits are zero then all elements are not zero */
18157 /* if some bit is non-zero then some element is zero */
18158 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
18159 tcg_gen_trunc_i64_tl(tresult, t0);
18160 tcg_temp_free_i64(t0);
18161 tcg_temp_free_i64(t1);
18164 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
18166 uint8_t df = (ctx->opcode >> 21) & 0x3;
18167 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18168 int64_t s16 = (int16_t)ctx->opcode;
18170 check_msa_access(ctx);
18172 if (ctx->insn_flags & ISA_MIPS32R6 && ctx->hflags & MIPS_HFLAG_BMASK) {
18173 generate_exception_end(ctx, EXCP_RI);
18174 return;
18176 switch (op1) {
18177 case OPC_BZ_V:
18178 case OPC_BNZ_V:
18180 TCGv_i64 t0 = tcg_temp_new_i64();
18181 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
18182 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
18183 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
18184 tcg_gen_trunc_i64_tl(bcond, t0);
18185 tcg_temp_free_i64(t0);
18187 break;
18188 case OPC_BZ_B:
18189 case OPC_BZ_H:
18190 case OPC_BZ_W:
18191 case OPC_BZ_D:
18192 gen_check_zero_element(bcond, df, wt);
18193 break;
18194 case OPC_BNZ_B:
18195 case OPC_BNZ_H:
18196 case OPC_BNZ_W:
18197 case OPC_BNZ_D:
18198 gen_check_zero_element(bcond, df, wt);
18199 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
18200 break;
18203 ctx->btarget = ctx->pc + (s16 << 2) + 4;
18205 ctx->hflags |= MIPS_HFLAG_BC;
18206 ctx->hflags |= MIPS_HFLAG_BDS32;
18209 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
18211 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
18212 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
18213 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18214 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18216 TCGv_i32 twd = tcg_const_i32(wd);
18217 TCGv_i32 tws = tcg_const_i32(ws);
18218 TCGv_i32 ti8 = tcg_const_i32(i8);
18220 switch (MASK_MSA_I8(ctx->opcode)) {
18221 case OPC_ANDI_B:
18222 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
18223 break;
18224 case OPC_ORI_B:
18225 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
18226 break;
18227 case OPC_NORI_B:
18228 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
18229 break;
18230 case OPC_XORI_B:
18231 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
18232 break;
18233 case OPC_BMNZI_B:
18234 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
18235 break;
18236 case OPC_BMZI_B:
18237 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
18238 break;
18239 case OPC_BSELI_B:
18240 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
18241 break;
18242 case OPC_SHF_B:
18243 case OPC_SHF_H:
18244 case OPC_SHF_W:
18246 uint8_t df = (ctx->opcode >> 24) & 0x3;
18247 if (df == DF_DOUBLE) {
18248 generate_exception_end(ctx, EXCP_RI);
18249 } else {
18250 TCGv_i32 tdf = tcg_const_i32(df);
18251 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
18252 tcg_temp_free_i32(tdf);
18255 break;
18256 default:
18257 MIPS_INVAL("MSA instruction");
18258 generate_exception_end(ctx, EXCP_RI);
18259 break;
18262 tcg_temp_free_i32(twd);
18263 tcg_temp_free_i32(tws);
18264 tcg_temp_free_i32(ti8);
18267 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
18269 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18270 uint8_t df = (ctx->opcode >> 21) & 0x3;
18271 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
18272 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
18273 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18274 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18276 TCGv_i32 tdf = tcg_const_i32(df);
18277 TCGv_i32 twd = tcg_const_i32(wd);
18278 TCGv_i32 tws = tcg_const_i32(ws);
18279 TCGv_i32 timm = tcg_temp_new_i32();
18280 tcg_gen_movi_i32(timm, u5);
18282 switch (MASK_MSA_I5(ctx->opcode)) {
18283 case OPC_ADDVI_df:
18284 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
18285 break;
18286 case OPC_SUBVI_df:
18287 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
18288 break;
18289 case OPC_MAXI_S_df:
18290 tcg_gen_movi_i32(timm, s5);
18291 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
18292 break;
18293 case OPC_MAXI_U_df:
18294 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
18295 break;
18296 case OPC_MINI_S_df:
18297 tcg_gen_movi_i32(timm, s5);
18298 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
18299 break;
18300 case OPC_MINI_U_df:
18301 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
18302 break;
18303 case OPC_CEQI_df:
18304 tcg_gen_movi_i32(timm, s5);
18305 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
18306 break;
18307 case OPC_CLTI_S_df:
18308 tcg_gen_movi_i32(timm, s5);
18309 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
18310 break;
18311 case OPC_CLTI_U_df:
18312 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
18313 break;
18314 case OPC_CLEI_S_df:
18315 tcg_gen_movi_i32(timm, s5);
18316 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
18317 break;
18318 case OPC_CLEI_U_df:
18319 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
18320 break;
18321 case OPC_LDI_df:
18323 int32_t s10 = sextract32(ctx->opcode, 11, 10);
18324 tcg_gen_movi_i32(timm, s10);
18325 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
18327 break;
18328 default:
18329 MIPS_INVAL("MSA instruction");
18330 generate_exception_end(ctx, EXCP_RI);
18331 break;
18334 tcg_temp_free_i32(tdf);
18335 tcg_temp_free_i32(twd);
18336 tcg_temp_free_i32(tws);
18337 tcg_temp_free_i32(timm);
18340 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
18342 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18343 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
18344 uint32_t df = 0, m = 0;
18345 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18346 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18348 TCGv_i32 tdf;
18349 TCGv_i32 tm;
18350 TCGv_i32 twd;
18351 TCGv_i32 tws;
18353 if ((dfm & 0x40) == 0x00) {
18354 m = dfm & 0x3f;
18355 df = DF_DOUBLE;
18356 } else if ((dfm & 0x60) == 0x40) {
18357 m = dfm & 0x1f;
18358 df = DF_WORD;
18359 } else if ((dfm & 0x70) == 0x60) {
18360 m = dfm & 0x0f;
18361 df = DF_HALF;
18362 } else if ((dfm & 0x78) == 0x70) {
18363 m = dfm & 0x7;
18364 df = DF_BYTE;
18365 } else {
18366 generate_exception_end(ctx, EXCP_RI);
18367 return;
18370 tdf = tcg_const_i32(df);
18371 tm = tcg_const_i32(m);
18372 twd = tcg_const_i32(wd);
18373 tws = tcg_const_i32(ws);
18375 switch (MASK_MSA_BIT(ctx->opcode)) {
18376 case OPC_SLLI_df:
18377 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
18378 break;
18379 case OPC_SRAI_df:
18380 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
18381 break;
18382 case OPC_SRLI_df:
18383 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
18384 break;
18385 case OPC_BCLRI_df:
18386 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
18387 break;
18388 case OPC_BSETI_df:
18389 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
18390 break;
18391 case OPC_BNEGI_df:
18392 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
18393 break;
18394 case OPC_BINSLI_df:
18395 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
18396 break;
18397 case OPC_BINSRI_df:
18398 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
18399 break;
18400 case OPC_SAT_S_df:
18401 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
18402 break;
18403 case OPC_SAT_U_df:
18404 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
18405 break;
18406 case OPC_SRARI_df:
18407 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
18408 break;
18409 case OPC_SRLRI_df:
18410 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
18411 break;
18412 default:
18413 MIPS_INVAL("MSA instruction");
18414 generate_exception_end(ctx, EXCP_RI);
18415 break;
18418 tcg_temp_free_i32(tdf);
18419 tcg_temp_free_i32(tm);
18420 tcg_temp_free_i32(twd);
18421 tcg_temp_free_i32(tws);
18424 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
18426 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18427 uint8_t df = (ctx->opcode >> 21) & 0x3;
18428 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18429 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18430 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18432 TCGv_i32 tdf = tcg_const_i32(df);
18433 TCGv_i32 twd = tcg_const_i32(wd);
18434 TCGv_i32 tws = tcg_const_i32(ws);
18435 TCGv_i32 twt = tcg_const_i32(wt);
18437 switch (MASK_MSA_3R(ctx->opcode)) {
18438 case OPC_SLL_df:
18439 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
18440 break;
18441 case OPC_ADDV_df:
18442 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
18443 break;
18444 case OPC_CEQ_df:
18445 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
18446 break;
18447 case OPC_ADD_A_df:
18448 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
18449 break;
18450 case OPC_SUBS_S_df:
18451 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
18452 break;
18453 case OPC_MULV_df:
18454 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
18455 break;
18456 case OPC_SLD_df:
18457 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
18458 break;
18459 case OPC_VSHF_df:
18460 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
18461 break;
18462 case OPC_SRA_df:
18463 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
18464 break;
18465 case OPC_SUBV_df:
18466 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
18467 break;
18468 case OPC_ADDS_A_df:
18469 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
18470 break;
18471 case OPC_SUBS_U_df:
18472 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
18473 break;
18474 case OPC_MADDV_df:
18475 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
18476 break;
18477 case OPC_SPLAT_df:
18478 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
18479 break;
18480 case OPC_SRAR_df:
18481 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
18482 break;
18483 case OPC_SRL_df:
18484 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
18485 break;
18486 case OPC_MAX_S_df:
18487 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
18488 break;
18489 case OPC_CLT_S_df:
18490 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
18491 break;
18492 case OPC_ADDS_S_df:
18493 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
18494 break;
18495 case OPC_SUBSUS_U_df:
18496 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
18497 break;
18498 case OPC_MSUBV_df:
18499 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
18500 break;
18501 case OPC_PCKEV_df:
18502 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
18503 break;
18504 case OPC_SRLR_df:
18505 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
18506 break;
18507 case OPC_BCLR_df:
18508 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
18509 break;
18510 case OPC_MAX_U_df:
18511 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
18512 break;
18513 case OPC_CLT_U_df:
18514 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
18515 break;
18516 case OPC_ADDS_U_df:
18517 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
18518 break;
18519 case OPC_SUBSUU_S_df:
18520 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
18521 break;
18522 case OPC_PCKOD_df:
18523 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
18524 break;
18525 case OPC_BSET_df:
18526 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
18527 break;
18528 case OPC_MIN_S_df:
18529 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
18530 break;
18531 case OPC_CLE_S_df:
18532 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
18533 break;
18534 case OPC_AVE_S_df:
18535 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
18536 break;
18537 case OPC_ASUB_S_df:
18538 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
18539 break;
18540 case OPC_DIV_S_df:
18541 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
18542 break;
18543 case OPC_ILVL_df:
18544 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
18545 break;
18546 case OPC_BNEG_df:
18547 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
18548 break;
18549 case OPC_MIN_U_df:
18550 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
18551 break;
18552 case OPC_CLE_U_df:
18553 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
18554 break;
18555 case OPC_AVE_U_df:
18556 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
18557 break;
18558 case OPC_ASUB_U_df:
18559 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
18560 break;
18561 case OPC_DIV_U_df:
18562 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
18563 break;
18564 case OPC_ILVR_df:
18565 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
18566 break;
18567 case OPC_BINSL_df:
18568 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
18569 break;
18570 case OPC_MAX_A_df:
18571 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
18572 break;
18573 case OPC_AVER_S_df:
18574 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
18575 break;
18576 case OPC_MOD_S_df:
18577 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
18578 break;
18579 case OPC_ILVEV_df:
18580 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
18581 break;
18582 case OPC_BINSR_df:
18583 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
18584 break;
18585 case OPC_MIN_A_df:
18586 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
18587 break;
18588 case OPC_AVER_U_df:
18589 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
18590 break;
18591 case OPC_MOD_U_df:
18592 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
18593 break;
18594 case OPC_ILVOD_df:
18595 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
18596 break;
18598 case OPC_DOTP_S_df:
18599 case OPC_DOTP_U_df:
18600 case OPC_DPADD_S_df:
18601 case OPC_DPADD_U_df:
18602 case OPC_DPSUB_S_df:
18603 case OPC_HADD_S_df:
18604 case OPC_DPSUB_U_df:
18605 case OPC_HADD_U_df:
18606 case OPC_HSUB_S_df:
18607 case OPC_HSUB_U_df:
18608 if (df == DF_BYTE) {
18609 generate_exception_end(ctx, EXCP_RI);
18610 break;
18612 switch (MASK_MSA_3R(ctx->opcode)) {
18613 case OPC_DOTP_S_df:
18614 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
18615 break;
18616 case OPC_DOTP_U_df:
18617 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
18618 break;
18619 case OPC_DPADD_S_df:
18620 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
18621 break;
18622 case OPC_DPADD_U_df:
18623 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
18624 break;
18625 case OPC_DPSUB_S_df:
18626 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
18627 break;
18628 case OPC_HADD_S_df:
18629 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
18630 break;
18631 case OPC_DPSUB_U_df:
18632 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
18633 break;
18634 case OPC_HADD_U_df:
18635 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
18636 break;
18637 case OPC_HSUB_S_df:
18638 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
18639 break;
18640 case OPC_HSUB_U_df:
18641 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
18642 break;
18644 break;
18645 default:
18646 MIPS_INVAL("MSA instruction");
18647 generate_exception_end(ctx, EXCP_RI);
18648 break;
18650 tcg_temp_free_i32(twd);
18651 tcg_temp_free_i32(tws);
18652 tcg_temp_free_i32(twt);
18653 tcg_temp_free_i32(tdf);
18656 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
18658 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
18659 uint8_t source = (ctx->opcode >> 11) & 0x1f;
18660 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
18661 TCGv telm = tcg_temp_new();
18662 TCGv_i32 tsr = tcg_const_i32(source);
18663 TCGv_i32 tdt = tcg_const_i32(dest);
18665 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
18666 case OPC_CTCMSA:
18667 gen_load_gpr(telm, source);
18668 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
18669 break;
18670 case OPC_CFCMSA:
18671 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
18672 gen_store_gpr(telm, dest);
18673 break;
18674 case OPC_MOVE_V:
18675 gen_helper_msa_move_v(cpu_env, tdt, tsr);
18676 break;
18677 default:
18678 MIPS_INVAL("MSA instruction");
18679 generate_exception_end(ctx, EXCP_RI);
18680 break;
18683 tcg_temp_free(telm);
18684 tcg_temp_free_i32(tdt);
18685 tcg_temp_free_i32(tsr);
18688 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
18689 uint32_t n)
18691 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
18692 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18693 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18695 TCGv_i32 tws = tcg_const_i32(ws);
18696 TCGv_i32 twd = tcg_const_i32(wd);
18697 TCGv_i32 tn = tcg_const_i32(n);
18698 TCGv_i32 tdf = tcg_const_i32(df);
18700 switch (MASK_MSA_ELM(ctx->opcode)) {
18701 case OPC_SLDI_df:
18702 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
18703 break;
18704 case OPC_SPLATI_df:
18705 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
18706 break;
18707 case OPC_INSVE_df:
18708 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
18709 break;
18710 case OPC_COPY_S_df:
18711 case OPC_COPY_U_df:
18712 case OPC_INSERT_df:
18713 #if !defined(TARGET_MIPS64)
18714 /* Double format valid only for MIPS64 */
18715 if (df == DF_DOUBLE) {
18716 generate_exception_end(ctx, EXCP_RI);
18717 break;
18719 #endif
18720 switch (MASK_MSA_ELM(ctx->opcode)) {
18721 case OPC_COPY_S_df:
18722 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
18723 break;
18724 case OPC_COPY_U_df:
18725 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
18726 break;
18727 case OPC_INSERT_df:
18728 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
18729 break;
18731 break;
18732 default:
18733 MIPS_INVAL("MSA instruction");
18734 generate_exception_end(ctx, EXCP_RI);
18736 tcg_temp_free_i32(twd);
18737 tcg_temp_free_i32(tws);
18738 tcg_temp_free_i32(tn);
18739 tcg_temp_free_i32(tdf);
18742 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
18744 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
18745 uint32_t df = 0, n = 0;
18747 if ((dfn & 0x30) == 0x00) {
18748 n = dfn & 0x0f;
18749 df = DF_BYTE;
18750 } else if ((dfn & 0x38) == 0x20) {
18751 n = dfn & 0x07;
18752 df = DF_HALF;
18753 } else if ((dfn & 0x3c) == 0x30) {
18754 n = dfn & 0x03;
18755 df = DF_WORD;
18756 } else if ((dfn & 0x3e) == 0x38) {
18757 n = dfn & 0x01;
18758 df = DF_DOUBLE;
18759 } else if (dfn == 0x3E) {
18760 /* CTCMSA, CFCMSA, MOVE.V */
18761 gen_msa_elm_3e(env, ctx);
18762 return;
18763 } else {
18764 generate_exception_end(ctx, EXCP_RI);
18765 return;
18768 gen_msa_elm_df(env, ctx, df, n);
18771 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
18773 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
18774 uint8_t df = (ctx->opcode >> 21) & 0x1;
18775 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18776 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18777 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18779 TCGv_i32 twd = tcg_const_i32(wd);
18780 TCGv_i32 tws = tcg_const_i32(ws);
18781 TCGv_i32 twt = tcg_const_i32(wt);
18782 TCGv_i32 tdf = tcg_temp_new_i32();
18784 /* adjust df value for floating-point instruction */
18785 tcg_gen_movi_i32(tdf, df + 2);
18787 switch (MASK_MSA_3RF(ctx->opcode)) {
18788 case OPC_FCAF_df:
18789 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
18790 break;
18791 case OPC_FADD_df:
18792 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
18793 break;
18794 case OPC_FCUN_df:
18795 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
18796 break;
18797 case OPC_FSUB_df:
18798 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
18799 break;
18800 case OPC_FCOR_df:
18801 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
18802 break;
18803 case OPC_FCEQ_df:
18804 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
18805 break;
18806 case OPC_FMUL_df:
18807 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
18808 break;
18809 case OPC_FCUNE_df:
18810 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
18811 break;
18812 case OPC_FCUEQ_df:
18813 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
18814 break;
18815 case OPC_FDIV_df:
18816 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
18817 break;
18818 case OPC_FCNE_df:
18819 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
18820 break;
18821 case OPC_FCLT_df:
18822 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
18823 break;
18824 case OPC_FMADD_df:
18825 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
18826 break;
18827 case OPC_MUL_Q_df:
18828 tcg_gen_movi_i32(tdf, df + 1);
18829 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
18830 break;
18831 case OPC_FCULT_df:
18832 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
18833 break;
18834 case OPC_FMSUB_df:
18835 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
18836 break;
18837 case OPC_MADD_Q_df:
18838 tcg_gen_movi_i32(tdf, df + 1);
18839 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
18840 break;
18841 case OPC_FCLE_df:
18842 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
18843 break;
18844 case OPC_MSUB_Q_df:
18845 tcg_gen_movi_i32(tdf, df + 1);
18846 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
18847 break;
18848 case OPC_FCULE_df:
18849 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
18850 break;
18851 case OPC_FEXP2_df:
18852 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
18853 break;
18854 case OPC_FSAF_df:
18855 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
18856 break;
18857 case OPC_FEXDO_df:
18858 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
18859 break;
18860 case OPC_FSUN_df:
18861 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
18862 break;
18863 case OPC_FSOR_df:
18864 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
18865 break;
18866 case OPC_FSEQ_df:
18867 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
18868 break;
18869 case OPC_FTQ_df:
18870 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
18871 break;
18872 case OPC_FSUNE_df:
18873 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
18874 break;
18875 case OPC_FSUEQ_df:
18876 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
18877 break;
18878 case OPC_FSNE_df:
18879 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
18880 break;
18881 case OPC_FSLT_df:
18882 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
18883 break;
18884 case OPC_FMIN_df:
18885 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
18886 break;
18887 case OPC_MULR_Q_df:
18888 tcg_gen_movi_i32(tdf, df + 1);
18889 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
18890 break;
18891 case OPC_FSULT_df:
18892 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
18893 break;
18894 case OPC_FMIN_A_df:
18895 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
18896 break;
18897 case OPC_MADDR_Q_df:
18898 tcg_gen_movi_i32(tdf, df + 1);
18899 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
18900 break;
18901 case OPC_FSLE_df:
18902 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
18903 break;
18904 case OPC_FMAX_df:
18905 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
18906 break;
18907 case OPC_MSUBR_Q_df:
18908 tcg_gen_movi_i32(tdf, df + 1);
18909 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
18910 break;
18911 case OPC_FSULE_df:
18912 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
18913 break;
18914 case OPC_FMAX_A_df:
18915 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
18916 break;
18917 default:
18918 MIPS_INVAL("MSA instruction");
18919 generate_exception_end(ctx, EXCP_RI);
18920 break;
18923 tcg_temp_free_i32(twd);
18924 tcg_temp_free_i32(tws);
18925 tcg_temp_free_i32(twt);
18926 tcg_temp_free_i32(tdf);
18929 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
18931 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
18932 (op & (0x7 << 18)))
18933 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18934 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18935 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18936 uint8_t df = (ctx->opcode >> 16) & 0x3;
18937 TCGv_i32 twd = tcg_const_i32(wd);
18938 TCGv_i32 tws = tcg_const_i32(ws);
18939 TCGv_i32 twt = tcg_const_i32(wt);
18940 TCGv_i32 tdf = tcg_const_i32(df);
18942 switch (MASK_MSA_2R(ctx->opcode)) {
18943 case OPC_FILL_df:
18944 #if !defined(TARGET_MIPS64)
18945 /* Double format valid only for MIPS64 */
18946 if (df == DF_DOUBLE) {
18947 generate_exception_end(ctx, EXCP_RI);
18948 break;
18950 #endif
18951 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
18952 break;
18953 case OPC_PCNT_df:
18954 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
18955 break;
18956 case OPC_NLOC_df:
18957 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
18958 break;
18959 case OPC_NLZC_df:
18960 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
18961 break;
18962 default:
18963 MIPS_INVAL("MSA instruction");
18964 generate_exception_end(ctx, EXCP_RI);
18965 break;
18968 tcg_temp_free_i32(twd);
18969 tcg_temp_free_i32(tws);
18970 tcg_temp_free_i32(twt);
18971 tcg_temp_free_i32(tdf);
18974 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
18976 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
18977 (op & (0xf << 17)))
18978 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18979 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18980 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18981 uint8_t df = (ctx->opcode >> 16) & 0x1;
18982 TCGv_i32 twd = tcg_const_i32(wd);
18983 TCGv_i32 tws = tcg_const_i32(ws);
18984 TCGv_i32 twt = tcg_const_i32(wt);
18985 /* adjust df value for floating-point instruction */
18986 TCGv_i32 tdf = tcg_const_i32(df + 2);
18988 switch (MASK_MSA_2RF(ctx->opcode)) {
18989 case OPC_FCLASS_df:
18990 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
18991 break;
18992 case OPC_FTRUNC_S_df:
18993 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
18994 break;
18995 case OPC_FTRUNC_U_df:
18996 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
18997 break;
18998 case OPC_FSQRT_df:
18999 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
19000 break;
19001 case OPC_FRSQRT_df:
19002 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
19003 break;
19004 case OPC_FRCP_df:
19005 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
19006 break;
19007 case OPC_FRINT_df:
19008 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
19009 break;
19010 case OPC_FLOG2_df:
19011 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
19012 break;
19013 case OPC_FEXUPL_df:
19014 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
19015 break;
19016 case OPC_FEXUPR_df:
19017 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
19018 break;
19019 case OPC_FFQL_df:
19020 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
19021 break;
19022 case OPC_FFQR_df:
19023 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
19024 break;
19025 case OPC_FTINT_S_df:
19026 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
19027 break;
19028 case OPC_FTINT_U_df:
19029 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
19030 break;
19031 case OPC_FFINT_S_df:
19032 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
19033 break;
19034 case OPC_FFINT_U_df:
19035 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
19036 break;
19039 tcg_temp_free_i32(twd);
19040 tcg_temp_free_i32(tws);
19041 tcg_temp_free_i32(twt);
19042 tcg_temp_free_i32(tdf);
19045 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
19047 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
19048 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
19049 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
19050 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19051 TCGv_i32 twd = tcg_const_i32(wd);
19052 TCGv_i32 tws = tcg_const_i32(ws);
19053 TCGv_i32 twt = tcg_const_i32(wt);
19055 switch (MASK_MSA_VEC(ctx->opcode)) {
19056 case OPC_AND_V:
19057 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
19058 break;
19059 case OPC_OR_V:
19060 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
19061 break;
19062 case OPC_NOR_V:
19063 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
19064 break;
19065 case OPC_XOR_V:
19066 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
19067 break;
19068 case OPC_BMNZ_V:
19069 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
19070 break;
19071 case OPC_BMZ_V:
19072 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
19073 break;
19074 case OPC_BSEL_V:
19075 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
19076 break;
19077 default:
19078 MIPS_INVAL("MSA instruction");
19079 generate_exception_end(ctx, EXCP_RI);
19080 break;
19083 tcg_temp_free_i32(twd);
19084 tcg_temp_free_i32(tws);
19085 tcg_temp_free_i32(twt);
19088 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
19090 switch (MASK_MSA_VEC(ctx->opcode)) {
19091 case OPC_AND_V:
19092 case OPC_OR_V:
19093 case OPC_NOR_V:
19094 case OPC_XOR_V:
19095 case OPC_BMNZ_V:
19096 case OPC_BMZ_V:
19097 case OPC_BSEL_V:
19098 gen_msa_vec_v(env, ctx);
19099 break;
19100 case OPC_MSA_2R:
19101 gen_msa_2r(env, ctx);
19102 break;
19103 case OPC_MSA_2RF:
19104 gen_msa_2rf(env, ctx);
19105 break;
19106 default:
19107 MIPS_INVAL("MSA instruction");
19108 generate_exception_end(ctx, EXCP_RI);
19109 break;
19113 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
19115 uint32_t opcode = ctx->opcode;
19116 check_insn(ctx, ASE_MSA);
19117 check_msa_access(ctx);
19119 switch (MASK_MSA_MINOR(opcode)) {
19120 case OPC_MSA_I8_00:
19121 case OPC_MSA_I8_01:
19122 case OPC_MSA_I8_02:
19123 gen_msa_i8(env, ctx);
19124 break;
19125 case OPC_MSA_I5_06:
19126 case OPC_MSA_I5_07:
19127 gen_msa_i5(env, ctx);
19128 break;
19129 case OPC_MSA_BIT_09:
19130 case OPC_MSA_BIT_0A:
19131 gen_msa_bit(env, ctx);
19132 break;
19133 case OPC_MSA_3R_0D:
19134 case OPC_MSA_3R_0E:
19135 case OPC_MSA_3R_0F:
19136 case OPC_MSA_3R_10:
19137 case OPC_MSA_3R_11:
19138 case OPC_MSA_3R_12:
19139 case OPC_MSA_3R_13:
19140 case OPC_MSA_3R_14:
19141 case OPC_MSA_3R_15:
19142 gen_msa_3r(env, ctx);
19143 break;
19144 case OPC_MSA_ELM:
19145 gen_msa_elm(env, ctx);
19146 break;
19147 case OPC_MSA_3RF_1A:
19148 case OPC_MSA_3RF_1B:
19149 case OPC_MSA_3RF_1C:
19150 gen_msa_3rf(env, ctx);
19151 break;
19152 case OPC_MSA_VEC:
19153 gen_msa_vec(env, ctx);
19154 break;
19155 case OPC_LD_B:
19156 case OPC_LD_H:
19157 case OPC_LD_W:
19158 case OPC_LD_D:
19159 case OPC_ST_B:
19160 case OPC_ST_H:
19161 case OPC_ST_W:
19162 case OPC_ST_D:
19164 int32_t s10 = sextract32(ctx->opcode, 16, 10);
19165 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
19166 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19167 uint8_t df = (ctx->opcode >> 0) & 0x3;
19169 TCGv_i32 twd = tcg_const_i32(wd);
19170 TCGv taddr = tcg_temp_new();
19171 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
19173 switch (MASK_MSA_MINOR(opcode)) {
19174 case OPC_LD_B:
19175 gen_helper_msa_ld_b(cpu_env, twd, taddr);
19176 break;
19177 case OPC_LD_H:
19178 gen_helper_msa_ld_h(cpu_env, twd, taddr);
19179 break;
19180 case OPC_LD_W:
19181 gen_helper_msa_ld_w(cpu_env, twd, taddr);
19182 break;
19183 case OPC_LD_D:
19184 gen_helper_msa_ld_d(cpu_env, twd, taddr);
19185 break;
19186 case OPC_ST_B:
19187 gen_helper_msa_st_b(cpu_env, twd, taddr);
19188 break;
19189 case OPC_ST_H:
19190 gen_helper_msa_st_h(cpu_env, twd, taddr);
19191 break;
19192 case OPC_ST_W:
19193 gen_helper_msa_st_w(cpu_env, twd, taddr);
19194 break;
19195 case OPC_ST_D:
19196 gen_helper_msa_st_d(cpu_env, twd, taddr);
19197 break;
19200 tcg_temp_free_i32(twd);
19201 tcg_temp_free(taddr);
19203 break;
19204 default:
19205 MIPS_INVAL("MSA instruction");
19206 generate_exception_end(ctx, EXCP_RI);
19207 break;
19212 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
19214 int32_t offset;
19215 int rs, rt, rd, sa;
19216 uint32_t op, op1;
19217 int16_t imm;
19219 /* make sure instructions are on a word boundary */
19220 if (ctx->pc & 0x3) {
19221 env->CP0_BadVAddr = ctx->pc;
19222 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
19223 return;
19226 /* Handle blikely not taken case */
19227 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
19228 TCGLabel *l1 = gen_new_label();
19230 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
19231 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
19232 gen_goto_tb(ctx, 1, ctx->pc + 4);
19233 gen_set_label(l1);
19236 op = MASK_OP_MAJOR(ctx->opcode);
19237 rs = (ctx->opcode >> 21) & 0x1f;
19238 rt = (ctx->opcode >> 16) & 0x1f;
19239 rd = (ctx->opcode >> 11) & 0x1f;
19240 sa = (ctx->opcode >> 6) & 0x1f;
19241 imm = (int16_t)ctx->opcode;
19242 switch (op) {
19243 case OPC_SPECIAL:
19244 decode_opc_special(env, ctx);
19245 break;
19246 case OPC_SPECIAL2:
19247 decode_opc_special2_legacy(env, ctx);
19248 break;
19249 case OPC_SPECIAL3:
19250 decode_opc_special3(env, ctx);
19251 break;
19252 case OPC_REGIMM:
19253 op1 = MASK_REGIMM(ctx->opcode);
19254 switch (op1) {
19255 case OPC_BLTZL: /* REGIMM branches */
19256 case OPC_BGEZL:
19257 case OPC_BLTZALL:
19258 case OPC_BGEZALL:
19259 check_insn(ctx, ISA_MIPS2);
19260 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19261 /* Fallthrough */
19262 case OPC_BLTZ:
19263 case OPC_BGEZ:
19264 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
19265 break;
19266 case OPC_BLTZAL:
19267 case OPC_BGEZAL:
19268 if (ctx->insn_flags & ISA_MIPS32R6) {
19269 if (rs == 0) {
19270 /* OPC_NAL, OPC_BAL */
19271 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
19272 } else {
19273 generate_exception_end(ctx, EXCP_RI);
19275 } else {
19276 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
19278 break;
19279 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
19280 case OPC_TNEI:
19281 check_insn(ctx, ISA_MIPS2);
19282 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19283 gen_trap(ctx, op1, rs, -1, imm);
19284 break;
19285 case OPC_SIGRIE:
19286 check_insn(ctx, ISA_MIPS32R6);
19287 generate_exception_end(ctx, EXCP_RI);
19288 break;
19289 case OPC_SYNCI:
19290 check_insn(ctx, ISA_MIPS32R2);
19291 /* Break the TB to be able to sync copied instructions
19292 immediately */
19293 ctx->bstate = BS_STOP;
19294 break;
19295 case OPC_BPOSGE32: /* MIPS DSP branch */
19296 #if defined(TARGET_MIPS64)
19297 case OPC_BPOSGE64:
19298 #endif
19299 check_dsp(ctx);
19300 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
19301 break;
19302 #if defined(TARGET_MIPS64)
19303 case OPC_DAHI:
19304 check_insn(ctx, ISA_MIPS32R6);
19305 check_mips_64(ctx);
19306 if (rs != 0) {
19307 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
19309 break;
19310 case OPC_DATI:
19311 check_insn(ctx, ISA_MIPS32R6);
19312 check_mips_64(ctx);
19313 if (rs != 0) {
19314 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
19316 break;
19317 #endif
19318 default: /* Invalid */
19319 MIPS_INVAL("regimm");
19320 generate_exception_end(ctx, EXCP_RI);
19321 break;
19323 break;
19324 case OPC_CP0:
19325 check_cp0_enabled(ctx);
19326 op1 = MASK_CP0(ctx->opcode);
19327 switch (op1) {
19328 case OPC_MFC0:
19329 case OPC_MTC0:
19330 case OPC_MFTR:
19331 case OPC_MTTR:
19332 case OPC_MFHC0:
19333 case OPC_MTHC0:
19334 #if defined(TARGET_MIPS64)
19335 case OPC_DMFC0:
19336 case OPC_DMTC0:
19337 #endif
19338 #ifndef CONFIG_USER_ONLY
19339 gen_cp0(env, ctx, op1, rt, rd);
19340 #endif /* !CONFIG_USER_ONLY */
19341 break;
19342 case OPC_C0_FIRST ... OPC_C0_LAST:
19343 #ifndef CONFIG_USER_ONLY
19344 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
19345 #endif /* !CONFIG_USER_ONLY */
19346 break;
19347 case OPC_MFMC0:
19348 #ifndef CONFIG_USER_ONLY
19350 uint32_t op2;
19351 TCGv t0 = tcg_temp_new();
19353 op2 = MASK_MFMC0(ctx->opcode);
19354 switch (op2) {
19355 case OPC_DMT:
19356 check_insn(ctx, ASE_MT);
19357 gen_helper_dmt(t0);
19358 gen_store_gpr(t0, rt);
19359 break;
19360 case OPC_EMT:
19361 check_insn(ctx, ASE_MT);
19362 gen_helper_emt(t0);
19363 gen_store_gpr(t0, rt);
19364 break;
19365 case OPC_DVPE:
19366 check_insn(ctx, ASE_MT);
19367 gen_helper_dvpe(t0, cpu_env);
19368 gen_store_gpr(t0, rt);
19369 break;
19370 case OPC_EVPE:
19371 check_insn(ctx, ASE_MT);
19372 gen_helper_evpe(t0, cpu_env);
19373 gen_store_gpr(t0, rt);
19374 break;
19375 case OPC_DVP:
19376 check_insn(ctx, ISA_MIPS32R6);
19377 if (ctx->vp) {
19378 gen_helper_dvp(t0, cpu_env);
19379 gen_store_gpr(t0, rt);
19381 break;
19382 case OPC_EVP:
19383 check_insn(ctx, ISA_MIPS32R6);
19384 if (ctx->vp) {
19385 gen_helper_evp(t0, cpu_env);
19386 gen_store_gpr(t0, rt);
19388 break;
19389 case OPC_DI:
19390 check_insn(ctx, ISA_MIPS32R2);
19391 save_cpu_state(ctx, 1);
19392 gen_helper_di(t0, cpu_env);
19393 gen_store_gpr(t0, rt);
19394 /* Stop translation as we may have switched
19395 the execution mode. */
19396 ctx->bstate = BS_STOP;
19397 break;
19398 case OPC_EI:
19399 check_insn(ctx, ISA_MIPS32R2);
19400 save_cpu_state(ctx, 1);
19401 gen_helper_ei(t0, cpu_env);
19402 gen_store_gpr(t0, rt);
19403 /* Stop translation as we may have switched
19404 the execution mode. */
19405 ctx->bstate = BS_STOP;
19406 break;
19407 default: /* Invalid */
19408 MIPS_INVAL("mfmc0");
19409 generate_exception_end(ctx, EXCP_RI);
19410 break;
19412 tcg_temp_free(t0);
19414 #endif /* !CONFIG_USER_ONLY */
19415 break;
19416 case OPC_RDPGPR:
19417 check_insn(ctx, ISA_MIPS32R2);
19418 gen_load_srsgpr(rt, rd);
19419 break;
19420 case OPC_WRPGPR:
19421 check_insn(ctx, ISA_MIPS32R2);
19422 gen_store_srsgpr(rt, rd);
19423 break;
19424 default:
19425 MIPS_INVAL("cp0");
19426 generate_exception_end(ctx, EXCP_RI);
19427 break;
19429 break;
19430 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
19431 if (ctx->insn_flags & ISA_MIPS32R6) {
19432 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
19433 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19434 } else {
19435 /* OPC_ADDI */
19436 /* Arithmetic with immediate opcode */
19437 gen_arith_imm(ctx, op, rt, rs, imm);
19439 break;
19440 case OPC_ADDIU:
19441 gen_arith_imm(ctx, op, rt, rs, imm);
19442 break;
19443 case OPC_SLTI: /* Set on less than with immediate opcode */
19444 case OPC_SLTIU:
19445 gen_slt_imm(ctx, op, rt, rs, imm);
19446 break;
19447 case OPC_ANDI: /* Arithmetic with immediate opcode */
19448 case OPC_LUI: /* OPC_AUI */
19449 case OPC_ORI:
19450 case OPC_XORI:
19451 gen_logic_imm(ctx, op, rt, rs, imm);
19452 break;
19453 case OPC_J ... OPC_JAL: /* Jump */
19454 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
19455 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
19456 break;
19457 /* Branch */
19458 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
19459 if (ctx->insn_flags & ISA_MIPS32R6) {
19460 if (rt == 0) {
19461 generate_exception_end(ctx, EXCP_RI);
19462 break;
19464 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
19465 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19466 } else {
19467 /* OPC_BLEZL */
19468 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19470 break;
19471 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
19472 if (ctx->insn_flags & ISA_MIPS32R6) {
19473 if (rt == 0) {
19474 generate_exception_end(ctx, EXCP_RI);
19475 break;
19477 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
19478 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19479 } else {
19480 /* OPC_BGTZL */
19481 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19483 break;
19484 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
19485 if (rt == 0) {
19486 /* OPC_BLEZ */
19487 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19488 } else {
19489 check_insn(ctx, ISA_MIPS32R6);
19490 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
19491 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19493 break;
19494 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
19495 if (rt == 0) {
19496 /* OPC_BGTZ */
19497 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19498 } else {
19499 check_insn(ctx, ISA_MIPS32R6);
19500 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
19501 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19503 break;
19504 case OPC_BEQL:
19505 case OPC_BNEL:
19506 check_insn(ctx, ISA_MIPS2);
19507 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19508 /* Fallthrough */
19509 case OPC_BEQ:
19510 case OPC_BNE:
19511 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19512 break;
19513 case OPC_LL: /* Load and stores */
19514 check_insn(ctx, ISA_MIPS2);
19515 /* Fallthrough */
19516 case OPC_LWL:
19517 case OPC_LWR:
19518 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19519 /* Fallthrough */
19520 case OPC_LB ... OPC_LH:
19521 case OPC_LW ... OPC_LHU:
19522 gen_ld(ctx, op, rt, rs, imm);
19523 break;
19524 case OPC_SWL:
19525 case OPC_SWR:
19526 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19527 /* fall through */
19528 case OPC_SB ... OPC_SH:
19529 case OPC_SW:
19530 gen_st(ctx, op, rt, rs, imm);
19531 break;
19532 case OPC_SC:
19533 check_insn(ctx, ISA_MIPS2);
19534 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19535 gen_st_cond(ctx, op, rt, rs, imm);
19536 break;
19537 case OPC_CACHE:
19538 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19539 check_cp0_enabled(ctx);
19540 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
19541 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
19542 gen_cache_operation(ctx, rt, rs, imm);
19544 /* Treat as NOP. */
19545 break;
19546 case OPC_PREF:
19547 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19548 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
19549 /* Treat as NOP. */
19550 break;
19552 /* Floating point (COP1). */
19553 case OPC_LWC1:
19554 case OPC_LDC1:
19555 case OPC_SWC1:
19556 case OPC_SDC1:
19557 gen_cop1_ldst(ctx, op, rt, rs, imm);
19558 break;
19560 case OPC_CP1:
19561 op1 = MASK_CP1(ctx->opcode);
19563 switch (op1) {
19564 case OPC_MFHC1:
19565 case OPC_MTHC1:
19566 check_cp1_enabled(ctx);
19567 check_insn(ctx, ISA_MIPS32R2);
19568 case OPC_MFC1:
19569 case OPC_CFC1:
19570 case OPC_MTC1:
19571 case OPC_CTC1:
19572 check_cp1_enabled(ctx);
19573 gen_cp1(ctx, op1, rt, rd);
19574 break;
19575 #if defined(TARGET_MIPS64)
19576 case OPC_DMFC1:
19577 case OPC_DMTC1:
19578 check_cp1_enabled(ctx);
19579 check_insn(ctx, ISA_MIPS3);
19580 check_mips_64(ctx);
19581 gen_cp1(ctx, op1, rt, rd);
19582 break;
19583 #endif
19584 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
19585 check_cp1_enabled(ctx);
19586 if (ctx->insn_flags & ISA_MIPS32R6) {
19587 /* OPC_BC1EQZ */
19588 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
19589 rt, imm << 2, 4);
19590 } else {
19591 /* OPC_BC1ANY2 */
19592 check_cop1x(ctx);
19593 check_insn(ctx, ASE_MIPS3D);
19594 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
19595 (rt >> 2) & 0x7, imm << 2);
19597 break;
19598 case OPC_BC1NEZ:
19599 check_cp1_enabled(ctx);
19600 check_insn(ctx, ISA_MIPS32R6);
19601 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
19602 rt, imm << 2, 4);
19603 break;
19604 case OPC_BC1ANY4:
19605 check_cp1_enabled(ctx);
19606 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19607 check_cop1x(ctx);
19608 check_insn(ctx, ASE_MIPS3D);
19609 /* fall through */
19610 case OPC_BC1:
19611 check_cp1_enabled(ctx);
19612 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19613 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
19614 (rt >> 2) & 0x7, imm << 2);
19615 break;
19616 case OPC_PS_FMT:
19617 check_ps(ctx);
19618 /* fall through */
19619 case OPC_S_FMT:
19620 case OPC_D_FMT:
19621 check_cp1_enabled(ctx);
19622 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
19623 (imm >> 8) & 0x7);
19624 break;
19625 case OPC_W_FMT:
19626 case OPC_L_FMT:
19628 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
19629 check_cp1_enabled(ctx);
19630 if (ctx->insn_flags & ISA_MIPS32R6) {
19631 switch (r6_op) {
19632 case R6_OPC_CMP_AF_S:
19633 case R6_OPC_CMP_UN_S:
19634 case R6_OPC_CMP_EQ_S:
19635 case R6_OPC_CMP_UEQ_S:
19636 case R6_OPC_CMP_LT_S:
19637 case R6_OPC_CMP_ULT_S:
19638 case R6_OPC_CMP_LE_S:
19639 case R6_OPC_CMP_ULE_S:
19640 case R6_OPC_CMP_SAF_S:
19641 case R6_OPC_CMP_SUN_S:
19642 case R6_OPC_CMP_SEQ_S:
19643 case R6_OPC_CMP_SEUQ_S:
19644 case R6_OPC_CMP_SLT_S:
19645 case R6_OPC_CMP_SULT_S:
19646 case R6_OPC_CMP_SLE_S:
19647 case R6_OPC_CMP_SULE_S:
19648 case R6_OPC_CMP_OR_S:
19649 case R6_OPC_CMP_UNE_S:
19650 case R6_OPC_CMP_NE_S:
19651 case R6_OPC_CMP_SOR_S:
19652 case R6_OPC_CMP_SUNE_S:
19653 case R6_OPC_CMP_SNE_S:
19654 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
19655 break;
19656 case R6_OPC_CMP_AF_D:
19657 case R6_OPC_CMP_UN_D:
19658 case R6_OPC_CMP_EQ_D:
19659 case R6_OPC_CMP_UEQ_D:
19660 case R6_OPC_CMP_LT_D:
19661 case R6_OPC_CMP_ULT_D:
19662 case R6_OPC_CMP_LE_D:
19663 case R6_OPC_CMP_ULE_D:
19664 case R6_OPC_CMP_SAF_D:
19665 case R6_OPC_CMP_SUN_D:
19666 case R6_OPC_CMP_SEQ_D:
19667 case R6_OPC_CMP_SEUQ_D:
19668 case R6_OPC_CMP_SLT_D:
19669 case R6_OPC_CMP_SULT_D:
19670 case R6_OPC_CMP_SLE_D:
19671 case R6_OPC_CMP_SULE_D:
19672 case R6_OPC_CMP_OR_D:
19673 case R6_OPC_CMP_UNE_D:
19674 case R6_OPC_CMP_NE_D:
19675 case R6_OPC_CMP_SOR_D:
19676 case R6_OPC_CMP_SUNE_D:
19677 case R6_OPC_CMP_SNE_D:
19678 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
19679 break;
19680 default:
19681 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
19682 rt, rd, sa, (imm >> 8) & 0x7);
19684 break;
19686 } else {
19687 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
19688 (imm >> 8) & 0x7);
19690 break;
19692 case OPC_BZ_V:
19693 case OPC_BNZ_V:
19694 case OPC_BZ_B:
19695 case OPC_BZ_H:
19696 case OPC_BZ_W:
19697 case OPC_BZ_D:
19698 case OPC_BNZ_B:
19699 case OPC_BNZ_H:
19700 case OPC_BNZ_W:
19701 case OPC_BNZ_D:
19702 check_insn(ctx, ASE_MSA);
19703 gen_msa_branch(env, ctx, op1);
19704 break;
19705 default:
19706 MIPS_INVAL("cp1");
19707 generate_exception_end(ctx, EXCP_RI);
19708 break;
19710 break;
19712 /* Compact branches [R6] and COP2 [non-R6] */
19713 case OPC_BC: /* OPC_LWC2 */
19714 case OPC_BALC: /* OPC_SWC2 */
19715 if (ctx->insn_flags & ISA_MIPS32R6) {
19716 /* OPC_BC, OPC_BALC */
19717 gen_compute_compact_branch(ctx, op, 0, 0,
19718 sextract32(ctx->opcode << 2, 0, 28));
19719 } else {
19720 /* OPC_LWC2, OPC_SWC2 */
19721 /* COP2: Not implemented. */
19722 generate_exception_err(ctx, EXCP_CpU, 2);
19724 break;
19725 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
19726 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
19727 if (ctx->insn_flags & ISA_MIPS32R6) {
19728 if (rs != 0) {
19729 /* OPC_BEQZC, OPC_BNEZC */
19730 gen_compute_compact_branch(ctx, op, rs, 0,
19731 sextract32(ctx->opcode << 2, 0, 23));
19732 } else {
19733 /* OPC_JIC, OPC_JIALC */
19734 gen_compute_compact_branch(ctx, op, 0, rt, imm);
19736 } else {
19737 /* OPC_LWC2, OPC_SWC2 */
19738 /* COP2: Not implemented. */
19739 generate_exception_err(ctx, EXCP_CpU, 2);
19741 break;
19742 case OPC_CP2:
19743 check_insn(ctx, INSN_LOONGSON2F);
19744 /* Note that these instructions use different fields. */
19745 gen_loongson_multimedia(ctx, sa, rd, rt);
19746 break;
19748 case OPC_CP3:
19749 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19750 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
19751 check_cp1_enabled(ctx);
19752 op1 = MASK_CP3(ctx->opcode);
19753 switch (op1) {
19754 case OPC_LUXC1:
19755 case OPC_SUXC1:
19756 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
19757 /* Fallthrough */
19758 case OPC_LWXC1:
19759 case OPC_LDXC1:
19760 case OPC_SWXC1:
19761 case OPC_SDXC1:
19762 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
19763 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
19764 break;
19765 case OPC_PREFX:
19766 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
19767 /* Treat as NOP. */
19768 break;
19769 case OPC_ALNV_PS:
19770 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
19771 /* Fallthrough */
19772 case OPC_MADD_S:
19773 case OPC_MADD_D:
19774 case OPC_MADD_PS:
19775 case OPC_MSUB_S:
19776 case OPC_MSUB_D:
19777 case OPC_MSUB_PS:
19778 case OPC_NMADD_S:
19779 case OPC_NMADD_D:
19780 case OPC_NMADD_PS:
19781 case OPC_NMSUB_S:
19782 case OPC_NMSUB_D:
19783 case OPC_NMSUB_PS:
19784 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
19785 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
19786 break;
19787 default:
19788 MIPS_INVAL("cp3");
19789 generate_exception_end(ctx, EXCP_RI);
19790 break;
19792 } else {
19793 generate_exception_err(ctx, EXCP_CpU, 1);
19795 break;
19797 #if defined(TARGET_MIPS64)
19798 /* MIPS64 opcodes */
19799 case OPC_LDL ... OPC_LDR:
19800 case OPC_LLD:
19801 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19802 /* fall through */
19803 case OPC_LWU:
19804 case OPC_LD:
19805 check_insn(ctx, ISA_MIPS3);
19806 check_mips_64(ctx);
19807 gen_ld(ctx, op, rt, rs, imm);
19808 break;
19809 case OPC_SDL ... OPC_SDR:
19810 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19811 /* fall through */
19812 case OPC_SD:
19813 check_insn(ctx, ISA_MIPS3);
19814 check_mips_64(ctx);
19815 gen_st(ctx, op, rt, rs, imm);
19816 break;
19817 case OPC_SCD:
19818 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19819 check_insn(ctx, ISA_MIPS3);
19820 check_mips_64(ctx);
19821 gen_st_cond(ctx, op, rt, rs, imm);
19822 break;
19823 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
19824 if (ctx->insn_flags & ISA_MIPS32R6) {
19825 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
19826 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19827 } else {
19828 /* OPC_DADDI */
19829 check_insn(ctx, ISA_MIPS3);
19830 check_mips_64(ctx);
19831 gen_arith_imm(ctx, op, rt, rs, imm);
19833 break;
19834 case OPC_DADDIU:
19835 check_insn(ctx, ISA_MIPS3);
19836 check_mips_64(ctx);
19837 gen_arith_imm(ctx, op, rt, rs, imm);
19838 break;
19839 #else
19840 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
19841 if (ctx->insn_flags & ISA_MIPS32R6) {
19842 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19843 } else {
19844 MIPS_INVAL("major opcode");
19845 generate_exception_end(ctx, EXCP_RI);
19847 break;
19848 #endif
19849 case OPC_DAUI: /* OPC_JALX */
19850 if (ctx->insn_flags & ISA_MIPS32R6) {
19851 #if defined(TARGET_MIPS64)
19852 /* OPC_DAUI */
19853 check_mips_64(ctx);
19854 if (rs == 0) {
19855 generate_exception(ctx, EXCP_RI);
19856 } else if (rt != 0) {
19857 TCGv t0 = tcg_temp_new();
19858 gen_load_gpr(t0, rs);
19859 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
19860 tcg_temp_free(t0);
19862 #else
19863 generate_exception_end(ctx, EXCP_RI);
19864 MIPS_INVAL("major opcode");
19865 #endif
19866 } else {
19867 /* OPC_JALX */
19868 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
19869 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
19870 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
19872 break;
19873 case OPC_MSA: /* OPC_MDMX */
19874 /* MDMX: Not implemented. */
19875 gen_msa(env, ctx);
19876 break;
19877 case OPC_PCREL:
19878 check_insn(ctx, ISA_MIPS32R6);
19879 gen_pcrel(ctx, ctx->opcode, ctx->pc, rs);
19880 break;
19881 default: /* Invalid */
19882 MIPS_INVAL("major opcode");
19883 generate_exception_end(ctx, EXCP_RI);
19884 break;
19888 void gen_intermediate_code(CPUMIPSState *env, struct TranslationBlock *tb)
19890 MIPSCPU *cpu = mips_env_get_cpu(env);
19891 CPUState *cs = CPU(cpu);
19892 DisasContext ctx;
19893 target_ulong pc_start;
19894 target_ulong next_page_start;
19895 int num_insns;
19896 int max_insns;
19897 int insn_bytes;
19898 int is_slot;
19900 pc_start = tb->pc;
19901 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
19902 ctx.pc = pc_start;
19903 ctx.saved_pc = -1;
19904 ctx.singlestep_enabled = cs->singlestep_enabled;
19905 ctx.insn_flags = env->insn_flags;
19906 ctx.CP0_Config1 = env->CP0_Config1;
19907 ctx.tb = tb;
19908 ctx.bstate = BS_NONE;
19909 ctx.btarget = 0;
19910 ctx.kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
19911 ctx.rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
19912 ctx.ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
19913 ctx.bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
19914 ctx.bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
19915 ctx.PAMask = env->PAMask;
19916 ctx.mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
19917 ctx.CP0_LLAddr_shift = env->CP0_LLAddr_shift;
19918 ctx.cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
19919 /* Restore delay slot state from the tb context. */
19920 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
19921 ctx.ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
19922 ctx.ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
19923 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
19924 ctx.vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
19925 ctx.mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
19926 ctx.nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
19927 ctx.abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
19928 restore_cpu_state(env, &ctx);
19929 #ifdef CONFIG_USER_ONLY
19930 ctx.mem_idx = MIPS_HFLAG_UM;
19931 #else
19932 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
19933 #endif
19934 ctx.default_tcg_memop_mask = (ctx.insn_flags & ISA_MIPS32R6) ?
19935 MO_UNALN : MO_ALIGN;
19936 num_insns = 0;
19937 max_insns = tb->cflags & CF_COUNT_MASK;
19938 if (max_insns == 0) {
19939 max_insns = CF_COUNT_MASK;
19941 if (max_insns > TCG_MAX_INSNS) {
19942 max_insns = TCG_MAX_INSNS;
19945 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
19946 gen_tb_start(tb);
19947 while (ctx.bstate == BS_NONE) {
19948 tcg_gen_insn_start(ctx.pc, ctx.hflags & MIPS_HFLAG_BMASK, ctx.btarget);
19949 num_insns++;
19951 if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) {
19952 save_cpu_state(&ctx, 1);
19953 ctx.bstate = BS_BRANCH;
19954 gen_helper_raise_exception_debug(cpu_env);
19955 /* The address covered by the breakpoint must be included in
19956 [tb->pc, tb->pc + tb->size) in order to for it to be
19957 properly cleared -- thus we increment the PC here so that
19958 the logic setting tb->size below does the right thing. */
19959 ctx.pc += 4;
19960 goto done_generating;
19963 if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
19964 gen_io_start();
19967 is_slot = ctx.hflags & MIPS_HFLAG_BMASK;
19968 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
19969 ctx.opcode = cpu_ldl_code(env, ctx.pc);
19970 insn_bytes = 4;
19971 decode_opc(env, &ctx);
19972 } else if (ctx.insn_flags & ASE_MICROMIPS) {
19973 ctx.opcode = cpu_lduw_code(env, ctx.pc);
19974 insn_bytes = decode_micromips_opc(env, &ctx);
19975 } else if (ctx.insn_flags & ASE_MIPS16) {
19976 ctx.opcode = cpu_lduw_code(env, ctx.pc);
19977 insn_bytes = decode_mips16_opc(env, &ctx);
19978 } else {
19979 generate_exception_end(&ctx, EXCP_RI);
19980 break;
19983 if (ctx.hflags & MIPS_HFLAG_BMASK) {
19984 if (!(ctx.hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
19985 MIPS_HFLAG_FBNSLOT))) {
19986 /* force to generate branch as there is neither delay nor
19987 forbidden slot */
19988 is_slot = 1;
19990 if ((ctx.hflags & MIPS_HFLAG_M16) &&
19991 (ctx.hflags & MIPS_HFLAG_FBNSLOT)) {
19992 /* Force to generate branch as microMIPS R6 doesn't restrict
19993 branches in the forbidden slot. */
19994 is_slot = 1;
19997 if (is_slot) {
19998 gen_branch(&ctx, insn_bytes);
20000 ctx.pc += insn_bytes;
20002 /* Execute a branch and its delay slot as a single instruction.
20003 This is what GDB expects and is consistent with what the
20004 hardware does (e.g. if a delay slot instruction faults, the
20005 reported PC is the PC of the branch). */
20006 if (cs->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0) {
20007 break;
20010 if (ctx.pc >= next_page_start) {
20011 break;
20014 if (tcg_op_buf_full()) {
20015 break;
20018 if (num_insns >= max_insns)
20019 break;
20021 if (singlestep)
20022 break;
20024 if (tb->cflags & CF_LAST_IO) {
20025 gen_io_end();
20027 if (cs->singlestep_enabled && ctx.bstate != BS_BRANCH) {
20028 save_cpu_state(&ctx, ctx.bstate != BS_EXCP);
20029 gen_helper_raise_exception_debug(cpu_env);
20030 } else {
20031 switch (ctx.bstate) {
20032 case BS_STOP:
20033 gen_goto_tb(&ctx, 0, ctx.pc);
20034 break;
20035 case BS_NONE:
20036 save_cpu_state(&ctx, 0);
20037 gen_goto_tb(&ctx, 0, ctx.pc);
20038 break;
20039 case BS_EXCP:
20040 tcg_gen_exit_tb(0);
20041 break;
20042 case BS_BRANCH:
20043 default:
20044 break;
20047 done_generating:
20048 gen_tb_end(tb, num_insns);
20050 tb->size = ctx.pc - pc_start;
20051 tb->icount = num_insns;
20053 #ifdef DEBUG_DISAS
20054 LOG_DISAS("\n");
20055 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
20056 && qemu_log_in_addr_range(pc_start)) {
20057 qemu_log_lock();
20058 qemu_log("IN: %s\n", lookup_symbol(pc_start));
20059 log_target_disas(cs, pc_start, ctx.pc - pc_start, 0);
20060 qemu_log("\n");
20061 qemu_log_unlock();
20063 #endif
20066 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
20067 int flags)
20069 int i;
20070 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
20072 #define printfpr(fp) \
20073 do { \
20074 if (is_fpu64) \
20075 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
20076 " fd:%13g fs:%13g psu: %13g\n", \
20077 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
20078 (double)(fp)->fd, \
20079 (double)(fp)->fs[FP_ENDIAN_IDX], \
20080 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
20081 else { \
20082 fpr_t tmp; \
20083 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
20084 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
20085 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
20086 " fd:%13g fs:%13g psu:%13g\n", \
20087 tmp.w[FP_ENDIAN_IDX], tmp.d, \
20088 (double)tmp.fd, \
20089 (double)tmp.fs[FP_ENDIAN_IDX], \
20090 (double)tmp.fs[!FP_ENDIAN_IDX]); \
20092 } while(0)
20095 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
20096 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
20097 get_float_exception_flags(&env->active_fpu.fp_status));
20098 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
20099 fpu_fprintf(f, "%3s: ", fregnames[i]);
20100 printfpr(&env->active_fpu.fpr[i]);
20103 #undef printfpr
20106 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
20107 int flags)
20109 MIPSCPU *cpu = MIPS_CPU(cs);
20110 CPUMIPSState *env = &cpu->env;
20111 int i;
20113 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
20114 " LO=0x" TARGET_FMT_lx " ds %04x "
20115 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
20116 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
20117 env->hflags, env->btarget, env->bcond);
20118 for (i = 0; i < 32; i++) {
20119 if ((i & 3) == 0)
20120 cpu_fprintf(f, "GPR%02d:", i);
20121 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
20122 if ((i & 3) == 3)
20123 cpu_fprintf(f, "\n");
20126 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
20127 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
20128 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
20129 PRIx64 "\n",
20130 env->CP0_Config0, env->CP0_Config1, env->lladdr);
20131 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
20132 env->CP0_Config2, env->CP0_Config3);
20133 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
20134 env->CP0_Config4, env->CP0_Config5);
20135 if (env->hflags & MIPS_HFLAG_FPU)
20136 fpu_dump_state(env, f, cpu_fprintf, flags);
20139 void mips_tcg_init(void)
20141 int i;
20142 static int inited;
20144 /* Initialize various static tables. */
20145 if (inited)
20146 return;
20148 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
20149 tcg_ctx.tcg_env = cpu_env;
20151 TCGV_UNUSED(cpu_gpr[0]);
20152 for (i = 1; i < 32; i++)
20153 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
20154 offsetof(CPUMIPSState, active_tc.gpr[i]),
20155 regnames[i]);
20157 for (i = 0; i < 32; i++) {
20158 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
20159 msa_wr_d[i * 2] =
20160 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
20161 /* The scalar floating-point unit (FPU) registers are mapped on
20162 * the MSA vector registers. */
20163 fpu_f64[i] = msa_wr_d[i * 2];
20164 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
20165 msa_wr_d[i * 2 + 1] =
20166 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
20169 cpu_PC = tcg_global_mem_new(cpu_env,
20170 offsetof(CPUMIPSState, active_tc.PC), "PC");
20171 for (i = 0; i < MIPS_DSP_ACC; i++) {
20172 cpu_HI[i] = tcg_global_mem_new(cpu_env,
20173 offsetof(CPUMIPSState, active_tc.HI[i]),
20174 regnames_HI[i]);
20175 cpu_LO[i] = tcg_global_mem_new(cpu_env,
20176 offsetof(CPUMIPSState, active_tc.LO[i]),
20177 regnames_LO[i]);
20179 cpu_dspctrl = tcg_global_mem_new(cpu_env,
20180 offsetof(CPUMIPSState, active_tc.DSPControl),
20181 "DSPControl");
20182 bcond = tcg_global_mem_new(cpu_env,
20183 offsetof(CPUMIPSState, bcond), "bcond");
20184 btarget = tcg_global_mem_new(cpu_env,
20185 offsetof(CPUMIPSState, btarget), "btarget");
20186 hflags = tcg_global_mem_new_i32(cpu_env,
20187 offsetof(CPUMIPSState, hflags), "hflags");
20189 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
20190 offsetof(CPUMIPSState, active_fpu.fcr0),
20191 "fcr0");
20192 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
20193 offsetof(CPUMIPSState, active_fpu.fcr31),
20194 "fcr31");
20196 inited = 1;
20199 #include "translate_init.c"
20201 MIPSCPU *cpu_mips_init(const char *cpu_model)
20203 MIPSCPU *cpu;
20204 CPUMIPSState *env;
20205 const mips_def_t *def;
20207 def = cpu_mips_find_by_name(cpu_model);
20208 if (!def)
20209 return NULL;
20210 cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
20211 env = &cpu->env;
20212 env->cpu_model = def;
20213 env->exception_base = (int32_t)0xBFC00000;
20215 #ifndef CONFIG_USER_ONLY
20216 mmu_init(env, def);
20217 #endif
20218 fpu_init(env, def);
20219 mvp_init(env, def);
20221 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
20223 return cpu;
20226 bool cpu_supports_cps_smp(const char *cpu_model)
20228 const mips_def_t *def = cpu_mips_find_by_name(cpu_model);
20229 if (!def) {
20230 return false;
20233 return (def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
20236 bool cpu_supports_isa(const char *cpu_model, unsigned int isa)
20238 const mips_def_t *def = cpu_mips_find_by_name(cpu_model);
20239 if (!def) {
20240 return false;
20243 return (def->insn_flags & isa) != 0;
20246 void cpu_set_exception_base(int vp_index, target_ulong address)
20248 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
20249 vp->env.exception_base = address;
20252 void cpu_state_reset(CPUMIPSState *env)
20254 MIPSCPU *cpu = mips_env_get_cpu(env);
20255 CPUState *cs = CPU(cpu);
20257 /* Reset registers to their default values */
20258 env->CP0_PRid = env->cpu_model->CP0_PRid;
20259 env->CP0_Config0 = env->cpu_model->CP0_Config0;
20260 #ifdef TARGET_WORDS_BIGENDIAN
20261 env->CP0_Config0 |= (1 << CP0C0_BE);
20262 #endif
20263 env->CP0_Config1 = env->cpu_model->CP0_Config1;
20264 env->CP0_Config2 = env->cpu_model->CP0_Config2;
20265 env->CP0_Config3 = env->cpu_model->CP0_Config3;
20266 env->CP0_Config4 = env->cpu_model->CP0_Config4;
20267 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
20268 env->CP0_Config5 = env->cpu_model->CP0_Config5;
20269 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
20270 env->CP0_Config6 = env->cpu_model->CP0_Config6;
20271 env->CP0_Config7 = env->cpu_model->CP0_Config7;
20272 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
20273 << env->cpu_model->CP0_LLAddr_shift;
20274 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
20275 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
20276 env->CCRes = env->cpu_model->CCRes;
20277 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
20278 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
20279 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
20280 env->current_tc = 0;
20281 env->SEGBITS = env->cpu_model->SEGBITS;
20282 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
20283 #if defined(TARGET_MIPS64)
20284 if (env->cpu_model->insn_flags & ISA_MIPS3) {
20285 env->SEGMask |= 3ULL << 62;
20287 #endif
20288 env->PABITS = env->cpu_model->PABITS;
20289 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
20290 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
20291 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
20292 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
20293 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
20294 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
20295 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
20296 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
20297 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
20298 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
20299 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
20300 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
20301 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
20302 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
20303 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
20304 env->msair = env->cpu_model->MSAIR;
20305 env->insn_flags = env->cpu_model->insn_flags;
20307 #if defined(CONFIG_USER_ONLY)
20308 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
20309 # ifdef TARGET_MIPS64
20310 /* Enable 64-bit register mode. */
20311 env->CP0_Status |= (1 << CP0St_PX);
20312 # endif
20313 # ifdef TARGET_ABI_MIPSN64
20314 /* Enable 64-bit address mode. */
20315 env->CP0_Status |= (1 << CP0St_UX);
20316 # endif
20317 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
20318 hardware registers. */
20319 env->CP0_HWREna |= 0x0000000F;
20320 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
20321 env->CP0_Status |= (1 << CP0St_CU1);
20323 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
20324 env->CP0_Status |= (1 << CP0St_MX);
20326 # if defined(TARGET_MIPS64)
20327 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
20328 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
20329 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
20330 env->CP0_Status |= (1 << CP0St_FR);
20332 # endif
20333 #else
20334 if (env->hflags & MIPS_HFLAG_BMASK) {
20335 /* If the exception was raised from a delay slot,
20336 come back to the jump. */
20337 env->CP0_ErrorEPC = (env->active_tc.PC
20338 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
20339 } else {
20340 env->CP0_ErrorEPC = env->active_tc.PC;
20342 env->active_tc.PC = env->exception_base;
20343 env->CP0_Random = env->tlb->nb_tlb - 1;
20344 env->tlb->tlb_in_use = env->tlb->nb_tlb;
20345 env->CP0_Wired = 0;
20346 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
20347 env->CP0_EBase = (cs->cpu_index & 0x3FF);
20348 if (kvm_enabled()) {
20349 env->CP0_EBase |= 0x40000000;
20350 } else {
20351 env->CP0_EBase |= 0x80000000;
20353 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
20354 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
20356 env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
20357 0x3ff : 0xff;
20358 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
20359 /* vectored interrupts not implemented, timer on int 7,
20360 no performance counters. */
20361 env->CP0_IntCtl = 0xe0000000;
20363 int i;
20365 for (i = 0; i < 7; i++) {
20366 env->CP0_WatchLo[i] = 0;
20367 env->CP0_WatchHi[i] = 0x80000000;
20369 env->CP0_WatchLo[7] = 0;
20370 env->CP0_WatchHi[7] = 0;
20372 /* Count register increments in debug mode, EJTAG version 1 */
20373 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
20375 cpu_mips_store_count(env, 1);
20377 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
20378 int i;
20380 /* Only TC0 on VPE 0 starts as active. */
20381 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
20382 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
20383 env->tcs[i].CP0_TCHalt = 1;
20385 env->active_tc.CP0_TCHalt = 1;
20386 cs->halted = 1;
20388 if (cs->cpu_index == 0) {
20389 /* VPE0 starts up enabled. */
20390 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
20391 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
20393 /* TC0 starts up unhalted. */
20394 cs->halted = 0;
20395 env->active_tc.CP0_TCHalt = 0;
20396 env->tcs[0].CP0_TCHalt = 0;
20397 /* With thread 0 active. */
20398 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
20399 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
20402 #endif
20403 if ((env->insn_flags & ISA_MIPS32R6) &&
20404 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
20405 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
20406 env->CP0_Status |= (1 << CP0St_FR);
20409 /* MSA */
20410 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
20411 msa_reset(env);
20414 compute_hflags(env);
20415 restore_fp_status(env);
20416 restore_pamask(env);
20417 cs->exception_index = EXCP_NONE;
20419 if (semihosting_get_argc()) {
20420 /* UHI interface can be used to obtain argc and argv */
20421 env->active_tc.gpr[4] = -1;
20425 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
20426 target_ulong *data)
20428 env->active_tc.PC = data[0];
20429 env->hflags &= ~MIPS_HFLAG_BMASK;
20430 env->hflags |= data[1];
20431 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
20432 case MIPS_HFLAG_BR:
20433 break;
20434 case MIPS_HFLAG_BC:
20435 case MIPS_HFLAG_BL:
20436 case MIPS_HFLAG_B:
20437 env->btarget = data[2];
20438 break;